From 4931b0984b1a526c6c86a47b200c2dbb58d2fa50 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 3 Mar 2010 20:09:48 +0100 Subject: [PATCH 001/673] Network infrastructure --- commands/net.c | 296 ++++++++++++++++++++++++++++++++++++++++++ commands/probe.c | 2 +- conf/common.rmk | 6 + include/grub/device.h | 6 +- include/grub/err.h | 5 +- include/grub/net.h | 248 +++++++++++++++++++++++++++++------ kern/fs.c | 2 +- 7 files changed, 522 insertions(+), 43 deletions(-) create mode 100644 commands/net.c diff --git a/commands/net.c b/commands/net.c new file mode 100644 index 000000000..288ba4c2a --- /dev/null +++ b/commands/net.c @@ -0,0 +1,296 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 . + */ + +#include +#include +#include +#include +#include + +struct grub_net_route *grub_net_routes = NULL; +struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; +struct grub_net_card *grub_net_cards = NULL; +struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr) +{ + FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) + { + grub_err_t err; + err = grub_net_resolve_address_in_protocol (*prot, name, addr); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Unrecognised address %s"), + name); +} + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf) +{ + struct grub_net_route *route; + int depth = 0; + int routecnt = 0; + struct grub_net_network_level_protocol *prot = NULL; + grub_net_network_level_address_t curtarget = addr; + + *gateway = addr; + + FOR_NET_ROUTES(route) + routecnt++; + + for (depth = 0; depth < routecnt + 2; depth++) + { + FOR_NET_ROUTES(route) + { + if (depth && prot != route->prot) + continue; + prot = route->prot; + if (!route->prot->match_net (route->target, curtarget)) + continue; + + if (route->is_gateway) + { + if (depth == 0) + *gateway = route->gw; + curtarget = route->gw; + break; + } + *interf = route->interface; + return GRUB_ERR_NONE; + } + if (route == NULL) + return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable"); + } + + return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected"); +} + +static grub_err_t +grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1])) + break; + if (inter == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); + + inter->protocol->fini (inter); + grub_net_network_level_interface_unregister (inter); + grub_free (inter->name); + grub_free (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_protocol *prot; + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); + + FOR_NET_CARDS (card) + if (grub_strcmp (card->name, args[1])) + break; + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); + + FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) + if (grub_strcmp (prot->name, args[2])) + break; + + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); + + err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); + if (err) + return err; + + inter = grub_zalloc (sizeof (*inter)); + if (!inter) + return grub_errno; + + inter->name = grub_strdup (args[0]); + inter->protocol = prot; + grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + inter->card = card; + + err = prot->init (inter); + if (err) + { + grub_free (inter->name); + grub_free (inter); + return err; + } + grub_net_network_level_interface_register (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_route *route; + struct grub_net_route **prev; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next), + route = *prev) + if (grub_strcmp (route->name, args[0]) == 0) + { + *prev = route->next; + grub_free (route->name); + grub_free (route); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_protocol *prot; + struct grub_net_route *route; + + if (argc < 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("At least 3 arguments are expected")); + + route = grub_zalloc (sizeof (*route)); + if (!route) + return grub_errno; + + route->name = grub_strdup (args[0]); + if (!route->name) + { + grub_free (route); + return grub_errno; + } + + FOR_NET_NETWORK_LEVEL_PROTOCOLS(prot) + { + grub_err_t err; + err = prot->net_ntoa (args[1], &(route->target)); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + break; + } + + if (!prot) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("Unrecognised address %s"), args[1]); + } + + if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) + { + grub_err_t err; + route->is_gateway = 1; + err = grub_net_resolve_address_in_protocol (prot, + args[3], &(route->gw)); + if (err) + { + grub_free (route->name); + grub_free (route); + return err; + } + } + else + { + struct grub_net_network_level_interface *inter; + route->is_gateway = 0; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[2])) + break; + + if (!inter) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Unrecognised interface %s"), args[2]); + } + route->interface = inter; + } + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; + +GRUB_MOD_INIT(net) +{ + cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, + "SHORTNAME CARD PROTOCOL ADDRESS", + N_("Add a network address.")); + cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, + "SHORTNAME", + N_("Delete a network address.")); + cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute, + "SHORTNAME NET [INTERFACE| gw GATEWAY]", + N_("Add a network route.")); + cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, + "SHORTNAME", + N_("Delete a network route.")); +} + +GRUB_MOD_FINI(net) +{ + grub_unregister_command (cmd_addaddr); + grub_unregister_command (cmd_deladdr); + grub_unregister_command (cmd_addroute); + grub_unregister_command (cmd_delroute); +} diff --git a/commands/probe.c b/commands/probe.c index c2cc599e9..002ede85e 100644 --- a/commands/probe.c +++ b/commands/probe.c @@ -72,7 +72,7 @@ grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args) { const char *val = "none"; if (dev->net) - val = dev->net->dev->name; + val = dev->net->name; if (dev->disk) val = dev->disk->dev->name; if (state[0].set) diff --git a/conf/common.rmk b/conf/common.rmk index 0f67622b5..cee808a35 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -828,4 +828,10 @@ bin_UTILITIES += grub-mkpasswd-pbkdf2 grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/emu/misc.c kern/emu/mm.c kern/err.c grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1 +pkglib_MODULES += net.mod +net_mod_SOURCES = commands/net.c +net_mod_CFLAGS = $(COMMON_CFLAGS) +net_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/gcry.mk + diff --git a/include/grub/device.h b/include/grub/device.h index f0e8a8ca8..d68c26e66 100644 --- a/include/grub/device.h +++ b/include/grub/device.h @@ -24,8 +24,12 @@ #include struct grub_disk; -struct grub_net; struct grub_fs; +struct grub_net +{ + char *name; + struct grub_fs *fs; +}; struct grub_device { diff --git a/include/grub/err.h b/include/grub/err.h index e44705389..493796d62 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -54,7 +54,10 @@ typedef enum GRUB_ERR_MENU, GRUB_ERR_TIMEOUT, GRUB_ERR_IO, - GRUB_ERR_ACCESS_DENIED + GRUB_ERR_ACCESS_DENIED, + GRUB_ERR_NET_BAD_ADDRESS, + GRUB_ERR_NET_ROUTE_LOOP, + GRUB_ERR_NET_NO_ROUTE } grub_err_t; diff --git a/include/grub/net.h b/include/grub/net.h index c6d71d5b6..4ca873f74 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2007 Free Software Foundation, Inc. + * Copyright (C) 2010 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 @@ -19,54 +19,224 @@ #ifndef GRUB_NET_HEADER #define GRUB_NET_HEADER 1 -#include -#include #include +#include +#include -struct grub_net; +struct grub_net_card; -struct grub_net_dev +struct grub_net_card_driver { - /* The device name. */ - const char *name; - - /* FIXME: Just a template. */ - int (*probe) (struct grub_net *net, const void *addr); - void (*reset) (struct grub_net *net); - int (*poll) (struct grub_net *net); - void (*transmit) (struct grub_net *net, const void *destip, - unsigned srcsock, unsigned destsock, const void *packet); - void (*disable) (struct grub_net *net); - - /* The next net device. */ - struct grub_net_dev *next; + grub_err_t (*send) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); }; -typedef struct grub_net_dev *grub_net_dev_t; -struct grub_fs; - -struct grub_net +struct grub_net_card { - /* The net name. */ - const char *name; - - /* The underlying disk device. */ - grub_net_dev_t dev; - - /* The binding filesystem. */ - struct grub_fs *fs; - - /* FIXME: More data would be required, such as an IP address, a mask, - a gateway, etc. */ - - /* Device-specific data. */ + struct grub_net_card *next; + char *name; + struct grub_net_card_driver *driver; void *data; }; -typedef struct grub_net *grub_net_t; -/* FIXME: How to abstract networks? More consideration is necessary. */ +struct grub_net_network_level_interface; + +typedef union grub_net_network_level_address +{ + grub_uint32_t ipv4; +} grub_net_network_level_netaddress_t; + +typedef union grub_net_network_level_netaddress +{ + struct { + grub_uint32_t base; + int masksize; + } ipv4; +} grub_net_network_level_address_t; + +typedef enum grub_network_level_protocol_id +{ + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_level_protocol_id_t; + +struct grub_net_network_level_interface; + +struct grub_net_network_level_protocol +{ + struct grub_net_network_level_protocol *next; + char *name; + grub_network_level_protocol_id_t id; + grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); + char * (*aton) (union grub_net_network_level_address addr); + grub_err_t (*net_ntoa) (char *name, + grub_net_network_level_netaddress_t *addr); + char * (*net_aton) (grub_net_network_level_netaddress_t addr); + int (* match_net) (grub_net_network_level_netaddress_t net, + grub_net_network_level_address_t addr); + grub_err_t (*init) (struct grub_net_network_level_interface *dev); + grub_err_t (*fini) (struct grub_net_network_level_interface *dev); + grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); +}; + +struct grub_net_network_level_interface +{ + struct grub_net_network_level_interface *next; + char *name; + /* Underlying protocol. */ + struct grub_net_network_level_protocol *protocol; + struct grub_net_card *card; + union grub_net_network_level_address address; + void *data; +}; + +struct grub_net_route +{ + struct grub_net_route *next; + grub_net_network_level_netaddress_t target; + char *name; + struct grub_net_network_level_protocol *prot; + int is_gateway; + union + { + struct grub_net_network_level_interface *interface; + grub_net_network_level_address_t gw; + }; +}; + +struct grub_net_session; + +struct grub_net_session_level_protocol +{ + void (*close) (struct grub_net_session *session); + grub_ssize_t (*recv) (struct grub_net_session *session, void *buf, + grub_size_t size); + grub_err_t (*send) (struct grub_net_session *session, void *buf, + grub_size_t size); +}; + +struct grub_net_session +{ + struct grub_net_session_level_protocol *protocol; + void *data; +}; + +static inline void +grub_net_session_close (struct grub_net_session *session) +{ + session->protocol->close (session); +} + +static inline grub_err_t +grub_net_session_send (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->send (session, buf, size); +} + +static inline grub_ssize_t +grub_net_session_recv (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->recv (session, buf, size); +} + +extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; + +static inline void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + +extern struct grub_net_route *grub_net_routes; + +static inline void +grub_net_route_register (struct grub_net_route *route) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +static inline void +grub_net_route_unregister (struct grub_net_route *route) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) + +extern struct grub_net_card *grub_net_cards; + +static inline void +grub_net_card_register (struct grub_net_card *card) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +static inline void +grub_net_card_unregister (struct grub_net_card *card) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) + +extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; + +static inline void +grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +static inline void +grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) + +static inline grub_err_t +grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, + char *name, + grub_net_network_level_address_t *addr) +{ + return prot->ntoa (name, addr); +} + +struct grub_net_session * +grub_net_open_tcp (char *address, grub_uint16_t port); + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr); + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf); -/* Note: Networks are very different from disks, because networks must - be initialized before used, and the status is persistent. */ #endif /* ! GRUB_NET_HEADER */ diff --git a/kern/fs.c b/kern/fs.c index cf800f4cc..8ffb93c8b 100644 --- a/kern/fs.c +++ b/kern/fs.c @@ -94,7 +94,7 @@ grub_fs_probe (grub_device_t device) count--; } } - else if (device->net->fs) + else if (device->net) return device->net->fs; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); From 1bf0e31cfb90a05389715ebda22734dff7f38d7c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 3 Mar 2010 20:09:48 +0100 Subject: [PATCH 002/673] Network infrastructure --- commands/net.c | 296 ++++++++++++++++++++++++++++++++++++++++++ commands/probe.c | 2 +- conf/common.rmk | 6 + include/grub/device.h | 6 +- include/grub/err.h | 5 +- include/grub/net.h | 248 +++++++++++++++++++++++++++++------ kern/fs.c | 2 +- 7 files changed, 522 insertions(+), 43 deletions(-) create mode 100644 commands/net.c diff --git a/commands/net.c b/commands/net.c new file mode 100644 index 000000000..288ba4c2a --- /dev/null +++ b/commands/net.c @@ -0,0 +1,296 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 . + */ + +#include +#include +#include +#include +#include + +struct grub_net_route *grub_net_routes = NULL; +struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; +struct grub_net_card *grub_net_cards = NULL; +struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr) +{ + FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) + { + grub_err_t err; + err = grub_net_resolve_address_in_protocol (*prot, name, addr); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Unrecognised address %s"), + name); +} + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf) +{ + struct grub_net_route *route; + int depth = 0; + int routecnt = 0; + struct grub_net_network_level_protocol *prot = NULL; + grub_net_network_level_address_t curtarget = addr; + + *gateway = addr; + + FOR_NET_ROUTES(route) + routecnt++; + + for (depth = 0; depth < routecnt + 2; depth++) + { + FOR_NET_ROUTES(route) + { + if (depth && prot != route->prot) + continue; + prot = route->prot; + if (!route->prot->match_net (route->target, curtarget)) + continue; + + if (route->is_gateway) + { + if (depth == 0) + *gateway = route->gw; + curtarget = route->gw; + break; + } + *interf = route->interface; + return GRUB_ERR_NONE; + } + if (route == NULL) + return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable"); + } + + return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected"); +} + +static grub_err_t +grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1])) + break; + if (inter == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); + + inter->protocol->fini (inter); + grub_net_network_level_interface_unregister (inter); + grub_free (inter->name); + grub_free (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_protocol *prot; + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inter; + + if (argc != 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); + + FOR_NET_CARDS (card) + if (grub_strcmp (card->name, args[1])) + break; + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); + + FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) + if (grub_strcmp (prot->name, args[2])) + break; + + if (card == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); + + err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); + if (err) + return err; + + inter = grub_zalloc (sizeof (*inter)); + if (!inter) + return grub_errno; + + inter->name = grub_strdup (args[0]); + inter->protocol = prot; + grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + inter->card = card; + + err = prot->init (inter); + if (err) + { + grub_free (inter->name); + grub_free (inter); + return err; + } + grub_net_network_level_interface_register (inter); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_route *route; + struct grub_net_route **prev; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next), + route = *prev) + if (grub_strcmp (route->name, args[0]) == 0) + { + *prev = route->next; + grub_free (route->name); + grub_free (route); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_protocol *prot; + struct grub_net_route *route; + + if (argc < 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("At least 3 arguments are expected")); + + route = grub_zalloc (sizeof (*route)); + if (!route) + return grub_errno; + + route->name = grub_strdup (args[0]); + if (!route->name) + { + grub_free (route); + return grub_errno; + } + + FOR_NET_NETWORK_LEVEL_PROTOCOLS(prot) + { + grub_err_t err; + err = prot->net_ntoa (args[1], &(route->target)); + if (err == GRUB_ERR_NET_BAD_ADDRESS) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + break; + } + + if (!prot) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("Unrecognised address %s"), args[1]); + } + + if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) + { + grub_err_t err; + route->is_gateway = 1; + err = grub_net_resolve_address_in_protocol (prot, + args[3], &(route->gw)); + if (err) + { + grub_free (route->name); + grub_free (route); + return err; + } + } + else + { + struct grub_net_network_level_interface *inter; + route->is_gateway = 0; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[2])) + break; + + if (!inter) + { + grub_free (route->name); + grub_free (route); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("Unrecognised interface %s"), args[2]); + } + route->interface = inter; + } + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; + +GRUB_MOD_INIT(net) +{ + cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, + "SHORTNAME CARD PROTOCOL ADDRESS", + N_("Add a network address.")); + cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, + "SHORTNAME", + N_("Delete a network address.")); + cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute, + "SHORTNAME NET [INTERFACE| gw GATEWAY]", + N_("Add a network route.")); + cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, + "SHORTNAME", + N_("Delete a network route.")); +} + +GRUB_MOD_FINI(net) +{ + grub_unregister_command (cmd_addaddr); + grub_unregister_command (cmd_deladdr); + grub_unregister_command (cmd_addroute); + grub_unregister_command (cmd_delroute); +} diff --git a/commands/probe.c b/commands/probe.c index c2cc599e9..002ede85e 100644 --- a/commands/probe.c +++ b/commands/probe.c @@ -72,7 +72,7 @@ grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args) { const char *val = "none"; if (dev->net) - val = dev->net->dev->name; + val = dev->net->name; if (dev->disk) val = dev->disk->dev->name; if (state[0].set) diff --git a/conf/common.rmk b/conf/common.rmk index 7effa8af3..f1ed1478d 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -779,4 +779,10 @@ bin_UTILITIES += grub-mkpasswd-pbkdf2 grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/err.c grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1 +pkglib_MODULES += net.mod +net_mod_SOURCES = commands/net.c +net_mod_CFLAGS = $(COMMON_CFLAGS) +net_mod_LDFLAGS = $(COMMON_LDFLAGS) + include $(srcdir)/conf/gcry.mk + diff --git a/include/grub/device.h b/include/grub/device.h index f0e8a8ca8..d68c26e66 100644 --- a/include/grub/device.h +++ b/include/grub/device.h @@ -24,8 +24,12 @@ #include struct grub_disk; -struct grub_net; struct grub_fs; +struct grub_net +{ + char *name; + struct grub_fs *fs; +}; struct grub_device { diff --git a/include/grub/err.h b/include/grub/err.h index e44705389..493796d62 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -54,7 +54,10 @@ typedef enum GRUB_ERR_MENU, GRUB_ERR_TIMEOUT, GRUB_ERR_IO, - GRUB_ERR_ACCESS_DENIED + GRUB_ERR_ACCESS_DENIED, + GRUB_ERR_NET_BAD_ADDRESS, + GRUB_ERR_NET_ROUTE_LOOP, + GRUB_ERR_NET_NO_ROUTE } grub_err_t; diff --git a/include/grub/net.h b/include/grub/net.h index c6d71d5b6..4ca873f74 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2007 Free Software Foundation, Inc. + * Copyright (C) 2010 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 @@ -19,54 +19,224 @@ #ifndef GRUB_NET_HEADER #define GRUB_NET_HEADER 1 -#include -#include #include +#include +#include -struct grub_net; +struct grub_net_card; -struct grub_net_dev +struct grub_net_card_driver { - /* The device name. */ - const char *name; - - /* FIXME: Just a template. */ - int (*probe) (struct grub_net *net, const void *addr); - void (*reset) (struct grub_net *net); - int (*poll) (struct grub_net *net); - void (*transmit) (struct grub_net *net, const void *destip, - unsigned srcsock, unsigned destsock, const void *packet); - void (*disable) (struct grub_net *net); - - /* The next net device. */ - struct grub_net_dev *next; + grub_err_t (*send) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_card *dev, void *buf, + grub_size_t buflen); }; -typedef struct grub_net_dev *grub_net_dev_t; -struct grub_fs; - -struct grub_net +struct grub_net_card { - /* The net name. */ - const char *name; - - /* The underlying disk device. */ - grub_net_dev_t dev; - - /* The binding filesystem. */ - struct grub_fs *fs; - - /* FIXME: More data would be required, such as an IP address, a mask, - a gateway, etc. */ - - /* Device-specific data. */ + struct grub_net_card *next; + char *name; + struct grub_net_card_driver *driver; void *data; }; -typedef struct grub_net *grub_net_t; -/* FIXME: How to abstract networks? More consideration is necessary. */ +struct grub_net_network_level_interface; + +typedef union grub_net_network_level_address +{ + grub_uint32_t ipv4; +} grub_net_network_level_netaddress_t; + +typedef union grub_net_network_level_netaddress +{ + struct { + grub_uint32_t base; + int masksize; + } ipv4; +} grub_net_network_level_address_t; + +typedef enum grub_network_level_protocol_id +{ + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_level_protocol_id_t; + +struct grub_net_network_level_interface; + +struct grub_net_network_level_protocol +{ + struct grub_net_network_level_protocol *next; + char *name; + grub_network_level_protocol_id_t id; + grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); + char * (*aton) (union grub_net_network_level_address addr); + grub_err_t (*net_ntoa) (char *name, + grub_net_network_level_netaddress_t *addr); + char * (*net_aton) (grub_net_network_level_netaddress_t addr); + int (* match_net) (grub_net_network_level_netaddress_t net, + grub_net_network_level_address_t addr); + grub_err_t (*init) (struct grub_net_network_level_interface *dev); + grub_err_t (*fini) (struct grub_net_network_level_interface *dev); + grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); + grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, + grub_size_t buflen); +}; + +struct grub_net_network_level_interface +{ + struct grub_net_network_level_interface *next; + char *name; + /* Underlying protocol. */ + struct grub_net_network_level_protocol *protocol; + struct grub_net_card *card; + union grub_net_network_level_address address; + void *data; +}; + +struct grub_net_route +{ + struct grub_net_route *next; + grub_net_network_level_netaddress_t target; + char *name; + struct grub_net_network_level_protocol *prot; + int is_gateway; + union + { + struct grub_net_network_level_interface *interface; + grub_net_network_level_address_t gw; + }; +}; + +struct grub_net_session; + +struct grub_net_session_level_protocol +{ + void (*close) (struct grub_net_session *session); + grub_ssize_t (*recv) (struct grub_net_session *session, void *buf, + grub_size_t size); + grub_err_t (*send) (struct grub_net_session *session, void *buf, + grub_size_t size); +}; + +struct grub_net_session +{ + struct grub_net_session_level_protocol *protocol; + void *data; +}; + +static inline void +grub_net_session_close (struct grub_net_session *session) +{ + session->protocol->close (session); +} + +static inline grub_err_t +grub_net_session_send (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->send (session, buf, size); +} + +static inline grub_ssize_t +grub_net_session_recv (struct grub_net_session *session, void *buf, + grub_size_t size) +{ + return session->protocol->recv (session, buf, size); +} + +extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; + +static inline void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + +extern struct grub_net_route *grub_net_routes; + +static inline void +grub_net_route_register (struct grub_net_route *route) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +static inline void +grub_net_route_unregister (struct grub_net_route *route) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) + +extern struct grub_net_card *grub_net_cards; + +static inline void +grub_net_card_register (struct grub_net_card *card) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +static inline void +grub_net_card_unregister (struct grub_net_card *card) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + +#define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) + +extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; + +static inline void +grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +static inline void +grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), + GRUB_AS_LIST (prot)); +} + +#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) + +static inline grub_err_t +grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, + char *name, + grub_net_network_level_address_t *addr) +{ + return prot->ntoa (name, addr); +} + +struct grub_net_session * +grub_net_open_tcp (char *address, grub_uint16_t port); + +grub_err_t +grub_net_resolve_address (struct grub_net_network_level_protocol **prot, + char *name, + grub_net_network_level_address_t *addr); + +grub_err_t +grub_net_route_address (grub_net_network_level_address_t addr, + grub_net_network_level_address_t *gateway, + struct grub_net_network_level_interface **interf); -/* Note: Networks are very different from disks, because networks must - be initialized before used, and the status is persistent. */ #endif /* ! GRUB_NET_HEADER */ diff --git a/kern/fs.c b/kern/fs.c index 0c456377f..7bd1445b0 100644 --- a/kern/fs.c +++ b/kern/fs.c @@ -124,7 +124,7 @@ grub_fs_probe (grub_device_t device) count--; } } - else if (device->net->fs) + else if (device->net) return device->net->fs; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); From 066528b4b18ed5870be40ef333bc85d2344ee812 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Tue, 27 Apr 2010 18:05:35 -0300 Subject: [PATCH 003/673] Initial Implementation of TFTP protocol and new protocol structs. --- conf/powerpc-ieee1275.rmk | 8 +- include/grub/net.h | 19 ++++- include/grub/net/arp.h | 23 ++++++ include/grub/net/device.h | 7 ++ include/grub/net/ethernet.h | 12 +++ include/grub/net/ieee1275/interface.h | 21 ++++++ include/grub/net/interface.h | 17 +++++ include/grub/net/ip.h | 25 +++++++ include/grub/net/netbuff.h | 27 +++++++ include/grub/net/protocol.h | 50 +++++++++++++ include/grub/net/tftp.h | 74 +++++++++++++++++++ include/grub/net/type_net.h | 7 ++ include/grub/net/udp.h | 22 ++++++ net/arp.c | 0 net/device.c | 0 net/ethernet.c | 54 ++++++++++++++ net/ieee1275/interface.c | 80 ++++++++++++++++++++ net/interface.c | 0 net/ip.c | 95 ++++++++++++++++++++++++ net/netbuff.c | 72 ++++++++++++++++++ net/protocol.c | 21 ++++++ net/tftp.c | 102 ++++++++++++++++++++++++++ net/udp.c | 59 +++++++++++++++ 23 files changed, 789 insertions(+), 6 deletions(-) create mode 100644 include/grub/net/arp.h create mode 100644 include/grub/net/device.h create mode 100644 include/grub/net/ethernet.h create mode 100644 include/grub/net/ieee1275/interface.h create mode 100644 include/grub/net/interface.h create mode 100644 include/grub/net/ip.h create mode 100644 include/grub/net/netbuff.h create mode 100644 include/grub/net/protocol.h create mode 100644 include/grub/net/tftp.h create mode 100644 include/grub/net/type_net.h create mode 100644 include/grub/net/udp.h create mode 100644 net/arp.c create mode 100644 net/device.c create mode 100644 net/ethernet.c create mode 100644 net/ieee1275/interface.c create mode 100644 net/interface.c create mode 100644 net/ip.c create mode 100644 net/netbuff.c create mode 100644 net/protocol.c create mode 100644 net/tftp.c create mode 100644 net/udp.c diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index be95b30ba..14d04f93e 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -3,7 +3,10 @@ # Images. -kernel_img_HEADERS += ieee1275/ieee1275.h +<<<<<<< TREE +kernel_img_HEADERS += ieee1275/ieee1275.h \ + command.h i18n.h env_private.h net/ip.h net/udp.h net/ethernet.h net/arp.h net/tftp.h\ + net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h # Programs pkglib_PROGRAMS = kernel.img @@ -20,7 +23,8 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/ieee1275/openfw.c disk/ieee1275/ofdisk.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ - symlist.c kern/$(target_cpu)/cache.S + symlist.c kern/$(target_cpu)/cache.S net/ip.c net/tftp.c net/udp.c net/ethernet.c net/arp.c \ + net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x200000,-Bstatic diff --git a/include/grub/net.h b/include/grub/net.h index 4ca873f74..75efd51d6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -22,15 +22,20 @@ #include #include #include +#include struct grub_net_card; struct grub_net_card_driver { - grub_err_t (*send) (struct grub_net_card *dev, void *buf, - grub_size_t buflen); - grub_size_t (*recv) (struct grub_net_card *dev, void *buf, - grub_size_t buflen); + grub_err_t (*send) (struct grub_net_card *dev,struct grub_net_buff *nb); + grub_size_t (*recv) (struct grub_net_card *dev,struct grub_net_buff *nb); +}; + +struct grub_net_addr +{ + grub_uint8_t *addr; + grub_size_t len; }; struct grub_net_card @@ -38,6 +43,12 @@ struct grub_net_card struct grub_net_card *next; char *name; struct grub_net_card_driver *driver; + /*transport layer address*/ + struct grub_net_addr *tla; + /*internet layer address*/ + struct grub_net_addr *ila; + /*link layer address*/ + struct grub_net_addr *lla; void *data; }; diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h new file mode 100644 index 000000000..0ac2ec832 --- /dev/null +++ b/include/grub/net/arp.h @@ -0,0 +1,23 @@ +#ifndef GRUB_NET_ARP_HEADER +#define GRUB_NET_ARP_HEADER 1 + +#include +struct arprequest { + grub_int16_t hwtype; /* hardware type (must be ARPHRD_ETHER) */ + grub_int16_t protocol; /* protocol type (must be ETH_P_IP) */ + grub_int8_t hwlen; /* hardware address length (must be 6) */ + grub_int8_t protolen; /* protocol address length (must be 4) */ + grub_uint16_t opcode; /* ARP opcode */ + grub_uint8_t shwaddr[6]; /* sender's hardware address */ + grub_uint32_t sipaddr; /* sender's IP address */ + grub_uint8_t thwaddr[6]; /* target's hardware address */ + grub_uint32_t tipaddr; /* target's IP address */ +}__attribute__ ((packed)); + + +struct arp_pkt{ + struct etherhdr ether; + struct arprequest arpr; +} __attribute__ ((packed)); + +#endif diff --git a/include/grub/net/device.h b/include/grub/net/device.h new file mode 100644 index 000000000..9f1b9bf1d --- /dev/null +++ b/include/grub/net/device.h @@ -0,0 +1,7 @@ +struct grub_net_card +{ + struct grub_net_card *next; + char *name; + struct grub_net_card_driver *driver; + void *data; +}; diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h new file mode 100644 index 000000000..46aa04f60 --- /dev/null +++ b/include/grub/net/ethernet.h @@ -0,0 +1,12 @@ +#ifndef GRUB_NET_ETHERNET_HEADER +#define GRUB_NET_ETHERNET_HEADER 1 +#include +struct etherhdr { + grub_uint8_t dst[6]; + grub_uint8_t src[6]; + grub_uint16_t type; +} __attribute__ ((packed)) ; + +void ethernet_ini(void); +void ethernet_fini(void); +#endif diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h new file mode 100644 index 000000000..edc242cab --- /dev/null +++ b/include/grub/net/ieee1275/interface.h @@ -0,0 +1,21 @@ +#ifndef GRUB_IEEE1275_INTERFACE_HEADER +#define GRUB_IEEE1275_INTERFACE_HEADER 1 + +#include +#include +#include + +grub_ofnet_t EXPORT_VAR(grub_net); + +grub_bootp_t EXPORT_VAR(bootp_pckt); +grub_uint32_t get_server_ip(void); +grub_uint32_t get_client_ip(void); +grub_uint8_t* get_server_mac (void); +grub_uint8_t* get_client_mac (void); + +int send_card_buffer (void *buffer,int buff_len); +int get_card_buffer (void *buffer,int buff_len); +int card_open (void); +int card_close (void); + +#endif diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h new file mode 100644 index 000000000..0e11c86ba --- /dev/null +++ b/include/grub/net/interface.h @@ -0,0 +1,17 @@ +#ifndef GRUB_INTERFACE_HEADER +#define GRUB_INTERFACE_HEADER +#include +#include +/* +extern struct grub_net_topprotocol; + +struct grub_net_interface +{ + struct grub_net_card *card; + struct grub_net_topprotocol* topprot; + struct grub_net_addr *tla; + struct grub_net_addr *ila; + struct grub_net_addr *lla; +}; +*/ +#endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h new file mode 100644 index 000000000..e1f45dcfa --- /dev/null +++ b/include/grub/net/ip.h @@ -0,0 +1,25 @@ +#ifndef GRUB_NET_IP_HEADER +#define GRUB_NET_IP_HEADER 1 +#include + + +struct iphdr { + grub_uint8_t verhdrlen; + grub_uint8_t service; + grub_uint16_t len; + grub_uint16_t ident; + grub_uint16_t frags; + grub_uint8_t ttl; + grub_uint8_t protocol; + grub_uint16_t chksum; + grub_uint32_t src; + grub_uint32_t dest; +} __attribute__ ((packed)) ; + +#define IP_UDP 17 /* UDP protocol */ +#define IP_BROADCAST 0xFFFFFFFF + +grub_uint16_t ipchksum(void *ipv, int len); +void ipv4_ini(void); +void ipv4_fini(void); +#endif diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h new file mode 100644 index 000000000..7d63be1f5 --- /dev/null +++ b/include/grub/net/netbuff.h @@ -0,0 +1,27 @@ +#ifndef GRUB_NETBUFF_HEADER +#define GRUB_NETBUFF_HEADER + +#include + +#define NETBUFF_ALIGN 2048 +#define NETBUFFMINLEN 64 + +struct grub_net_buff +{ + /*Pointer to the start of the buffer*/ + char *head; + /*Pointer to the data */ + char *data; + /*Pointer to the tail */ + char *tail; + /*Pointer to the end of the buffer*/ + char *end; +}; + +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len); +struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); +#endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h new file mode 100644 index 000000000..2c979481b --- /dev/null +++ b/include/grub/net/protocol.h @@ -0,0 +1,50 @@ +#ifndef GRUB_PROTOCOL_HEADER +#define GRUB_PROTOCOL_HEADER +#include +#include +#include +#include +struct protocol_operations; +struct grub_net_protocol; +struct grub_net_interface; + +struct grub_net_protocol +{ + struct grub_net_protocol *next; + char *name; + grub_err_t (*open) (struct grub_net_interface* inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*open_confirm) (struct grub_net_interface *inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*get_payload) (struct grub_net_interface *inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*get_payload_confirm) (struct grub_net_interface* inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_net_interface *inf, + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*send) (struct grub_net_interface *inf , + struct grub_net_protocol *prot, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_interface *inf , + struct grub_net_protocol *prot, struct grub_net_buff *nb); +}; + +typedef struct grub_net_protocol *grub_net_protocol_t; + +struct grub_net_interface +{ + struct grub_net_card *card; + struct grub_net_protocol* prot; + char *path; + char *username; + char *password; + /*transport layer addres*/ + struct grub_net_addr *tla; + /*internet layer addres*/ + struct grub_net_addr *ila; + /*link layer addres*/ + struct grub_net_addr *lla; +}; + +void grub_protocol_register (grub_net_protocol_t prot); +void grub_protocol_unregister (grub_net_protocol_t prot); +#endif diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h new file mode 100644 index 000000000..4148096c5 --- /dev/null +++ b/include/grub/net/tftp.h @@ -0,0 +1,74 @@ +#ifndef GRUB_NET_TFTP_HEADER +#define GRUB_NET_TFTP_HEADER 1 + +#include +#include +#include + +/* IP port for the MTFTP server used for Intel's PXE */ +#define MTFTP_SERVER_PORT 75 +#define MTFTP_CLIENT_PORT 76 + +#define TFTP_DEFAULTSIZE_PACKET 512 +#define TFTP_MAX_PACKET 1432 + +/* IP port for the TFTP server */ +#define TFTP_SERVER_PORT 69 +#define TFTP_CLIENT_PORT 2000 + + +/* We define these based on what's in arpa/tftp.h. We just like our + * names better, cause they're clearer */ +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 +#define TFTP_OACK 6 + +#define TFTP_CODE_EOF 1 +#define TFTP_CODE_MORE 2 +#define TFTP_CODE_ERROR 3 +#define TFTP_CODE_BOOT 4 +#define TFTP_CODE_CFG 5 + +#define TFTP_EUNDEF 0 /* not defined */ +#define TFTP_ENOTFOUND 1 /* file not found */ +#define TFTP_EACCESS 2 /* access violation */ +#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */ +#define TFTP_EBADOP 4 /* illegal TFTP operation */ +#define TFTP_EBADID 5 /* unknown transfer ID */ +#define TFTP_EEXISTS 6 /* file already exists */ +#define TFTP_ENOUSER 7 /* no such user */ +#define TFTP_DEFAULT_FILENAME "kernel" + + + + + + /* * own here because this is cleaner, and maps to the same data layout. + * */ +struct tftphdr { + grub_uint16_t opcode; + union { + grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; + struct { + grub_uint16_t block; + grub_int8_t download[TFTP_MAX_PACKET]; + } data; + struct { + grub_uint16_t block; + } ack; + struct { + grub_uint16_t errcode; + grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; + } err; + struct { + grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2]; + } oack; + } u; +} __attribute__ ((packed)) ; + +void tftp_ini(void); +void tftp_fini(void); +#endif diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h new file mode 100644 index 000000000..33f2d802d --- /dev/null +++ b/include/grub/net/type_net.h @@ -0,0 +1,7 @@ +#ifndef GRUB_TYPES_NET_HEADER +#define GRUB_TYPES_NET_HEADER 1 + +#define UDP_PCKT 0x11 +#define IP_PCKT 0x0800 + +#endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h new file mode 100644 index 000000000..dbfcecef0 --- /dev/null +++ b/include/grub/net/udp.h @@ -0,0 +1,22 @@ +#ifndef GRUB_NET_UDP_HEADER +#define GRUB_NET_UDP_HEADER 1 +#include +/* +typedef enum + { + GRUB_PROT_TFTP + } protocol_type; +*/ + +#define GRUB_PROT_TFTP 1 + +struct udphdr { + grub_uint16_t src; + grub_uint16_t dst; + grub_uint16_t len; + grub_uint16_t chksum; +} __attribute__ ((packed)); + +void udp_ini(void); +void udp_fini(void); +#endif diff --git a/net/arp.c b/net/arp.c new file mode 100644 index 000000000..e69de29bb diff --git a/net/device.c b/net/device.c new file mode 100644 index 000000000..e69de29bb diff --git a/net/ethernet.c b/net/ethernet.c new file mode 100644 index 000000000..fc64803e7 --- /dev/null +++ b/net/ethernet.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static grub_err_t +send_ethernet_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot __attribute__ ((unused)) + ,struct grub_net_buff *nb) +{ + + struct etherhdr *eth; + grub_err_t err; + + if((err = grub_netbuff_push (nb,sizeof(*eth)) ) != GRUB_ERR_NONE) + return err; + eth = (struct etherhdr *) nb->data; + grub_memcpy (eth->src,inf->card->lla->addr,6 * sizeof (grub_uint8_t )); + grub_memcpy (eth->dst,inf->lla->addr,6 * sizeof (grub_uint8_t )); + eth->type = 0x0800; + + return inf->card->driver->send(inf->card,nb); +} + +static struct grub_net_protocol grub_ethernet_protocol = +{ + .name = "udp", + .send = send_ethernet_packet +}; + +void ethernet_ini(void) +{ + grub_protocol_register (&grub_ethernet_protocol); +} + +void ethernet_fini(void) +{ + grub_protocol_unregister (&grub_ethernet_protocol); +} +/* +int read_ethernet_packet(buffer,bufflen, int type) +{ + + struct etherhdr eth; + eth.type = 0; + + get_card_buffer (ð,sizeof (eth)); + + + +}*/ diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c new file mode 100644 index 000000000..5a246ffa5 --- /dev/null +++ b/net/ieee1275/interface.c @@ -0,0 +1,80 @@ +#include +#include + +grub_uint32_t get_server_ip (void) +{ + return bootp_pckt->siaddr; +} + +grub_uint32_t get_client_ip (void) +{ + return bootp_pckt->yiaddr; +} + +grub_uint8_t* get_server_mac (void) +{ + grub_uint8_t *mac; + + mac = grub_malloc (6 * sizeof(grub_uint8_t)); + mac[0] = 0x00 ; + mac[1] = 0x11 ; + mac[2] = 0x25 ; + mac[3] = 0xca ; + mac[4] = 0x1f ; + mac[5] = 0x01 ; + + return mac; + +} + +grub_uint8_t* get_client_mac (void) +{ + grub_uint8_t *mac; + + mac = grub_malloc (6 * sizeof (grub_uint8_t)); + mac[0] = 0x0a ; + mac[1] = 0x11 ; + mac[2] = 0xbd ; + mac[3] = 0xe3 ; + mac[4] = 0xe3 ; + mac[5] = 0x04 ; + + return mac; +} + +static grub_ieee1275_ihandle_t handle; +int card_open (void) +{ + + grub_ieee1275_open (grub_net->dev , &handle); + return 1;//error + +} +int card_close (void) +{ + + if (handle) + grub_ieee1275_close (handle); + return 0; +} + + +int send_card_buffer (void *buffer,int buff_len) +{ + + int actual; + + grub_ieee1275_write (handle,buffer,buff_len,&actual); + + return actual; +} + +int get_card_buffer (void *buffer,int buff_len) +{ + + int actual; + + grub_ieee1275_read (handle,buffer,buff_len,&actual); + + return actual; +} diff --git a/net/interface.c b/net/interface.c new file mode 100644 index 000000000..e69de29bb diff --git a/net/ip.c b/net/ip.c new file mode 100644 index 000000000..c669ff6d7 --- /dev/null +++ b/net/ip.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct grub_net_protocol *grub_ipv4_prot; + +grub_uint16_t +ipchksum(void *ipv, int len) +{ + grub_uint16_t *ip = (grub_uint16_t *)ipv; + grub_uint32_t sum = 0; + + + len >>= 1; + while (len--) { + sum += *(ip++); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + + return((~sum) & 0x0000FFFF); +} + + +static grub_err_t +send_ip_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb ) +{ + + struct iphdr *iph; + grub_err_t err; + + if((err = grub_netbuff_push(nb,sizeof(*iph)) ) != GRUB_ERR_NONE) + return err; + iph = (struct iphdr *) nb->data; + + /*FIXME dont work in litte endian machines*/ + //grub_uint8_t ver = 4; + //grub_uint8_t hdrlen = sizeof (struct iphdr)/4; + iph->verhdrlen = (4<<4 | 5); + iph->service = 0; + iph->len = sizeof(*iph); + iph->ident = 0x2b5f; + iph->frags = 0; + iph->ttl = 0xff; + iph->protocol = 0x11; + //grub_memcpy(&(iph->src) ,inf->card->ila->addr,inf->card->ila->len); + iph->src = *((grub_uint32_t *)inf->card->ila->addr); + //grub_memcpy(&(iph->dest) ,inf->ila->addr,inf->ila->len); + iph->dest = *((grub_uint32_t *)inf->ila->addr); + + iph->chksum = 0 ; + iph->chksum = ipchksum((void *)nb->head, sizeof(*iph)); + + + return prot->next->send(inf,prot->next,nb); +} + +static struct grub_net_protocol grub_ipv4_protocol = +{ + .name = "ipv4", + .send = send_ip_packet, + .recv = NULL +}; + +void ipv4_ini(void) +{ + grub_protocol_register (&grub_ipv4_protocol); +} + +void ipv4_fini(void) +{ + grub_protocol_unregister (&grub_ipv4_protocol); +} + +/* +int read_ip_packet (void *buffer,int *bufflen) +{ + struct iphdr iph; + iph.protocol = 0; + + while ( iph.protocol != IP_UDP) + { + read_ethernet_packet(buffer,bufflen,IP_PROTOCOL); + grub_memcpy (&iph,buffer,sizeof (iph)); + } + + buffer += sizeof (iph); + *buff_len -= sizeof (iph); + +}*/ diff --git a/net/netbuff.c b/net/netbuff.c new file mode 100644 index 000000000..342260f43 --- /dev/null +++ b/net/netbuff.c @@ -0,0 +1,72 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 . + */ + +#include +#include +#include +#include + + +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->tail += len; + if (net_buff->tail > net_buff->end) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->tail -= len; + if (net_buff->tail < net_buff->head) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data -= len; + if (net_buff->data < net_buff->head) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data += len; + if (net_buff->data > net_buff->end) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len) +{ + net_buff->data += len; + net_buff->tail += len; + if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return GRUB_ERR_NONE; +} + +struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ) +{ + if (len < NETBUFFMINLEN) + len = NETBUFFMINLEN; + len = ALIGN_UP (len,NETBUFF_ALIGN); + return (struct grub_net_buff *) grub_memalign (len,NETBUFF_ALIGN); +} diff --git a/net/protocol.c b/net/protocol.c new file mode 100644 index 000000000..a6117dc2c --- /dev/null +++ b/net/protocol.c @@ -0,0 +1,21 @@ +#include + +static grub_net_protocol_t grub_net_protocols; + +void grub_protocol_register (grub_net_protocol_t prot) +{ + prot->next = grub_net_protocols; + grub_net_protocols = prot; +} + +void grub_protocol_unregister (grub_net_protocol_t prot) +{ + grub_net_protocol_t *p, q; + + for (p = &grub_net_protocols, q = *p; q; p = &(q->next), q = q->next) + if (q == prot) + { + *p = q->next; + break; + } +} diff --git a/net/tftp.c b/net/tftp.c new file mode 100644 index 000000000..fdca184e9 --- /dev/null +++ b/net/tftp.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*send read request*/ +static grub_err_t +send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protocol *prot,struct grub_net_buff *nb) +{ + /*Start TFTP header*/ + + struct tftphdr *tftph; + char *rrq; + int rrqlen; + int hdrlen; + grub_err_t err; + + if((err = grub_netbuff_push (nb,sizeof(*tftph))) != GRUB_ERR_NONE) + return err; + + tftph = (struct tftphdr *) nb->data; + + rrq = (char *) tftph->u.rrq; + rrqlen = 0; + + tftph->opcode = TFTP_RRQ; + grub_strcpy (rrq,inf->path); + rrqlen += grub_strlen (inf->path) + 1; + rrq += grub_strlen (inf->path) + 1; + /*passar opcoes como parametro ou usar default?*/ + + grub_strcpy (rrq,"octet"); + rrqlen += grub_strlen ("octet") + 1; + rrq += grub_strlen ("octet") + 1; + + grub_strcpy (rrq,"blksize"); + rrqlen += grub_strlen("blksize") + 1; + rrq += grub_strlen ("blksize") + 1; + + grub_strcpy (rrq,"1024"); + rrqlen += grub_strlen ("1024") + 1; + rrq += grub_strlen ("1024") + 1; + + grub_strcpy (rrq,"tsize"); + rrqlen += grub_strlen ("tsize") + 1; + rrq += grub_strlen ("tsize") + 1; + + grub_strcpy (rrq,"0"); + rrqlen += grub_strlen ("0") + 1; + rrq += grub_strlen ("0") + 1; + hdrlen = sizeof (tftph->opcode) + rrqlen; + + grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); + + return prot->next->send(inf,prot->next,nb); +} + +/* +int send_tftp_ack(int block, int port){ + + tftp_t pckt; + int pcktlen; + pckt.opcode = TFTP_ACK; + pckt.u.ack.block = block; + pcktlen = sizeof (pckt.opcode) + sizeof (pckt.u.ack.block); + + port = 4; + return 0;// send_udp_packet (&pckt,pcktlen,TFTP_CLIENT_PORT,port); +} + +*/ + +static struct grub_net_protocol grub_tftp_protocol = +{ + .name = "tftp", + .open = send_tftp_rr + +}; + +void tftp_ini(void) +{ + grub_protocol_register (&grub_tftp_protocol); +} + +void tftp_fini(void) +{ + grub_protocol_unregister (&grub_tftp_protocol); +} +/* +int read_tftp_pckt (grub_uint16_t port, void *buffer, int &buff_len){ + + + read_udp_packet (port,buffer,buff_len); + + +}*/ diff --git a/net/udp.c b/net/udp.c new file mode 100644 index 000000000..600eec542 --- /dev/null +++ b/net/udp.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +/*Assumes that there is allocated memory to the header before the buffer address. */ +static grub_err_t +send_udp_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb) +{ + + struct udphdr *udph; + grub_err_t err; + + if((err = grub_netbuff_push (nb,sizeof(*udph)) ) != GRUB_ERR_NONE) + return err; + + udph = (struct udphdr *) nb->data; + udph->src = *((grub_uint16_t *) inf->card->tla->addr); + udph->dst = *((grub_uint16_t *) inf->tla->addr); + /*no chksum*/ + udph->chksum = 0; + udph->len = sizeof (sizeof (*udph)) + nb->end - nb->head; + + return prot->next->send(inf,prot->next,nb); +} + +static struct grub_net_protocol grub_udp_protocol = +{ + .name = "udp", + .send = send_udp_packet +}; + +void udp_ini(void) +{ + grub_protocol_register (&grub_udp_protocol); +} + +void udp_fini(void) +{ + grub_protocol_unregister (&grub_udp_protocol); +} + +/* +int read_udp_packet (grub_uint16_t port,void *buffer,int *buff_len) +{ + + struct udphdr udph; + udph.dst = 0; + + while ( udph.dst != port) + { + read_ip_packet (buffer,bufflen); + grub_memcpy (&udph,buffer,sizeof (udph)); + } + + buffer += sizeof (udph); + *buff_len -= sizeof (udph); + +}*/ From 8d402bc9a8041f0ed15290901e0ff5f115ed5cc0 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Apr 2010 17:56:09 -0300 Subject: [PATCH 004/673] small change in the interface structure. --- include/grub/net.h | 14 ++++++++++++++ include/grub/net/interface.h | 18 ++++++++++++++---- include/grub/net/protocol.h | 33 +++++++++------------------------ net/ethernet.c | 3 ++- net/ip.c | 5 +++-- net/tftp.c | 5 +++-- net/udp.c | 5 +++-- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/include/grub/net.h b/include/grub/net.h index 75efd51d6..f021f0e9c 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -26,8 +26,22 @@ struct grub_net_card; +typedef enum +{ + GRUB_NET_TFTP_ID, + GRUB_NET_UDP_ID, + GRUB_NET_IPV4_ID, + GRUB_NET_IPV6_ID, + GRUB_NET_ETHERNET_ID, + GRUB_NET_ARP_ID, + GRUB_NET_DHCP_ID + +}protocol_type_t; + struct grub_net_card_driver { + grub_err_t (*init) (struct grub_net_card *dev); + grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (struct grub_net_card *dev,struct grub_net_buff *nb); grub_size_t (*recv) (struct grub_net_card *dev,struct grub_net_buff *nb); }; diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h index 0e11c86ba..2e0ddfcc8 100644 --- a/include/grub/net/interface.h +++ b/include/grub/net/interface.h @@ -2,16 +2,26 @@ #define GRUB_INTERFACE_HEADER #include #include -/* -extern struct grub_net_topprotocol; + +struct grub_net_protstack +{ + struct grub_net_protstack *next; + struct grub_net_protocol* prot; +}; struct grub_net_interface { struct grub_net_card *card; - struct grub_net_topprotocol* topprot; + struct grub_net_protstack* protstack; + char *path; + char *username; + char *password; + /*transport layer addres*/ struct grub_net_addr *tla; + /*internet layer addres*/ struct grub_net_addr *ila; + /*link layer addres*/ struct grub_net_addr *lla; }; -*/ + #endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index 2c979481b..1efc2ab7b 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -4,47 +4,32 @@ #include #include #include -struct protocol_operations; + struct grub_net_protocol; struct grub_net_interface; +struct grub_net_protstack; struct grub_net_protocol { struct grub_net_protocol *next; char *name; grub_err_t (*open) (struct grub_net_interface* inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*open_confirm) (struct grub_net_interface *inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*get_payload) (struct grub_net_interface *inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*get_payload_confirm) (struct grub_net_interface* inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*close) (struct grub_net_interface *inf, - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*send) (struct grub_net_interface *inf , - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); grub_err_t (*recv) (struct grub_net_interface *inf , - struct grub_net_protocol *prot, struct grub_net_buff *nb); + struct grub_net_protstack *protstack, struct grub_net_buff *nb); }; typedef struct grub_net_protocol *grub_net_protocol_t; - -struct grub_net_interface -{ - struct grub_net_card *card; - struct grub_net_protocol* prot; - char *path; - char *username; - char *password; - /*transport layer addres*/ - struct grub_net_addr *tla; - /*internet layer addres*/ - struct grub_net_addr *ila; - /*link layer addres*/ - struct grub_net_addr *lla; -}; - void grub_protocol_register (grub_net_protocol_t prot); void grub_protocol_unregister (grub_net_protocol_t prot); #endif diff --git a/net/ethernet.c b/net/ethernet.c index fc64803e7..8c13966c1 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -6,9 +6,10 @@ #include #include #include +#include static grub_err_t -send_ethernet_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot __attribute__ ((unused)) +send_ethernet_packet (struct grub_net_interface *inf,struct grub_net_protstack *protstack __attribute__ ((unused)) ,struct grub_net_buff *nb) { diff --git a/net/ip.c b/net/ip.c index c669ff6d7..6fe58adb0 100644 --- a/net/ip.c +++ b/net/ip.c @@ -5,6 +5,7 @@ #include #include #include +#include #include struct grub_net_protocol *grub_ipv4_prot; @@ -28,7 +29,7 @@ ipchksum(void *ipv, int len) static grub_err_t -send_ip_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb ) +send_ip_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb ) { struct iphdr *iph; @@ -57,7 +58,7 @@ send_ip_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, iph->chksum = ipchksum((void *)nb->head, sizeof(*iph)); - return prot->next->send(inf,prot->next,nb); + return protstack->next->prot->send(inf,protstack->next,nb); } static struct grub_net_protocol grub_ipv4_protocol = diff --git a/net/tftp.c b/net/tftp.c index fdca184e9..3f481fe58 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -8,10 +8,11 @@ #include #include #include +#include /*send read request*/ static grub_err_t -send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protocol *prot,struct grub_net_buff *nb) +send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protstack *protstack,struct grub_net_buff *nb) { /*Start TFTP header*/ @@ -58,7 +59,7 @@ send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protocol *prot,str grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); - return prot->next->send(inf,prot->next,nb); + return protstack->next->prot->send(inf,protstack->next,nb); } /* diff --git a/net/udp.c b/net/udp.c index 600eec542..2a4a7690b 100644 --- a/net/udp.c +++ b/net/udp.c @@ -3,9 +3,10 @@ #include #include #include +#include /*Assumes that there is allocated memory to the header before the buffer address. */ static grub_err_t -send_udp_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, struct grub_net_buff *nb) +send_udp_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb) { struct udphdr *udph; @@ -21,7 +22,7 @@ send_udp_packet (struct grub_net_interface *inf, struct grub_net_protocol *prot, udph->chksum = 0; udph->len = sizeof (sizeof (*udph)) + nb->end - nb->head; - return prot->next->send(inf,prot->next,nb); + return protstack->next->prot->send(inf,protstack->next,nb); } static struct grub_net_protocol grub_udp_protocol = From d17a9fea4ac98b3aebea13f2b280c98afcd19c03 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:05:14 -0300 Subject: [PATCH 005/673] Add interface struct for communication between protocols and protocols stack. Changed the protocols structs to use one struct for each layer. --- include/grub/net/arp.h | 8 +- include/grub/net/ieee1275/interface.h | 14 ++-- include/grub/net/interface.h | 77 ++++++++++++++---- include/grub/net/netbuff.h | 3 + include/grub/net/protocol.h | 110 ++++++++++++++++++++------ include/grub/net/tftp.h | 6 +- include/grub/net/type_net.h | 25 ++++++ include/grub/net/udp.h | 19 ++--- 8 files changed, 194 insertions(+), 68 deletions(-) diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 0ac2ec832..86ae2deea 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -2,7 +2,7 @@ #define GRUB_NET_ARP_HEADER 1 #include -struct arprequest { +struct arphdr{ grub_int16_t hwtype; /* hardware type (must be ARPHRD_ETHER) */ grub_int16_t protocol; /* protocol type (must be ETH_P_IP) */ grub_int8_t hwlen; /* hardware address length (must be 6) */ @@ -14,10 +14,4 @@ struct arprequest { grub_uint32_t tipaddr; /* target's IP address */ }__attribute__ ((packed)); - -struct arp_pkt{ - struct etherhdr ether; - struct arprequest arpr; -} __attribute__ ((packed)); - #endif diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h index edc242cab..16f624c05 100644 --- a/include/grub/net/ieee1275/interface.h +++ b/include/grub/net/ieee1275/interface.h @@ -4,17 +4,15 @@ #include #include #include +#include -grub_ofnet_t EXPORT_VAR(grub_net); -grub_bootp_t EXPORT_VAR(bootp_pckt); -grub_uint32_t get_server_ip(void); -grub_uint32_t get_client_ip(void); -grub_uint8_t* get_server_mac (void); -grub_uint8_t* get_client_mac (void); +grub_ofnet_t grub_net; -int send_card_buffer (void *buffer,int buff_len); -int get_card_buffer (void *buffer,int buff_len); +grub_bootp_t bootp_pckt; + +int send_card_buffer (struct grub_net_buff *pack); +int get_card_packet (struct grub_net_buff *pack); int card_open (void); int card_close (void); diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h index 2e0ddfcc8..4d100fd75 100644 --- a/include/grub/net/interface.h +++ b/include/grub/net/interface.h @@ -1,27 +1,70 @@ #ifndef GRUB_INTERFACE_HEADER #define GRUB_INTERFACE_HEADER -#include -#include +//#include +#include +#include +#include -struct grub_net_protstack +struct grub_net_protocol_stack { - struct grub_net_protstack *next; - struct grub_net_protocol* prot; + struct grub_net_protocol_stack *next; + char *name; + grub_net_protocol_id_t id; + void *interface; }; -struct grub_net_interface +struct grub_net_application_transport_interface { - struct grub_net_card *card; - struct grub_net_protstack* protstack; - char *path; - char *username; - char *password; - /*transport layer addres*/ - struct grub_net_addr *tla; - /*internet layer addres*/ - struct grub_net_addr *ila; - /*link layer addres*/ - struct grub_net_addr *lla; + struct grub_net_transport_network_interface *inner_layer; + void *data; + struct grub_net_application_layer_protocol *app_prot; + struct grub_net_transport_layer_protocol *trans_prot; }; +struct grub_net_transport_network_interface +{ + struct grub_net_network_link_interface *inner_layer; + void *data; + struct grub_net_transport_layer_protocol *trans_prot; + struct grub_net_network_layer_protocol *net_prot; +}; + +struct grub_net_network_link_interface +{ + void *data; + struct grub_net_network_layer_protocol *net_prot; + struct grub_net_link_layer_protocol *link_prot; +}; + + +extern struct grub_net_protocol_stack *grub_net_protocol_stacks; +static inline void +grub_net_stack_register (struct grub_net_protocol_stack *stack) +{ + + grub_list_push (GRUB_AS_LIST_P (&grub_net_protocol_stacks), + GRUB_AS_LIST (stack)); +} +/* +void grub_net_stack_unregister (struct grub_net_protocol_stack *stack) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_protocol_stacks), + GRUB_AS_LIST (stack)); +}*/ + +struct grub_net_protocol_stack *grub_net_protocol_stack_get (char *name); + +/* +static inline void +grub_net_interface_application_transport_register (struct grub_net_application_transport_interface); +static inline void +grub_net_interface_application_transport_unregister (struct grub_net_application_transport_interface); +static inline void +grub_net_interface_transport_network_register (struct grub_net_transport_network_interface); +static inline void +grub_net_interface_transport_network_unregister (struct grub_net_transport_network_interface); +static inline void +grub_net_interface_network_link_register (struct grub_net_network_link_interface); +static inline void +grub_net_interface_network_link_unregister (struct grub_net_network_link_interface);*/ #endif diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h index 7d63be1f5..8ce508ead 100644 --- a/include/grub/net/netbuff.h +++ b/include/grub/net/netbuff.h @@ -23,5 +23,8 @@ grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len); grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len); grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len); grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); +grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff); +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); #endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index 1efc2ab7b..b7a3e5d3b 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -1,35 +1,101 @@ #ifndef GRUB_PROTOCOL_HEADER #define GRUB_PROTOCOL_HEADER #include -#include +#include #include -#include +#include struct grub_net_protocol; -struct grub_net_interface; -struct grub_net_protstack; +struct grub_net_protocol_stack; +struct grub_net_network_layer_interface; -struct grub_net_protocol + +typedef enum grub_network_layer_protocol_id { - struct grub_net_protocol *next; + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_layer_protocol_id_t; + +struct grub_net_application_layer_protocol +{ + struct grub_net_application_layer_protocol *next; char *name; - grub_err_t (*open) (struct grub_net_interface* inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*open_confirm) (struct grub_net_interface *inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*get_payload) (struct grub_net_interface *inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*get_payload_confirm) (struct grub_net_interface* inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*close) (struct grub_net_interface *inf, - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*send) (struct grub_net_interface *inf , - struct grub_net_protstack *protstack, struct grub_net_buff *nb); - grub_err_t (*recv) (struct grub_net_interface *inf , - struct grub_net_protstack *protstack, struct grub_net_buff *nb); + grub_net_protocol_id_t id; + int (*get_file_size) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb,char *filename); + grub_err_t (*open) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb,char *filename); + grub_err_t (*send_ack) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*send) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); }; +struct grub_net_transport_layer_protocol +{ + struct grub_net_transport_layer_protocol *next; + char *name; + grub_net_protocol_id_t id; + //grub_transport_layer_protocol_id_t id; + grub_err_t (*open) (struct grub_net_network_layer_interface* inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb); + grub_err_t (*send_ack) (struct grub_net_network_layer_interface* inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); + grub_err_t (*send) (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_net_network_layer_interface *inf, + struct grub_net_protocol_stack *protocol_stack, struct grub_net_buff *nb); +}; + +struct grub_net_network_layer_protocol +{ + struct grub_net_network_layer_protocol *next; + char *name; + grub_net_protocol_id_t id; + //grub_network_layer_protocol_id_t id; + grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr); + char * (*aton) (union grub_net_network_layer_address addr); + grub_err_t (*net_ntoa) (char *name, + grub_net_network_layer_netaddress_t *addr); + char * (*net_aton) (grub_net_network_layer_netaddress_t addr); + int (* match_net) (grub_net_network_layer_netaddress_t net, + grub_net_network_layer_address_t addr); + grub_err_t (*send) (struct grub_net_network_layer_interface *inf , + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf , + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb); +}; + +struct grub_net_link_layer_protocol +{ + + struct grub_net_link_layer_protocol *next; + char *name; + grub_net_protocol_id_t id; + grub_err_t (*send) (struct grub_net_network_layer_interface *inf , + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + grub_err_t (*recv) (struct grub_net_network_layer_interface *inf , + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); +}; + +extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols; + typedef struct grub_net_protocol *grub_net_protocol_t; -void grub_protocol_register (grub_net_protocol_t prot); -void grub_protocol_unregister (grub_net_protocol_t prot); +void grub_net_application_layer_protocol_register (struct grub_net_application_layer_protocol *prot); +void grub_net_application_layer_protocol_unregister (struct grub_net_application_layer_protocol *prot); +struct grub_net_application_layer_protocol *grub_net_application_layer_protocol_get (grub_net_protocol_id_t id); +void grub_net_transport_layer_protocol_register (struct grub_net_transport_layer_protocol *prot); +void grub_net_transport_layer_protocol_unregister (struct grub_net_transport_layer_protocol *prot); +struct grub_net_transport_layer_protocol *grub_net_transport_layer_protocol_get (grub_net_protocol_id_t id); +void grub_net_network_layer_protocol_register (struct grub_net_network_layer_protocol *prot); +void grub_net_network_layer_protocol_unregister (struct grub_net_network_layer_protocol *prot); +struct grub_net_network_layer_protocol *grub_net_network_layer_protocol_get (grub_net_protocol_id_t id); +void grub_net_link_layer_protocol_register (struct grub_net_link_layer_protocol *prot); +void grub_net_link_layer_protocol_unregister (struct grub_net_link_layer_protocol *prot); +struct grub_net_link_layer_protocol *grub_net_link_layer_protocol_get (grub_net_protocol_id_t id); #endif diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h index 4148096c5..1f1c48616 100644 --- a/include/grub/net/tftp.h +++ b/include/grub/net/tftp.h @@ -14,7 +14,7 @@ /* IP port for the TFTP server */ #define TFTP_SERVER_PORT 69 -#define TFTP_CLIENT_PORT 2000 +#define TFTP_CLIENT_PORT 26300 /* We define these based on what's in arpa/tftp.h. We just like our @@ -42,10 +42,6 @@ #define TFTP_ENOUSER 7 /* no such user */ #define TFTP_DEFAULT_FILENAME "kernel" - - - - /* * own here because this is cleaner, and maps to the same data layout. * */ struct tftphdr { diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h index 33f2d802d..276c50bf9 100644 --- a/include/grub/net/type_net.h +++ b/include/grub/net/type_net.h @@ -1,7 +1,32 @@ #ifndef GRUB_TYPES_NET_HEADER #define GRUB_TYPES_NET_HEADER 1 +#include + #define UDP_PCKT 0x11 #define IP_PCKT 0x0800 +typedef enum +{ + GRUB_NET_TFTP_ID, + GRUB_NET_UDP_ID, + GRUB_NET_IPV4_ID, + GRUB_NET_IPV6_ID, + GRUB_NET_ETHERNET_ID, + GRUB_NET_ARP_ID, + GRUB_NET_DHCP_ID +}grub_net_protocol_id_t; + +typedef union grub_net_network_layer_address +{ + grub_uint32_t ipv4; +} grub_net_network_layer_netaddress_t; + +typedef union grub_net_network_layer_netaddress +{ + struct { + grub_uint32_t base; + int masksize; + } ipv4; +} grub_net_network_layer_address_t; #endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index dbfcecef0..dfc1776a4 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -1,22 +1,23 @@ #ifndef GRUB_NET_UDP_HEADER #define GRUB_NET_UDP_HEADER 1 #include -/* -typedef enum - { - GRUB_PROT_TFTP - } protocol_type; -*/ -#define GRUB_PROT_TFTP 1 - -struct udphdr { +struct udphdr +{ grub_uint16_t src; grub_uint16_t dst; grub_uint16_t len; grub_uint16_t chksum; } __attribute__ ((packed)); +struct udp_interf +{ + grub_uint16_t src; + grub_uint16_t dst; +}; + + + void udp_ini(void); void udp_fini(void); #endif From c3639ae731b7043f641090b38995a73aceda70c9 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:13:26 -0300 Subject: [PATCH 006/673] File manipulation. Based in OF implementation. For debug porpouse and will be changed later. --- fs/ieee1275/ofnet.c | 355 ++++++++++++++++++++++++++++++++++ include/grub/ieee1275/ofnet.h | 95 +++++++++ 2 files changed, 450 insertions(+) create mode 100644 fs/ieee1275/ofnet.c create mode 100644 include/grub/ieee1275/ofnet.h diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c new file mode 100644 index 000000000..196aadcf2 --- /dev/null +++ b/fs/ieee1275/ofnet.c @@ -0,0 +1,355 @@ +/* ofnet.c - Driver to provide access to the ofnet filesystem */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUFFERADDR 0X00000000 +#define BUFFERSIZE 0x02000000 +#define U64MAXSIZE 18446744073709551615ULL + + +//static grub_ieee1275_ihandle_t handle = 0; + + +static int +grub_ofnet_iterate (int (*hook) (const char *name)) +{ + if (hook ("net")) + return 1; + return 0; +} + +static grub_err_t +grub_ofnet_open (const char *name, grub_disk_t disk) +{ + + + if (grub_strcmp (name, "network")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); + + disk->total_sectors = U64MAXSIZE; + disk->id = (unsigned long) "net"; + + disk->has_partitions = 0; + disk->data = 0; + + return GRUB_ERR_NONE; +} + +static void +grub_ofnet_close (grub_disk_t disk __attribute((unused))) +{ +} + +static grub_err_t +grub_ofnet_read (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + char *buf __attribute((unused))) +{ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ofnet_write (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + const char *buf __attribute((unused))) +{ + return GRUB_ERR_NONE; +} + +static struct grub_disk_dev grub_ofnet_dev = + { + .name = "net", + .id = GRUB_DISK_DEVICE_OFNET_ID, + .iterate = grub_ofnet_iterate, + .open = grub_ofnet_open, + .close = grub_ofnet_close, + .read = grub_ofnet_read, + .write = grub_ofnet_write, + .next = 0 + }; + +static grub_err_t +grub_ofnetfs_dir (grub_device_t device , + const char *path __attribute((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) __attribute((unused))) +{ + if(grub_strcmp (device->disk->name,"network")) + { + return grub_error (GRUB_ERR_BAD_FS, "not an net filesystem"); + } + return GRUB_ERR_NONE; +} + +static grub_ssize_t +grub_ofnetfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + grub_size_t actual; + actual = len <= (file->size - file->offset)?len:file->size - file->offset; + grub_memcpy(buf, (void *)( (grub_addr_t) file->data + (grub_addr_t)file->offset), actual); + return actual; +} + +static grub_err_t +grub_ofnetfs_close (grub_file_t file) +{ + grub_ieee1275_release ((grub_addr_t) file->data,file->size); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ofnetfs_open (struct grub_file *file , const char *name ) +{ + //void *buffer; + //grub_addr_t addr; + if (name[0] == '/') + name++; + if(grub_strcmp (file->device->disk->name,"network")) + { + + return 1; + } + grub_printf("name = %s\n",name); + + struct grub_net_protocol_stack *stack; + struct grub_net_buff *pack; + struct grub_net_application_transport_interface *app_interface; + int file_size; + char *datap; + int amount = 0; + grub_addr_t found_addr; + + stack = grub_net_protocol_stack_get ("tftp"); + app_interface = (struct grub_net_application_transport_interface *) stack->interface; + pack = grub_netbuff_alloc (80*1024); + grub_netbuff_reserve (pack,80*1024); + file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); + + + for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) + { + grub_printf("traing to claim %d bytes at 0x%x\n",file_size,found_addr); + if (grub_claimmap (found_addr , file_size) != -1) + break; + } + grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); + file->data = (void *) found_addr; + grub_printf("file->data = 0x%x\n",(int)file->data); + grub_printf("file_size = %d\n",file_size); + grub_printf("OPEN\n"); + grub_netbuff_clear(pack); + grub_netbuff_reserve (pack,80*1024); + app_interface->app_prot->open (NULL,stack,pack,(char *) name); + + do { + //if (app_interface->app_prot->recv (NULL,stack,pack) == GRUB_ERR_NONE) + grub_printf("RECEIVE PACKET\n"); + grub_netbuff_clear(pack); + grub_netbuff_reserve (pack,80*1024); + app_interface->app_prot->recv (NULL,stack,pack); + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + grub_printf("RECEIVED PACKET\n"); + // { + grub_printf("payload_size= %d\n",pack->tail - pack->data); + grub_printf("amount= %d\n",amount); + grub_printf("file_size= %d\n",file_size); + datap = (char *)file->data + amount; + amount += (pack->tail - pack->data); + grub_printf("datap = 0x%x\n",(int)datap ); + // amount += pack->tail - pack->data; + grub_memcpy(datap, pack->data, pack->tail - pack->data); + grub_printf("SEND ACK\n"); + + grub_netbuff_clear(pack); + grub_netbuff_reserve (pack,80*1024); + app_interface->app_prot->send_ack (NULL,stack,pack); + + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + + grub_printf("SENT ACK\n"); + //} + // file->data = grub_realloc(file->data,amount); + + }while (amount < file_size); + grub_printf("transfer complete\n"); + file->size = file_size; + +// grub_netbuff_free(pack); + /*Start ARP header*/ + // arp.arpr.hwtype = 0x1; /* hardware type (must be ARPHRD_ETHER) */ + // arp.arpr.protocol = 0x0800; /* protocol type (must be ETH_P_IP) */ + // arp.arpr.hwlen = 0x6; /* hardware address length (must be 6) */ + // arp.arpr.protolen = 0x4; /* protocol address length (must be 4) */ + // arp.arpr.opcode = 0x1; /* ARP opcode */ + + + /*arp.arpr.shwaddr[0] =0x0a ; + arp.arpr.shwaddr[1] =0x11 ; + arp.arpr.shwaddr[2] =0xbd ; + arp.arpr.shwaddr[3] =0xe3 ; + arp.arpr.shwaddr[4] =0xe3 ; + arp.arpr.shwaddr[5] =0x04 ; + arp.arpr.sipaddr = dhcp_pckt -> yiaddr; */ /* sender's IP address */ + /*arp.arpr.thwaddr[0] =0; + arp.arpr.thwaddr[1] =0; + arp.arpr.thwaddr[2] =0; + arp.arpr.thwaddr[3] =0; + arp.arpr.thwaddr[4] =0; + arp.arpr.thwaddr[5] =0; + arp.arpr.tipaddr = dhcp_pckt -> siaddr; */ /* target's IP address */ + /*END ARP header */ + return grub_errno; +} + + +static grub_err_t +grub_ofnetfs_label (grub_device_t device __attribute ((unused)), + char **label __attribute ((unused))) +{ + *label = 0; + return GRUB_ERR_NONE; +} + +static struct grub_fs grub_ofnetfs_fs = + { + .name = "ofnetfs", + .dir = grub_ofnetfs_dir, + .open = grub_ofnetfs_open, + .read = grub_ofnetfs_read, + .close = grub_ofnetfs_close, + .label = grub_ofnetfs_label, + .next = 0 + }; + +static char * +grub_ieee1275_get_devargs (const char *path) +{ + int len; + char *colon = grub_strchr (path, ':'); + len = colon - path; + if (! colon) + return 0; + + return grub_strndup (path,len); +} + +static int +grub_ofnet_detect (void) +{ + + char *devalias; + char bootpath[64]; /* XXX check length */ + grub_ieee1275_phandle_t root; + grub_uint32_t net_type; + + grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen); + if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, + sizeof (bootpath), 0)) + { + /* Should never happen. */ + grub_printf ("/chosen/bootpath property missing!\n"); + return 0; + } + devalias = grub_ieee1275_get_aliasdevname (bootpath); + + if (grub_strcmp(devalias ,"network")) + return 0; + + grub_net = grub_malloc (sizeof *grub_net ); + grub_net->name = "net"; + grub_net->dev = grub_ieee1275_get_devargs (bootpath); + grub_ieee1275_finddevice ("/", &root); + grub_ieee1275_get_integer_property (root, "ibm,fw-net-compatibility", + &net_type, sizeof net_type, 0); + grub_printf("root = %d\n",root); + grub_printf("net_type= %d\n",net_type); + grub_net->type = net_type; + + return 1; +} + + +#define IPMASK 0x000000FF +#define IPSIZE 16 +#define IPTEMPLATE "%d.%d.%d.%d" +char * +grub_ip2str (grub_uint32_t ip) +{ + char* str_ip; +// str_ip = grub_malloc(IPSIZE); + str_ip = grub_xasprintf (IPTEMPLATE, ip >> 24 & IPMASK, ip >> 16 & IPMASK, ip >> 8 & IPMASK, ip & IPMASK); + grub_printf ("str_ip = %s\n",str_ip); + grub_printf ("template = "IPTEMPLATE"\n" , ip >> 24 & IPMASK, ip >> 16 & IPMASK, ip >> 8 & IPMASK, ip & IPMASK); + return str_ip; +} + +void +grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet) +{ + netinfo->sip = grub_ip2str(packet->siaddr); + netinfo->cip = grub_ip2str(packet->yiaddr); + netinfo->gat = grub_ip2str(packet->giaddr); + grub_printf("packet->siaddr = %x\n",packet->siaddr); + grub_printf("netinfo-> = %s\n",netinfo->sip); + grub_printf("packet->yiaddr = %x\n",packet->yiaddr); + grub_printf("netinfo-> = %s\n",netinfo->cip); + grub_printf("packet->giaddr = %x\n",packet->giaddr); + grub_printf("netinfo-> = %s\n",netinfo->gat); +} +void +grub_ofnet_init(void) +{ + tftp_ini (); + bootp_pckt = grub_getbootp (); + if(grub_ofnet_detect ()) + { + grub_get_netinfo (grub_net, bootp_pckt ); + grub_disk_dev_register (&grub_ofnet_dev); + grub_fs_register (&grub_ofnetfs_fs); + } + card_open (); +} +void +grub_ofnet_fini(void) +{ + grub_fs_unregister (&grub_ofnetfs_fs); + grub_disk_dev_unregister (&grub_ofnet_dev); +} diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h new file mode 100644 index 000000000..7daadf61d --- /dev/null +++ b/include/grub/ieee1275/ofnet.h @@ -0,0 +1,95 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2007 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 . + */ + +#ifndef GRUB_OFNET_HEADER +#define GRUB_OFNET_HEADER 1 + +#include +#include +#include + +extern void grub_ofnet_init(void); +extern void grub_ofnet_fini(void); +/* +struct grub_net; + +struct grub_net_dev +{ + / The device name. / + const char *name; + + / FIXME: Just a template. / + int (*probe) (struct grub_net *net, const void *addr); + void (*reset) (struct grub_net *net); + int (*poll) (struct grub_net *net); + void (*transmit) (struct grub_net *net, const void *destip, + unsigned srcsock, unsigned destsock, const void *packet); + void (*disable) (struct grub_net *net); + + / The next net device. / + struct grub_net_dev *next; +}; +typedef struct grub_net_dev *grub_net_dev_t; + +struct grub_fs; +*/ +struct grub_ofnet +{ + /* The net name. */ + const char *name; + + /* The OF device string. */ + char *dev; + /*server ip*/ + char *sip; + /*client ip*/ + char *cip; + /*gateway*/ + char *gat; + /**/ + int type; +}; + +typedef struct grub_ofnet *grub_ofnet_t; + +struct grub_bootp { + grub_uint8_t op; /* 1 = BOOTREQUEST, 2 = BOOTREPLY */ + grub_uint8_t htype; /* Hardware address type. */ + grub_uint8_t hlen; /* Hardware address length */ + grub_uint8_t hops; /* Used by gateways in cross-gateway booting. */ + grub_uint32_t xid; /* Transaction ID */ + grub_uint16_t secs; /* Seconds elapsed. */ + grub_uint16_t unused; /* Unused. */ + grub_uint32_t ciaddr; /* Client IP address, */ + grub_uint32_t yiaddr; /* Client IP address filled by server. */ + grub_uint32_t siaddr; /* Server IP address. */ + grub_uint32_t giaddr; /* Gateway IP address. */ + unsigned char chaddr [16]; /* Client hardware address */ + char sname [64]; /* Server name */ + char file [128]; /* Boot filename */ +// grub_uint32_t filesize ; /*File size (testing)*/ + unsigned char vend [64]; +}; + +typedef struct grub_bootp* grub_bootp_t; + +char * grub_get_filestr(const char * ); +char * grub_ip2str (grub_uint32_t ip); +void grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet); +grub_bootp_t grub_getbootp (void); +#endif /* ! GRUB_NET_HEADER */ From 60cdb895da65aaa09dcb256d03063c3a711a61e2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:15:45 -0300 Subject: [PATCH 007/673] Adaptation for the new protocols and interface structs. implementation of receive in the protocols. Also all unwanted packets are discarded. --- commands/net.c | 38 ++++---- include/grub/net.h | 118 ++++++------------------ net/ethernet.c | 88 ++++++++++++------ net/interface.c | 38 ++++++++ net/ip.c | 66 ++++++++++---- net/netbuff.c | 41 +++++++-- net/protocol.c | 50 ++++++---- net/tftp.c | 223 ++++++++++++++++++++++++++++++++++++++------- net/udp.c | 69 +++++++++++--- 9 files changed, 505 insertions(+), 226 deletions(-) diff --git a/commands/net.c b/commands/net.c index 288ba4c2a..b8ceb36f4 100644 --- a/commands/net.c +++ b/commands/net.c @@ -23,14 +23,14 @@ #include struct grub_net_route *grub_net_routes = NULL; -struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; +struct grub_net_network_layer_interface *grub_net_network_layer_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; -struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; +struct grub_net_network_layer_protocol *grub_net_network_layer_protocols = NULL; grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, +grub_net_resolve_address (struct grub_net_network_layer_protocol **prot, char *name, - grub_net_network_level_address_t *addr) + grub_net_network_layer_address_t *addr) { FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) { @@ -50,15 +50,15 @@ grub_net_resolve_address (struct grub_net_network_level_protocol **prot, } grub_err_t -grub_net_route_address (grub_net_network_level_address_t addr, - grub_net_network_level_address_t *gateway, - struct grub_net_network_level_interface **interf) +grub_net_route_address (grub_net_network_layer_address_t addr, + grub_net_network_layer_address_t *gateway, + struct grub_net_network_layer_interface **interf) { struct grub_net_route *route; int depth = 0; int routecnt = 0; - struct grub_net_network_level_protocol *prot = NULL; - grub_net_network_level_address_t curtarget = addr; + struct grub_net_network_layer_protocol *prot = NULL; + grub_net_network_layer_address_t curtarget = addr; *gateway = addr; @@ -96,7 +96,7 @@ static grub_err_t grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { - struct grub_net_network_level_interface *inter; + struct grub_net_network_layer_interface *inter; if (argc != 4) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); @@ -107,8 +107,8 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); - inter->protocol->fini (inter); - grub_net_network_level_interface_unregister (inter); +// inter->protocol->fini (inter); + grub_net_network_layer_interface_unregister (inter); grub_free (inter->name); grub_free (inter); @@ -120,10 +120,10 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { struct grub_net_card *card; - struct grub_net_network_level_protocol *prot; + struct grub_net_network_layer_protocol *prot; grub_err_t err; - grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inter; + grub_net_network_layer_address_t addr; + struct grub_net_network_layer_interface *inter; if (argc != 4) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); @@ -154,14 +154,14 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); inter->card = card; - err = prot->init (inter); + // err = prot->init (inter); if (err) { grub_free (inter->name); grub_free (inter); return err; } - grub_net_network_level_interface_register (inter); + grub_net_network_layer_interface_register (inter); return GRUB_ERR_NONE; } @@ -192,7 +192,7 @@ static grub_err_t grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { - struct grub_net_network_level_protocol *prot; + struct grub_net_network_layer_protocol *prot; struct grub_net_route *route; if (argc < 3) @@ -247,7 +247,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), } else { - struct grub_net_network_level_interface *inter; + struct grub_net_network_layer_interface *inter; route->is_gateway = 0; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) diff --git a/include/grub/net.h b/include/grub/net.h index f021f0e9c..abb8a3167 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -23,20 +23,11 @@ #include #include #include +#include +#include struct grub_net_card; -typedef enum -{ - GRUB_NET_TFTP_ID, - GRUB_NET_UDP_ID, - GRUB_NET_IPV4_ID, - GRUB_NET_IPV6_ID, - GRUB_NET_ETHERNET_ID, - GRUB_NET_ARP_ID, - GRUB_NET_DHCP_ID - -}protocol_type_t; struct grub_net_card_driver { @@ -66,76 +57,36 @@ struct grub_net_card void *data; }; -struct grub_net_network_level_interface; +//struct grub_net_network_layer_interface; -typedef union grub_net_network_level_address +struct grub_net_network_layer_interface { - grub_uint32_t ipv4; -} grub_net_network_level_netaddress_t; - -typedef union grub_net_network_level_netaddress -{ - struct { - grub_uint32_t base; - int masksize; - } ipv4; -} grub_net_network_level_address_t; - -typedef enum grub_network_level_protocol_id -{ - GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 -} grub_network_level_protocol_id_t; - -struct grub_net_network_level_interface; - -struct grub_net_network_level_protocol -{ - struct grub_net_network_level_protocol *next; - char *name; - grub_network_level_protocol_id_t id; - grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); - char * (*aton) (union grub_net_network_level_address addr); - grub_err_t (*net_ntoa) (char *name, - grub_net_network_level_netaddress_t *addr); - char * (*net_aton) (grub_net_network_level_netaddress_t addr); - int (* match_net) (grub_net_network_level_netaddress_t net, - grub_net_network_level_address_t addr); - grub_err_t (*init) (struct grub_net_network_level_interface *dev); - grub_err_t (*fini) (struct grub_net_network_level_interface *dev); - grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); - grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); -}; - -struct grub_net_network_level_interface -{ - struct grub_net_network_level_interface *next; + struct grub_net_network_layer_interface *next; char *name; /* Underlying protocol. */ - struct grub_net_network_level_protocol *protocol; + struct grub_net_network_layer_protocol *protocol; struct grub_net_card *card; - union grub_net_network_level_address address; + union grub_net_network_layer_address address; void *data; }; struct grub_net_route { struct grub_net_route *next; - grub_net_network_level_netaddress_t target; + grub_net_network_layer_netaddress_t target; char *name; - struct grub_net_network_level_protocol *prot; + struct grub_net_network_layer_protocol *prot; int is_gateway; union { - struct grub_net_network_level_interface *interface; - grub_net_network_level_address_t gw; + struct grub_net_network_layer_interface *interface; + grub_net_network_layer_address_t gw; }; }; struct grub_net_session; -struct grub_net_session_level_protocol +struct grub_net_session_layer_protocol { void (*close) (struct grub_net_session *session); grub_ssize_t (*recv) (struct grub_net_session *session, void *buf, @@ -146,7 +97,7 @@ struct grub_net_session_level_protocol struct grub_net_session { - struct grub_net_session_level_protocol *protocol; + struct grub_net_session_layer_protocol *protocol; void *data; }; @@ -170,23 +121,23 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, return session->protocol->recv (session, buf, size); } -extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; +struct grub_net_network_layer_interface *grub_net_network_layer_interfaces; static inline void -grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +grub_net_network_layer_interface_register (struct grub_net_network_layer_interface *inter) { - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_layer_interfaces), GRUB_AS_LIST (inter)); } static inline void -grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +grub_net_network_layer_interface_unregister (struct grub_net_network_layer_interface *inter) { - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_layer_interfaces), GRUB_AS_LIST (inter)); } -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_layer_interfaces; var; var = var->next) extern struct grub_net_route *grub_net_routes; @@ -224,28 +175,13 @@ grub_net_card_unregister (struct grub_net_card *card) #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) -extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; -static inline void -grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -static inline void -grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) +#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_layer_protocols; (var); (var) = (var)->next) static inline grub_err_t -grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, +grub_net_resolve_address_in_protocol (struct grub_net_network_layer_protocol *prot, char *name, - grub_net_network_level_address_t *addr) + grub_net_network_layer_address_t *addr) { return prot->ntoa (name, addr); } @@ -254,14 +190,14 @@ struct grub_net_session * grub_net_open_tcp (char *address, grub_uint16_t port); grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, +grub_net_resolve_address (struct grub_net_network_layer_protocol **prot, char *name, - grub_net_network_level_address_t *addr); + grub_net_network_layer_address_t *addr); grub_err_t -grub_net_route_address (grub_net_network_level_address_t addr, - grub_net_network_level_address_t *gateway, - struct grub_net_network_level_interface **interf); +grub_net_route_address (grub_net_network_layer_address_t addr, + grub_net_network_layer_address_t *gateway, + struct grub_net_network_layer_interface **interf); #endif /* ! GRUB_NET_HEADER */ diff --git a/net/ethernet.c b/net/ethernet.c index 8c13966c1..a4bdbff5b 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -5,51 +5,85 @@ #include #include #include -#include #include +#include static grub_err_t -send_ethernet_packet (struct grub_net_interface *inf,struct grub_net_protstack *protstack __attribute__ ((unused)) - ,struct grub_net_buff *nb) +send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), + struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) { - struct etherhdr *eth; - grub_err_t err; - - if((err = grub_netbuff_push (nb,sizeof(*eth)) ) != GRUB_ERR_NONE) - return err; + struct etherhdr *eth; + + grub_netbuff_push (nb,sizeof(*eth)); eth = (struct etherhdr *) nb->data; - grub_memcpy (eth->src,inf->card->lla->addr,6 * sizeof (grub_uint8_t )); - grub_memcpy (eth->dst,inf->lla->addr,6 * sizeof (grub_uint8_t )); + eth->dst[0] =0x00; + eth->dst[1] =0x11; + eth->dst[2] =0x25; + eth->dst[3] =0xca; + eth->dst[4] =0x1f; + eth->dst[5] =0x01; + eth->src[0] =0x0a; + eth->src[1] =0x11; + eth->src[2] =0xbd; + eth->src[3] =0xe3; + eth->src[4] =0xe3; + eth->src[5] =0x04; + eth->type = 0x0800; - - return inf->card->driver->send(inf->card,nb); + + return send_card_buffer(nb); +// return inf->card->driver->send(inf->card,nb); } -static struct grub_net_protocol grub_ethernet_protocol = + +static grub_err_t +recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), + struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) { - .name = "udp", - .send = send_ethernet_packet + struct etherhdr *eth; + while (1) + { + get_card_packet (nb); + eth = (struct etherhdr *) nb->data; + /*change for grub_memcmp*/ + if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && + eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && eth->type == 0x800) + { + //grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], + // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); + // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], + // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); + //grub_printf("ethernet eth->type 0x%x\n",eth->type); + //grub_printf("out from ethernet\n"); + grub_netbuff_pull(nb,sizeof(*eth)); + return 0; + } + } +/* - get ethernet header + - verify if the next layer is the desired one. + - if not. get another packet. + - remove ethernet header from buffer*/ + return 0; +} + + +static struct grub_net_link_layer_protocol grub_ethernet_protocol = +{ + .name = "ethernet", + .id = GRUB_NET_ETHERNET_ID, + .send = send_ethernet_packet, + .recv = recv_ethernet_packet }; void ethernet_ini(void) { - grub_protocol_register (&grub_ethernet_protocol); + grub_net_link_layer_protocol_register (&grub_ethernet_protocol); } void ethernet_fini(void) { - grub_protocol_unregister (&grub_ethernet_protocol); + grub_net_link_layer_protocol_unregister (&grub_ethernet_protocol); } -/* -int read_ethernet_packet(buffer,bufflen, int type) -{ - - struct etherhdr eth; - eth.type = 0; - - get_card_buffer (ð,sizeof (eth)); - -}*/ diff --git a/net/interface.c b/net/interface.c index e69de29bb..bacabf4cb 100644 --- a/net/interface.c +++ b/net/interface.c @@ -0,0 +1,38 @@ +/*#include + +#define INTERFACE_REGISTER_FUNCTIONS(layerprevious,layernext) \ +struct grub_net_##layername_layer_protocol *grub_net_##layername_layer_protocols;\ +\ +void grub_net_##layerprevious_##layernext_interface_register (struct grub_net_##layername_layer_protocol *prot)\ +{\ + grub_list_push (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ +\ +void grub_net_##layerprevious_##layernext_interface_unregister (struct grub_net_##layername_layer_protocol *prot);\ +{\ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ + +INTERFACE_REGISTER_FUNCTIONS("application","transport"); +INTERFACE_REGISTER_FUNCTIONS("transport","network"); +INTERFACE_REGISTER_FUNCTIONS("network","link"); +INTERFACE_REGISTER_FUNCTIONS("link");*/ + +#include +#include +struct grub_net_protocol_stack *grub_net_protocol_stacks; +struct grub_net_protocol_stack + *grub_net_protocol_stack_get (char *name) +{ + struct grub_net_protocol_stack *p; + + for (p = grub_net_protocol_stacks; p; p = p->next) + { + if (!grub_strcmp(p->name,name)) + return p; + } + + return NULL; +} diff --git a/net/ip.c b/net/ip.c index 6fe58adb0..5eaa74f90 100644 --- a/net/ip.c +++ b/net/ip.c @@ -1,11 +1,11 @@ #include -#include #include #include #include -#include -#include #include +#include +#include +#include #include struct grub_net_protocol *grub_ipv4_prot; @@ -29,14 +29,14 @@ ipchksum(void *ipv, int len) static grub_err_t -send_ip_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb ) +send_ip_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb ) { struct iphdr *iph; - grub_err_t err; + static int id = 0x2400; - if((err = grub_netbuff_push(nb,sizeof(*iph)) ) != GRUB_ERR_NONE) - return err; + grub_netbuff_push(nb,sizeof(*iph)); iph = (struct iphdr *) nb->data; /*FIXME dont work in litte endian machines*/ @@ -44,38 +44,64 @@ send_ip_packet (struct grub_net_interface *inf, struct grub_net_protstack *prots //grub_uint8_t hdrlen = sizeof (struct iphdr)/4; iph->verhdrlen = (4<<4 | 5); iph->service = 0; - iph->len = sizeof(*iph); - iph->ident = 0x2b5f; + iph->len = nb->tail - nb-> data;//sizeof(*iph); + iph->ident = ++id; iph->frags = 0; iph->ttl = 0xff; iph->protocol = 0x11; - //grub_memcpy(&(iph->src) ,inf->card->ila->addr,inf->card->ila->len); - iph->src = *((grub_uint32_t *)inf->card->ila->addr); - //grub_memcpy(&(iph->dest) ,inf->ila->addr,inf->ila->len); - iph->dest = *((grub_uint32_t *)inf->ila->addr); + iph->src = (grub_uint32_t) bootp_pckt -> yiaddr; //inf->address.ipv4; // *((grub_uint32_t *)inf->card->ila->addr); + iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr); iph->chksum = 0 ; - iph->chksum = ipchksum((void *)nb->head, sizeof(*iph)); + iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - - return protstack->next->prot->send(inf,protstack->next,nb); + return trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb); + //return protstack->next->prot->send(inf,protstack->next,nb); } -static struct grub_net_protocol grub_ipv4_protocol = +static grub_err_t +recv_ip_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_transport_network_interface *trans_net_inf, struct grub_net_buff *nb ) +{ + + struct iphdr *iph; + while (1) + { + trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); + iph = (struct iphdr *) nb->data; + if (iph->dest == 0x0908eaaa && iph->src == 0x0908ea92 && iph->protocol == 0x11) + { + grub_netbuff_pull(nb,sizeof(*iph)); + return 0; + } + } +/* grub_printf("ip.src 0x%x\n",iph->src); + grub_printf("ip.dst 0x%x\n",iph->dest); + grub_printf("ip.len 0x%x\n",iph->len); + grub_printf("ip.protocol 0x%x\n",iph->protocol); + */ + /* - get ip header + - verify if is the next layer is correct + -*/ + return 0; +} + +static struct grub_net_network_layer_protocol grub_ipv4_protocol = { .name = "ipv4", + .id = GRUB_NET_IPV4_ID, .send = send_ip_packet, - .recv = NULL + .recv = recv_ip_packet }; void ipv4_ini(void) { - grub_protocol_register (&grub_ipv4_protocol); + grub_net_network_layer_protocol_register (&grub_ipv4_protocol); } void ipv4_fini(void) { - grub_protocol_unregister (&grub_ipv4_protocol); + grub_net_network_layer_protocol_unregister (&grub_ipv4_protocol); } /* diff --git a/net/netbuff.c b/net/netbuff.c index 342260f43..136d55bc4 100644 --- a/net/netbuff.c +++ b/net/netbuff.c @@ -26,7 +26,7 @@ grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->tail += len; if (net_buff->tail > net_buff->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); return GRUB_ERR_NONE; } @@ -34,15 +34,20 @@ grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->tail -= len; if (net_buff->tail < net_buff->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range."); return GRUB_ERR_NONE; } grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->data -= len; +/* grub_printf("push len =%d\n",len); + grub_printf("pack->head =%x\n",(unsigned int)net_buff->head); + grub_printf("pack->data =%x\n",(unsigned int)net_buff->data); + grub_printf("pack->tail =%x\n",(unsigned int)net_buff->tail); + grub_printf("pack->end =%x\n",(unsigned int)net_buff->end);*/ if (net_buff->data < net_buff->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); return GRUB_ERR_NONE; } @@ -50,7 +55,7 @@ grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->data += len; if (net_buff->data > net_buff->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range."); return GRUB_ERR_NONE; } @@ -59,14 +64,36 @@ grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len net_buff->data += len; net_buff->tail += len; if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of the packet range."); + return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range."); return GRUB_ERR_NONE; } -struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ) +struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) { + struct grub_net_buff *nb; + void *data; + if (len < NETBUFFMINLEN) len = NETBUFFMINLEN; + len = ALIGN_UP (len,NETBUFF_ALIGN); - return (struct grub_net_buff *) grub_memalign (len,NETBUFF_ALIGN); + data = grub_memalign (len + sizeof (*nb),NETBUFF_ALIGN); + nb = (struct grub_net_buff *) ((int)data + len); + nb->head = nb->data = nb->tail = data; + nb->end = (char *) nb; + + return nb; +} + +grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff) +{ + grub_free (net_buff); + return 0; + +} + +grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff) +{ + net_buff->data = net_buff->tail = net_buff->head; + return 0; } diff --git a/net/protocol.c b/net/protocol.c index a6117dc2c..05d4471d2 100644 --- a/net/protocol.c +++ b/net/protocol.c @@ -1,21 +1,37 @@ #include +#include +#include -static grub_net_protocol_t grub_net_protocols; - -void grub_protocol_register (grub_net_protocol_t prot) -{ - prot->next = grub_net_protocols; - grub_net_protocols = prot; +#define PROTOCOL_REGISTER_FUNCTIONS(layername) \ +struct grub_net_##layername##_layer_protocol *grub_net_##layername##_layer_protocols;\ +\ +void grub_net_##layername##_layer_protocol_register (struct grub_net_##layername##_layer_protocol *prot)\ +{\ + grub_list_push (GRUB_AS_LIST_P (&grub_net_##layername##_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ +\ +void grub_net_##layername##_layer_protocol_unregister (struct grub_net_##layername##_layer_protocol *prot)\ +{\ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_##layername##_layer_protocols),\ + GRUB_AS_LIST (prot));\ +}\ +\ +struct grub_net_##layername##_layer_protocol \ + *grub_net_##layername##_layer_protocol_get (grub_net_protocol_id_t id)\ +{\ + struct grub_net_##layername##_layer_protocol *p;\ +\ + for (p = grub_net_##layername##_layer_protocols; p; p = p->next)\ + {\ + if (p->id == id)\ + return p;\ + }\ + \ + return NULL; \ } -void grub_protocol_unregister (grub_net_protocol_t prot) -{ - grub_net_protocol_t *p, q; - - for (p = &grub_net_protocols, q = *p; q; p = &(q->next), q = q->next) - if (q == prot) - { - *p = q->next; - break; - } -} +PROTOCOL_REGISTER_FUNCTIONS(application); +PROTOCOL_REGISTER_FUNCTIONS(transport); +PROTOCOL_REGISTER_FUNCTIONS(network); +PROTOCOL_REGISTER_FUNCTIONS(link); diff --git a/net/tftp.c b/net/tftp.c index 3f481fe58..1f04ef47e 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -4,42 +4,94 @@ #include #include #include -#include #include #include -#include #include +#include +#include +#include + +int block,rrq_count=0; +struct { + int block_size; + int size; +} tftp_file; + + +char *get_tok_val(char **tok, char **val, char **str_opt,char *end); +void process_option(char *tok, char *val); + +char *get_tok_val(char **tok, char **val,char **str_opt,char *end) +{ + char *p = *str_opt; + *tok = p; + p += grub_strlen(p) + 1; + + if(p > end) + return NULL; + + *val = p; + p += grub_strlen(p) + 1; + *str_opt = p; + return *tok; +} + +void process_option(char *tok, char *val) +{ + if (!grub_strcmp(tok,"blksize")) + { + tftp_file.block_size = grub_strtoul (val,NULL,0); + return; + } + + if (!grub_strcmp(tok,"tsize")) + { + tftp_file.size = grub_strtoul (val,NULL,0); + return; + } + +} + +//void tftp_open (char *options); /*send read request*/ static grub_err_t -send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protstack *protstack,struct grub_net_buff *nb) +tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb, char *filename) { - /*Start TFTP header*/ - struct tftphdr *tftph; char *rrq; int rrqlen; int hdrlen; - grub_err_t err; + struct udp_interf *udp_interf; + struct grub_net_application_transport_interface *app_interface = (struct grub_net_application_transport_interface *) protstack->interface; - if((err = grub_netbuff_push (nb,sizeof(*tftph))) != GRUB_ERR_NONE) - return err; + app_interface = (struct grub_net_application_transport_interface *) protstack->interface; + grub_netbuff_push (nb,sizeof (*tftph)); + udp_interf = (struct udp_interf *) app_interface->data; + udp_interf->src = TFTP_CLIENT_PORT + rrq_count++; + grub_printf("open tfpt udp_port = %d\n",udp_interf->src); + udp_interf->dst = TFTP_SERVER_PORT; tftph = (struct tftphdr *) nb->data; rrq = (char *) tftph->u.rrq; rrqlen = 0; tftph->opcode = TFTP_RRQ; - grub_strcpy (rrq,inf->path); - rrqlen += grub_strlen (inf->path) + 1; - rrq += grub_strlen (inf->path) + 1; + grub_strcpy (rrq,filename); + rrqlen += grub_strlen (filename) + 1; + rrq += grub_strlen (filename) + 1; /*passar opcoes como parametro ou usar default?*/ grub_strcpy (rrq,"octet"); rrqlen += grub_strlen ("octet") + 1; rrq += grub_strlen ("octet") + 1; + //grub_strcpy (rrq,"netascii"); + //rrqlen += grub_strlen ("netascii") + 1; + //rrq += grub_strlen ("netascii") + 1; + grub_strcpy (rrq,"blksize"); rrqlen += grub_strlen("blksize") + 1; rrq += grub_strlen ("blksize") + 1; @@ -59,39 +111,146 @@ send_tftp_rr (struct grub_net_interface *inf, struct grub_net_protstack *protsta grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); - return protstack->next->prot->send(inf,protstack->next,nb); + app_interface->trans_prot->send (inf,protstack->interface,nb); + /*Receive OACK*/ + return app_interface->app_prot->recv(inf,protstack,nb); } -/* -int send_tftp_ack(int block, int port){ - - tftp_t pckt; - int pcktlen; - pckt.opcode = TFTP_ACK; - pckt.u.ack.block = block; - pcktlen = sizeof (pckt.opcode) + sizeof (pckt.u.ack.block); - - port = 4; - return 0;// send_udp_packet (&pckt,pcktlen,TFTP_CLIENT_PORT,port); -} - -*/ - -static struct grub_net_protocol grub_tftp_protocol = +static grub_err_t +tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb) { - .name = "tftp", - .open = send_tftp_rr + struct tftphdr *tftph; + char *token,*value,*temp; + struct grub_net_application_transport_interface *app_interface = + (struct grub_net_application_transport_interface *) protstack->interface; + + app_interface->trans_prot->recv (inf,protstack->interface,nb); + + tftph = (struct tftphdr *) nb->data; + switch (tftph->opcode) + { + case TFTP_OACK: + /*process oack packet*/ + temp = (char *) tftph->u.oack.data; + while(get_tok_val(&token,&value,&temp,nb->tail)) + { + grub_printf("tok = <%s> val = <%s>\n",token,value); + process_option(token,value); + } + + //buff_clean + nb->data = nb->tail; + grub_printf("OACK---------------------------------------------------------\n"); + grub_printf("block_size=%d\n",tftp_file.block_size); + grub_printf("file_size=%d\n",tftp_file.size); + grub_printf("OACK---------------------------------------------------------\n"); + block = 0; + break; + case TFTP_DATA: + grub_netbuff_pull (nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); + if (tftph->u.data.block == block + 1) + block = tftph->u.data.block; + else + grub_netbuff_clear(nb); + break; + case TFTP_ERROR: + nb->data = nb->tail; + break; + } + return 0;// tftp_send_ack (inf,protstack,nb,tftph->u.data.block); + /*remove tftp header and return. + nb should now contain only the payload*/ +} + +static grub_err_t +tftp_send_ack (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb) +{ + struct tftphdr *tftph; + struct grub_net_application_transport_interface *app_interface = (struct grub_net_application_transport_interface *) protstack->interface; + + nb->data = nb->tail = nb->end; + + grub_netbuff_push (nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); + + tftph = (struct tftphdr *) nb->data; + tftph->opcode = TFTP_ACK; + tftph->u.ack.block = block; + + return app_interface->trans_prot->send (inf,protstack->interface,nb); +} + +static int tftp_file_size (struct grub_net_network_layer_interface* inf , + struct grub_net_protocol_stack *protocol_stack , struct grub_net_buff *nb ,char *filename ) +{ + + tftp_open (inf, protocol_stack,nb, filename); + return tftp_file.size; +} + +static grub_err_t +tftp_close (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack __attribute((unused)),struct grub_net_buff *nb __attribute((unused))) +{ + + return 0; +} + +static struct grub_net_application_transport_interface grub_net_tftp_app_trans_interf; +static struct grub_net_transport_network_interface grub_net_tftp_trans_net_interf; +static struct grub_net_network_link_interface grub_net_tftp_net_link_interf; +static struct grub_net_protocol_stack grub_net_tftp_stack = +{ + .name = "tftp", + .id = GRUB_NET_TFTP_ID, + .interface = (void *) &grub_net_tftp_app_trans_interf + }; +static struct grub_net_application_layer_protocol grub_tftp_protocol = +{ + .name = "tftp", + .id = GRUB_NET_TFTP_ID, + .open = tftp_open, + .recv = tftp_receive, + .send_ack = tftp_send_ack, + .get_file_size = tftp_file_size, + .close = tftp_close +}; + +static struct udp_interf tftp_udp_interf; + void tftp_ini(void) { - grub_protocol_register (&grub_tftp_protocol); + + ethernet_ini (); + ipv4_ini (); + udp_ini (); + grub_net_application_layer_protocol_register (&grub_tftp_protocol); + grub_net_stack_register (&grub_net_tftp_stack); + + grub_net_tftp_app_trans_interf.app_prot = &grub_tftp_protocol; + grub_net_tftp_app_trans_interf.trans_prot = grub_net_transport_layer_protocol_get (GRUB_NET_UDP_ID); + grub_net_tftp_app_trans_interf.inner_layer = &grub_net_tftp_trans_net_interf; + grub_net_tftp_app_trans_interf.data = &tftp_udp_interf; + + grub_net_tftp_trans_net_interf.trans_prot = grub_net_tftp_app_trans_interf.trans_prot; + grub_net_tftp_trans_net_interf.net_prot = grub_net_network_layer_protocol_get (GRUB_NET_IPV4_ID); + grub_net_tftp_trans_net_interf.inner_layer = &grub_net_tftp_net_link_interf; + + grub_net_tftp_net_link_interf.net_prot = grub_net_tftp_trans_net_interf.net_prot; + grub_net_tftp_net_link_interf.link_prot = grub_net_link_layer_protocol_get (GRUB_NET_ETHERNET_ID) ; + + } void tftp_fini(void) { - grub_protocol_unregister (&grub_tftp_protocol); + + + grub_net_application_layer_protocol_unregister (&grub_tftp_protocol); } /* int read_tftp_pckt (grub_uint16_t port, void *buffer, int &buff_len){ diff --git a/net/udp.c b/net/udp.c index 2a4a7690b..fb81aef93 100644 --- a/net/udp.c +++ b/net/udp.c @@ -4,41 +4,84 @@ #include #include #include -/*Assumes that there is allocated memory to the header before the buffer address. */ + static grub_err_t -send_udp_packet (struct grub_net_interface *inf, struct grub_net_protstack *protstack, struct grub_net_buff *nb) +send_udp_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb) { struct udphdr *udph; - grub_err_t err; + struct udp_interf *udp_interf; - if((err = grub_netbuff_push (nb,sizeof(*udph)) ) != GRUB_ERR_NONE) - return err; + grub_netbuff_push (nb,sizeof(*udph)); udph = (struct udphdr *) nb->data; - udph->src = *((grub_uint16_t *) inf->card->tla->addr); - udph->dst = *((grub_uint16_t *) inf->tla->addr); + udp_interf = (struct udp_interf *) app_trans_inf->data; + udph->src = udp_interf->src; + udph->dst = udp_interf->dst; + /*no chksum*/ udph->chksum = 0; - udph->len = sizeof (sizeof (*udph)) + nb->end - nb->head; + udph->len = nb->tail - nb->data; - return protstack->next->prot->send(inf,protstack->next,nb); + return app_trans_inf->inner_layer->net_prot->send(inf,app_trans_inf->inner_layer,nb); } -static struct grub_net_protocol grub_udp_protocol = +static grub_err_t +receive_udp_packet (struct grub_net_network_layer_interface *inf, + struct grub_net_application_transport_interface *app_trans_inf, struct grub_net_buff *nb) +{ + + struct udphdr *udph; + struct udp_interf *udp_interf; + udp_interf = (struct udp_interf *) app_trans_inf->data; + + while(1) + { + app_trans_inf->inner_layer->net_prot->recv(inf,app_trans_inf->inner_layer,nb); + + udph = (struct udphdr *) nb->data; + // grub_printf("udph->dst %d\n",udph->dst); + // grub_printf("udp_interf->src %d\n",udp_interf->src); + if (udph->dst == udp_interf->src) + { + grub_netbuff_pull (nb,sizeof(*udph)); + + // udp_interf->src = udph->dst; + udp_interf->dst = udph->src; + + // grub_printf("udph->dst %d\n",udph->dst); + // grub_printf("udph->src %d\n",udph->src); + // grub_printf("udph->len %d\n",udph->len); + // grub_printf("udph->chksum %x\n",udph->chksum); + + /* - get udp header.. + - verify if is in the desired port + - if not. get another packet + - remove udp header*/ + + return 0; + } + } +} + + +static struct grub_net_transport_layer_protocol grub_udp_protocol = { .name = "udp", - .send = send_udp_packet + .id = GRUB_NET_UDP_ID, + .send = send_udp_packet, + .recv = receive_udp_packet }; void udp_ini(void) { - grub_protocol_register (&grub_udp_protocol); + grub_net_transport_layer_protocol_register (&grub_udp_protocol); } void udp_fini(void) { - grub_protocol_unregister (&grub_udp_protocol); + grub_net_transport_layer_protocol_unregister (&grub_udp_protocol); } /* From 8c599704a75bad68bd4d903fc1b111cba91bd354 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Mon, 21 Jun 2010 19:20:55 -0300 Subject: [PATCH 008/673] Network code specific for ieee1275 machines. Used to parse BOOTP packet from the server and use write/read on the network card. May be removed later. --- conf/powerpc-ieee1275.rmk | 3 +- include/grub/disk.h | 3 +- include/grub/ieee1275/ieee1275.h | 3 +- kern/ieee1275/init.c | 4 +- kern/ieee1275/openfw.c | 68 ++++++++++++++++-- kern/main.c | 8 +-- net/ieee1275/interface.c | 120 ++++++++++++++++++------------- 7 files changed, 144 insertions(+), 65 deletions(-) diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 14d04f93e..ead6d4230 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -24,7 +24,8 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ symlist.c kern/$(target_cpu)/cache.S net/ip.c net/tftp.c net/udp.c net/ethernet.c net/arp.c \ - net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c + net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c \ + fs/ieee1275/ofnet.c kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x200000,-Bstatic diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..1bdfb639b 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -42,7 +42,8 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_FILE_ID, - GRUB_DISK_DEVICE_LUKS_ID + GRUB_DISK_DEVICE_LUKS_ID, + GRUB_DISK_DEVICE_OFNET_ID }; struct grub_disk; diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index b30909c68..f4c8b4edf 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -182,9 +182,8 @@ EXPORT_FUNC(grub_ieee1275_map) (grub_addr_t phys, grub_addr_t virt, char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path); char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path); - int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); - +char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/kern/ieee1275/init.c b/kern/ieee1275/init.c index b7e5c337e..1e108c920 100644 --- a/kern/ieee1275/init.c +++ b/kern/ieee1275/init.c @@ -32,6 +32,7 @@ #include #include #include +#include /* The minimal heap size we can live with. */ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) @@ -223,13 +224,14 @@ grub_machine_init (void) grub_ssize_t actual; grub_ieee1275_init (); - + grub_console_init (); #ifdef __i386__ grub_get_extended_memory (); #endif grub_claim_heap (); grub_ofdisk_init (); + grub_ofnet_init(); /* Process commandline. */ if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args, diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c index 5693f3be0..337fc4b7e 100644 --- a/kern/ieee1275/openfw.c +++ b/kern/ieee1275/openfw.c @@ -22,11 +22,13 @@ #include #include #include +#include enum grub_ieee1275_parse_type { GRUB_PARSE_FILENAME, GRUB_PARSE_PARTITION, + GRUB_PARSE_DEVICE }; /* Walk children of 'devpath', calling hook for each. */ @@ -366,12 +368,14 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) ret = grub_strndup (args, (grub_size_t)(comma - args)); } } - else + + else if (!grub_strcmp ("network", type)) + { + if (ptype == GRUB_PARSE_DEVICE) + ret = grub_strdup(device); + } + else { - /* XXX Handle net devices by configuring & registering a grub_net_dev - here, then return its name? - Example path: "net:,,,,,". */ grub_printf ("Unsupported type %s for device %s\n", type, device); } @@ -381,6 +385,12 @@ fail: return ret; } +char * +grub_ieee1275_get_aliasdevname (const char *path) +{ + return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE); +} + char * grub_ieee1275_get_filename (const char *path) { @@ -432,3 +442,51 @@ grub_halt (void) grub_ieee1275_interpret ("power-off", 0); grub_ieee1275_interpret ("poweroff", 0); } + +static const struct +{ + char *name; + int offset; +} + +bootp_response_properties[] = +{ + { .name = "bootp-response", .offset = 0 }, + { .name = "dhcp-response", .offset = 0 }, + { .name = "bootpreply-packet", .offset = 0x2a }, +}; + +#define SIZE(X) ( sizeof (X) / sizeof(X[0])) + +grub_bootp_t +grub_getbootp( void ) +{ + grub_bootp_t packet = grub_malloc(sizeof *packet); + void *bootp_response = NULL; + grub_ssize_t size; + unsigned int i; + // grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen); + for ( i = 0; i < SIZE(bootp_response_properties); i++) + { + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + bootp_response_properties[i].name, &size)>=0) + break; + } + + if ( size <0 ) + { + grub_printf("Error to get bootp\n"); + return NULL; + } + + if (grub_ieee1275_get_property (grub_ieee1275_chosen, bootp_response_properties[i].name , bootp_response , + size, 0) < 0) + { + grub_printf("Error to get bootp\n"); + return NULL; + } + + packet = (void *) ((int)bootp_response + bootp_response_properties[i].offset); + return packet; +} + diff --git a/kern/main.c b/kern/main.c index 8b6c8a180..3320c4a68 100644 --- a/kern/main.c +++ b/kern/main.c @@ -95,14 +95,14 @@ grub_load_modules (void) grub_module_iterate (hook); } - +/* static void grub_load_config (void) { auto int hook (struct grub_module_header *); int hook (struct grub_module_header *header) { - /* Not an embedded config, skip. */ + / Not an embedded config, skip. / if (header->type != OBJ_TYPE_CONFIG) return 0; @@ -113,7 +113,7 @@ grub_load_config (void) grub_module_iterate (hook); } - +*/ /* Write hook for the environment variables of root. Remove surrounding parentheses, if any. */ static char * @@ -192,7 +192,7 @@ grub_main (void) grub_register_core_commands (); - grub_load_config (); + //grub_load_config (); grub_load_normal_mode (); grub_rescue_run (); } diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index 5a246ffa5..fbd887ad2 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -1,55 +1,21 @@ #include +#include #include - -grub_uint32_t get_server_ip (void) -{ - return bootp_pckt->siaddr; -} - -grub_uint32_t get_client_ip (void) -{ - return bootp_pckt->yiaddr; -} - -grub_uint8_t* get_server_mac (void) -{ - grub_uint8_t *mac; - - mac = grub_malloc (6 * sizeof(grub_uint8_t)); - mac[0] = 0x00 ; - mac[1] = 0x11 ; - mac[2] = 0x25 ; - mac[3] = 0xca ; - mac[4] = 0x1f ; - mac[5] = 0x01 ; - - return mac; - -} - -grub_uint8_t* get_client_mac (void) -{ - grub_uint8_t *mac; - - mac = grub_malloc (6 * sizeof (grub_uint8_t)); - mac[0] = 0x0a ; - mac[1] = 0x11 ; - mac[2] = 0xbd ; - mac[3] = 0xe3 ; - mac[4] = 0xe3 ; - mac[5] = 0x04 ; - - return mac; -} +#include +#include +#include +#include +#include static grub_ieee1275_ihandle_t handle; int card_open (void) { grub_ieee1275_open (grub_net->dev , &handle); - return 1;//error + return 0; } + int card_close (void) { @@ -59,22 +25,74 @@ int card_close (void) } -int send_card_buffer (void *buffer,int buff_len) +int send_card_buffer (struct grub_net_buff *pack) { - int actual; - - grub_ieee1275_write (handle,buffer,buff_len,&actual); + int actual; + //grub_printf("packet size transmited: %d\n",pack->tail - pack->data); + grub_ieee1275_write (handle,pack->data,pack->tail - pack->data,&actual); +// grub_printf("actual transmited %d\n",actual); return actual; } -int get_card_buffer (void *buffer,int buff_len) +int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) { - int actual; + int actual; + char *datap; + struct iphdr *iph; + struct etherhdr *eth; + struct arphdr *arph; + pack->data = pack->tail = pack->head; + datap = pack->data; + do + { + grub_ieee1275_read (handle,datap,sizeof (*eth),&actual); + // if (actual <= 0) + // grub_millisleep(10); - grub_ieee1275_read (handle,buffer,buff_len,&actual); - - return actual; + }while (actual <= 0); + eth = (struct etherhdr *) datap; + datap += sizeof(*eth); + + // grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], + // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); + // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], + // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); +// grub_printf ("eth.type 0x%x\n",eth->type); + + switch (eth->type) + { + case 0x806: + + grub_ieee1275_read (handle,datap,sizeof (*arph),&actual); + arph = (struct arphdr *) datap; + + grub_netbuff_put (pack,sizeof (*eth) + sizeof (*arph)); + break; + case 0x800: + grub_ieee1275_read (handle,datap,sizeof (*iph),&actual); + iph = (struct iphdr *) datap; + datap += sizeof(*iph); + + // grub_printf("ip.src 0x%x\n",iph->src); + // grub_printf("ip.dst 0x%x\n",iph->dest); + // grub_printf("ip.len 0x%x\n",iph->len); + // grub_printf("ip.protocol 0x%x\n",iph->protocol); + + grub_ieee1275_read (handle,datap,iph->len - sizeof (*iph),&actual); + + + grub_netbuff_put (pack,sizeof (*eth) + iph->len); + break; + case 0x86DD: + grub_printf("Ipv6 not yet implemented.\n"); + break; + default: + grub_printf("Unknow packet %x\n",eth->type); + break; + } +// grub_printf("packsize %d\n",pack->tail - pack->data); + return 0;// sizeof (eth) + iph.len; } From bf6d9eeb531e19d88c1705688468b89ea44c9031 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 23 Jun 2010 14:47:55 -0300 Subject: [PATCH 009/673] Abort transference when getting file size. --- net/tftp.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index 1f04ef47e..8e89ed1f4 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -71,7 +71,6 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), udp_interf = (struct udp_interf *) app_interface->data; udp_interf->src = TFTP_CLIENT_PORT + rrq_count++; - grub_printf("open tfpt udp_port = %d\n",udp_interf->src); udp_interf->dst = TFTP_SERVER_PORT; tftph = (struct tftphdr *) nb->data; @@ -135,16 +134,15 @@ tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)) temp = (char *) tftph->u.oack.data; while(get_tok_val(&token,&value,&temp,nb->tail)) { - grub_printf("tok = <%s> val = <%s>\n",token,value); process_option(token,value); } //buff_clean nb->data = nb->tail; - grub_printf("OACK---------------------------------------------------------\n"); - grub_printf("block_size=%d\n",tftp_file.block_size); - grub_printf("file_size=%d\n",tftp_file.size); - grub_printf("OACK---------------------------------------------------------\n"); + // grub_printf("OACK---------------------------------------------------------\n"); + //grub_printf("block_size=%d\n",tftp_file.block_size); + // grub_printf("file_size=%d\n",tftp_file.size); + // grub_printf("OACK---------------------------------------------------------\n"); block = 0; break; case TFTP_DATA: @@ -182,11 +180,39 @@ tftp_send_ack (struct grub_net_network_layer_interface *inf __attribute((unused) return app_interface->trans_prot->send (inf,protstack->interface,nb); } +static grub_err_t +tftp_send_err (struct grub_net_network_layer_interface *inf __attribute((unused)), + struct grub_net_protocol_stack *protstack,struct grub_net_buff *nb, char *errmsg, int errcode) +{ + + struct tftphdr *tftph; + struct grub_net_application_transport_interface *app_interface + = (struct grub_net_application_transport_interface *) protstack->interface; + int msglen = 0; + int hdrlen = 0; + nb->data = nb->tail = nb->end; + + grub_netbuff_push (nb,sizeof (*tftph)); + + tftph = (struct tftphdr *) nb->data; + tftph->opcode = TFTP_ERROR; + tftph->u.err.errcode = errcode; + + grub_strcpy ((char *)tftph->u.err.errmsg,errmsg); + msglen += grub_strlen (errmsg) + 1; + hdrlen = sizeof (tftph->opcode) + sizeof (tftph->u.err.errcode) + msglen; + grub_netbuff_unput (nb,nb->tail - (nb->data + hdrlen)); + + return app_interface->trans_prot->send (inf,protstack->interface,nb); +} + static int tftp_file_size (struct grub_net_network_layer_interface* inf , struct grub_net_protocol_stack *protocol_stack , struct grub_net_buff *nb ,char *filename ) { tftp_open (inf, protocol_stack,nb, filename); + tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0); + return tftp_file.size; } From 1edb7287ff681aa6889e397ab4c891ea93246f2f Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 23 Jun 2010 14:49:46 -0300 Subject: [PATCH 010/673] Parse ipv6 header on incoming packets. --- conf/powerpc-ieee1275.rmk | 1 - fs/ieee1275/ofnet.c | 31 +++++++++++++++---------------- include/grub/net/ip.h | 12 ++++++++++++ net/ieee1275/interface.c | 14 ++++++++++++-- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index ead6d4230..f0faef489 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -3,7 +3,6 @@ # Images. -<<<<<<< TREE kernel_img_HEADERS += ieee1275/ieee1275.h \ command.h i18n.h env_private.h net/ip.h net/udp.h net/ethernet.h net/arp.h net/tftp.h\ net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 196aadcf2..3bbb5c227 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -145,7 +145,7 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) return 1; } - grub_printf("name = %s\n",name); + // grub_printf("name = %s\n",name); struct grub_net_protocol_stack *stack; struct grub_net_buff *pack; @@ -164,38 +164,37 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) { - grub_printf("traing to claim %d bytes at 0x%x\n",file_size,found_addr); +// grub_printf("trying to claim %d bytes at 0x%x\n",file_size,found_addr); if (grub_claimmap (found_addr , file_size) != -1) break; } - grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); +// grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); file->data = (void *) found_addr; - grub_printf("file->data = 0x%x\n",(int)file->data); - grub_printf("file_size = %d\n",file_size); - grub_printf("OPEN\n"); +// grub_printf("file->data = 0x%x\n",(int)file->data); +// grub_printf("file_size = %d\n",file_size); +// grub_printf("OPEN\n"); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->open (NULL,stack,pack,(char *) name); do { //if (app_interface->app_prot->recv (NULL,stack,pack) == GRUB_ERR_NONE) - grub_printf("RECEIVE PACKET\n"); +// grub_printf("RECEIVE PACKET\n"); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->recv (NULL,stack,pack); if (grub_errno != GRUB_ERR_NONE) return grub_errno; - grub_printf("RECEIVED PACKET\n"); +// grub_printf("RECEIVED PACKET\n"); // { - grub_printf("payload_size= %d\n",pack->tail - pack->data); - grub_printf("amount= %d\n",amount); - grub_printf("file_size= %d\n",file_size); +// grub_printf("payload_size= %d\n",pack->tail - pack->data); +// grub_printf("amount= %d\n",amount); +// grub_printf("file_size= %d\n",file_size); datap = (char *)file->data + amount; amount += (pack->tail - pack->data); - grub_printf("datap = 0x%x\n",(int)datap ); - // amount += pack->tail - pack->data; +// grub_printf("datap = 0x%x\n",(int)datap ); grub_memcpy(datap, pack->data, pack->tail - pack->data); - grub_printf("SEND ACK\n"); +// grub_printf("SEND ACK\n"); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); @@ -204,12 +203,12 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) if (grub_errno != GRUB_ERR_NONE) return grub_errno; - grub_printf("SENT ACK\n"); +// grub_printf("SENT ACK\n"); //} // file->data = grub_realloc(file->data,amount); }while (amount < file_size); - grub_printf("transfer complete\n"); +// grub_printf("transfer complete\n"); file->size = file_size; // grub_netbuff_free(pack); diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index e1f45dcfa..cb119ac6f 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -16,6 +16,18 @@ struct iphdr { grub_uint32_t dest; } __attribute__ ((packed)) ; +struct ip6hdr +{ + grub_uint8_t version:4, + priority:4; + grub_uint8_t flow_lbl[3]; + grub_uint16_t payload_len; + grub_uint8_t nexthdr; + grub_uint8_t hop_limit; + grub_uint8_t saddr[16]; + grub_uint8_t daddr[16]; +} __attribute__ ((packed)); + #define IP_UDP 17 /* UDP protocol */ #define IP_BROADCAST 0xFFFFFFFF diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index fbd887ad2..1100ee85d 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -44,6 +44,7 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) struct iphdr *iph; struct etherhdr *eth; struct arphdr *arph; + struct ip6hdr *ip6h; pack->data = pack->tail = pack->head; datap = pack->data; do @@ -86,11 +87,20 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) grub_netbuff_put (pack,sizeof (*eth) + iph->len); break; + case 0x86DD: - grub_printf("Ipv6 not yet implemented.\n"); + grub_printf("!!!!!!!!!!!!!!!!!IPV6 packet received!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + grub_ieee1275_read (handle,datap,sizeof (*ip6h),&actual); + ip6h = (struct ip6hdr *) datap; + grub_printf("ip6hdr->payload_len = %x\n",ip6h->payload_len); + grub_printf("ip6hdr->nexthdr = %x\n",ip6h->nexthdr); + + datap += sizeof(*ip6h); + grub_ieee1275_read (handle,datap,ip6h->payload_len - sizeof (*ip6h),&actual); break; + default: - grub_printf("Unknow packet %x\n",eth->type); + grub_printf("Unknow packet %x\n",eth->type); break; } // grub_printf("packsize %d\n",pack->tail - pack->data); From 3ec6213b179b3b82611e4caa35dae37a16fd2045 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Tue, 29 Jun 2010 06:50:15 -0300 Subject: [PATCH 011/673] Clean Debug messages --- fs/ieee1275/ofnet.c | 75 ++++++++++--------------------------- include/grub/net/type_net.h | 1 + net/ethernet.c | 6 +++ net/ieee1275/interface.c | 16 -------- net/ip.c | 7 ++++ net/netbuff.c | 7 +--- net/tftp.c | 6 ++- net/udp.c | 8 +++- 8 files changed, 46 insertions(+), 80 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 3bbb5c227..a9d16e7e0 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -56,7 +56,7 @@ grub_ofnet_open (const char *name, grub_disk_t disk) { - if (grub_strcmp (name, "network")) + if (grub_strcmp (name, "net")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); disk->total_sectors = U64MAXSIZE; @@ -109,7 +109,7 @@ grub_ofnetfs_dir (grub_device_t device , int (*hook) (const char *filename, const struct grub_dirhook_info *info) __attribute((unused))) { - if(grub_strcmp (device->disk->name,"network")) + if(grub_strcmp (device->disk->name,"net")) { return grub_error (GRUB_ERR_BAD_FS, "not an net filesystem"); } @@ -140,7 +140,7 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) //grub_addr_t addr; if (name[0] == '/') name++; - if(grub_strcmp (file->device->disk->name,"network")) + if(grub_strcmp (file->device->disk->name,"net")) { return 1; @@ -161,80 +161,43 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) grub_netbuff_reserve (pack,80*1024); file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); - for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) { -// grub_printf("trying to claim %d bytes at 0x%x\n",file_size,found_addr); if (grub_claimmap (found_addr , file_size) != -1) break; } -// grub_printf("Claimed %d bytes at 0x%x\n",file_size,found_addr); file->data = (void *) found_addr; -// grub_printf("file->data = 0x%x\n",(int)file->data); -// grub_printf("file_size = %d\n",file_size); -// grub_printf("OPEN\n"); + grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->open (NULL,stack,pack,(char *) name); - do { - //if (app_interface->app_prot->recv (NULL,stack,pack) == GRUB_ERR_NONE) -// grub_printf("RECEIVE PACKET\n"); + do + { grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->recv (NULL,stack,pack); if (grub_errno != GRUB_ERR_NONE) - return grub_errno; -// grub_printf("RECEIVED PACKET\n"); - // { -// grub_printf("payload_size= %d\n",pack->tail - pack->data); -// grub_printf("amount= %d\n",amount); -// grub_printf("file_size= %d\n",file_size); - datap = (char *)file->data + amount; - amount += (pack->tail - pack->data); -// grub_printf("datap = 0x%x\n",(int)datap ); - grub_memcpy(datap, pack->data, pack->tail - pack->data); -// grub_printf("SEND ACK\n"); - + goto error; + if ((pack->tail - pack->data)) + { + // file->data = grub_realloc(file->data,amount + pack->tail - pack->data); + datap = (char *)file->data + amount; + amount += (pack->tail - pack->data); + grub_memcpy(datap , pack->data, pack->tail - pack->data); + } grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->send_ack (NULL,stack,pack); if (grub_errno != GRUB_ERR_NONE) - return grub_errno; - -// grub_printf("SENT ACK\n"); - //} - // file->data = grub_realloc(file->data,amount); + goto error; }while (amount < file_size); -// grub_printf("transfer complete\n"); - file->size = file_size; - -// grub_netbuff_free(pack); - /*Start ARP header*/ - // arp.arpr.hwtype = 0x1; /* hardware type (must be ARPHRD_ETHER) */ - // arp.arpr.protocol = 0x0800; /* protocol type (must be ETH_P_IP) */ - // arp.arpr.hwlen = 0x6; /* hardware address length (must be 6) */ - // arp.arpr.protolen = 0x4; /* protocol address length (must be 4) */ - // arp.arpr.opcode = 0x1; /* ARP opcode */ - - - /*arp.arpr.shwaddr[0] =0x0a ; - arp.arpr.shwaddr[1] =0x11 ; - arp.arpr.shwaddr[2] =0xbd ; - arp.arpr.shwaddr[3] =0xe3 ; - arp.arpr.shwaddr[4] =0xe3 ; - arp.arpr.shwaddr[5] =0x04 ; - arp.arpr.sipaddr = dhcp_pckt -> yiaddr; */ /* sender's IP address */ - /*arp.arpr.thwaddr[0] =0; - arp.arpr.thwaddr[1] =0; - arp.arpr.thwaddr[2] =0; - arp.arpr.thwaddr[3] =0; - arp.arpr.thwaddr[4] =0; - arp.arpr.thwaddr[5] =0; - arp.arpr.tipaddr = dhcp_pckt -> siaddr; */ /* target's IP address */ - /*END ARP header */ + file->size = file_size; + + error: + grub_netbuff_free(pack); return grub_errno; } diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h index 276c50bf9..a1717d6a7 100644 --- a/include/grub/net/type_net.h +++ b/include/grub/net/type_net.h @@ -5,6 +5,7 @@ #define UDP_PCKT 0x11 #define IP_PCKT 0x0800 +#define TIMEOUT_TIME_MS 3*1000 typedef enum { GRUB_NET_TFTP_ID, diff --git a/net/ethernet.c b/net/ethernet.c index a4bdbff5b..2bcb8107d 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -7,6 +7,7 @@ #include #include #include +#include static grub_err_t send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), @@ -42,6 +43,8 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) { struct etherhdr *eth; + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); while (1) { get_card_packet (nb); @@ -59,6 +62,9 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ grub_netbuff_pull(nb,sizeof(*eth)); return 0; } + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } /* - get ethernet header - verify if the next layer is the desired one. diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index 1100ee85d..be9810fb2 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -29,9 +29,7 @@ int send_card_buffer (struct grub_net_buff *pack) { int actual; - //grub_printf("packet size transmited: %d\n",pack->tail - pack->data); grub_ieee1275_write (handle,pack->data,pack->tail - pack->data,&actual); -// grub_printf("actual transmited %d\n",actual); return actual; } @@ -50,18 +48,11 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) do { grub_ieee1275_read (handle,datap,sizeof (*eth),&actual); - // if (actual <= 0) - // grub_millisleep(10); }while (actual <= 0); eth = (struct etherhdr *) datap; datap += sizeof(*eth); - // grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], - // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); - // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], - // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); -// grub_printf ("eth.type 0x%x\n",eth->type); switch (eth->type) { @@ -77,10 +68,6 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) iph = (struct iphdr *) datap; datap += sizeof(*iph); - // grub_printf("ip.src 0x%x\n",iph->src); - // grub_printf("ip.dst 0x%x\n",iph->dest); - // grub_printf("ip.len 0x%x\n",iph->len); - // grub_printf("ip.protocol 0x%x\n",iph->protocol); grub_ieee1275_read (handle,datap,iph->len - sizeof (*iph),&actual); @@ -89,11 +76,8 @@ int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) break; case 0x86DD: - grub_printf("!!!!!!!!!!!!!!!!!IPV6 packet received!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); grub_ieee1275_read (handle,datap,sizeof (*ip6h),&actual); ip6h = (struct ip6hdr *) datap; - grub_printf("ip6hdr->payload_len = %x\n",ip6h->payload_len); - grub_printf("ip6hdr->nexthdr = %x\n",ip6h->nexthdr); datap += sizeof(*ip6h); grub_ieee1275_read (handle,datap,ip6h->payload_len - sizeof (*ip6h),&actual); diff --git a/net/ip.c b/net/ip.c index 5eaa74f90..044cfde6b 100644 --- a/net/ip.c +++ b/net/ip.c @@ -7,6 +7,7 @@ #include #include #include +#include struct grub_net_protocol *grub_ipv4_prot; @@ -65,6 +66,8 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, { struct iphdr *iph; + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); while (1) { trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); @@ -74,6 +77,10 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, grub_netbuff_pull(nb,sizeof(*iph)); return 0; } + + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } /* grub_printf("ip.src 0x%x\n",iph->src); grub_printf("ip.dst 0x%x\n",iph->dest); diff --git a/net/netbuff.c b/net/netbuff.c index 136d55bc4..ce52233b6 100644 --- a/net/netbuff.c +++ b/net/netbuff.c @@ -41,11 +41,6 @@ grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) { net_buff->data -= len; -/* grub_printf("push len =%d\n",len); - grub_printf("pack->head =%x\n",(unsigned int)net_buff->head); - grub_printf("pack->data =%x\n",(unsigned int)net_buff->data); - grub_printf("pack->tail =%x\n",(unsigned int)net_buff->tail); - grub_printf("pack->end =%x\n",(unsigned int)net_buff->end);*/ if (net_buff->data < net_buff->head) return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); return GRUB_ERR_NONE; @@ -87,7 +82,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff) { - grub_free (net_buff); + grub_free (net_buff->head); return 0; } diff --git a/net/tftp.c b/net/tftp.c index 8e89ed1f4..dff0f134c 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -70,7 +70,7 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), grub_netbuff_push (nb,sizeof (*tftph)); udp_interf = (struct udp_interf *) app_interface->data; - udp_interf->src = TFTP_CLIENT_PORT + rrq_count++; + udp_interf->src = TFTP_CLIENT_PORT;// + rrq_count++; udp_interf->dst = TFTP_SERVER_PORT; tftph = (struct tftphdr *) nb->data; @@ -112,6 +112,8 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), app_interface->trans_prot->send (inf,protstack->interface,nb); /*Receive OACK*/ + grub_netbuff_clear (nb); + grub_netbuff_reserve (nb,80*1024); return app_interface->app_prot->recv(inf,protstack,nb); } @@ -211,6 +213,8 @@ static int tftp_file_size (struct grub_net_network_layer_interface* inf , { tftp_open (inf, protocol_stack,nb, filename); + grub_netbuff_clear (nb); + grub_netbuff_reserve (nb,80*1024); tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0); return tftp_file.size; diff --git a/net/udp.c b/net/udp.c index fb81aef93..0321fd58a 100644 --- a/net/udp.c +++ b/net/udp.c @@ -4,6 +4,7 @@ #include #include #include +#include static grub_err_t send_udp_packet (struct grub_net_network_layer_interface *inf, @@ -35,7 +36,8 @@ receive_udp_packet (struct grub_net_network_layer_interface *inf, struct udphdr *udph; struct udp_interf *udp_interf; udp_interf = (struct udp_interf *) app_trans_inf->data; - + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); while(1) { app_trans_inf->inner_layer->net_prot->recv(inf,app_trans_inf->inner_layer,nb); @@ -62,6 +64,10 @@ receive_udp_packet (struct grub_net_network_layer_interface *inf, return 0; } + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + return grub_error (GRUB_ERR_TIMEOUT, "Time out."); + } } From f8795693f1c3caa557b8658ac3d8661b1f84b739 Mon Sep 17 00:00:00 2001 From: Paulo de Rezende Pinatti Date: Tue, 13 Jul 2010 11:22:35 -0300 Subject: [PATCH 012/673] Added support to netdisk specified in the form (net,protocol,server_ip,username,password) an to list its information with command ls. * fs/ieee1275/ofnet.c (grub_ofnet_open): parse parameters to determine netdisk data * fs/ieee1275/ofnet.c (grub_ofnet_close): dealloc netdisk data * include/grub/disk.h: added struct grub_netdisk_data * include/grub/ieee1275/ofnet.h: added newline * kern/disk.c (grub_disk_open): ignore partition check for netdisk * normal/misc.c (grub_normal_print_device_info): added support to list netdisk information --- fs/ieee1275/ofnet.c | 159 ++++++++++++++++++++++++++++++++-- include/grub/disk.h | 17 ++++ include/grub/ieee1275/ofnet.h | 1 + kern/disk.c | 4 +- normal/misc.c | 39 +++++++++ 5 files changed, 213 insertions(+), 7 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index a9d16e7e0..9010317ba 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -42,6 +42,85 @@ //static grub_ieee1275_ihandle_t handle = 0; +static const char * +find_sep (const char *name) +{ + const char *p = name; + char c = *p; + + if (c == '\0') + return NULL; + + do + { + if (c == '\\' && *p == ',') + p++; + else if (c == ',') + return p - 1; + } while ((c = *p++) != '\0'); + return p - 1; +} + +static grub_err_t +retrieve_field(const char *src, char **field, const char **rest) +{ + const char *p; + grub_size_t len; + + p = find_sep(src); + if (! p) + { + *field = NULL; + *rest = src; + return 0; + } + + len = p - src; + *field = grub_malloc (len + 1); + if (! *field) + { + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + } + + grub_memcpy (*field, src, len); + (*field)[len] = '\0'; + + if (*p == '\0') + *rest = p; + else + *rest = p + 1; + return 0; +} + +static grub_err_t +parse_ip (const char *val, grub_uint32_t *ip, const char **rest) +{ + grub_uint32_t newip = 0; + unsigned long t; + int i; + const char *ptr = val; + + for (i = 0; i < 4; i++) + { + t = grub_strtoul (ptr, (char **) &ptr, 0); + if (grub_errno) + return grub_errno; + if (t & ~0xff) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + newip >>= 8; + newip |= (t << 24); + if (i != 3 && *ptr != '.') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + ptr++; + } + ptr = ptr - 1; + if ( *ptr != '\0' && *ptr != ',') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + *ip = newip; + if (rest) + *rest = ptr; + return 0; +} static int grub_ofnet_iterate (int (*hook) (const char *name)) @@ -54,23 +133,93 @@ grub_ofnet_iterate (int (*hook) (const char *name)) static grub_err_t grub_ofnet_open (const char *name, grub_disk_t disk) { - + grub_err_t err; + const char *p1, *p2; + char *user = NULL, *pwd = NULL; + grub_netdisk_data_t data; + grub_netdisk_protocol_t proto; + grub_uint32_t server_ip = 0; if (grub_strcmp (name, "net")) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); - disk->total_sectors = U64MAXSIZE; + p1 = find_sep(disk->name); + if (! p1 || *p1 == '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing"); + p1++; + + // parse protocol + p2 = find_sep(p1); + if (! p2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no protocol specified"); + if ((p2 - p1 == 4) && (! grub_strncasecmp(p1, "tftp", p2 - p1))) + proto = GRUB_NETDISK_PROTOCOL_TFTP; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid protocol specified"); + + // parse server ip + if ( *p2 == '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no server ip specified"); + p1 = p2 + 1; + err = parse_ip(p1, &server_ip, &p2); + if (err) + return err; + + // parse username (optional) + if ( *p2 == ',') + p2++; + err = retrieve_field(p2, &user, &p1); + if (err) + return err; + if (user) + { + // parse password (optional) + err = retrieve_field(p1, &pwd, &p2); + if (err) + { + grub_free(user); + return err; + } + } + + if (! disk->data) + { + data = grub_malloc (sizeof(*data)); + disk->data = data; + } + else + { + data = disk->data; + if (data->username) + grub_free(data->username); + if (data->password) + grub_free(data->password); + } + data->protocol = proto; + data->server_ip = server_ip; + data->username = user; + data->password = pwd; + + disk->total_sectors = 0; disk->id = (unsigned long) "net"; disk->has_partitions = 0; - disk->data = 0; return GRUB_ERR_NONE; } static void -grub_ofnet_close (grub_disk_t disk __attribute((unused))) +grub_ofnet_close (grub_disk_t disk) { + grub_netdisk_data_t data = disk->data; + if (data) + { + if (data->username) + grub_free(data->username); + if (data->password) + grub_free(data->password); + grub_free(data); + } } static grub_err_t diff --git a/include/grub/disk.h b/include/grub/disk.h index 1bdfb639b..dc8bc5018 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -119,6 +119,23 @@ struct grub_disk }; typedef struct grub_disk *grub_disk_t; +/* Net Disk */ +enum grub_netdisk_protocol +{ + GRUB_NETDISK_PROTOCOL_TFTP +}; +typedef enum grub_netdisk_protocol grub_netdisk_protocol_t; + +struct grub_netdisk_data +{ + grub_netdisk_protocol_t protocol; + grub_uint32_t server_ip; + grub_uint32_t port; + char *username; + char *password; +}; +typedef struct grub_netdisk_data *grub_netdisk_data_t; + #ifdef GRUB_UTIL struct grub_disk_memberlist { diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index 7daadf61d..a26c22235 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -25,6 +25,7 @@ extern void grub_ofnet_init(void); extern void grub_ofnet_fini(void); + /* struct grub_net; diff --git a/kern/disk.c b/kern/disk.c index ccd5f200f..051e59aca 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -281,7 +281,7 @@ grub_disk_open (const char *name) goto fail; } - if (p && ! disk->has_partitions) + if (p && ! disk->has_partitions && grub_strcmp (raw, "net")) { grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk"); goto fail; @@ -289,7 +289,7 @@ grub_disk_open (const char *name) disk->dev = dev; - if (p) + if (p && grub_strcmp (raw, "net")) { disk->partition = grub_partition_probe (disk, p + 1); if (! disk->partition) diff --git a/normal/misc.c b/normal/misc.c index 17ba372ce..d53fe711c 100644 --- a/normal/misc.c +++ b/normal/misc.c @@ -32,8 +32,47 @@ grub_err_t grub_normal_print_device_info (const char *name) { grub_device_t dev; + grub_netdisk_data_t data; char *p; + if ((! grub_strcmp(name, "net")) || (! grub_strncmp(name, "net,", 4))) + { + grub_printf_ (N_("Device network:")); + grub_putchar (' '); + + dev = grub_device_open (name); + if (! dev || ! dev->disk || ! dev->disk->data) + grub_printf ("%s", _("Network information not available")); + else + { + data = dev->disk->data; + grub_putchar ('\n'); + grub_putchar ('\t'); + if (data->protocol == GRUB_NETDISK_PROTOCOL_TFTP) + grub_printf_(N_("Protocol: %s"), "TFTP"); + else + grub_printf_(N_("Protocol: %s"), "Unknown"); + grub_putchar ('\n'); + grub_putchar ('\t'); + grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip & 0xff, data->server_ip >> 8 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 24 & 0xff); + if (data->username) + { + grub_putchar ('\n'); + grub_putchar ('\t'); + grub_printf_(N_("Username: %s"), data->username); + if (data->password) + { + grub_putchar ('\n'); + grub_putchar ('\t'); + grub_printf_(N_("Password: %s"), data->password); + } + } + } + grub_putchar ('\n'); + + return GRUB_ERR_NONE; + } + p = grub_strchr (name, ','); if (p) { From 7e8b77c03359b2537dee39ded103b2f126157dd8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 19 Jul 2010 21:22:54 +0200 Subject: [PATCH 013/673] AHCI skeleton --- conf/i386.rmk | 5 + disk/ahci.c | 311 ++++++++++++++++++++++++++++++++++++++++++++ include/grub/scsi.h | 3 +- 3 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 disk/ahci.c diff --git a/conf/i386.rmk b/conf/i386.rmk index b1df584a6..54edb468b 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -36,6 +36,11 @@ ata_mod_SOURCES = disk/ata.c ata_mod_CFLAGS = $(COMMON_CFLAGS) ata_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += ahci.mod +ahci_mod_SOURCES = disk/ahci.c +ahci_mod_CFLAGS = $(COMMON_CFLAGS) +ahci_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For setpci.mod pkglib_MODULES += setpci.mod setpci_mod_SOURCES = commands/setpci.c diff --git a/disk/ahci.c b/disk/ahci.c new file mode 100644 index 000000000..1372fd651 --- /dev/null +++ b/disk/ahci.c @@ -0,0 +1,311 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007, 2008, 2009, 2010 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 . + */ + +#include +#include +#include +#include +#include +#include + +struct grub_ahci_cmd_head +{ + grub_uint32_t unused[8]; +}; + +struct grub_ahci_hba_port +{ + grub_uint64_t command_list_base; + grub_uint32_t unused[12]; + grub_uint32_t sata_active; + grub_uint32_t command_issue; + grub_uint32_t unused[16]; +}; + +struct grub_ahci_hba +{ + grub_uint32_t cap; +#define GRUB_AHCI_HBA_CAP_MASK 0x1f + grub_uint32_t global_control; +#define GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN 0x80000000 + grub_uint32_t ports_implemented; + grub_uint32_t unused1[7]; + grub_uint32_t bios_handoff; +#define GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED 1 +#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNED 2 +#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED 8 +#define GRUB_AHCI_BIOS_HANDOFF_RWC 8 + grub_uint32_t unused2[53]; + struct grub_ahci_hba_port ports[32]; +}; + +struct grub_ahci_device +{ + struct grub_ahci_device *next; + volatile struct grub_ahci_hba *hba; + int port; + int num; + struct grub_pci_dma_chunk *command_list_chunk; + volatile struct grub_ahci_cmd_head *command_list; +}; + +static struct grub_ahci_device *grub_ahci_devices; +static int numdevs; + +static int NESTED_FUNC_ATTR +grub_ahci_pciinit (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint32_t class; + grub_uint32_t bar; + int nports; + volatile struct grub_ahci_hba *hba; + + /* Read class. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + /* Check if this class ID matches that of a PCI IDE Controller. */ + if (class >> 8 != 0x010601) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); + bar = grub_pci_read (addr); + + if (bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_MEM_PREFETCH) + != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) + return 0; + + hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, + sizeof (hba)); + + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + + nports = hba->cap & GRUB_AHCI_HBA_CAP_MASK; + + if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) + { + grub_uint64_t endtime; + + grub_dprintf ("ahci", "Requesting AHCI ownership\n"); + hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC) + | GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n"); + endtime = grub_get_time_ms () + 1000; + while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + && grub_get_time_ms () < endtime); + if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + { + grub_dprintf ("ahci", "Forcibly taking ownership\n"); + hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED; + } + else + grub_dprintf ("ahci", "AHCI ownership obtained\n"); + } + else + grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + + for (i = 0; i < nports; i++) + { + struct grub_ahci_device *adev; + struct grub_pci_dma_chunk *command_list; + + if (!(hba->ports_implemented & (1 << i))) + continue; + + command_list = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_head)); + if (!command_list) + return 1; + + adev = grub_malloc (sizeof (*adev)); + if (!adev) + { + grub_dma_free (command_list); + return 1; + } + + adev->hba = hba; + adev->port = i; + adev->num = numdevs++; + adev->command_list_chunk = command_list; + adev->command_list = grub_dma_get_virt (command_list); + adev->hba->ports[i].command_list_base = grub_dma_get_phys (command_list); + grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), + GRUB_AS_LIST (adev)); + } + + return 0; +} + +static grub_err_t +grub_ahci_initialize (void) +{ + grub_pci_iterate (grub_ahci_pciinit); + return grub_errno; +} + + + + +static int +grub_ahci_iterate (int (*hook) (int bus, int luns)) +{ + struct grub_ahci_device *dev; + + FOR_LIST_ELEMENTS(dev, grub_ahci_devices) + if (hook (dev->num, 1)) + return 1; + + return 0; +} + +#if 0 +static int +find_free_cmd_slot (struct grub_ahci_device *dev) +{ + int i; + for (i = 0; i < 32; i++) + { + if (dev->hda->ports[dev->port].command_issue & (1 << i)) + continue; + if (dev->hda->ports[dev->port].sata_active & (1 << i)) + continue; + return i; + } + return -1; +} +#endif + +static grub_err_t +grub_ahci_packet (struct grub_ahci_device *dev, char *packet, + grub_size_t size) +{ + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ahci_read (struct grub_scsi *scsi, + grub_size_t cmdsize __attribute__((unused)), + char *cmd, grub_size_t size, char *buf) +{ + struct grub_ahci_device *dev = (struct grub_ahci_device *) scsi->data; + + grub_dprintf("ahci", "grub_ahci_read (size=%llu)\n", (unsigned long long) size); + + if (grub_atapi_packet (dev, cmd, size)) + return grub_errno; + + grub_size_t nread = 0; + while (nread < size) + { + /* Wait for !BSY, DRQ, I/O, !C/D. */ + if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_DATA_IN, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + /* Get byte count for this DRQ assertion. */ + unsigned cnt = grub_ata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 + | grub_ata_regget (dev, GRUB_ATAPI_REG_CNTLOW); + grub_dprintf("ata", "DRQ count=%u\n", cnt); + + /* Count of last transfer may be uneven. */ + if (! (0 < cnt && cnt <= size - nread && (! (cnt & 1) || cnt == size - nread))) + return grub_error (GRUB_ERR_READ_ERROR, "invalid ATAPI transfer count"); + + /* Read the data. */ + grub_ata_pio_read (dev, buf + nread, cnt); + + if (cnt & 1) + buf[nread + cnt - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); + + nread += cnt; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ahci_write (struct grub_scsi *scsi __attribute__((unused)), + grub_size_t cmdsize __attribute__((unused)), + char *cmd __attribute__((unused)), + grub_size_t size __attribute__((unused)), + char *buf __attribute__((unused))) +{ + // XXX: scsi.mod does not use write yet. + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "AHCI write not implemented"); +} + +static grub_err_t +grub_ahci_open (int devnum, struct grub_scsi *scsi) +{ + struct grub_ahci_device *dev; + + FOR_LIST_ELEMENTS(dev, grub_ahci_devices) + { + if (dev->num == devnum) + break; + } + + grub_dprintf ("ata", "opening AHCI dev `ahci%d'\n", devnum); + + if (! dev) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device"); + + scsi->data = dev; + + return GRUB_ERR_NONE; +} + + +static struct grub_scsi_dev grub_ahci_dev = + { + .name = "ahci", + .id = GRUB_SCSI_SUBSYSTEM_AHCI, + .iterate = grub_ahci_iterate, + .open = grub_ahci_open, + .read = grub_ahci_read, + .write = grub_ahci_write + }; + + + +GRUB_MOD_INIT(ahci) +{ + /* To prevent two drivers operating on the same disks. */ + grub_disk_firmware_is_tainted = 1; + if (grub_disk_firmware_fini) + { + grub_disk_firmware_fini (); + grub_disk_firmware_fini = NULL; + } + + /* AHCI initialization. */ + grub_ahci_initialize (); + + /* AHCI devices are handled by scsi.mod. */ + grub_scsi_dev_register (&grub_ahci_dev); +} + +GRUB_MOD_FINI(ahci) +{ + grub_scsi_dev_unregister (&grub_ahci_dev); +} diff --git a/include/grub/scsi.h b/include/grub/scsi.h index b3c60f3e8..289cd8e4a 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -29,7 +29,8 @@ struct grub_scsi; enum { GRUB_SCSI_SUBSYSTEM_USBMS, - GRUB_SCSI_SUBSYSTEM_ATAPI + GRUB_SCSI_SUBSYSTEM_ATAPI, + GRUB_SCSI_SUBSYSTEM_AHCI }; #define GRUB_SCSI_ID_SUBSYSTEM_SHIFT 24 From 818a356eb196a2c2ca5af7d580b9920c8564ebcc Mon Sep 17 00:00:00 2001 From: Paulo de Rezende Pinatti Date: Thu, 29 Jul 2010 16:36:17 -0300 Subject: [PATCH 014/673] Fixed get_card_packet to correctly read data from network card into buffer. * net/ieee1275/interface.c (get_card_packet): read data regardless of ethernet header --- net/ieee1275/interface.c | 54 +++------------------------------------- 1 file changed, 4 insertions(+), 50 deletions(-) diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c index be9810fb2..342044041 100644 --- a/net/ieee1275/interface.c +++ b/net/ieee1275/interface.c @@ -1,9 +1,4 @@ #include -#include -#include -#include -#include -#include #include #include @@ -37,56 +32,15 @@ int send_card_buffer (struct grub_net_buff *pack) int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) { - int actual; - char *datap; - struct iphdr *iph; - struct etherhdr *eth; - struct arphdr *arph; - struct ip6hdr *ip6h; + int actual, rc; pack->data = pack->tail = pack->head; - datap = pack->data; do { - grub_ieee1275_read (handle,datap,sizeof (*eth),&actual); + rc = grub_ieee1275_read (handle,pack->data,1500,&actual); - }while (actual <= 0); - eth = (struct etherhdr *) datap; - datap += sizeof(*eth); - + }while (actual <= 0 || rc < 0); + grub_netbuff_put (pack, actual); - switch (eth->type) - { - case 0x806: - - grub_ieee1275_read (handle,datap,sizeof (*arph),&actual); - arph = (struct arphdr *) datap; - - grub_netbuff_put (pack,sizeof (*eth) + sizeof (*arph)); - break; - case 0x800: - grub_ieee1275_read (handle,datap,sizeof (*iph),&actual); - iph = (struct iphdr *) datap; - datap += sizeof(*iph); - - - grub_ieee1275_read (handle,datap,iph->len - sizeof (*iph),&actual); - - - grub_netbuff_put (pack,sizeof (*eth) + iph->len); - break; - - case 0x86DD: - grub_ieee1275_read (handle,datap,sizeof (*ip6h),&actual); - ip6h = (struct ip6hdr *) datap; - - datap += sizeof(*ip6h); - grub_ieee1275_read (handle,datap,ip6h->payload_len - sizeof (*ip6h),&actual); - break; - - default: - grub_printf("Unknow packet %x\n",eth->type); - break; - } // grub_printf("packsize %d\n",pack->tail - pack->data); return 0;// sizeof (eth) + iph.len; } From 11d1ea5df607d8d2e6463f482f24e92c9cb609be Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 17:52:54 -0300 Subject: [PATCH 015/673] Use server and client IP from the bootp packet. --- net/ip.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/ip.c b/net/ip.c index 044cfde6b..65b0f2b70 100644 --- a/net/ip.c +++ b/net/ip.c @@ -72,7 +72,9 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, { trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); iph = (struct iphdr *) nb->data; - if (iph->dest == 0x0908eaaa && iph->src == 0x0908ea92 && iph->protocol == 0x11) + if (iph->protocol == 0x11 && + iph->dest == (grub_uint32_t) bootp_pckt -> yiaddr && + iph->src == (grub_uint32_t) bootp_pckt -> siaddr ) { grub_netbuff_pull(nb,sizeof(*iph)); return 0; @@ -82,11 +84,11 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, if (current_time - start_time > TIMEOUT_TIME_MS) return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } -/* grub_printf("ip.src 0x%x\n",iph->src); - grub_printf("ip.dst 0x%x\n",iph->dest); - grub_printf("ip.len 0x%x\n",iph->len); - grub_printf("ip.protocol 0x%x\n",iph->protocol); - */ +// grub_printf("ip.src 0x%x\n",iph->src); +// grub_printf("ip.dst 0x%x\n",iph->dest); +// grub_printf("ip.len 0x%x\n",iph->len); +// grub_printf("ip.protocol 0x%x\n",iph->protocol); + /* - get ip header - verify if is the next layer is correct -*/ From f89661762a82b0784965ca27d88473e704648cf2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 18:07:09 -0300 Subject: [PATCH 016/673] Only open the card in netboot. --- fs/ieee1275/ofnet.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 9010317ba..82b5235cc 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -141,6 +141,7 @@ grub_ofnet_open (const char *name, grub_disk_t disk) grub_uint32_t server_ip = 0; if (grub_strcmp (name, "net")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a net disk"); p1 = find_sep(disk->name); @@ -258,7 +259,7 @@ grub_ofnetfs_dir (grub_device_t device , int (*hook) (const char *filename, const struct grub_dirhook_info *info) __attribute((unused))) { - if(grub_strcmp (device->disk->name,"net")) + if(grub_strncmp (device->disk->name,"net",3)) { return grub_error (GRUB_ERR_BAD_FS, "not an net filesystem"); } @@ -287,9 +288,10 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) { //void *buffer; //grub_addr_t addr; + if (name[0] == '/') name++; - if(grub_strcmp (file->device->disk->name,"net")) + if(grub_strncmp (file->device->disk->name,"net",3)) { return 1; @@ -311,15 +313,17 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) - { - if (grub_claimmap (found_addr , file_size) != -1) - break; - } + { + if (grub_claimmap (found_addr , file_size) != -1) + break; + } file->data = (void *) found_addr; grub_netbuff_clear(pack); grub_netbuff_reserve (pack,80*1024); app_interface->app_prot->open (NULL,stack,pack,(char *) name); + if (grub_errno != GRUB_ERR_NONE) + goto error; do { @@ -401,7 +405,7 @@ grub_ofnet_detect (void) } devalias = grub_ieee1275_get_aliasdevname (bootpath); - if (grub_strcmp(devalias ,"network")) + if (grub_strncmp(devalias ,"net",3)) return 0; grub_net = grub_malloc (sizeof *grub_net ); @@ -455,8 +459,8 @@ grub_ofnet_init(void) grub_get_netinfo (grub_net, bootp_pckt ); grub_disk_dev_register (&grub_ofnet_dev); grub_fs_register (&grub_ofnetfs_fs); + card_open (); } - card_open (); } void grub_ofnet_fini(void) From 17ef14c91669b1c7a8c32f106148c142a488a9c4 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 18:13:00 -0300 Subject: [PATCH 017/673] Process errot packets in TFTP reply. --- net/tftp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index dff0f134c..0fb43105d 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -140,7 +140,7 @@ tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)) } //buff_clean - nb->data = nb->tail; + grub_netbuff_clear(nb); // grub_printf("OACK---------------------------------------------------------\n"); //grub_printf("block_size=%d\n",tftp_file.block_size); // grub_printf("file_size=%d\n",tftp_file.size); @@ -155,7 +155,8 @@ tftp_receive (struct grub_net_network_layer_interface *inf __attribute((unused)) grub_netbuff_clear(nb); break; case TFTP_ERROR: - nb->data = nb->tail; + grub_netbuff_clear (nb); + return grub_error (GRUB_ERR_ACCESS_DENIED, (char *)tftph->u.err.errmsg); break; } From 7c978f06900fc81e185bc0c8977f935c0185927c Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 29 Jul 2010 18:17:01 -0300 Subject: [PATCH 018/673] Implement the size field. --- include/grub/net/ethernet.h | 24 ++++++++++++-- net/ethernet.c | 65 ++++++++++++++++++++----------------- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 46aa04f60..9043a5f02 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -1,11 +1,31 @@ #ifndef GRUB_NET_ETHERNET_HEADER #define GRUB_NET_ETHERNET_HEADER 1 #include -struct etherhdr { +#define LLCADDRMASK 0x7f + +struct etherhdr +{ grub_uint8_t dst[6]; grub_uint8_t src[6]; grub_uint16_t type; -} __attribute__ ((packed)) ; +} __attribute__ ((packed)); + +#define PCP (x) x & 0xe000 +#define CFI (x) x & 0x1000 +#define VID (x) x & 0x0fff + +struct llchdr +{ +grub_uint8_t dsap; +grub_uint8_t ssap; +grub_uint8_t ctrl; +} __attribute__ ((packed)); + +struct snaphdr +{ +grub_uint8_t oui[3]; +grub_uint16_t type; +} __attribute__ ((packed)); void ethernet_ini(void); void ethernet_fini(void); diff --git a/net/ethernet.c b/net/ethernet.c index 2bcb8107d..ab5992133 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -18,19 +18,13 @@ send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ grub_netbuff_push (nb,sizeof(*eth)); eth = (struct etherhdr *) nb->data; - eth->dst[0] =0x00; - eth->dst[1] =0x11; - eth->dst[2] =0x25; - eth->dst[3] =0xca; - eth->dst[4] =0x1f; - eth->dst[5] =0x01; - eth->src[0] =0x0a; - eth->src[1] =0x11; - eth->src[2] =0xbd; - eth->src[3] =0xe3; - eth->src[4] =0xe3; - eth->src[5] =0x04; - + eth->dst[0] = 0x00; + eth->dst[1] = 0x11; + eth->dst[2] = 0x25; + eth->dst[3] = 0xca; + eth->dst[4] = 0x1f; + eth->dst[5] = 0x01; + grub_memcpy (eth->src, bootp_pckt -> chaddr,6); eth->type = 0x0800; return send_card_buffer(nb); @@ -44,25 +38,38 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ { struct etherhdr *eth; grub_uint64_t start_time, current_time; + struct llchdr *llch; + struct snaphdr *snaph; + grub_uint16_t type; start_time = grub_get_time_ms(); - while (1) - { - get_card_packet (nb); - eth = (struct etherhdr *) nb->data; + while (1) + { + get_card_packet (nb); + eth = (struct etherhdr *) nb->data; + type = eth->type; + grub_netbuff_pull(nb,sizeof (*eth)); + // grub_printf("ethernet type 58 %x\n",type); + // grub_printf("ethernet eth->type 58 %x\n",type); + if (eth->type <=1500) + { + llch = (struct llchdr *) nb->data; + type = llch->dsap & LLCADDRMASK; + + if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) + { + grub_netbuff_pull (nb,sizeof(*llch)); + snaph = (struct snaphdr *) nb->data; + type = snaph->type; + } + } + /*change for grub_memcmp*/ - if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && - eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && eth->type == 0x800) - { - //grub_printf("ethernet eth->dst %x:%x:%x:%x:%x:%x\n",eth->dst[0], - // eth->dst[1],eth->dst[2],eth->dst[3],eth->dst[4],eth->dst[5]); - // grub_printf("ethernet eth->src %x:%x:%x:%x:%x:%x\n",eth->src[0],eth->src[1], - // eth->src[2],eth->src[3],eth->src[4],eth->src[5]); - //grub_printf("ethernet eth->type 0x%x\n",eth->type); - //grub_printf("out from ethernet\n"); - grub_netbuff_pull(nb,sizeof(*eth)); + //if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && + // eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && type == 0x800) + if(type == 0x800) return 0; - } - current_time = grub_get_time_ms(); + + current_time = grub_get_time_ms (); if (current_time - start_time > TIMEOUT_TIME_MS) return grub_error (GRUB_ERR_TIMEOUT, "Time out."); } From 10830203a09d8afdb8f10ab322042bbcdecece16 Mon Sep 17 00:00:00 2001 From: Paulo de Rezende Pinatti Date: Fri, 13 Aug 2010 14:42:16 -0300 Subject: [PATCH 019/673] Added ARP protocol to network stack and fixed bug in grub_netbuff_alloc function. * include/grub/net/arp.h: added arp header, arp cache entry and related constants and functions * net/arp.c: added functions arp_init_table, arp_find_entry, arp_resolve and arp_receive * net/ethernet.c (send_ethernet_packet): replaced hardcoded hardware address by parameter target_addr * net/ethernet.c (recv_ethernet_packet): added call to arp_receive when packet is of type 0x803 (ARP) and only return when packet is of type determined by parameter ethertype * net/ip.c (send_ip_packet): added call to arp_resolve to determine hardware address of destination * net/netbuff.c (grub_netbuff_alloc): fixed swapped parameters in call to grub_memalign --- fs/ieee1275/ofnet.c | 48 +++++--- include/grub/net/arp.h | 49 +++++++-- include/grub/net/interface.h | 2 +- include/grub/net/ip.h | 1 + include/grub/net/protocol.h | 10 +- net/arp.c | 207 +++++++++++++++++++++++++++++++++++ net/ethernet.c | 38 ++++--- net/interface.c | 1 - net/ip.c | 27 ++++- net/netbuff.c | 2 +- net/tftp.c | 4 +- normal/misc.c | 2 +- 12 files changed, 335 insertions(+), 56 deletions(-) diff --git a/fs/ieee1275/ofnet.c b/fs/ieee1275/ofnet.c index 82b5235cc..cf7eeb5b2 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/ieee1275/ofnet.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -95,7 +96,7 @@ retrieve_field(const char *src, char **field, const char **rest) static grub_err_t parse_ip (const char *val, grub_uint32_t *ip, const char **rest) { - grub_uint32_t newip = 0; + grub_uint8_t *p = (grub_uint8_t *) ip; unsigned long t; int i; const char *ptr = val; @@ -107,8 +108,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) return grub_errno; if (t & ~0xff) return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - newip >>= 8; - newip |= (t << 24); + p[i] = (grub_uint8_t) t; if (i != 3 && *ptr != '.') return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); ptr++; @@ -116,7 +116,6 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) ptr = ptr - 1; if ( *ptr != '\0' && *ptr != ',') return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - *ip = newip; if (rest) *rest = ptr; return 0; @@ -305,12 +304,33 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) char *datap; int amount = 0; grub_addr_t found_addr; + grub_netdisk_data_t netdisk_data = (grub_netdisk_data_t) file->device->disk->data; + // TODO: replace getting IP and MAC from bootp by routing functions + struct grub_net_network_layer_interface net_interface; + struct grub_net_card net_card; + struct grub_net_addr ila, lla; + ila.addr = (grub_uint8_t *) &(bootp_pckt->yiaddr); + ila.len = 4; + lla.addr = (grub_uint8_t *) &(bootp_pckt->chaddr); + lla.len = 6; + net_card.ila = &ila; + net_card.lla = &lla; + net_interface.card = &net_card; + // END TODO + + if(! netdisk_data) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing"); + + if(netdisk_data->protocol == GRUB_NETDISK_PROTOCOL_TFTP) + stack = grub_net_protocol_stack_get ("tftp"); + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid protocol specified"); - stack = grub_net_protocol_stack_get ("tftp"); app_interface = (struct grub_net_application_transport_interface *) stack->interface; - pack = grub_netbuff_alloc (80*1024); - grub_netbuff_reserve (pack,80*1024); - file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name); + app_interface->inner_layer->data = (void *) &(netdisk_data->server_ip); + pack = grub_netbuff_alloc (2048); + grub_netbuff_reserve (pack,2048); + file_size = app_interface->app_prot->get_file_size(&net_interface,stack,pack,(char *) name); for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) { @@ -320,16 +340,16 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) file->data = (void *) found_addr; grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,80*1024); - app_interface->app_prot->open (NULL,stack,pack,(char *) name); + grub_netbuff_reserve (pack,2048); + app_interface->app_prot->open (&net_interface,stack,pack,(char *) name); if (grub_errno != GRUB_ERR_NONE) goto error; do { grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,80*1024); - app_interface->app_prot->recv (NULL,stack,pack); + grub_netbuff_reserve (pack,2048); + app_interface->app_prot->recv (&net_interface,stack,pack); if (grub_errno != GRUB_ERR_NONE) goto error; if ((pack->tail - pack->data)) @@ -340,8 +360,8 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) grub_memcpy(datap , pack->data, pack->tail - pack->data); } grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,80*1024); - app_interface->app_prot->send_ack (NULL,stack,pack); + grub_netbuff_reserve (pack,2048); + app_interface->app_prot->send_ack (&net_interface,stack,pack); if (grub_errno != GRUB_ERR_NONE) goto error; diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 86ae2deea..75260aeb3 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -1,17 +1,42 @@ #ifndef GRUB_NET_ARP_HEADER #define GRUB_NET_ARP_HEADER 1 +#include +#include +#include -#include -struct arphdr{ - grub_int16_t hwtype; /* hardware type (must be ARPHRD_ETHER) */ - grub_int16_t protocol; /* protocol type (must be ETH_P_IP) */ - grub_int8_t hwlen; /* hardware address length (must be 6) */ - grub_int8_t protolen; /* protocol address length (must be 4) */ - grub_uint16_t opcode; /* ARP opcode */ - grub_uint8_t shwaddr[6]; /* sender's hardware address */ - grub_uint32_t sipaddr; /* sender's IP address */ - grub_uint8_t thwaddr[6]; /* target's hardware address */ - grub_uint32_t tipaddr; /* target's IP address */ -}__attribute__ ((packed)); +/* IANA ARP constant to define hardware type as ethernet */ +#define ARPHRD_ETHERNET 1 +/* IANA Ethertype */ +#define ARP_ETHERTYPE 0x806 + +/* Size for cache table */ +#define SIZE_ARP_TABLE 5 + +/* ARP header operation codes */ +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +struct arp_entry { + grub_uint8_t avail; + struct grub_net_network_layer_protocol *nl_protocol; + struct grub_net_link_layer_protocol *ll_protocol; + struct grub_net_addr nl_address; + struct grub_net_addr ll_address; +}; + +struct arphdr { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; +} __attribute__ ((packed)); + +extern grub_err_t arp_receive(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + +extern grub_err_t arp_resolve(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_addr *proto_addr, +struct grub_net_addr *hw_addr); #endif diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h index 4d100fd75..cf24dd22e 100644 --- a/include/grub/net/interface.h +++ b/include/grub/net/interface.h @@ -37,7 +37,7 @@ struct grub_net_network_link_interface }; -extern struct grub_net_protocol_stack *grub_net_protocol_stacks; +struct grub_net_protocol_stack *grub_net_protocol_stacks; static inline void grub_net_stack_register (struct grub_net_protocol_stack *stack) { diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index cb119ac6f..5baacd439 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -2,6 +2,7 @@ #define GRUB_NET_IP_HEADER 1 #include +#define IP_ETHERTYPE 0x800 /* IANA Ethertype */ struct iphdr { grub_uint8_t verhdrlen; diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index b7a3e5d3b..ffc3dd719 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -8,7 +8,7 @@ struct grub_net_protocol; struct grub_net_protocol_stack; struct grub_net_network_layer_interface; - +struct grub_net_addr; typedef enum grub_network_layer_protocol_id { @@ -57,6 +57,7 @@ struct grub_net_network_layer_protocol struct grub_net_network_layer_protocol *next; char *name; grub_net_protocol_id_t id; + grub_uint16_t type; /* IANA Ethertype */ //grub_network_layer_protocol_id_t id; grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr); char * (*aton) (union grub_net_network_layer_address addr); @@ -76,11 +77,14 @@ struct grub_net_link_layer_protocol struct grub_net_link_layer_protocol *next; char *name; + grub_uint16_t type; /* ARP hardware type */ grub_net_protocol_id_t id; grub_err_t (*send) (struct grub_net_network_layer_interface *inf , - struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb, + struct grub_net_addr target_addr, grub_uint16_t ethertype); grub_err_t (*recv) (struct grub_net_network_layer_interface *inf , - struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb); + struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb, + grub_uint16_t ethertype); }; extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols; diff --git a/net/arp.c b/net/arp.c index e69de29bb..c02ea011d 100644 --- a/net/arp.c +++ b/net/arp.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct arp_entry arp_table[SIZE_ARP_TABLE]; +static grub_int8_t new_table_entry = -1; + +static void arp_init_table(void) +{ + struct arp_entry *entry = &(arp_table[0]); + for(;entry<=&(arp_table[SIZE_ARP_TABLE-1]);entry++) + { + entry->avail = 0; + entry->nl_protocol = NULL; + entry->ll_protocol = NULL; + entry->nl_address.addr = NULL; + entry->nl_address.len = 0; + entry->ll_address.addr = NULL; + entry->ll_address.len = 0; + } + new_table_entry = 0; +} + +static struct arp_entry * +arp_find_entry(struct grub_net_network_link_interface *net_link_inf, const void *proto_address, grub_uint8_t address_len) +{ + grub_uint8_t i; + for(i=0;i < SIZE_ARP_TABLE; i++) + { + if(arp_table[i].avail == 1 && + arp_table[i].nl_protocol->type == net_link_inf->net_prot->type && + arp_table[i].ll_protocol->type == net_link_inf->link_prot->type && + (!grub_memcmp(arp_table[i].nl_address.addr, proto_address, address_len))) + return &(arp_table[i]); + } + return NULL; +} + +grub_err_t arp_resolve(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_addr *proto_addr, +struct grub_net_addr *hw_addr) +{ + struct arp_entry *entry; + struct grub_net_buff *nb; + struct arphdr *arp_header; + struct grub_net_addr target_hw_addr; + grub_uint8_t *aux, i; + + /* Check cache table */ + entry = arp_find_entry(net_link_inf, proto_addr->addr, proto_addr->len); + if (entry) + { + hw_addr->addr = grub_malloc(entry->ll_address.len); + if (! hw_addr->addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(hw_addr->addr, entry->ll_address.addr, entry->ll_address.len); + hw_addr->len = entry->ll_address.len; + return GRUB_ERR_NONE; + } + /* Build a request packet */ + nb = grub_netbuff_alloc (2048); + grub_netbuff_reserve(nb, 2048); + grub_netbuff_push(nb, sizeof(*arp_header) + 2*(inf->card->lla->len + inf->card->ila->len)); + arp_header = (struct arphdr *)nb->data; + arp_header->hrd = net_link_inf->link_prot->type; + arp_header->pro = net_link_inf->net_prot->type; + arp_header->hln = inf->card->lla->len; + arp_header->pln = inf->card->ila->len; + arp_header->op = ARP_REQUEST; + aux = (grub_uint8_t *)arp_header + sizeof(*arp_header); + /* Sender hardware address */ + grub_memcpy(aux, inf->card->lla->addr, inf->card->lla->len); + aux += inf->card->lla->len; + /* Sender protocol address */ + grub_memcpy(aux, inf->card->ila->addr, inf->card->ila->len); + aux += inf->card->ila->len; + /* Target hardware address */ + for(i=0; i < inf->card->lla->len; i++) + aux[i] = 0x00; + aux += inf->card->lla->len; + /* Target protocol address */ + grub_memcpy(aux, proto_addr->addr, inf->card->ila->len); + + target_hw_addr.addr = grub_malloc(inf->card->lla->len); + target_hw_addr.len = inf->card->lla->len; + for(i=0; i < target_hw_addr.len; i++) + (target_hw_addr.addr)[i] = 0xFF; + net_link_inf->link_prot->send(inf, net_link_inf, nb, target_hw_addr, ARP_ETHERTYPE); + grub_free(target_hw_addr.addr); + grub_netbuff_clear(nb); + grub_netbuff_reserve(nb, 2048); + + grub_uint64_t start_time, current_time; + start_time = grub_get_time_ms(); + do + { + net_link_inf->link_prot->recv(inf, net_link_inf, nb, ARP_ETHERTYPE); + /* Now check cache table again */ + entry = arp_find_entry(net_link_inf, proto_addr->addr, proto_addr->len); + if (entry) + { + hw_addr->addr = grub_malloc(entry->ll_address.len); + if (! hw_addr->addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(hw_addr->addr, entry->ll_address.addr, entry->ll_address.len); + hw_addr->len = entry->ll_address.len; + grub_netbuff_clear(nb); + return GRUB_ERR_NONE; + } + current_time = grub_get_time_ms(); + if (current_time - start_time > TIMEOUT_TIME_MS) + break; + } while (! entry); + grub_netbuff_clear(nb); + return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address."); +} + +grub_err_t arp_receive(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), +struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb) +{ + struct arphdr *arp_header = (struct arphdr *)nb->data; + struct arp_entry *entry; + grub_uint8_t merge = 0; + + /* Verify hardware type, protocol type, hardware address length, protocol address length */ + if (arp_header->hrd != net_link_inf->link_prot->type || arp_header->pro != net_link_inf->net_prot->type || + arp_header->hln != inf->card->lla->len || arp_header->pln != inf->card->ila->len) + return GRUB_ERR_NONE; + + grub_uint8_t *sender_hardware_address, *sender_protocol_address, *target_hardware_address, *target_protocol_address; + sender_hardware_address = (grub_uint8_t *)arp_header + sizeof(*arp_header); + sender_protocol_address = sender_hardware_address + arp_header->hln; + target_hardware_address = sender_protocol_address + arp_header->pln; + target_protocol_address = target_hardware_address + arp_header->hln; + /* Check if the sender is in the cache table */ + entry = arp_find_entry(net_link_inf, sender_protocol_address, arp_header->pln); + /* Update sender hardware address */ + if (entry) + { + if (entry->ll_address.addr) + grub_free(entry->ll_address.addr); + entry->ll_address.addr = grub_malloc(arp_header->hln); + if (! entry->ll_address.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(entry->ll_address.addr, sender_hardware_address, arp_header->hln); + entry->ll_address.len = arp_header->hln; + merge = 1; + } + /* Am I the protocol address target? */ + if (! grub_memcmp(target_protocol_address, inf->card->ila->addr, arp_header->pln)) + { + /* Add sender to cache table */ + if (! merge) + { + if (new_table_entry == -1) + arp_init_table(); + entry = &(arp_table[new_table_entry]); + entry->avail = 1; + entry->ll_protocol = net_link_inf->link_prot; + entry->nl_protocol = net_link_inf->net_prot; + if (entry->nl_address.addr) + grub_free(entry->nl_address.addr); + entry->nl_address.addr = grub_malloc(arp_header->pln); + if (! entry->nl_address.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(entry->nl_address.addr, sender_protocol_address, arp_header->pln); + entry->nl_address.len = arp_header->pln; + if (entry->ll_address.addr) + grub_free(entry->ll_address.addr); + entry->ll_address.addr = grub_malloc(arp_header->hln); + if (! entry->ll_address.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(entry->ll_address.addr, sender_hardware_address, arp_header->hln); + entry->ll_address.len = arp_header->hln; + new_table_entry++; + if (new_table_entry == SIZE_ARP_TABLE) + new_table_entry = 0; + } + if (arp_header->op == ARP_REQUEST) + { + struct grub_net_addr aux; + /* Swap hardware fields */ + grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); + grub_memcpy(sender_hardware_address, inf->card->lla->addr, arp_header->hln); + /* Swap protocol fields */ + aux.addr = grub_malloc(arp_header->pln); + if (! aux.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(aux.addr, sender_protocol_address, arp_header->pln); + grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); + grub_memcpy(target_protocol_address, aux.addr, arp_header->pln); + grub_free(aux.addr); + /* Change operation to REPLY and send packet */ + arp_header->op = ARP_REPLY; + aux.addr = target_hardware_address; + aux.len = arp_header->hln; + net_link_inf->link_prot->send(inf, net_link_inf, nb, aux, ARP_ETHERTYPE); + } + } + return GRUB_ERR_NONE; +} diff --git a/net/ethernet.c b/net/ethernet.c index ab5992133..14bc41c5b 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -8,24 +8,21 @@ #include #include #include +#include static grub_err_t send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), - struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) +struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb, +struct grub_net_addr target_addr, grub_uint16_t ethertype) { struct etherhdr *eth; grub_netbuff_push (nb,sizeof(*eth)); eth = (struct etherhdr *) nb->data; - eth->dst[0] = 0x00; - eth->dst[1] = 0x11; - eth->dst[2] = 0x25; - eth->dst[3] = 0xca; - eth->dst[4] = 0x1f; - eth->dst[5] = 0x01; - grub_memcpy (eth->src, bootp_pckt -> chaddr,6); - eth->type = 0x0800; + grub_memcpy(eth->dst, target_addr.addr, target_addr.len); + grub_memcpy(eth->src, bootp_pckt->chaddr, 6); + eth->type = ethertype; return send_card_buffer(nb); // return inf->card->driver->send(inf->card,nb); @@ -34,7 +31,8 @@ send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ static grub_err_t recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)), - struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb) +struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb, +grub_uint16_t ethertype) { struct etherhdr *eth; grub_uint64_t start_time, current_time; @@ -63,12 +61,17 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ } } - /*change for grub_memcmp*/ - //if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 && - // eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && type == 0x800) - if(type == 0x800) - return 0; - + /* ARP packet */ + if (type == ARP_ETHERTYPE) + { + arp_receive(inf, net_link_inf, nb); + if (ethertype == ARP_ETHERTYPE) + return GRUB_ERR_NONE; + } + /* IP packet */ + else if(type == IP_ETHERTYPE && ethertype == IP_ETHERTYPE) + return GRUB_ERR_NONE; + current_time = grub_get_time_ms (); if (current_time - start_time > TIMEOUT_TIME_MS) return grub_error (GRUB_ERR_TIMEOUT, "Time out."); @@ -77,7 +80,7 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ - verify if the next layer is the desired one. - if not. get another packet. - remove ethernet header from buffer*/ - return 0; + return GRUB_ERR_NONE; } @@ -85,6 +88,7 @@ static struct grub_net_link_layer_protocol grub_ethernet_protocol = { .name = "ethernet", .id = GRUB_NET_ETHERNET_ID, + .type = ARPHRD_ETHERNET, .send = send_ethernet_packet, .recv = recv_ethernet_packet }; diff --git a/net/interface.c b/net/interface.c index bacabf4cb..f17b3e66b 100644 --- a/net/interface.c +++ b/net/interface.c @@ -22,7 +22,6 @@ INTERFACE_REGISTER_FUNCTIONS("link");*/ #include #include -struct grub_net_protocol_stack *grub_net_protocol_stacks; struct grub_net_protocol_stack *grub_net_protocol_stack_get (char *name) { diff --git a/net/ip.c b/net/ip.c index 65b0f2b70..142f33e70 100644 --- a/net/ip.c +++ b/net/ip.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,8 @@ send_ip_packet (struct grub_net_network_layer_interface *inf, struct iphdr *iph; static int id = 0x2400; + struct grub_net_addr nl_target_addr, ll_target_addr; + grub_err_t rc; grub_netbuff_push(nb,sizeof(*iph)); iph = (struct iphdr *) nb->data; @@ -51,12 +54,26 @@ send_ip_packet (struct grub_net_network_layer_interface *inf, iph->ttl = 0xff; iph->protocol = 0x11; iph->src = (grub_uint32_t) bootp_pckt -> yiaddr; //inf->address.ipv4; // *((grub_uint32_t *)inf->card->ila->addr); - iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr); + // iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr); + iph->dest = *((grub_uint32_t *) (trans_net_inf->data)); iph->chksum = 0 ; iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - return trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb); + /* Determine link layer target address via ARP */ + nl_target_addr.len = sizeof(iph->dest); + nl_target_addr.addr = grub_malloc(nl_target_addr.len); + if (! nl_target_addr.addr) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory"); + grub_memcpy(nl_target_addr.addr, &(iph->dest), nl_target_addr.len); + rc = arp_resolve(inf, trans_net_inf->inner_layer, &nl_target_addr, &ll_target_addr); + grub_free(nl_target_addr.addr); + if (rc != GRUB_ERR_NONE) + return rc; + + rc = trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb,ll_target_addr, IP_ETHERTYPE); + grub_free(ll_target_addr.addr); + return rc; //return protstack->next->prot->send(inf,protstack->next,nb); } @@ -70,11 +87,12 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, start_time = grub_get_time_ms(); while (1) { - trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb); + trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb,IP_ETHERTYPE); iph = (struct iphdr *) nb->data; if (iph->protocol == 0x11 && iph->dest == (grub_uint32_t) bootp_pckt -> yiaddr && - iph->src == (grub_uint32_t) bootp_pckt -> siaddr ) + //iph->src == (grub_uint32_t) bootp_pckt -> siaddr ) + iph->src == *((grub_uint32_t *) (trans_net_inf->data)) ) { grub_netbuff_pull(nb,sizeof(*iph)); return 0; @@ -99,6 +117,7 @@ static struct grub_net_network_layer_protocol grub_ipv4_protocol = { .name = "ipv4", .id = GRUB_NET_IPV4_ID, + .type = IP_ETHERTYPE, .send = send_ip_packet, .recv = recv_ip_packet }; diff --git a/net/netbuff.c b/net/netbuff.c index ce52233b6..4f6a1da84 100644 --- a/net/netbuff.c +++ b/net/netbuff.c @@ -72,7 +72,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) len = NETBUFFMINLEN; len = ALIGN_UP (len,NETBUFF_ALIGN); - data = grub_memalign (len + sizeof (*nb),NETBUFF_ALIGN); + data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); nb = (struct grub_net_buff *) ((int)data + len); nb->head = nb->data = nb->tail = data; nb->end = (char *) nb; diff --git a/net/tftp.c b/net/tftp.c index 0fb43105d..2aeae38e9 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -113,7 +113,7 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)), app_interface->trans_prot->send (inf,protstack->interface,nb); /*Receive OACK*/ grub_netbuff_clear (nb); - grub_netbuff_reserve (nb,80*1024); + grub_netbuff_reserve (nb,2048); return app_interface->app_prot->recv(inf,protstack,nb); } @@ -215,7 +215,7 @@ static int tftp_file_size (struct grub_net_network_layer_interface* inf , tftp_open (inf, protocol_stack,nb, filename); grub_netbuff_clear (nb); - grub_netbuff_reserve (nb,80*1024); + grub_netbuff_reserve (nb,2048); tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0); return tftp_file.size; diff --git a/normal/misc.c b/normal/misc.c index d53fe711c..30967e174 100644 --- a/normal/misc.c +++ b/normal/misc.c @@ -54,7 +54,7 @@ grub_normal_print_device_info (const char *name) grub_printf_(N_("Protocol: %s"), "Unknown"); grub_putchar ('\n'); grub_putchar ('\t'); - grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip & 0xff, data->server_ip >> 8 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 24 & 0xff); + grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip >> 24 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 8 & 0xff, data->server_ip & 0xff); if (data->username) { grub_putchar ('\n'); From 9a9852df79f459b52d51214ed51863b1828d42b1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 00:07:55 +0200 Subject: [PATCH 020/673] Hook network protocols --- grub-core/Makefile.am | 1 + grub-core/commands/net.c | 33 +++++++++++++++++++++++++++++++++ grub-core/kern/device.c | 23 ++++++++++++++++------- grub-core/kern/fs.c | 2 +- include/grub/device.h | 7 +------ include/grub/net.h | 37 +++++++++++++++++++++++++++++++++++-- 6 files changed, 87 insertions(+), 16 deletions(-) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5d13d0313..1fcc3d00d 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -74,6 +74,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h if COND_i386_pc KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 288ba4c2a..904c61a92 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -269,6 +269,37 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +grub_net_app_level_t grub_net_app_level_list; + +static grub_net_t +grub_net_open_real (const char *name) +{ + const char *comma = grub_strchr (name, ','); + grub_net_app_level_t proto; + + if (!comma) + comma = name + grub_strlen (name); + FOR_NET_APP_LEVEL (proto) + { + if (comma - name == (grub_ssize_t) grub_strlen (proto->name) + && grub_memcmp (proto->name, name, comma - name) == 0) + { + grub_net_t ret = grub_malloc (sizeof (*ret)); + if (!ret) + return NULL; + ret->protocol = proto; + ret->name = grub_strdup (name); + if (!ret->name) + { + grub_free (ret); + return NULL; + } + return ret; + } + } + return NULL; +} + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; GRUB_MOD_INIT(net) @@ -285,6 +316,7 @@ GRUB_MOD_INIT(net) cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, "SHORTNAME", N_("Delete a network route.")); + grub_net_open = grub_net_open_real; } GRUB_MOD_FINI(net) @@ -293,4 +325,5 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); grub_unregister_command (cmd_delroute); + grub_net_open = NULL; } diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 4273fedfe..9de545910 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -26,6 +26,8 @@ #include #include +grub_net_t (*grub_net_open) (const char *name) = NULL; + grub_device_t grub_device_open (const char *name) { @@ -46,15 +48,16 @@ grub_device_open (const char *name) if (! dev) goto fail; + dev->net = NULL; /* Try to open a disk. */ - disk = grub_disk_open (name); - if (! disk) - goto fail; + dev->disk = grub_disk_open (name); + if (dev->disk) + return dev; + if (grub_net_open) + dev->net = grub_net_open (name); - dev->disk = disk; - dev->net = 0; /* FIXME */ - - return dev; + if (dev->net) + return dev; fail: if (disk) @@ -71,6 +74,12 @@ grub_device_close (grub_device_t device) if (device->disk) grub_disk_close (device->disk); + if (device->net) + { + grub_free (device->net->name); + grub_free (device->net); + } + grub_free (device); return grub_errno; diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index 8ffb93c8b..c4d6efa96 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -95,7 +95,7 @@ grub_fs_probe (grub_device_t device) } } else if (device->net) - return device->net->fs; + return device->net->protocol; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); return 0; diff --git a/include/grub/device.h b/include/grub/device.h index d68c26e66..f3e43bf60 100644 --- a/include/grub/device.h +++ b/include/grub/device.h @@ -24,12 +24,7 @@ #include struct grub_disk; -struct grub_fs; -struct grub_net -{ - char *name; - struct grub_fs *fs; -}; +struct grub_net; struct grub_device { diff --git a/include/grub/net.h b/include/grub/net.h index 4ca873f74..b5e852f9b 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -22,6 +22,17 @@ #include #include #include +#include + +typedef struct grub_fs *grub_net_app_level_t; + +typedef struct grub_net +{ + char *name; + grub_net_app_level_t protocol; +} *grub_net_t; + +extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); struct grub_net_card; @@ -46,7 +57,7 @@ struct grub_net_network_level_interface; typedef union grub_net_network_level_address { grub_uint32_t ipv4; -} grub_net_network_level_netaddress_t; +} grub_net_network_level_address_t; typedef union grub_net_network_level_netaddress { @@ -54,7 +65,7 @@ typedef union grub_net_network_level_netaddress grub_uint32_t base; int masksize; } ipv4; -} grub_net_network_level_address_t; +} grub_net_network_level_netaddress_t; typedef enum grub_network_level_protocol_id { @@ -163,6 +174,28 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +extern grub_net_app_level_t grub_net_app_level_list; + +#ifndef GRUB_LST_GENERATOR +static inline void +grub_net_app_level_register (grub_net_app_level_t proto) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_app_level_list), + GRUB_AS_LIST (proto)); +} +#endif + +static inline void +grub_net_app_level_unregister (grub_net_app_level_t proto) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_app_level_list), + GRUB_AS_LIST (proto)); +} + +#define FOR_NET_APP_LEVEL(var) FOR_LIST_ELEMENTS((var), \ + (grub_net_app_level_list)) + + extern struct grub_net_route *grub_net_routes; static inline void From 03b170647d564e2211bb9f3745b18d67eb0c4158 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 17:18:02 +0200 Subject: [PATCH 021/673] Restructure pxe --- Makefile.util.def | 1 + grub-core/commands/ls.c | 13 ++ grub-core/commands/net.c | 361 +++++++++++++++++++++++++++---------- grub-core/fs/i386/pc/pxe.c | 268 +++++++++++++-------------- include/grub/net.h | 131 +++----------- 5 files changed, 433 insertions(+), 341 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 35bcd81b2..fe6894306 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -30,6 +30,7 @@ library = { common = grub-core/commands/blocklist.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; + common = grub-core/commands/net.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/host.c; common = grub-core/disk/loopback.c; diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 9ee0a7a31..3179d271e 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -31,6 +31,7 @@ #include #include #include +#include static const struct grub_arg_option options[] = { @@ -45,6 +46,8 @@ static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; static grub_err_t grub_ls_list_devices (int longlist) { + grub_net_app_level_t proto; + auto int grub_ls_print_devices (const char *name); int grub_ls_print_devices (const char *name) { @@ -58,6 +61,16 @@ grub_ls_list_devices (int longlist) grub_device_iterate (grub_ls_print_devices); grub_xputs ("\n"); + + grub_puts_ (N_ ("Network protocols:\n")); + + FOR_NET_APP_LEVEL (proto) + { + grub_printf ("%s ", proto->name); + } + + grub_xputs ("\n"); + grub_refresh (); return 0; diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 904c61a92..2062e1bd0 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -22,30 +22,135 @@ #include #include +struct grub_net_route +{ + struct grub_net_route *next; + grub_net_network_level_netaddress_t target; + char *name; + struct grub_net_network_level_protocol *prot; + int is_gateway; + union + { + struct grub_net_network_level_interface *interface; + grub_net_network_level_address_t gw; + }; +}; + struct grub_net_route *grub_net_routes = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; -grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, - char *name, - grub_net_network_level_address_t *addr) +static inline void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) { - FOR_NET_NETWORK_LEVEL_PROTOCOLS (*prot) + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + +static inline void +grub_net_route_register (struct grub_net_route *route) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +static inline void +grub_net_route_unregister (struct grub_net_route *route) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), + GRUB_AS_LIST (route)); +} + +#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) + +static int +parse_ip (const char *val, grub_uint32_t *ip, const char **rest) +{ + grub_uint32_t newip = 0; + unsigned long t; + int i; + const char *ptr = val; + + for (i = 0; i < 4; i++) { - grub_err_t err; - err = grub_net_resolve_address_in_protocol (*prot, name, addr); - if (err == GRUB_ERR_NET_BAD_ADDRESS) + t = grub_strtoul (ptr, (char **) &ptr, 0); + if (grub_errno) { grub_errno = GRUB_ERR_NONE; - continue; + return 0; } - if (err) - return err; + if (t & ~0xff) + return 0; + newip >>= 8; + newip |= (t << 24); + if (i != 3 && *ptr != '.') + return 0; + ptr++; + } + *ip = newip; + if (rest) + *rest = ptr - 1; + return 0; +} + +static int +match_net (const grub_net_network_level_netaddress_t *net, + const grub_net_network_level_address_t *addr) +{ + if (net->type != addr->type) + return 0; + switch (net->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + { + grub_int32_t mask = (1 << net->ipv4.masksize) - 1; + return ((net->ipv4.base & mask) == (addr->ipv4 & mask)); + } + } + return 0; +} + +grub_err_t +grub_net_resolve_address (const char *name, + grub_net_network_level_address_t *addr) +{ + if (parse_ip (name, &addr->ipv4, NULL)) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("Unrecognised address %s"), + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), + name); +} + +grub_err_t +grub_net_resolve_net_address (const char *name, + grub_net_network_level_netaddress_t *addr) +{ + const char *rest; + if (parse_ip (name, &addr->ipv4.base, &rest)) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + if (*rest == '/') + { + addr->ipv4.masksize = grub_strtoul (rest + 1, NULL, 0); + if (!grub_errno) + return GRUB_ERR_NONE; + } + addr->ipv4.masksize = 32; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), name); } @@ -71,8 +176,7 @@ grub_net_route_address (grub_net_network_level_address_t addr, { if (depth && prot != route->prot) continue; - prot = route->prot; - if (!route->prot->match_net (route->target, curtarget)) + if (!match_net (&route->target, &curtarget)) continue; if (route->is_gateway) @@ -107,7 +211,6 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); - inter->protocol->fini (inter); grub_net_network_level_interface_unregister (inter); grub_free (inter->name); grub_free (inter); @@ -115,18 +218,35 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +struct grub_net_network_level_interface * +grub_net_add_addr (const char *name, struct grub_net_card *card, + grub_net_network_level_address_t addr) +{ + struct grub_net_network_level_interface *inter; + + inter = grub_zalloc (sizeof (*inter)); + if (!inter) + return NULL; + + inter->name = grub_strdup (name); + grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + inter->card = card; + + grub_net_network_level_interface_register (inter); + + return inter; +} + static grub_err_t grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { struct grub_net_card *card; - struct grub_net_network_level_protocol *prot; - grub_err_t err; grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inter; + grub_err_t err; - if (argc != 4) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); + if (argc != 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); FOR_NET_CARDS (card) if (grub_strcmp (card->name, args[1])) @@ -134,36 +254,12 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), if (card == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); - FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) - if (grub_strcmp (prot->name, args[2])) - break; - - if (card == NULL) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); - - err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); + err = grub_net_resolve_address (args[2], &addr); if (err) return err; - inter = grub_zalloc (sizeof (*inter)); - if (!inter) - return grub_errno; - - inter->name = grub_strdup (args[0]); - inter->protocol = prot; - grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); - inter->card = card; - - err = prot->init (inter); - if (err) - { - grub_free (inter->name); - grub_free (inter); - return err; - } - grub_net_network_level_interface_register (inter); - - return GRUB_ERR_NONE; + grub_net_add_addr (args[0], card, addr); + return grub_errno; } static grub_err_t @@ -188,84 +284,157 @@ grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } -static grub_err_t -grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) +grub_err_t +grub_net_add_route (const char *name, + grub_net_network_level_netaddress_t target, + struct grub_net_network_level_interface *inter) { - struct grub_net_network_level_protocol *prot; struct grub_net_route *route; - if (argc < 3) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("At least 3 arguments are expected")); - route = grub_zalloc (sizeof (*route)); if (!route) return grub_errno; - route->name = grub_strdup (args[0]); + route->name = grub_strdup (name); if (!route->name) { grub_free (route); return grub_errno; } - FOR_NET_NETWORK_LEVEL_PROTOCOLS(prot) - { - grub_err_t err; - err = prot->net_ntoa (args[1], &(route->target)); - if (err == GRUB_ERR_NET_BAD_ADDRESS) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - if (err) - return err; - break; - } - - if (!prot) + route->target = target; + route->is_gateway = 0; + route->interface = inter; + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_net_add_route_gw (const char *name, + grub_net_network_level_netaddress_t target, + grub_net_network_level_address_t gw) +{ + struct grub_net_route *route; + + route = grub_zalloc (sizeof (*route)); + if (!route) + return grub_errno; + + route->name = grub_strdup (name); + if (!route->name) { - grub_free (route->name); grub_free (route); - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, - N_("Unrecognised address %s"), args[1]); + return grub_errno; } + route->target = target; + route->is_gateway = 1; + route->gw = gw; + + grub_net_route_register (route); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_net_network_level_netaddress_t target; + if (argc < 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("At least 3 arguments are expected")); + + grub_net_resolve_net_address (args[1], &target); + if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) { grub_err_t err; - route->is_gateway = 1; - err = grub_net_resolve_address_in_protocol (prot, - args[3], &(route->gw)); + grub_net_network_level_address_t gw; + + err = grub_net_resolve_address (args[3], &gw); if (err) - { - grub_free (route->name); - grub_free (route); - return err; - } + return err; + return grub_net_add_route_gw (args[0], target, gw); } else { struct grub_net_network_level_interface *inter; - route->is_gateway = 0; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) if (grub_strcmp (inter->name, args[2])) break; if (!inter) - { - grub_free (route->name); - grub_free (route); - return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("Unrecognised interface %s"), args[2]); - } - route->interface = inter; + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unrecognised interface %s"), args[2]); + return grub_net_add_route (args[0], target, inter); } +} - grub_net_route_register (route); +static void +print_net_address (const grub_net_network_level_netaddress_t *target) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + grub_printf ("%d.%d.%d.%d/%d ", ((target->ipv4.base >> 24) & 0xff), + ((target->ipv4.base >> 16) & 0xff), + ((target->ipv4.base >> 8) & 0xff), + ((target->ipv4.base >> 0) & 0xff), + target->ipv4.masksize); + break; + } +} +static void +print_address (const grub_net_network_level_address_t *target) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + grub_printf ("%d.%d.%d.%d ", ((target->ipv4 >> 24) & 0xff), + ((target->ipv4 >> 16) & 0xff), + ((target->ipv4 >> 8) & 0xff), + ((target->ipv4 >> 0) & 0xff)); + break; + } +} + +static grub_err_t +grub_cmd_listroutes (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_net_route *route; + FOR_NET_ROUTES(route) + { + grub_printf ("%s ", route->name); + print_net_address (&route->target); + if (route->is_gateway) + { + grub_printf ("gw "); + print_address (&route->gw); + } + else + grub_printf ("%s", route->interface->name); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_net_card *card; + FOR_NET_CARDS(card) + { + grub_printf ("%s ", card->name); + } + grub_printf ("\n"); return GRUB_ERR_NONE; } @@ -301,11 +470,12 @@ grub_net_open_real (const char *name) } static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; +static grub_command_t cmd_lsroutes, cmd_lscards; GRUB_MOD_INIT(net) { cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, - "SHORTNAME CARD PROTOCOL ADDRESS", + "SHORTNAME CARD ADDRESS", N_("Add a network address.")); cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, "SHORTNAME", @@ -316,6 +486,11 @@ GRUB_MOD_INIT(net) cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, "SHORTNAME", N_("Delete a network route.")); + cmd_lsroutes = grub_register_command ("net_ls_routes", grub_cmd_listroutes, + "", N_("list network routes")); + cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards, + "", N_("list network cards")); + grub_net_open = grub_net_open_real; } @@ -325,5 +500,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); grub_unregister_command (cmd_delroute); + grub_unregister_command (cmd_lsroutes); + grub_unregister_command (cmd_lscards); grub_net_open = NULL; } diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 0dd44a30a..20d0e1979 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -18,9 +18,8 @@ */ #include -#include +#include #include -#include #include #include #include @@ -33,13 +32,7 @@ #define SEGMENT(x) ((x) >> 4) #define OFFSET(x) ((x) & 0xF) #define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) -#define LINEAR(x) (void *) (((x >> 16) <<4) + (x & 0xFFFF)) - -struct grub_pxe_disk_data -{ - grub_uint32_t server_ip; - grub_uint32_t gateway_ip; -}; +#define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF)) struct grub_pxenv *grub_pxe_pxenv; static grub_uint32_t grub_pxe_your_ip; @@ -53,6 +46,8 @@ struct grub_pxe_data { grub_uint32_t packet_number; grub_uint32_t block_size; + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; char filename[0]; }; @@ -95,55 +90,33 @@ grub_pxe_scan (void) return ret; } -static int -grub_pxe_iterate (int (*hook) (const char *name)) +static grub_err_t +grub_pxefs_dir (grub_device_t device __attribute__ ((unused)), + const char *path __attribute__ ((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) + __attribute__ ((unused))) { - if (hook ("pxe")) - return 1; - return 0; + return GRUB_ERR_NONE; } static grub_err_t -parse_ip (const char *val, grub_uint32_t *ip, const char **rest) +grub_pxefs_open (struct grub_file *file, const char *name) { - grub_uint32_t newip = 0; - unsigned long t; - int i; - const char *ptr = val; - - for (i = 0; i < 4; i++) + union { - t = grub_strtoul (ptr, (char **) &ptr, 0); - if (grub_errno) - return grub_errno; - if (t & ~0xff) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - newip >>= 8; - newip |= (t << 24); - if (i != 3 && *ptr != '.') - return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); - ptr++; - } - *ip = newip; - if (rest) - *rest = ptr - 1; - return 0; -} - -static grub_err_t -grub_pxe_open (const char *name, grub_disk_t disk) -{ - struct grub_pxe_disk_data *data; - - if (grub_strcmp (name, "pxe") != 0 - && grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) != 0) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a pxe disk"); + struct grub_pxenv_tftp_get_fsize c1; + struct grub_pxenv_tftp_open c2; + } c; + struct grub_pxe_data *data; + grub_file_t file_int, bufio; data = grub_malloc (sizeof (*data)); if (!data) return grub_errno; - if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) +#if 0 + if (grub_strncmp (file->device->net->name, "pxe:", sizeof ("pxe:") - 1) == 0) { const char *ptr; grub_err_t err; @@ -161,93 +134,44 @@ grub_pxe_open (const char *name, grub_disk_t disk) else data->gateway_ip = grub_pxe_default_gateway_ip; } - else + else +#endif { - data->server_ip = grub_pxe_default_server_ip; - data->gateway_ip = grub_pxe_default_gateway_ip; + grub_net_network_level_address_t addr; + grub_net_network_level_address_t gateway; + struct grub_net_network_level_interface *interf; + grub_err_t err; + + if (grub_strncmp (file->device->net->name, + "pxe,", sizeof ("pxe,") - 1) == 0) + { + const char *ptr; + + ptr = name + sizeof ("pxe,") - 1; + err = grub_net_resolve_address (name + sizeof ("pxe,") - 1, &addr); + if (err) + return err; + } + else + { + addr.ipv4 = grub_pxe_default_server_ip; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + } + err = grub_net_route_address (addr, &gateway, &interf); + if (err) + return err; + data->server_ip = addr.ipv4; + data->gateway_ip = gateway.ipv4; } - disk->total_sectors = 0; - disk->id = (unsigned long) data; - - disk->has_partitions = 0; - disk->data = data; - - return GRUB_ERR_NONE; -} - -static void -grub_pxe_close (grub_disk_t disk) -{ - grub_free (disk->data); -} - -static grub_err_t -grub_pxe_read (grub_disk_t disk __attribute((unused)), - grub_disk_addr_t sector __attribute((unused)), - grub_size_t size __attribute((unused)), - char *buf __attribute((unused))) -{ - return GRUB_ERR_OUT_OF_RANGE; -} - -static grub_err_t -grub_pxe_write (grub_disk_t disk __attribute((unused)), - grub_disk_addr_t sector __attribute((unused)), - grub_size_t size __attribute((unused)), - const char *buf __attribute((unused))) -{ - return GRUB_ERR_OUT_OF_RANGE; -} - -static struct grub_disk_dev grub_pxe_dev = - { - .name = "pxe", - .id = GRUB_DISK_DEVICE_PXE_ID, - .iterate = grub_pxe_iterate, - .open = grub_pxe_open, - .close = grub_pxe_close, - .read = grub_pxe_read, - .write = grub_pxe_write, - .next = 0 - }; - -static grub_err_t -grub_pxefs_dir (grub_device_t device, - const char *path __attribute__ ((unused)), - int (*hook) (const char *filename, - const struct grub_dirhook_info *info) - __attribute__ ((unused))) -{ - if (device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) - return grub_error (GRUB_ERR_IO, "not a pxe disk"); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_pxefs_open (struct grub_file *file, const char *name) -{ - union - { - struct grub_pxenv_tftp_get_fsize c1; - struct grub_pxenv_tftp_open c2; - } c; - struct grub_pxe_data *data; - struct grub_pxe_disk_data *disk_data = file->device->disk->data; - grub_file_t file_int, bufio; - - if (file->device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) - return grub_error (GRUB_ERR_IO, "not a pxe disk"); - if (curr_file != 0) { grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry); curr_file = 0; } - c.c1.server_ip = disk_data->server_ip; - c.c1.gateway_ip = disk_data->gateway_ip; + c.c1.server_ip = data->server_ip; + c.c1.gateway_ip = data->gateway_ip; grub_strcpy ((char *)&c.c1.filename[0], name); grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry); if (c.c1.status) @@ -297,7 +221,6 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_pxenv_tftp_read c; struct grub_pxe_data *data; - struct grub_pxe_disk_data *disk_data = file->device->disk->data; grub_uint32_t pn, r; data = file->data; @@ -317,8 +240,8 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) if (curr_file != 0) grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry); - o.server_ip = disk_data->server_ip; - o.gateway_ip = disk_data->gateway_ip; + o.server_ip = data->server_ip; + o.gateway_ip = data->gateway_ip; grub_strcpy ((char *)&o.filename[0], data->filename); o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); o.packet_size = grub_pxe_blksize; @@ -513,18 +436,46 @@ grub_pxe_detect (void) grub_pxe_pxenv = pxenv; } +static grub_size_t +grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), + void *buf __attribute__ ((unused)), + grub_size_t buflen __attribute__ ((unused))) +{ + return 0; +} + +static grub_err_t +grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), + void *buf __attribute__ ((unused)), + grub_size_t buflen __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented"); +} + +struct grub_net_card_driver grub_pxe_card_driver = +{ + .send = grub_pxe_send, + .recv = grub_pxe_recv +}; + +struct grub_net_card grub_pxe_card = +{ + .driver = &grub_pxe_card_driver, + .name = "pxe" +}; + void grub_pxe_unload (void) { if (grub_pxe_pxenv) { - grub_fs_unregister (&grub_pxefs_fs); - grub_disk_dev_unregister (&grub_pxe_dev); - + grub_net_app_level_unregister (&grub_pxefs_fs); + grub_net_card_unregister (&grub_pxe_card); grub_pxe_pxenv = 0; } } +#if 0 static void set_ip_env (char *varname, grub_uint32_t ip) { @@ -556,7 +507,9 @@ write_ip_env (grub_uint32_t *ip, const char *val) return buf; } +#endif +#if 0 static char * grub_env_write_pxe_default_server (struct grub_env_var *var __attribute__ ((unused)), @@ -572,6 +525,7 @@ grub_env_write_pxe_default_gateway (struct grub_env_var *var { return write_ip_env (&grub_pxe_default_gateway_ip, val); } +#endif static char * grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), @@ -598,34 +552,58 @@ grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), return buf; } - GRUB_MOD_INIT(pxe) { grub_pxe_detect (); if (grub_pxe_pxenv) { char *buf; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inter; + +#if 0 + grub_register_variable_hook ("pxe_default_server", 0, + grub_env_write_pxe_default_server); + grub_register_variable_hook ("pxe_default_gateway", 0, + grub_env_write_pxe_default_gateway); +#endif + grub_register_variable_hook ("pxe_blksize", 0, + grub_env_write_pxe_blocksize); buf = grub_xasprintf ("%d", grub_pxe_blksize); if (buf) grub_env_set ("pxe_blksize", buf); grub_free (buf); +#if 0 set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); - set_ip_env ("pxe_default_gateway", grub_pxe_default_gateway_ip); - set_ip_env ("net_pxe_ip", grub_pxe_your_ip); - grub_register_variable_hook ("pxe_default_server", 0, - grub_env_write_pxe_default_server); - grub_register_variable_hook ("pxe_default_gateway", 0, - grub_env_write_pxe_default_gateway); +#endif - /* XXX: Is it possible to change IP in PXE? */ - grub_register_variable_hook ("net_pxe_ip", 0, - grub_env_write_readonly); - grub_register_variable_hook ("pxe_blksize", 0, - grub_env_write_pxe_blocksize); - grub_disk_dev_register (&grub_pxe_dev); - grub_fs_register (&grub_pxefs_fs); + grub_net_app_level_register (&grub_pxefs_fs); + grub_net_card_register (&grub_pxe_card); + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = grub_pxe_your_ip; + inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr); + if (grub_pxe_default_gateway_ip) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = grub_pxe_default_server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = grub_pxe_default_gateway_ip; + grub_net_add_route_gw ("pxe_default", target, gw); + } + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = grub_pxe_default_gateway_ip ? + : grub_pxe_default_server_ip; + target.ipv4.masksize = 32; + grub_net_add_route ("pxe_default", target, inter); + } } } diff --git a/include/grub/net.h b/include/grub/net.h index b5e852f9b..84e881efe 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -54,71 +54,37 @@ struct grub_net_card struct grub_net_network_level_interface; +typedef enum grub_network_level_protocol_id +{ + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 +} grub_network_level_protocol_id_t; + typedef union grub_net_network_level_address { + grub_network_level_protocol_id_t type; grub_uint32_t ipv4; } grub_net_network_level_address_t; typedef union grub_net_network_level_netaddress { + grub_network_level_protocol_id_t type; struct { grub_uint32_t base; int masksize; } ipv4; } grub_net_network_level_netaddress_t; -typedef enum grub_network_level_protocol_id -{ - GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 -} grub_network_level_protocol_id_t; - struct grub_net_network_level_interface; -struct grub_net_network_level_protocol -{ - struct grub_net_network_level_protocol *next; - char *name; - grub_network_level_protocol_id_t id; - grub_err_t (*ntoa) (char *name, grub_net_network_level_address_t *addr); - char * (*aton) (union grub_net_network_level_address addr); - grub_err_t (*net_ntoa) (char *name, - grub_net_network_level_netaddress_t *addr); - char * (*net_aton) (grub_net_network_level_netaddress_t addr); - int (* match_net) (grub_net_network_level_netaddress_t net, - grub_net_network_level_address_t addr); - grub_err_t (*init) (struct grub_net_network_level_interface *dev); - grub_err_t (*fini) (struct grub_net_network_level_interface *dev); - grub_err_t (*send) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); - grub_size_t (*recv) (struct grub_net_network_level_interface *dev, void *buf, - grub_size_t buflen); -}; - struct grub_net_network_level_interface { struct grub_net_network_level_interface *next; char *name; - /* Underlying protocol. */ - struct grub_net_network_level_protocol *protocol; struct grub_net_card *card; union grub_net_network_level_address address; void *data; }; -struct grub_net_route -{ - struct grub_net_route *next; - grub_net_network_level_netaddress_t target; - char *name; - struct grub_net_network_level_protocol *prot; - int is_gateway; - union - { - struct grub_net_network_level_interface *interface; - grub_net_network_level_address_t gw; - }; -}; - struct grub_net_session; struct grub_net_session_level_protocol @@ -156,24 +122,12 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, return session->protocol->recv (session, buf, size); } +struct grub_net_network_level_interface * +grub_net_add_addr (const char *name, struct grub_net_card *card, + grub_net_network_level_address_t addr); + extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; -static inline void -grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); -} - -static inline void -grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); -} - -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) - extern grub_net_app_level_t grub_net_app_level_list; #ifndef GRUB_LST_GENERATOR @@ -195,25 +149,6 @@ grub_net_app_level_unregister (grub_net_app_level_t proto) #define FOR_NET_APP_LEVEL(var) FOR_LIST_ELEMENTS((var), \ (grub_net_app_level_list)) - -extern struct grub_net_route *grub_net_routes; - -static inline void -grub_net_route_register (struct grub_net_route *route) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_routes), - GRUB_AS_LIST (route)); -} - -static inline void -grub_net_route_unregister (struct grub_net_route *route) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), - GRUB_AS_LIST (route)); -} - -#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) - extern struct grub_net_card *grub_net_cards; static inline void @@ -232,44 +167,32 @@ grub_net_card_unregister (struct grub_net_card *card) #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) -extern struct grub_net_network_level_protocol *grub_net_network_level_protocols; - -static inline void -grub_net_network_level_protocol_register (struct grub_net_network_level_protocol *prot) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -static inline void -grub_net_network_level_protocol_unregister (struct grub_net_network_level_protocol *prot) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_protocols), - GRUB_AS_LIST (prot)); -} - -#define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_level_protocols; (var); (var) = (var)->next) - -static inline grub_err_t -grub_net_resolve_address_in_protocol (struct grub_net_network_level_protocol *prot, - char *name, - grub_net_network_level_address_t *addr) -{ - return prot->ntoa (name, addr); -} - struct grub_net_session * grub_net_open_tcp (char *address, grub_uint16_t port); grub_err_t -grub_net_resolve_address (struct grub_net_network_level_protocol **prot, - char *name, +grub_net_resolve_address (const char *name, grub_net_network_level_address_t *addr); +grub_err_t +grub_net_resolve_net_address (const char *name, + grub_net_network_level_netaddress_t *addr); + grub_err_t grub_net_route_address (grub_net_network_level_address_t addr, grub_net_network_level_address_t *gateway, struct grub_net_network_level_interface **interf); +grub_err_t +grub_net_add_route (const char *name, + grub_net_network_level_netaddress_t target, + struct grub_net_network_level_interface *inter); + +grub_err_t +grub_net_add_route_gw (const char *name, + grub_net_network_level_netaddress_t target, + grub_net_network_level_address_t gw); + + #endif /* ! GRUB_NET_HEADER */ From e571f2332e90dec534f0b8beb1a943b699c1271b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 18:15:59 +0200 Subject: [PATCH 022/673] Fix regressions by previous commits --- grub-core/commands/ls.c | 6 ++++-- grub-core/commands/net.c | 38 +++++++++++++++++++++++++------------- grub-core/fs/i386/pc/pxe.c | 8 ++++---- grub-core/kern/device.c | 7 +++++-- include/grub/net.h | 22 ++++++++++++++-------- 5 files changed, 52 insertions(+), 29 deletions(-) diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 3179d271e..300c21cc9 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -47,6 +47,7 @@ static grub_err_t grub_ls_list_devices (int longlist) { grub_net_app_level_t proto; + int first = 1; auto int grub_ls_print_devices (const char *name); int grub_ls_print_devices (const char *name) @@ -62,10 +63,11 @@ grub_ls_list_devices (int longlist) grub_device_iterate (grub_ls_print_devices); grub_xputs ("\n"); - grub_puts_ (N_ ("Network protocols:\n")); - FOR_NET_APP_LEVEL (proto) { + if (first) + grub_puts_ (N_ ("Network protocols:")); + first = 0; grub_printf ("%s ", proto->name); } diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 2062e1bd0..9d28c2ff7 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -97,7 +97,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) return 0; ptr++; } - *ip = newip; + *ip = grub_cpu_to_le32 (newip); if (rest) *rest = ptr - 1; return 0; @@ -114,7 +114,8 @@ match_net (const grub_net_network_level_netaddress_t *net, case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_int32_t mask = (1 << net->ipv4.masksize) - 1; - return ((net->ipv4.base & mask) == (addr->ipv4 & mask)); + return ((grub_be_to_cpu32 (net->ipv4.base) & mask) + == (grub_be_to_cpu32 (addr->ipv4) & mask)); } } return 0; @@ -380,13 +381,17 @@ print_net_address (const grub_net_network_level_netaddress_t *target) switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - grub_printf ("%d.%d.%d.%d/%d ", ((target->ipv4.base >> 24) & 0xff), - ((target->ipv4.base >> 16) & 0xff), - ((target->ipv4.base >> 8) & 0xff), - ((target->ipv4.base >> 0) & 0xff), - target->ipv4.masksize); - break; + { + grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base); + grub_printf ("%d.%d.%d.%d/%d ", ((n >> 24) & 0xff), + ((n >> 16) & 0xff), + ((n >> 8) & 0xff), + ((n >> 0) & 0xff), + target->ipv4.masksize); + } + return; } + grub_printf ("Unknown address type %d\n", target->type); } static void @@ -395,12 +400,16 @@ print_address (const grub_net_network_level_address_t *target) switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - grub_printf ("%d.%d.%d.%d ", ((target->ipv4 >> 24) & 0xff), - ((target->ipv4 >> 16) & 0xff), - ((target->ipv4 >> 8) & 0xff), - ((target->ipv4 >> 0) & 0xff)); - break; + { + grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); + grub_printf ("%d.%d.%d.%d ", ((n >> 24) & 0xff), + ((n >> 16) & 0xff), + ((n >> 8) & 0xff), + ((n >> 0) & 0xff)); + } + return; } + grub_printf ("Unknown address type %d\n", target->type); } static grub_err_t @@ -420,6 +429,7 @@ grub_cmd_listroutes (struct grub_command *cmd __attribute__ ((unused)), } else grub_printf ("%s", route->interface->name); + grub_printf ("\n"); } return GRUB_ERR_NONE; } @@ -466,6 +476,8 @@ grub_net_open_real (const char *name) return ret; } } + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); + return NULL; } diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index eac3bf770..85d138bb0 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -306,7 +306,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)), static struct grub_fs grub_pxefs_fs = { - .name = "pxefs", + .name = "pxe", .dir = grub_pxefs_dir, .open = grub_pxefs_open, .read = grub_pxefs_read, @@ -590,7 +590,7 @@ GRUB_MOD_INIT(pxe) addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = grub_pxe_your_ip; inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr); - if (grub_pxe_default_gateway_ip) + if (grub_pxe_default_gateway_ip != grub_pxe_default_server_ip) { grub_net_network_level_netaddress_t target; grub_net_network_level_address_t gw; @@ -600,7 +600,7 @@ GRUB_MOD_INIT(pxe) target.ipv4.masksize = 32; gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; gw.ipv4 = grub_pxe_default_gateway_ip; - grub_net_add_route_gw ("pxe_default", target, gw); + grub_net_add_route_gw ("pxe_gw", target, gw); } { grub_net_network_level_netaddress_t target; @@ -608,7 +608,7 @@ GRUB_MOD_INIT(pxe) target.ipv4.base = grub_pxe_default_gateway_ip ? : grub_pxe_default_server_ip; target.ipv4.masksize = 32; - grub_net_add_route ("pxe_default", target, inter); + grub_net_add_route ("pxe", target, inter); } } } diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 9de545910..545487a6b 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -53,8 +53,11 @@ grub_device_open (const char *name) dev->disk = grub_disk_open (name); if (dev->disk) return dev; - if (grub_net_open) - dev->net = grub_net_open (name); + if (grub_net_open && grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + { + grub_errno = GRUB_ERR_NONE; + dev->net = grub_net_open (name); + } if (dev->net) return dev; diff --git a/include/grub/net.h b/include/grub/net.h index 84e881efe..4efd79f79 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -59,19 +59,25 @@ typedef enum grub_network_level_protocol_id GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 } grub_network_level_protocol_id_t; -typedef union grub_net_network_level_address +typedef struct grub_net_network_level_address { grub_network_level_protocol_id_t type; - grub_uint32_t ipv4; + union + { + grub_uint32_t ipv4; + }; } grub_net_network_level_address_t; -typedef union grub_net_network_level_netaddress +typedef struct grub_net_network_level_netaddress { grub_network_level_protocol_id_t type; - struct { - grub_uint32_t base; - int masksize; - } ipv4; + union + { + struct { + grub_uint32_t base; + int masksize; + } ipv4; + }; } grub_net_network_level_netaddress_t; struct grub_net_network_level_interface; @@ -81,7 +87,7 @@ struct grub_net_network_level_interface struct grub_net_network_level_interface *next; char *name; struct grub_net_card *card; - union grub_net_network_level_address address; + grub_net_network_level_address_t address; void *data; }; From 0f37e4936515fb9d2c2204d3640d33a2a5ae4595 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 20:00:56 +0200 Subject: [PATCH 023/673] Implement few variables --- grub-core/commands/net.c | 141 +++++++++++++++++++++++++++++++------ grub-core/fs/i386/pc/pxe.c | 35 +++------ include/grub/net.h | 35 ++++++++- 3 files changed, 161 insertions(+), 50 deletions(-) diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 9d28c2ff7..5a21178e5 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -21,6 +21,7 @@ #include #include #include +#include struct grub_net_route { @@ -41,13 +42,6 @@ struct grub_net_network_level_interface *grub_net_network_level_interfaces = NUL struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; -static inline void -grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); -} - static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { @@ -212,6 +206,10 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); + if (inter->flags & GRUB_NET_INTERFACE_PERMANENT) + return grub_error (GRUB_ERR_IO, + N_("you can't delete this address")); + grub_net_network_level_interface_unregister (inter); grub_free (inter->name); grub_free (inter); @@ -219,9 +217,104 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +/* + Currently suppoerted adresses: + IPv4: XXX.XXX.XXX.XXX + */ +#define MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") + +static void +addr_to_str (const grub_net_network_level_address_t *target, char *buf) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + { + grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); + grub_snprintf (buf, MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + ((n >> 24) & 0xff), ((n >> 16) & 0xff), + ((n >> 8) & 0xff), ((n >> 0) & 0xff)); + } + return; + } + grub_printf ("Unknown address type %d\n", target->type); +} + +/* + Currently suppoerted adresses: + ethernet: XX:XX:XX:XX:XX:XX + */ + +#define MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) + +static void +hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) +{ + str[0] = 0; + switch (addr->type) + { + case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: + { + char *ptr; + unsigned i; + for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++) + { + grub_snprintf (ptr, MAX_STR_HWADDR_LEN - (ptr - str), + "%02x:", addr->mac[i] & 0xff); + ptr += (sizeof ("XX:") - 1); + } + return; + } + } + grub_printf ("Unsupported hw address type %d\n", addr->type); +} + +/* FIXME: implement this. */ +static char * +hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +/* FIXME: implement this. */ +static char * +addr_set_env (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +static void +grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) +{ + { + char buf[MAX_STR_HWADDR_LEN]; + char name[grub_strlen (inter->name) + sizeof ("net__mac")]; + hwaddr_to_str (&inter->hwaddress, buf); + grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name); + grub_env_set (name, buf); + grub_register_variable_hook (name, 0, hwaddr_set_env); + } + + { + char buf[MAX_STR_ADDR_LEN]; + char name[grub_strlen (inter->name) + sizeof ("net__ip")]; + addr_to_str (&inter->address, buf); + grub_snprintf (name, sizeof (name), "net_%s_ip", inter->name); + grub_env_set (name, buf); + grub_register_variable_hook (name, 0, addr_set_env); + } + + grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), + GRUB_AS_LIST (inter)); +} + struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr) + grub_net_network_level_address_t addr, + grub_net_link_level_address_t hwaddress, + grub_net_interface_flags_t flags) { struct grub_net_network_level_interface *inter; @@ -231,6 +324,8 @@ grub_net_add_addr (const char *name, struct grub_net_card *card, inter->name = grub_strdup (name); grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); + grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress)); + inter->flags = flags; inter->card = card; grub_net_network_level_interface_register (inter); @@ -238,6 +333,7 @@ grub_net_add_addr (const char *name, struct grub_net_card *card, return inter; } +/* FIXME: support MAC specifying. */ static grub_err_t grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) @@ -245,6 +341,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_card *card; grub_net_network_level_address_t addr; grub_err_t err; + grub_net_interface_flags_t flags = 0; if (argc != 3) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); @@ -259,7 +356,15 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), if (err) return err; - grub_net_add_addr (args[0], card, addr); + if (card->flags & GRUB_NET_CARD_NO_MANUAL_INTERFACES) + return grub_error (GRUB_ERR_IO, + "this card doesn't support address addition"); + + if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE) + flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE; + + grub_net_add_addr (args[0], card, addr, card->default_address, + flags); return grub_errno; } @@ -397,19 +502,9 @@ print_net_address (const grub_net_network_level_netaddress_t *target) static void print_address (const grub_net_network_level_address_t *target) { - switch (target->type) - { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - { - grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); - grub_printf ("%d.%d.%d.%d ", ((n >> 24) & 0xff), - ((n >> 16) & 0xff), - ((n >> 8) & 0xff), - ((n >> 0) & 0xff)); - } - return; - } - grub_printf ("Unknown address type %d\n", target->type); + char buf[MAX_STR_ADDR_LEN]; + addr_to_str (target, buf); + grub_xputs (buf); } static grub_err_t @@ -487,7 +582,7 @@ static grub_command_t cmd_lsroutes, cmd_lscards; GRUB_MOD_INIT(net) { cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, - "SHORTNAME CARD ADDRESS", + "SHORTNAME CARD ADDRESS [HWADDRESS]", N_("Add a network address.")); cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, "SHORTNAME", diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 85d138bb0..1d9ea8f89 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -41,6 +41,7 @@ static grub_uint32_t grub_pxe_default_gateway_ip; static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE; static grub_file_t curr_file = 0; +static grub_net_link_level_address_t pxe_hwaddr; struct grub_pxe_data { @@ -322,29 +323,6 @@ grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), return NULL; } -static void -set_mac_env (grub_uint8_t *mac_addr, grub_size_t mac_len) -{ - char buf[(sizeof ("XX:") - 1) * mac_len + 1]; - char *ptr = buf; - unsigned i; - - for (i = 0; i < mac_len; i++) - { - grub_snprintf (ptr, sizeof (buf) - (ptr - buf), - "%02x:", mac_addr[i] & 0xff); - ptr += (sizeof ("XX:") - 1); - } - if (mac_len) - *(ptr - 1) = 0; - else - buf[0] = 0; - - grub_env_set ("net_pxe_mac", buf); - /* XXX: Is it possible to change MAC in PXE? */ - grub_register_variable_hook ("net_pxe_mac", 0, grub_env_write_readonly); -} - static void set_env_limn_ro (const char *varname, char *value, grub_size_t len) { @@ -432,8 +410,10 @@ grub_pxe_detect (void) grub_pxe_your_ip = bp->your_ip; grub_pxe_default_server_ip = bp->server_ip; grub_pxe_default_gateway_ip = bp->gateway_ip; - set_mac_env (bp->mac_addr, bp->hw_len < sizeof (bp->mac_addr) ? bp->hw_len - : sizeof (bp->mac_addr)); + grub_memcpy (pxe_hwaddr.mac, bp->mac_addr, + bp->hw_len < sizeof (pxe_hwaddr.mac) + ? bp->hw_len : sizeof (pxe_hwaddr.mac)); + pxe_hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file, sizeof (bp->boot_file)); set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name, @@ -589,7 +569,10 @@ GRUB_MOD_INIT(pxe) grub_net_card_register (&grub_pxe_card); addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = grub_pxe_your_ip; - inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr); + inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr, pxe_hwaddr, + GRUB_NET_INTERFACE_PERMANENT + | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE + | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE); if (grub_pxe_default_gateway_ip != grub_pxe_default_server_ip) { grub_net_network_level_netaddress_t target; diff --git a/include/grub/net.h b/include/grub/net.h index 4efd79f79..649bf4096 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -34,6 +34,33 @@ typedef struct grub_net extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); +typedef enum grub_link_level_protocol_id +{ + GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET +} grub_link_level_protocol_id_t; + +typedef struct grub_net_link_level_address +{ + grub_link_level_protocol_id_t type; + union + { + grub_uint8_t mac[6]; + }; +} grub_net_link_level_address_t; + +typedef enum grub_net_interface_flags + { + GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE = 1, + GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE = 2, + GRUB_NET_INTERFACE_PERMANENT = 4 + } grub_net_interface_flags_t; + +typedef enum grub_net_card_flags + { + GRUB_NET_CARD_HWADDRESS_IMMUTABLE = 1, + GRUB_NET_CARD_NO_MANUAL_INTERFACES = 2 + } grub_net_card_flags_t; + struct grub_net_card; struct grub_net_card_driver @@ -49,6 +76,8 @@ struct grub_net_card struct grub_net_card *next; char *name; struct grub_net_card_driver *driver; + grub_net_link_level_address_t default_address; + grub_net_card_flags_t flags; void *data; }; @@ -88,6 +117,8 @@ struct grub_net_network_level_interface char *name; struct grub_net_card *card; grub_net_network_level_address_t address; + grub_net_link_level_address_t hwaddress; + grub_net_interface_flags_t flags; void *data; }; @@ -130,7 +161,9 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr); + grub_net_network_level_address_t addr, + grub_net_link_level_address_t hwaddress, + grub_net_interface_flags_t flags); extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; From 308fad6dc87b752d32e383d8670a8a7fcf4bafa9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 22:10:55 +0200 Subject: [PATCH 024/673] Move DHCP parsing to net module and reintroduce most variables --- grub-core/commands/net.c | 161 +++++++++++++++++++++++-- grub-core/fs/i386/pc/pxe.c | 235 ++++++++++--------------------------- include/grub/i386/pc/pxe.h | 38 +----- include/grub/net.h | 43 +++++++ 4 files changed, 257 insertions(+), 220 deletions(-) diff --git a/grub-core/commands/net.c b/grub-core/commands/net.c index 5a21178e5..f1838569b 100644 --- a/grub-core/commands/net.c +++ b/grub-core/commands/net.c @@ -217,21 +217,15 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } -/* - Currently suppoerted adresses: - IPv4: XXX.XXX.XXX.XXX - */ -#define MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") - -static void -addr_to_str (const grub_net_network_level_address_t *target, char *buf) +void +grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) { switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); - grub_snprintf (buf, MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", ((n >> 24) & 0xff), ((n >> 16) & 0xff), ((n >> 8) & 0xff), ((n >> 0) & 0xff)); } @@ -298,9 +292,9 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa } { - char buf[MAX_STR_ADDR_LEN]; + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; char name[grub_strlen (inter->name) + sizeof ("net__ip")]; - addr_to_str (&inter->address, buf); + grub_net_addr_to_str (&inter->address, buf); grub_snprintf (name, sizeof (name), "net_%s_ip", inter->name); grub_env_set (name, buf); grub_register_variable_hook (name, 0, addr_set_env); @@ -327,6 +321,8 @@ grub_net_add_addr (const char *name, struct grub_net_card *card, grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress)); inter->flags = flags; inter->card = card; + inter->dhcp_ack = NULL; + inter->dhcp_acklen = 0; grub_net_network_level_interface_register (inter); @@ -502,8 +498,8 @@ print_net_address (const grub_net_network_level_netaddress_t *target) static void print_address (const grub_net_network_level_address_t *target) { - char buf[MAX_STR_ADDR_LEN]; - addr_to_str (target, buf); + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_addr_to_str (target, buf); grub_xputs (buf); } @@ -576,6 +572,145 @@ grub_net_open_real (const char *name) return NULL; } +static char * +grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +static void +set_env_limn_ro (const char *intername, const char *suffix, + char *value, grub_size_t len) +{ + char c; + char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_") + + grub_strlen (suffix)]; + grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix); + c = value[len]; + value[len] = 0; + grub_env_set (varname, value); + value[len] = c; + grub_register_variable_hook (varname, 0, grub_env_write_readonly); +} + +static void +parse_dhcp_vendor (const char *name, void *vend, int limit) +{ + grub_uint8_t *ptr, *ptr0; + + ptr = ptr0 = vend; + + if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != GRUB_NET_BOOTP_RFC1048_MAGIC) + return; + ptr = ptr + sizeof (grub_uint32_t); + while (ptr - ptr0 < limit) + { + grub_uint8_t tagtype; + grub_uint8_t taglength; + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return; + + taglength = *ptr++; + + switch (tagtype) + { + case 12: + set_env_limn_ro (name, "hostname", (char *) ptr, taglength); + break; + + case 15: + set_env_limn_ro (name, "domain", (char *) ptr, taglength); + break; + + case 17: + set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); + break; + + case 18: + set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); + break; + + /* If you need any other options please contact GRUB + developpement team. */ + } + + ptr += taglength; + } +} + +#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) + +struct grub_net_network_level_interface * +grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, + grub_net_interface_flags_t flags, + struct grub_net_bootp_ack *bp, + grub_size_t size) +{ + grub_net_network_level_address_t addr; + grub_net_link_level_address_t hwaddr; + struct grub_net_network_level_interface *inter; + + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = bp->your_ip; + + grub_memcpy (hwaddr.mac, bp->mac_addr, + bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len + : sizeof (hwaddr.mac)); + hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + inter = grub_net_add_addr (name, card, addr, hwaddr, flags); + if (bp->gateway_ip != bp->server_ip) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof ("_gw")]; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s_gw", name); + grub_net_add_route_gw (rname, target, gw); + } + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->gateway_ip; + target.ipv4.masksize = 32; + grub_net_add_route (name, target, inter); + } + + if (size > OFFSET_OF (boot_file, bp)) + set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, + sizeof (bp->boot_file)); + if (size > OFFSET_OF (server_name, bp)) + set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, + sizeof (bp->server_name)); + if (size > OFFSET_OF (vendor, bp)) + parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); + + inter->dhcp_ack = grub_malloc (size); + if (inter->dhcp_ack) + { + grub_memcpy (inter->dhcp_ack, bp, size); + inter->dhcp_acklen = size; + } + else + grub_errno = GRUB_ERR_NONE; + + return inter; +} + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards; diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 1d9ea8f89..513a8cb7d 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -35,13 +35,13 @@ #define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF)) struct grub_pxe_bangpxe *grub_pxe_pxenv; -static grub_uint32_t grub_pxe_your_ip; static grub_uint32_t grub_pxe_default_server_ip; +#if 0 static grub_uint32_t grub_pxe_default_gateway_ip; +#endif static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE; - +static grub_uint32_t pxe_rm_entry = 0; static grub_file_t curr_file = 0; -static grub_net_link_level_address_t pxe_hwaddr; struct grub_pxe_data { @@ -52,7 +52,6 @@ struct grub_pxe_data char filename[0]; }; -static grub_uint32_t pxe_rm_entry = 0; static struct grub_pxe_bangpxe * grub_pxe_scan (void) @@ -316,112 +315,6 @@ static struct grub_fs grub_pxefs_fs = .next = 0 }; -static char * -grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), - const char *val __attribute__ ((unused))) -{ - return NULL; -} - -static void -set_env_limn_ro (const char *varname, char *value, grub_size_t len) -{ - char c; - c = value[len]; - value[len] = 0; - grub_env_set (varname, value); - value[len] = c; - grub_register_variable_hook (varname, 0, grub_env_write_readonly); -} - -static void -parse_dhcp_vendor (void *vend, int limit) -{ - grub_uint8_t *ptr, *ptr0; - - ptr = ptr0 = vend; - - if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != 0x63825363) - return; - ptr = ptr + sizeof (grub_uint32_t); - while (ptr - ptr0 < limit) - { - grub_uint8_t tagtype; - grub_uint8_t taglength; - - tagtype = *ptr++; - - /* Pad tag. */ - if (tagtype == 0) - continue; - - /* End tag. */ - if (tagtype == 0xff) - return; - - taglength = *ptr++; - - switch (tagtype) - { - case 12: - set_env_limn_ro ("net_pxe_hostname", (char *) ptr, taglength); - break; - - case 15: - set_env_limn_ro ("net_pxe_domain", (char *) ptr, taglength); - break; - - case 17: - set_env_limn_ro ("net_pxe_rootpath", (char *) ptr, taglength); - break; - - case 18: - set_env_limn_ro ("net_pxe_extensionspath", (char *) ptr, taglength); - break; - - /* If you need any other options please contact GRUB - developpement team. */ - } - - ptr += taglength; - } -} - -static void -grub_pxe_detect (void) -{ - struct grub_pxe_bangpxe *pxenv; - struct grub_pxenv_get_cached_info ci; - struct grub_pxenv_boot_player *bp; - - pxenv = grub_pxe_scan (); - if (! pxenv) - return; - - ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; - ci.buffer = 0; - ci.buffer_size = 0; - grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); - if (ci.status) - return; - - bp = LINEAR (ci.buffer); - - grub_pxe_your_ip = bp->your_ip; - grub_pxe_default_server_ip = bp->server_ip; - grub_pxe_default_gateway_ip = bp->gateway_ip; - grub_memcpy (pxe_hwaddr.mac, bp->mac_addr, - bp->hw_len < sizeof (pxe_hwaddr.mac) - ? bp->hw_len : sizeof (pxe_hwaddr.mac)); - pxe_hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - set_env_limn_ro ("net_pxe_boot_file", (char *) bp->boot_file, - sizeof (bp->boot_file)); - set_env_limn_ro ("net_pxe_dhcp_server_name", (char *) bp->server_name, - sizeof (bp->server_name)); - parse_dhcp_vendor (&bp->vendor, sizeof (bp->vendor)); - grub_pxe_pxenv = pxenv; -} - static grub_size_t grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), void *buf __attribute__ ((unused)), @@ -461,14 +354,15 @@ grub_pxe_unload (void) } } -#if 0 static void set_ip_env (char *varname, grub_uint32_t ip) { - char buf[sizeof ("XXX.XXX.XXX.XXX")]; + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_network_level_address_t addr; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = ip; - grub_snprintf (buf, sizeof (buf), "%d.%d.%d.%d", (ip & 0xff), - (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff); + grub_net_addr_to_str (&addr, buf); grub_env_set (varname, buf); } @@ -477,25 +371,25 @@ write_ip_env (grub_uint32_t *ip, const char *val) { char *buf; grub_err_t err; - grub_uint32_t newip; - - err = parse_ip (val, &newip, 0); + grub_net_network_level_address_t addr; + + err = grub_net_resolve_address (val, &addr); if (err) return 0; + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + return NULL; /* Normalize the IP. */ - buf = grub_xasprintf ("%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff, - (newip >> 16) & 0xff, (newip >> 24) & 0xff); + buf = grub_malloc (GRUB_NET_MAX_STR_ADDR_LEN); if (!buf) return 0; + grub_net_addr_to_str (&addr, buf); - *ip = newip; + *ip = addr.ipv4; return buf; } -#endif -#if 0 static char * grub_env_write_pxe_default_server (struct grub_env_var *var __attribute__ ((unused)), @@ -504,6 +398,7 @@ grub_env_write_pxe_default_server (struct grub_env_var *var return write_ip_env (&grub_pxe_default_server_ip, val); } +#if 0 static char * grub_env_write_pxe_default_gateway (struct grub_env_var *var __attribute__ ((unused)), @@ -540,60 +435,58 @@ grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), GRUB_MOD_INIT(pxe) { - grub_pxe_detect (); - if (grub_pxe_pxenv) - { - char *buf; - grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inter; - -#if 0 - grub_register_variable_hook ("pxe_default_server", 0, - grub_env_write_pxe_default_server); - grub_register_variable_hook ("pxe_default_gateway", 0, - grub_env_write_pxe_default_gateway); -#endif - grub_register_variable_hook ("pxe_blksize", 0, - grub_env_write_pxe_blocksize); + struct grub_pxe_bangpxe *pxenv; + struct grub_pxenv_get_cached_info ci; + struct grub_net_bootp_ack *bp; + char *buf; - buf = grub_xasprintf ("%d", grub_pxe_blksize); - if (buf) - grub_env_set ("pxe_blksize", buf); - grub_free (buf); + pxenv = grub_pxe_scan (); + if (! pxenv) + return; + + ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; + ci.buffer = 0; + ci.buffer_size = 0; + grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); + if (ci.status) + return; + + bp = LINEAR (ci.buffer); + + grub_pxe_default_server_ip = bp->server_ip; + grub_pxe_pxenv = pxenv; + + set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); + grub_register_variable_hook ("pxe_default_server", 0, + grub_env_write_pxe_default_server); #if 0 - set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); + grub_pxe_default_gateway_ip = bp->gateway_ip; + + grub_register_variable_hook ("pxe_default_gateway", 0, + grub_env_write_pxe_default_gateway); #endif - grub_net_app_level_register (&grub_pxefs_fs); - grub_net_card_register (&grub_pxe_card); - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = grub_pxe_your_ip; - inter = grub_net_add_addr ("pxe", &grub_pxe_card, addr, pxe_hwaddr, - GRUB_NET_INTERFACE_PERMANENT - | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE - | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE); - if (grub_pxe_default_gateway_ip != grub_pxe_default_server_ip) - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = grub_pxe_default_server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = grub_pxe_default_gateway_ip; - grub_net_add_route_gw ("pxe_gw", target, gw); - } - { - grub_net_network_level_netaddress_t target; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = grub_pxe_default_gateway_ip ? - : grub_pxe_default_server_ip; - target.ipv4.masksize = 32; - grub_net_add_route ("pxe", target, inter); - } - } + buf = grub_xasprintf ("%d", grub_pxe_blksize); + if (buf) + grub_env_set ("pxe_blksize", buf); + grub_free (buf); + + grub_register_variable_hook ("pxe_blksize", 0, + grub_env_write_pxe_blocksize); + + grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, + bp->hw_len < sizeof (grub_pxe_card.default_address.mac) + ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + grub_net_app_level_register (&grub_pxefs_fs); + grub_net_card_register (&grub_pxe_card); + grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, + GRUB_NET_INTERFACE_PERMANENT + | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE + | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE, + bp, GRUB_PXE_BOOTP_SIZE); } GRUB_MOD_FINI(pxe) diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h index 62ece21b0..781b53df5 100644 --- a/include/grub/i386/pc/pxe.h +++ b/include/grub/i386/pc/pxe.h @@ -152,9 +152,9 @@ #define GRUB_PXE_BOOTP_BCAST 0x8000 #if 1 -#define GRUB_PXE_BOOTP_DHCPVEND 1024 /* DHCP extended vendor field size. */ +#define GRUB_PXE_BOOTP_SIZE (1024 + 236) /* DHCP extended vendor field size. */ #else -#define GRUB_PXE_BOOTP_DHCPVEND 312 /* DHCP standard vendor field size. */ +#define GRUB_PXE_BOOTP_SIZE (312 + 236) /* DHCP standard vendor field size. */ #endif #define GRUB_PXE_MIN_BLKSIZE 512 @@ -162,8 +162,6 @@ #define GRUB_PXE_TFTP_PORT 69 -#define GRUB_PXE_VM_RFC1048 0x63825363L - #define GRUB_PXE_ERR_LEN 0xFFFFFFFF #ifndef ASM_FILE @@ -214,38 +212,6 @@ struct grub_pxenv_get_cached_info grub_uint16_t buffer_limit; } __attribute__ ((packed)); -#define GRUB_PXE_MAC_ADDR_LEN 16 - -typedef grub_uint8_t grub_pxe_mac_addr_t[GRUB_PXE_MAC_ADDR_LEN]; - -struct grub_pxenv_boot_player -{ - grub_uint8_t opcode; - grub_uint8_t hw_type; /* hardware type. */ - grub_uint8_t hw_len; /* hardware addr len. */ - grub_uint8_t gate_hops; /* zero it. */ - grub_uint32_t ident; /* random number chosen by client. */ - grub_uint16_t seconds; /* seconds since did initial bootstrap. */ - grub_uint16_t flags; - grub_uint32_t client_ip; - grub_uint32_t your_ip; - grub_uint32_t server_ip; - grub_uint32_t gateway_ip; - grub_pxe_mac_addr_t mac_addr; - grub_uint8_t server_name[64]; - grub_uint8_t boot_file[128]; - union - { - grub_uint8_t d[GRUB_PXE_BOOTP_DHCPVEND]; /* raw array of vendor/dhcp options. */ - struct - { - grub_uint32_t magic; /* DHCP magic cookie. */ - grub_uint32_t flags; /* bootp flags/opcodes. */ - grub_uint8_t padding[56]; - } v; - } vendor; -} __attribute__ ((packed)); - struct grub_pxenv_tftp_open { grub_uint16_t status; diff --git a/include/grub/net.h b/include/grub/net.h index 649bf4096..ec334092d 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -119,6 +119,8 @@ struct grub_net_network_level_interface grub_net_network_level_address_t address; grub_net_link_level_address_t hwaddress; grub_net_interface_flags_t flags; + struct grub_net_bootp_ack *dhcp_ack; + grub_size_t dhcp_acklen; void *data; }; @@ -234,4 +236,45 @@ grub_net_add_route_gw (const char *name, grub_net_network_level_address_t gw); +#define GRUB_NET_BOOTP_MAC_ADDR_LEN 16 + +typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN]; + +struct grub_net_bootp_ack +{ + grub_uint8_t opcode; + grub_uint8_t hw_type; /* hardware type. */ + grub_uint8_t hw_len; /* hardware addr len. */ + grub_uint8_t gate_hops; /* zero it. */ + grub_uint32_t ident; /* random number chosen by client. */ + grub_uint16_t seconds; /* seconds since did initial bootstrap. */ + grub_uint16_t flags; + grub_uint32_t client_ip; + grub_uint32_t your_ip; + grub_uint32_t server_ip; + grub_uint32_t gateway_ip; + grub_net_bootp_mac_addr_t mac_addr; + grub_uint8_t server_name[64]; + grub_uint8_t boot_file[128]; + grub_uint8_t vendor[0]; +} __attribute__ ((packed)); + +#define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L + +struct grub_net_network_level_interface * +grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, + grub_net_interface_flags_t flags, + struct grub_net_bootp_ack *bp, + grub_size_t size); + +/* + Currently suppoerted adresses: + IPv4: XXX.XXX.XXX.XXX + */ +#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") + +void +grub_net_addr_to_str (const grub_net_network_level_address_t *target, + char *buf); + #endif /* ! GRUB_NET_HEADER */ From 9daa20394429830d83a26c4eda35ab1a085fadd9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 22:12:37 +0200 Subject: [PATCH 025/673] Reintroduce pxe: syntax --- grub-core/fs/i386/pc/pxe.c | 77 ++++++++++++++------------------------ 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index 513a8cb7d..dc447d92c 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -121,54 +121,35 @@ grub_pxefs_open (struct grub_file *file, const char *name) if (!data) return grub_errno; -#if 0 - if (grub_strncmp (file->device->net->name, "pxe:", sizeof ("pxe:") - 1) == 0) - { - const char *ptr; - grub_err_t err; - - ptr = name + sizeof ("pxe:") - 1; - err = parse_ip (ptr, &(data->server_ip), &ptr); - if (err) - return err; - if (*ptr == ':') - { - err = parse_ip (ptr + 1, &(data->gateway_ip), 0); - if (err) - return err; - } - else - data->gateway_ip = grub_pxe_default_gateway_ip; - } - else -#endif - { - grub_net_network_level_address_t addr; - grub_net_network_level_address_t gateway; - struct grub_net_network_level_interface *interf; - grub_err_t err; - - if (grub_strncmp (file->device->net->name, - "pxe,", sizeof ("pxe,") - 1) == 0) - { - const char *ptr; - - ptr = name + sizeof ("pxe,") - 1; - err = grub_net_resolve_address (name + sizeof ("pxe,") - 1, &addr); - if (err) - return err; - } - else - { - addr.ipv4 = grub_pxe_default_server_ip; - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - } - err = grub_net_route_address (addr, &gateway, &interf); - if (err) - return err; - data->server_ip = addr.ipv4; - data->gateway_ip = gateway.ipv4; - } + { + grub_net_network_level_address_t addr; + grub_net_network_level_address_t gateway; + struct grub_net_network_level_interface *interf; + grub_err_t err; + + if (grub_strncmp (file->device->net->name, + "pxe,", sizeof ("pxe,") - 1) == 0 + || grub_strncmp (file->device->net->name, + "pxe:", sizeof ("pxe:") - 1) == 0) + { + const char *ptr; + + ptr = name + sizeof ("pxe,") - 1; + err = grub_net_resolve_address (name + sizeof ("pxe,") - 1, &addr); + if (err) + return err; + } + else + { + addr.ipv4 = grub_pxe_default_server_ip; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + } + err = grub_net_route_address (addr, &gateway, &interf); + if (err) + return err; + data->server_ip = addr.ipv4; + data->gateway_ip = gateway.ipv4; + } if (curr_file != 0) { From c04256771534fc5dcd1ce71e335b37d5cacc7b42 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 22:20:48 +0200 Subject: [PATCH 026/673] Create directory net and move all net files there --- Makefile.util.def | 2 +- grub-core/Makefile.core.def | 4 ++-- grub-core/{fs => net}/i386/pc/pxe.c | 0 grub-core/{commands => net}/net.c | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename grub-core/{fs => net}/i386/pc/pxe.c (100%) rename grub-core/{commands => net}/net.c (100%) diff --git a/Makefile.util.def b/Makefile.util.def index 5fd53680d..68c105a9b 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -30,7 +30,7 @@ library = { common = grub-core/commands/blocklist.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; - common = grub-core/commands/net.c; + common = grub-core/net/net.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/host.c; common = grub-core/disk/loopback.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index fb68f344c..bd5d78160 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -930,7 +930,7 @@ module = { module = { name = pxe; - i386_pc = fs/i386/pc/pxe.c; + i386_pc = net/i386/pc/pxe.c; enable = i386_pc; }; @@ -1379,5 +1379,5 @@ module = { module = { name = net; - common = commands/net.c; + common = net/net.c; }; \ No newline at end of file diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c similarity index 100% rename from grub-core/fs/i386/pc/pxe.c rename to grub-core/net/i386/pc/pxe.c diff --git a/grub-core/commands/net.c b/grub-core/net/net.c similarity index 100% rename from grub-core/commands/net.c rename to grub-core/net/net.c From 779e9dc48071591aa3205bb6087459902820c746 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 00:44:57 +0200 Subject: [PATCH 027/673] Support Solaris DHCP ACK parsing --- grub-core/loader/i386/multiboot_mbi.c | 29 ++++++++++++++++++++++++++- grub-core/net/net.c | 2 -- include/grub/net.h | 4 ++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index bf17863cf..9d6497442 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -32,6 +32,7 @@ #include #include #include +#include /* The bits in the required part of flags field we don't support. */ #define UNSUPPORTED_FLAGS 0x0000fff8 @@ -189,12 +190,24 @@ grub_multiboot_load (grub_file_t file) static grub_size_t grub_multiboot_get_mbi_size (void) { - return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + grub_size_t ret; + struct grub_net_network_level_interface *net; + + ret = sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry) + elf_sec_entsize * elf_sec_num + 256 * sizeof (struct multiboot_color); + + FOR_NET_NETWORK_LEVEL_INTERFACES(net) + if (net->dhcp_ack) + { + ret += net->dhcp_acklen; + break; + } + + return ret; } /* Fill previously allocated Multiboot mmap. */ @@ -401,6 +414,20 @@ grub_multiboot_make_mbi (grub_uint32_t *target) mbi->flags |= MULTIBOOT_INFO_BOOTDEV; } + { + struct grub_net_network_level_interface *net; + FOR_NET_NETWORK_LEVEL_INTERFACES(net) + if (net->dhcp_ack) + { + grub_memcpy (ptrorig, net->dhcp_ack, net->dhcp_acklen); + mbi->drives_addr = ptrdest; + mbi->drives_length = net->dhcp_acklen; + ptrorig += net->dhcp_acklen; + ptrdest += net->dhcp_acklen; + break; + } + } + if (elf_sec_num) { mbi->u.elf_sec.addr = ptrdest; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index f1838569b..7c8992f8d 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -49,8 +49,6 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter GRUB_AS_LIST (inter)); } -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) - static inline void grub_net_route_register (struct grub_net_route *route) { diff --git a/include/grub/net.h b/include/grub/net.h index ec334092d..a0737d574 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -277,4 +277,8 @@ void grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf); +extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) + + #endif /* ! GRUB_NET_HEADER */ From 21e4963bcc9cd307c54762d1715a0d38d502dd9f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 01:12:47 +0200 Subject: [PATCH 028/673] Support net_get_dhcp_option --- grub-core/net/net.c | 128 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 7c8992f8d..5205e1938 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -709,8 +709,130 @@ grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, return inter; } +static char +hexdigit (grub_uint8_t val) +{ + if (val < 10) + return val + '0'; + return val + 'a' - 10; +} + +static grub_err_t +grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + int num; + grub_uint8_t *ptr; + grub_uint8_t taglength; + + if (argc < 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1])) + break; + + if (!inter) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unrecognised interface %s"), args[1]); + + if (!inter->dhcp_ack) + return grub_error (GRUB_ERR_IO, N_("no DHCP info found")); + + if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack)) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + + num = grub_strtoul (args[2], 0, 0); + if (grub_errno) + return grub_errno; + + ptr = inter->dhcp_ack->vendor; + + if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) + != GRUB_NET_BOOTP_RFC1048_MAGIC) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + ptr = ptr + sizeof (grub_uint32_t); + while (1) + { + grub_uint8_t tagtype; + + if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + taglength = *ptr++; + + if (tagtype == num) + break; + ptr += taglength; + } + + if (grub_strcmp (args[3], "string") == 0) + { + char *val = grub_malloc (taglength + 1); + if (!val) + return grub_errno; + grub_memcpy (val, ptr, taglength); + val[taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "number") == 0) + { + grub_uint64_t val = 0; + int i; + for (i = 0; i < taglength; i++) + val = (val << 8) | ptr[i]; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%llu\n", (unsigned long long) val); + else + { + char valn[64]; + grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val); + return grub_env_set (args[0], valn); + } + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "hex") == 0) + { + char *val = grub_malloc (2 * taglength + 1); + int i; + if (!val) + return grub_errno; + for (i = 0; i < taglength; i++) + { + val[2 * i] = hexdigit (ptr[i] >> 4); + val[2 * i + 1] = hexdigit (ptr[i] & 0xf); + } + val[2 * taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "unrecognised format specification %s", args[3]); +} + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; -static grub_command_t cmd_lsroutes, cmd_lscards; +static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp; GRUB_MOD_INIT(net) { @@ -730,6 +852,9 @@ GRUB_MOD_INIT(net) "", N_("list network routes")); cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards, "", N_("list network cards")); + cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, + N_("VAR INTERFACE NUMBER DESCRIPTION"), + N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); grub_net_open = grub_net_open_real; } @@ -742,5 +867,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_delroute); grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); + grub_unregister_command (cmd_getdhcp); grub_net_open = NULL; } From 9a9cee4e4347c0480fb9e19ce2732a2132c4e3f9 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 15 Sep 2010 13:00:51 -0300 Subject: [PATCH 029/673] Use the correct address types in net.c. implement ntoa ipv4 function. --- commands/net.c | 40 +++++++++++++++++++++++++++---------- include/grub/net.h | 29 +++++++++++++++++++++++---- include/grub/net/protocol.h | 5 +++-- include/grub/net/type_net.h | 8 ++++---- net/ip.c | 38 +++++++++++++++++++++++++++++++++-- 5 files changed, 97 insertions(+), 23 deletions(-) diff --git a/commands/net.c b/commands/net.c index b8ceb36f4..2558a309b 100644 --- a/commands/net.c +++ b/commands/net.c @@ -22,11 +22,8 @@ #include #include -struct grub_net_route *grub_net_routes = NULL; -struct grub_net_network_layer_interface *grub_net_network_layer_interfaces = NULL; -struct grub_net_card *grub_net_cards = NULL; -struct grub_net_network_layer_protocol *grub_net_network_layer_protocols = NULL; +/*Find which protocol understands the given address*/ grub_err_t grub_net_resolve_address (struct grub_net_network_layer_protocol **prot, char *name, @@ -102,7 +99,7 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1])) + if ( !grub_strcmp (inter->name, args[1])) break; if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); @@ -124,21 +121,36 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), grub_err_t err; grub_net_network_layer_address_t addr; struct grub_net_network_layer_interface *inter; + grub_printf("Enter add addr function.\n"); + + grub_printf("card list address in net.c = %x\n", (int) grub_net_cards); if (argc != 4) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("four arguments expected")); FOR_NET_CARDS (card) - if (grub_strcmp (card->name, args[1])) + { + grub_printf("card address = %x\n", (int) card); + grub_printf("card->name = %s\n",card->name); + grub_printf("args[1] = %s\n",args[1]); + if ( !grub_strcmp (card->name, args[1])) break; + } + + grub_printf("Out of the loop.\n"); + grub_printf("card address = %x\n", (int) card); + if (card == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); + grub_printf("protocols loop.\n"); FOR_NET_NETWORK_LEVEL_PROTOCOLS (prot) - if (grub_strcmp (prot->name, args[2])) + if ( !grub_strcmp (prot->name, args[2])) break; - if (card == NULL) + grub_printf("end protocols loop.\n"); + + if (prot == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("protocol not found")); err = grub_net_resolve_address_in_protocol (prot, args[3], &addr); @@ -163,6 +175,12 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), } grub_net_network_layer_interface_register (inter); + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + { + grub_printf("inter->name = %s\n",inter->name); + grub_printf("inter->address = %x\n",(int) (inter->address.ipv4)); + + } return GRUB_ERR_NONE; } @@ -178,7 +196,7 @@ grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), for (prev = &grub_net_routes, route = *prev; route; prev = &((*prev)->next), route = *prev) - if (grub_strcmp (route->name, args[0]) == 0) + if ( !grub_strcmp (route->name, args[0]) == 0) { *prev = route->next; grub_free (route->name); @@ -232,7 +250,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), N_("Unrecognised address %s"), args[1]); } - if (grub_strcmp (args[2], "gw") == 0 && argc >= 4) + if ( !grub_strcmp (args[2], "gw") == 0 && argc >= 4) { grub_err_t err; route->is_gateway = 1; @@ -251,7 +269,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), route->is_gateway = 0; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[2])) + if ( !grub_strcmp (inter->name, args[2])) break; if (!inter) diff --git a/include/grub/net.h b/include/grub/net.h index abb8a3167..18779dabe 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -31,6 +31,8 @@ struct grub_net_card; struct grub_net_card_driver { + struct grub_net_card_driver *next; + char *name; grub_err_t (*init) (struct grub_net_card *dev); grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (struct grub_net_card *dev,struct grub_net_buff *nb); @@ -66,7 +68,7 @@ struct grub_net_network_layer_interface /* Underlying protocol. */ struct grub_net_network_layer_protocol *protocol; struct grub_net_card *card; - union grub_net_network_layer_address address; + grub_net_network_layer_address_t address; void *data; }; @@ -121,7 +123,7 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, return session->protocol->recv (session, buf, size); } -struct grub_net_network_layer_interface *grub_net_network_layer_interfaces; +extern struct grub_net_network_layer_interface *EXPORT_VAR(grub_net_network_layer_interfaces); static inline void grub_net_network_layer_interface_register (struct grub_net_network_layer_interface *inter) @@ -139,7 +141,7 @@ grub_net_network_layer_interface_unregister (struct grub_net_network_layer_inter #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_layer_interfaces; var; var = var->next) -extern struct grub_net_route *grub_net_routes; +extern struct grub_net_route *EXPORT_VAR(grub_net_routes); static inline void grub_net_route_register (struct grub_net_route *route) @@ -157,7 +159,7 @@ grub_net_route_unregister (struct grub_net_route *route) #define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) -extern struct grub_net_card *grub_net_cards; +extern struct grub_net_card *EXPORT_VAR(grub_net_cards); static inline void grub_net_card_register (struct grub_net_card *card) @@ -174,7 +176,26 @@ grub_net_card_unregister (struct grub_net_card *card) } #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) +struct grub_net_card_driver *grub_net_card_drivers; +static inline void +grub_net_card_driver_register (struct grub_net_card_driver *driver) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +static inline void +grub_net_card_driver_unregister (struct grub_net_card_driver *driver) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +void ofdriver_ini(void); +void ofdriver_fini(void); + +#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next) #define FOR_NET_NETWORK_LEVEL_PROTOCOLS(var) for ((var) = grub_net_network_layer_protocols; (var); (var) = (var)->next) diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h index ffc3dd719..ce37404bc 100644 --- a/include/grub/net/protocol.h +++ b/include/grub/net/protocol.h @@ -1,6 +1,7 @@ #ifndef GRUB_PROTOCOL_HEADER #define GRUB_PROTOCOL_HEADER #include +#include #include #include #include @@ -60,7 +61,7 @@ struct grub_net_network_layer_protocol grub_uint16_t type; /* IANA Ethertype */ //grub_network_layer_protocol_id_t id; grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr); - char * (*aton) (union grub_net_network_layer_address addr); + char * (*aton) (grub_net_network_layer_address_t addr); grub_err_t (*net_ntoa) (char *name, grub_net_network_layer_netaddress_t *addr); char * (*net_aton) (grub_net_network_layer_netaddress_t addr); @@ -87,7 +88,7 @@ struct grub_net_link_layer_protocol grub_uint16_t ethertype); }; -extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols; +extern struct grub_net_network_layer_protocol *EXPORT_VAR(grub_net_network_layer_protocols); typedef struct grub_net_protocol *grub_net_protocol_t; void grub_net_application_layer_protocol_register (struct grub_net_application_layer_protocol *prot); diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h index a1717d6a7..f159b1de0 100644 --- a/include/grub/net/type_net.h +++ b/include/grub/net/type_net.h @@ -18,16 +18,16 @@ typedef enum }grub_net_protocol_id_t; -typedef union grub_net_network_layer_address +typedef union grub_net_network_layer_netaddress { grub_uint32_t ipv4; -} grub_net_network_layer_netaddress_t; +} grub_net_network_layer_address_t; -typedef union grub_net_network_layer_netaddress +typedef union grub_net_network_layer_address { struct { grub_uint32_t base; int masksize; } ipv4; -} grub_net_network_layer_address_t; +} grub_net_network_layer_netaddress_t; #endif diff --git a/net/ip.c b/net/ip.c index 142f33e70..8237603f2 100644 --- a/net/ip.c +++ b/net/ip.c @@ -68,8 +68,10 @@ send_ip_packet (struct grub_net_network_layer_interface *inf, grub_memcpy(nl_target_addr.addr, &(iph->dest), nl_target_addr.len); rc = arp_resolve(inf, trans_net_inf->inner_layer, &nl_target_addr, &ll_target_addr); grub_free(nl_target_addr.addr); - if (rc != GRUB_ERR_NONE) + if (rc != GRUB_ERR_NONE){ + grub_printf("Error in the ARP resolve.\n"); return rc; + } rc = trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb,ll_target_addr, IP_ETHERTYPE); grub_free(ll_target_addr.addr); @@ -113,13 +115,45 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf, return 0; } + +static grub_err_t +ipv4_ntoa (char *val, grub_net_network_layer_address_t *addr ) +{ + grub_uint8_t *p = (grub_uint8_t *) addr; + unsigned long t; + int i; + + for (i = 0; i < 4; i++) + { + t = grub_strtoul (val, (char **) &val, 0); + if (grub_errno) + return grub_errno; + + if (t & ~0xff) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + + p[i] = (grub_uint8_t) t; + if (i != 3 && *val != '.') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + + val++; + } + + val = val - 1; + if (*val != '\0') + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP."); + + return GRUB_ERR_NONE; +} + static struct grub_net_network_layer_protocol grub_ipv4_protocol = { .name = "ipv4", .id = GRUB_NET_IPV4_ID, .type = IP_ETHERTYPE, .send = send_ip_packet, - .recv = recv_ip_packet + .recv = recv_ip_packet, + .ntoa = ipv4_ntoa }; void ipv4_ini(void) From 87fdc7e8d28f20f355240219ea7e7a580e0f7303 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 15 Sep 2010 13:23:23 -0300 Subject: [PATCH 030/673] Create Open firmware pseudo driver. Change ofnet.c to disknet.c and remove almost all ieee1275 specific code. Create grub_net_malloc to handle iee1275 memory issues in a temporary solution. --- conf/powerpc-ieee1275.rmk | 6 +- fs/{ieee1275/ofnet.c => netdisk.c} | 142 ++++++++------------------ include/grub/ieee1275/ieee1275.h | 10 +- include/grub/ieee1275/ofnet.h | 29 +----- include/grub/net/disknet.h | 5 + include/grub/net/ethernet.h | 15 ++- include/grub/net/ieee1275/interface.h | 9 -- include/grub/net/mem.h | 9 ++ kern/ieee1275/openfw.c | 64 ++++++++++++ net/drivers/ieee1275/ofdriver.c | 74 ++++++++++++++ net/ethernet.c | 9 +- net/i386/mem.c | 10 ++ net/ieee1275/interface.c | 46 --------- net/ieee1275/mem.c | 32 ++++++ net/protocol.c | 2 + 15 files changed, 272 insertions(+), 190 deletions(-) rename fs/{ieee1275/ofnet.c => netdisk.c} (77%) create mode 100644 include/grub/net/disknet.h create mode 100644 include/grub/net/mem.h create mode 100644 net/drivers/ieee1275/ofdriver.c create mode 100644 net/i386/mem.c delete mode 100644 net/ieee1275/interface.c create mode 100644 net/ieee1275/mem.c diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index f0faef489..a70a1e962 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -5,7 +5,7 @@ kernel_img_HEADERS += ieee1275/ieee1275.h \ command.h i18n.h env_private.h net/ip.h net/udp.h net/ethernet.h net/arp.h net/tftp.h\ - net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h + net/ieee1275/interface.h net/type_net.h net.h net/interface.h net/protocol.h net/netbuff.h net/mem.h # Programs pkglib_PROGRAMS = kernel.img @@ -23,8 +23,8 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/time.c \ symlist.c kern/$(target_cpu)/cache.S net/ip.c net/tftp.c net/udp.c net/ethernet.c net/arp.c \ - net/ieee1275/interface.c net/interface.c net/protocol.c net/netbuff.c \ - fs/ieee1275/ofnet.c + net/drivers/ieee1275/ofdriver.c net/interface.c net/protocol.c net/netbuff.c \ + fs/netdisk.c net/ieee1275/mem.c kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS += $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x200000,-Bstatic diff --git a/fs/ieee1275/ofnet.c b/fs/netdisk.c similarity index 77% rename from fs/ieee1275/ofnet.c rename to fs/netdisk.c index cf7eeb5b2..2f6e97d52 100644 --- a/fs/ieee1275/ofnet.c +++ b/fs/netdisk.c @@ -23,26 +23,25 @@ #include #include #include -#include -#include -#include #include #include #include #include #include -#include #include #include #include +#include +#include + +struct grub_net_card *grub_net_cards = NULL; +struct grub_net_network_layer_interface *grub_net_network_layer_interfaces = NULL; +struct grub_net_route *grub_net_routes = NULL; #define BUFFERADDR 0X00000000 #define BUFFERSIZE 0x02000000 #define U64MAXSIZE 18446744073709551615ULL - -//static grub_ieee1275_ihandle_t handle = 0; - static const char * find_sep (const char *name) { @@ -295,29 +294,45 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) return 1; } - // grub_printf("name = %s\n",name); +/*TESt*/ + // grub_printf("name = %s\n",name); + struct grub_net_card *card; + struct grub_ofnetcard_data *ofdata; + FOR_NET_CARDS(card) + { + grub_printf("card address = %x\n", (int) card); + grub_printf ("card name = %s\n", card->name); + ofdata = card->data; + grub_printf("card path = %s\n", (char *) ofdata->path); + grub_printf("card handle = %d\n", ofdata->handle); + } + grub_printf("card list address in disknet.c = %x\n",(int) grub_net_cards); + card = grub_net_cards; + grub_printf("card address = %x\n", (int) card); +/*TESt*/ + struct grub_net_protocol_stack *stack; struct grub_net_buff *pack; struct grub_net_application_transport_interface *app_interface; int file_size; char *datap; int amount = 0; - grub_addr_t found_addr; grub_netdisk_data_t netdisk_data = (grub_netdisk_data_t) file->device->disk->data; + // TODO: replace getting IP and MAC from bootp by routing functions struct grub_net_network_layer_interface net_interface; - struct grub_net_card net_card; struct grub_net_addr ila, lla; - ila.addr = (grub_uint8_t *) &(bootp_pckt->yiaddr); + ila.addr = (grub_uint8_t *) & (bootp_pckt->yiaddr); ila.len = 4; - lla.addr = (grub_uint8_t *) &(bootp_pckt->chaddr); + lla.addr = (grub_uint8_t *) & (bootp_pckt->chaddr); lla.len = 6; - net_card.ila = &ila; - net_card.lla = &lla; - net_interface.card = &net_card; // END TODO + card->ila = &ila; + card->lla = &lla; + net_interface.card = card; + if(! netdisk_data) return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing"); @@ -328,37 +343,35 @@ grub_ofnetfs_open (struct grub_file *file , const char *name ) app_interface = (struct grub_net_application_transport_interface *) stack->interface; app_interface->inner_layer->data = (void *) &(netdisk_data->server_ip); + pack = grub_netbuff_alloc (2048); grub_netbuff_reserve (pack,2048); + file_size = app_interface->app_prot->get_file_size(&net_interface,stack,pack,(char *) name); - for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) - { - if (grub_claimmap (found_addr , file_size) != -1) - break; - } - file->data = (void *) found_addr; + file->data = grub_net_malloc (file_size); grub_netbuff_clear(pack); grub_netbuff_reserve (pack,2048); + app_interface->app_prot->open (&net_interface,stack,pack,(char *) name); if (grub_errno != GRUB_ERR_NONE) goto error; do { - grub_netbuff_clear(pack); - grub_netbuff_reserve (pack,2048); app_interface->app_prot->recv (&net_interface,stack,pack); + if (grub_errno != GRUB_ERR_NONE) goto error; + if ((pack->tail - pack->data)) { - // file->data = grub_realloc(file->data,amount + pack->tail - pack->data); datap = (char *)file->data + amount; amount += (pack->tail - pack->data); - grub_memcpy(datap , pack->data, pack->tail - pack->data); + grub_memcpy (datap , pack->data, pack->tail - pack->data); } + grub_netbuff_clear(pack); grub_netbuff_reserve (pack,2048); app_interface->app_prot->send_ack (&net_interface,stack,pack); @@ -394,54 +407,6 @@ static struct grub_fs grub_ofnetfs_fs = .next = 0 }; -static char * -grub_ieee1275_get_devargs (const char *path) -{ - int len; - char *colon = grub_strchr (path, ':'); - len = colon - path; - if (! colon) - return 0; - - return grub_strndup (path,len); -} - -static int -grub_ofnet_detect (void) -{ - - char *devalias; - char bootpath[64]; /* XXX check length */ - grub_ieee1275_phandle_t root; - grub_uint32_t net_type; - - grub_ieee1275_finddevice ("/chosen", &grub_ieee1275_chosen); - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, - sizeof (bootpath), 0)) - { - /* Should never happen. */ - grub_printf ("/chosen/bootpath property missing!\n"); - return 0; - } - devalias = grub_ieee1275_get_aliasdevname (bootpath); - - if (grub_strncmp(devalias ,"net",3)) - return 0; - - grub_net = grub_malloc (sizeof *grub_net ); - grub_net->name = "net"; - grub_net->dev = grub_ieee1275_get_devargs (bootpath); - grub_ieee1275_finddevice ("/", &root); - grub_ieee1275_get_integer_property (root, "ibm,fw-net-compatibility", - &net_type, sizeof net_type, 0); - grub_printf("root = %d\n",root); - grub_printf("net_type= %d\n",net_type); - grub_net->type = net_type; - - return 1; -} - - #define IPMASK 0x000000FF #define IPSIZE 16 #define IPTEMPLATE "%d.%d.%d.%d" @@ -456,34 +421,17 @@ grub_ip2str (grub_uint32_t ip) return str_ip; } + void -grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet) +grub_disknet_init(void) { - netinfo->sip = grub_ip2str(packet->siaddr); - netinfo->cip = grub_ip2str(packet->yiaddr); - netinfo->gat = grub_ip2str(packet->giaddr); - grub_printf("packet->siaddr = %x\n",packet->siaddr); - grub_printf("netinfo-> = %s\n",netinfo->sip); - grub_printf("packet->yiaddr = %x\n",packet->yiaddr); - grub_printf("netinfo-> = %s\n",netinfo->cip); - grub_printf("packet->giaddr = %x\n",packet->giaddr); - grub_printf("netinfo-> = %s\n",netinfo->gat); + + grub_disk_dev_register (&grub_ofnet_dev); + grub_fs_register (&grub_ofnetfs_fs); } + void -grub_ofnet_init(void) -{ - tftp_ini (); - bootp_pckt = grub_getbootp (); - if(grub_ofnet_detect ()) - { - grub_get_netinfo (grub_net, bootp_pckt ); - grub_disk_dev_register (&grub_ofnet_dev); - grub_fs_register (&grub_ofnetfs_fs); - card_open (); - } -} -void -grub_ofnet_fini(void) +grub_disknet_fini(void) { grub_fs_unregister (&grub_ofnetfs_fs); grub_disk_dev_unregister (&grub_ofnet_dev); diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index f4c8b4edf..8fb558fa7 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -24,7 +24,6 @@ #include #include -/* Maps a device alias to a pathname. */ struct grub_ieee1275_devalias { char *name; @@ -65,6 +64,13 @@ struct grub_ieee1275_common_hdr typedef grub_uint32_t grub_ieee1275_ihandle_t; typedef grub_uint32_t grub_ieee1275_phandle_t; +struct grub_ofnetcard_data +{ + char *path; + grub_ieee1275_ihandle_t handle; +}; + +/* Maps a device alias to a pathname. */ extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen); extern grub_ieee1275_ihandle_t EXPORT_VAR(grub_ieee1275_mmu); extern int (* EXPORT_VAR(grub_ieee1275_entry_fn)) (void *); @@ -186,4 +192,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); +void EXPORT_FUNC(grub_ofnet_findcards) (void); +void EXPORT_FUNC(grub_ofnet_probecards) (void); #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index a26c22235..ba4c62630 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -23,32 +23,9 @@ #include #include -extern void grub_ofnet_init(void); -extern void grub_ofnet_fini(void); +void grub_ofnet_init(void); +void grub_ofnet_fini(void); -/* -struct grub_net; - -struct grub_net_dev -{ - / The device name. / - const char *name; - - / FIXME: Just a template. / - int (*probe) (struct grub_net *net, const void *addr); - void (*reset) (struct grub_net *net); - int (*poll) (struct grub_net *net); - void (*transmit) (struct grub_net *net, const void *destip, - unsigned srcsock, unsigned destsock, const void *packet); - void (*disable) (struct grub_net *net); - - / The next net device. / - struct grub_net_dev *next; -}; -typedef struct grub_net_dev *grub_net_dev_t; - -struct grub_fs; -*/ struct grub_ofnet { /* The net name. */ @@ -85,7 +62,7 @@ struct grub_bootp { char file [128]; /* Boot filename */ // grub_uint32_t filesize ; /*File size (testing)*/ unsigned char vend [64]; -}; +}; typedef struct grub_bootp* grub_bootp_t; diff --git a/include/grub/net/disknet.h b/include/grub/net/disknet.h new file mode 100644 index 000000000..59aa2a320 --- /dev/null +++ b/include/grub/net/disknet.h @@ -0,0 +1,5 @@ +#ifndef GRUB_DISKNET_HEADER +#define GRUB_DISKNET_HEADER 1 + void grub_disknet_init(void); + void grub_disknet_fini(void); +#endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 9043a5f02..f4a6c22cf 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -10,9 +10,18 @@ struct etherhdr grub_uint16_t type; } __attribute__ ((packed)); -#define PCP (x) x & 0xe000 -#define CFI (x) x & 0x1000 -#define VID (x) x & 0x0fff +#define PCP(x) x & 0xe000 +#define CFI(x) x & 0x1000 +#define VID(x) x & 0x0fff +#define PRINT_ETH_ADDR(name,addr) grub_printf("%s %x:%x:%x:%x:%x:%x\n",\ + name,\ + addr[0],\ + addr[1],\ + addr[2],\ + addr[3],\ + addr[4],\ + addr[5]\ + ) struct llchdr { diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h index 16f624c05..c369e35a6 100644 --- a/include/grub/net/ieee1275/interface.h +++ b/include/grub/net/ieee1275/interface.h @@ -6,14 +6,5 @@ #include #include - -grub_ofnet_t grub_net; - grub_bootp_t bootp_pckt; - -int send_card_buffer (struct grub_net_buff *pack); -int get_card_packet (struct grub_net_buff *pack); -int card_open (void); -int card_close (void); - #endif diff --git a/include/grub/net/mem.h b/include/grub/net/mem.h new file mode 100644 index 000000000..bbdac512b --- /dev/null +++ b/include/grub/net/mem.h @@ -0,0 +1,9 @@ +#ifndef GRUB_NETMM_H +#define GRUB_NETMM_H 1 + +#include +#include + +void *EXPORT_FUNC(grub_net_malloc) (grub_size_t size); + +#endif /* ! GRUB_MM_H */ diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c index 337fc4b7e..2650ff3d4 100644 --- a/kern/ieee1275/openfw.c +++ b/kern/ieee1275/openfw.c @@ -23,6 +23,10 @@ #include #include #include +#include +#include +#include +#include enum grub_ieee1275_parse_type { @@ -490,3 +494,63 @@ grub_getbootp( void ) return packet; } +void grub_ofnet_findcards (void) +{ + struct grub_net_card *card; + int i = 0; + + auto int search_net_devices (struct grub_ieee1275_devalias *alias); + + int search_net_devices (struct grub_ieee1275_devalias *alias) + { + if ( !grub_strcmp (alias->type,"network") ) + { + + card = grub_malloc (sizeof (struct grub_net_card)); + struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); + ofdata->path = grub_strdup (alias->path); + card->data = ofdata; + card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); + grub_net_card_register (card); + } + return 0; + } + + /*Look at all nodes for devices of the type network*/ + grub_ieee1275_devices_iterate (search_net_devices); + +} + +void grub_ofnet_probecards (void) +{ + struct grub_net_card *card; + struct grub_net_card_driver *driver; + + /*Assign correspondent driver for each device. */ + FOR_NET_CARDS (card) + { + FOR_NET_CARD_DRIVERS (driver) + { + if (driver->init(card) == GRUB_ERR_NONE) + { + card->driver = driver; + continue; + } + } + } +} + +void +grub_ofnet_init(void) +{ + + ofdriver_ini(); + grub_ofnet_findcards(); + grub_ofnet_probecards(); + + /*init tftp stack - will be handled by module subsystem in the future*/ + tftp_ini (); + /*get bootp packet - won't be needed in the future*/ + bootp_pckt = grub_getbootp (); + grub_disknet_init(); +} diff --git a/net/drivers/ieee1275/ofdriver.c b/net/drivers/ieee1275/ofdriver.c new file mode 100644 index 000000000..5f6c3c2f6 --- /dev/null +++ b/net/drivers/ieee1275/ofdriver.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +static +grub_err_t card_open (struct grub_net_card *dev) +{ + + struct grub_ofnetcard_data *data = dev->data; + return grub_ieee1275_open (data->path,&(data->handle)); +} + +static +grub_err_t card_close (struct grub_net_card *dev) +{ + + struct grub_ofnetcard_data *data = dev->data; + + if (data->handle) + grub_ieee1275_close (data->handle); + return GRUB_ERR_NONE; +} + +static +grub_err_t send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + + int actual; + struct grub_ofnetcard_data *data = dev->data; + + return grub_ieee1275_write (data->handle,pack->data,pack->tail - pack->data,&actual); +} + +static +grub_err_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + + int actual, rc; + struct grub_ofnetcard_data *data = dev->data; + grub_netbuff_clear(pack); + + do + { + rc = grub_ieee1275_read (data->handle,pack->data,1500,&actual); + + }while (actual <= 0 || rc < 0); + grub_netbuff_put (pack, actual); + + return GRUB_ERR_NONE; +} + +static struct grub_net_card_driver ofdriver = +{ + .name = "ofnet", + .init = card_open, + .fini = card_close, + .send = send_card_buffer, + .recv = get_card_packet + +}; + +void ofdriver_ini(void) +{ + grub_net_card_driver_register (&ofdriver); +} + +void ofdriver_fini(void) +{ + grub_net_card_driver_unregister (&ofdriver); +} + + + diff --git a/net/ethernet.c b/net/ethernet.c index 14bc41c5b..7b578abab 100644 --- a/net/ethernet.c +++ b/net/ethernet.c @@ -22,10 +22,10 @@ struct grub_net_addr target_addr, grub_uint16_t ethertype) eth = (struct etherhdr *) nb->data; grub_memcpy(eth->dst, target_addr.addr, target_addr.len); grub_memcpy(eth->src, bootp_pckt->chaddr, 6); + eth->type = ethertype; - return send_card_buffer(nb); -// return inf->card->driver->send(inf->card,nb); + return inf->card->driver->send (inf->card,nb); } @@ -42,12 +42,11 @@ grub_uint16_t ethertype) start_time = grub_get_time_ms(); while (1) { - get_card_packet (nb); + inf->card->driver->recv (inf->card,nb); eth = (struct etherhdr *) nb->data; type = eth->type; grub_netbuff_pull(nb,sizeof (*eth)); - // grub_printf("ethernet type 58 %x\n",type); - // grub_printf("ethernet eth->type 58 %x\n",type); + if (eth->type <=1500) { llch = (struct llchdr *) nb->data; diff --git a/net/i386/mem.c b/net/i386/mem.c new file mode 100644 index 000000000..d6c98ea80 --- /dev/null +++ b/net/i386/mem.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include + + +void *grub_net_malloc (grub_size_t size) +{ + return grub_malloc (size); +} diff --git a/net/ieee1275/interface.c b/net/ieee1275/interface.c deleted file mode 100644 index 342044041..000000000 --- a/net/ieee1275/interface.c +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include - -static grub_ieee1275_ihandle_t handle; -int card_open (void) -{ - - grub_ieee1275_open (grub_net->dev , &handle); - return 0; - -} - -int card_close (void) -{ - - if (handle) - grub_ieee1275_close (handle); - return 0; -} - - -int send_card_buffer (struct grub_net_buff *pack) -{ - - int actual; - grub_ieee1275_write (handle,pack->data,pack->tail - pack->data,&actual); - - return actual; -} - -int get_card_packet (struct grub_net_buff *pack __attribute__ ((unused))) -{ - - int actual, rc; - pack->data = pack->tail = pack->head; - do - { - rc = grub_ieee1275_read (handle,pack->data,1500,&actual); - - }while (actual <= 0 || rc < 0); - grub_netbuff_put (pack, actual); - -// grub_printf("packsize %d\n",pack->tail - pack->data); - return 0;// sizeof (eth) + iph.len; -} diff --git a/net/ieee1275/mem.c b/net/ieee1275/mem.c new file mode 100644 index 000000000..416a04253 --- /dev/null +++ b/net/ieee1275/mem.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#define TRASHOLD_SIZE 5 * 1024 * 1024 + +void *grub_net_malloc (grub_size_t size) +{ + + int found = 0; + grub_addr_t found_addr; + + if (size <= TRASHOLD_SIZE) + return grub_malloc (size); + + for (found_addr = 0x800000; found_addr < + 2000 * 0x100000; found_addr += 0x100000) + { + if (grub_claimmap (found_addr , size) != -1) + { + found = 1; + break; + } + } + + if (!found) + grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + return found?(void *) found_addr:NULL; + +} diff --git a/net/protocol.c b/net/protocol.c index 05d4471d2..bdd7f3671 100644 --- a/net/protocol.c +++ b/net/protocol.c @@ -2,6 +2,8 @@ #include #include +struct grub_net_network_layer_protocol *grub_net_network_layer_protocols = NULL; + #define PROTOCOL_REGISTER_FUNCTIONS(layername) \ struct grub_net_##layername##_layer_protocol *grub_net_##layername##_layer_protocols;\ \ From 6b1b3423dd0d5c38d561d5b7ab5ea082ca7ef620 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 17:14:14 +0200 Subject: [PATCH 031/673] Fix error handling in ofnet --- grub-core/net/drivers/ieee1275/ofnet.c | 42 +++++++++++++++----------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 064f3d280..ce5276efe 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -3,18 +3,21 @@ #include #include -static -grub_err_t card_open (struct grub_net_card *dev) +static grub_err_t +card_open (struct grub_net_card *dev) { - + int status; struct grub_ofnetcard_data *data = dev->data; - return grub_ieee1275_open (data->path,&(data->handle)); + status = grub_ieee1275_open (data->path,&(data->handle)); + + if (status) + return grub_error (GRUB_ERR_IO, "couldn't open network card"); + return GRUB_ERR_NONE; } -static -grub_err_t card_close (struct grub_net_card *dev) +static grub_err_t +card_close (struct grub_net_card *dev) { - struct grub_ofnetcard_data *data = dev->data; if (data->handle) @@ -22,18 +25,23 @@ grub_err_t card_close (struct grub_net_card *dev) return GRUB_ERR_NONE; } -static -grub_err_t send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) -{ - +static grub_err_t +send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +{ int actual; + int status; struct grub_ofnetcard_data *data = dev->data; - return grub_ieee1275_write (data->handle,pack->data,pack->tail - pack->data,&actual); + status = grub_ieee1275_write (data->handle, pack->data, + pack->tail - pack->data, &actual); + + if (status) + return grub_error (GRUB_ERR_IO, "couldn't send network packet"); + return GRUB_ERR_NONE; } -static -grub_err_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +static grub_err_t +get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) { int actual, rc; @@ -41,10 +49,8 @@ grub_err_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pac grub_netbuff_clear(pack); do - { - rc = grub_ieee1275_read (data->handle,pack->data,1500,&actual); - - }while (actual <= 0 || rc < 0); + rc = grub_ieee1275_read (data->handle, pack->data, 1500, &actual); + while (actual <= 0 || rc < 0); grub_netbuff_put (pack, actual); return GRUB_ERR_NONE; From 90451bb1c951bbc90f479084b28ddb1e09d8ac8d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 17:14:43 +0200 Subject: [PATCH 032/673] networking in grub-emu --- grub-core/Makefile.core.def | 6 +++ grub-core/net/drivers/emu/emunet.c | 69 ++++++++++++++++++++++++++++++ include/grub/net.h | 6 ++- 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 grub-core/net/drivers/emu/emunet.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 5cacb6851..2f55ba5ec 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1398,3 +1398,9 @@ module = { ieee1275 = net/drivers/ieee1275/ofnet.c; enable = ieee1275; }; + +module = { + name = emunet; + emu = net/drivers/emu/emunet.c; + enable = ieee1275; +}; diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c new file mode 100644 index 000000000..8914a1d95 --- /dev/null +++ b/grub-core/net/drivers/emu/emunet.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include /* the L2 protocols */ +#include + +static grub_err_t +card_open (struct grub_net_card *dev) +{ + dev->data_num = socket (AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (dev->data_num < 0) + return grub_error (GRUB_ERR_IO, "couldn't open packet interface"); + return GRUB_ERR_NONE; +} + +static grub_err_t +card_close (struct grub_net_card *dev) +{ + close (dev->data_num); + return GRUB_ERR_NONE; +} + +static grub_err_t +send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + ssize_t actual; + + actual = write (dev->data_num, pack->data, pack->tail - pack->data); + if (actual < 0) + return grub_error (GRUB_ERR_IO, "couldn't send packets"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +{ + ssize_t actual; + + grub_netbuff_clear(pack); + actual = read (dev->data_num, pack->data, 1500); + if (actual < 0) + return grub_error (GRUB_ERR_IO, "couldn't receive packets"); + grub_netbuff_put (pack, actual); + + return GRUB_ERR_NONE; +} + +static struct grub_net_card_driver emudriver = +{ + .name = "emu", + .init = card_open, + .fini = card_close, + .send = send_card_buffer, + .recv = get_card_packet +}; + +GRUB_MOD_INIT(emunet) +{ + grub_net_card_driver_register (&emudriver); +} + +GRUB_MODE_FINI(emunet) +{ + grub_net_card_driver_unregister (&emudriver); +} + + + diff --git a/include/grub/net.h b/include/grub/net.h index ad553a69a..de188f615 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -84,7 +84,11 @@ struct grub_net_card struct grub_net_card_driver *driver; grub_net_link_level_address_t default_address; grub_net_card_flags_t flags; - void *data; + union + { + void *data; + int data_num; + }; }; struct grub_net_network_level_interface; From ce3a2ec0256a6442cc9a3b47a6d218baf3412c39 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 22 Sep 2010 20:34:20 +0200 Subject: [PATCH 033/673] Remove some dead code --- grub-core/Makefile.core.def | 1 - grub-core/net/arp.c | 3 +- grub-core/net/ethernet.c | 1 - grub-core/net/interface.c | 37 ------------------- grub-core/net/ip.c | 2 -- grub-core/net/netbuff.c | 2 +- grub-core/net/tftp.c | 2 -- grub-core/net/udp.c | 3 -- include/grub/net.h | 3 +- include/grub/net/arp.h | 1 - include/grub/net/interface.h | 70 ------------------------------------ include/grub/net/protocol.h | 9 ----- include/grub/net/type_net.h | 33 ----------------- 13 files changed, 3 insertions(+), 164 deletions(-) delete mode 100644 grub-core/net/interface.c delete mode 100644 include/grub/net/interface.h delete mode 100644 include/grub/net/protocol.h delete mode 100644 include/grub/net/type_net.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index d48c5d505..49dbd3f60 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1438,7 +1438,6 @@ module = { common = net/udp.c; common = net/ethernet.c; common = net/arp.c; - common = net/interface.c; common = net/netbuff.c; }; diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 5e10938ae..541b89411 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -92,7 +91,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, return GRUB_ERR_NONE; } current_time = grub_get_time_ms(); - if (current_time - start_time > TIMEOUT_TIME_MS) + if (current_time - start_time > 3000) break; } while (! entry); grub_netbuff_clear(nb); diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index d3a34aec6..a40e1f795 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/grub-core/net/interface.c b/grub-core/net/interface.c deleted file mode 100644 index f17b3e66b..000000000 --- a/grub-core/net/interface.c +++ /dev/null @@ -1,37 +0,0 @@ -/*#include - -#define INTERFACE_REGISTER_FUNCTIONS(layerprevious,layernext) \ -struct grub_net_##layername_layer_protocol *grub_net_##layername_layer_protocols;\ -\ -void grub_net_##layerprevious_##layernext_interface_register (struct grub_net_##layername_layer_protocol *prot)\ -{\ - grub_list_push (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ - GRUB_AS_LIST (prot));\ -}\ -\ -void grub_net_##layerprevious_##layernext_interface_unregister (struct grub_net_##layername_layer_protocol *prot);\ -{\ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_##layername_layer_protocols),\ - GRUB_AS_LIST (prot));\ -}\ - -INTERFACE_REGISTER_FUNCTIONS("application","transport"); -INTERFACE_REGISTER_FUNCTIONS("transport","network"); -INTERFACE_REGISTER_FUNCTIONS("network","link"); -INTERFACE_REGISTER_FUNCTIONS("link");*/ - -#include -#include -struct grub_net_protocol_stack - *grub_net_protocol_stack_get (char *name) -{ - struct grub_net_protocol_stack *p; - - for (p = grub_net_protocol_stacks; p; p = p->next) - { - if (!grub_strcmp(p->name,name)) - return p; - } - - return NULL; -} diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 264195ad3..023564a5a 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -2,8 +2,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index 4f6a1da84..cc366ae09 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -73,7 +73,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) len = ALIGN_UP (len,NETBUFF_ALIGN); data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); - nb = (struct grub_net_buff *) ((int)data + len); + nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); nb->head = nb->data = nb->tail = data; nb->end = (char *) nb; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index bb518b78f..b9e3f49c4 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -4,8 +4,6 @@ #include #include #include -#include -#include #include #include #include diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 27e23e826..a73431f83 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -1,10 +1,7 @@ #include #include #include -#include #include -#include -#include #include grub_err_t diff --git a/include/grub/net.h b/include/grub/net.h index de188f615..20bf3c0e6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -23,9 +23,8 @@ #include #include #include +#include #include -#include -#include typedef struct grub_fs *grub_net_app_level_t; diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index e547669a2..1475086e4 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -2,7 +2,6 @@ #define GRUB_NET_ARP_HEADER 1 #include #include -#include /* IANA ARP constant to define hardware type as ethernet */ #define ARPHRD_ETHERNET 1 diff --git a/include/grub/net/interface.h b/include/grub/net/interface.h deleted file mode 100644 index cf24dd22e..000000000 --- a/include/grub/net/interface.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef GRUB_INTERFACE_HEADER -#define GRUB_INTERFACE_HEADER -//#include -#include -#include -#include - -struct grub_net_protocol_stack -{ - struct grub_net_protocol_stack *next; - char *name; - grub_net_protocol_id_t id; - void *interface; -}; - -struct grub_net_application_transport_interface -{ - struct grub_net_transport_network_interface *inner_layer; - void *data; - struct grub_net_application_layer_protocol *app_prot; - struct grub_net_transport_layer_protocol *trans_prot; -}; - -struct grub_net_transport_network_interface -{ - struct grub_net_network_link_interface *inner_layer; - void *data; - struct grub_net_transport_layer_protocol *trans_prot; - struct grub_net_network_layer_protocol *net_prot; -}; - -struct grub_net_network_link_interface -{ - void *data; - struct grub_net_network_layer_protocol *net_prot; - struct grub_net_link_layer_protocol *link_prot; -}; - - -struct grub_net_protocol_stack *grub_net_protocol_stacks; -static inline void -grub_net_stack_register (struct grub_net_protocol_stack *stack) -{ - - grub_list_push (GRUB_AS_LIST_P (&grub_net_protocol_stacks), - GRUB_AS_LIST (stack)); -} -/* -void grub_net_stack_unregister (struct grub_net_protocol_stack *stack) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_protocol_stacks), - GRUB_AS_LIST (stack)); -}*/ - -struct grub_net_protocol_stack *grub_net_protocol_stack_get (char *name); - -/* -static inline void -grub_net_interface_application_transport_register (struct grub_net_application_transport_interface); -static inline void -grub_net_interface_application_transport_unregister (struct grub_net_application_transport_interface); -static inline void -grub_net_interface_transport_network_register (struct grub_net_transport_network_interface); -static inline void -grub_net_interface_transport_network_unregister (struct grub_net_transport_network_interface); -static inline void -grub_net_interface_network_link_register (struct grub_net_network_link_interface); -static inline void -grub_net_interface_network_link_unregister (struct grub_net_network_link_interface);*/ -#endif diff --git a/include/grub/net/protocol.h b/include/grub/net/protocol.h deleted file mode 100644 index da54b073f..000000000 --- a/include/grub/net/protocol.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef GRUB_PROTOCOL_HEADER -#define GRUB_PROTOCOL_HEADER -#include -#include -#include -#include -#include - -#endif diff --git a/include/grub/net/type_net.h b/include/grub/net/type_net.h deleted file mode 100644 index f159b1de0..000000000 --- a/include/grub/net/type_net.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef GRUB_TYPES_NET_HEADER -#define GRUB_TYPES_NET_HEADER 1 -#include - - -#define UDP_PCKT 0x11 -#define IP_PCKT 0x0800 -#define TIMEOUT_TIME_MS 3*1000 -typedef enum -{ - GRUB_NET_TFTP_ID, - GRUB_NET_UDP_ID, - GRUB_NET_IPV4_ID, - GRUB_NET_IPV6_ID, - GRUB_NET_ETHERNET_ID, - GRUB_NET_ARP_ID, - GRUB_NET_DHCP_ID -}grub_net_protocol_id_t; - - -typedef union grub_net_network_layer_netaddress -{ - grub_uint32_t ipv4; -} grub_net_network_layer_address_t; - -typedef union grub_net_network_layer_address -{ - struct { - grub_uint32_t base; - int masksize; - } ipv4; -} grub_net_network_layer_netaddress_t; -#endif From 04d22dddd985e49779fbdd570d1b4f0847dc4347 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Sep 2010 00:45:39 +0200 Subject: [PATCH 034/673] Fix a bunch of net issues --- grub-core/net/arp.c | 85 ++++++++-------- grub-core/net/drivers/emu/emunet.c | 84 ++++++++++------ grub-core/net/ethernet.c | 14 +-- grub-core/net/ip.c | 11 +- grub-core/net/net.c | 6 +- grub-core/net/tftp.c | 155 +++++++++++------------------ include/grub/net/arp.h | 12 +-- include/grub/net/ethernet.h | 8 ++ include/grub/net/ip.h | 2 - 9 files changed, 181 insertions(+), 196 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 541b89411..c7b5d0573 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -6,7 +6,7 @@ #include #include -static struct arp_entry arp_table[SIZE_ARP_TABLE]; +static struct arp_entry arp_table[10]; static grub_int8_t new_table_entry = -1; static @@ -19,8 +19,8 @@ void arp_init_table(void) static struct arp_entry * arp_find_entry (const grub_net_network_level_address_t *proto) { - grub_uint8_t i; - for(i=0;i < SIZE_ARP_TABLE; i++) + unsigned i; + for(i = 0; i < ARRAY_SIZE (arp_table); i++) { if(arp_table[i].avail == 1 && arp_table[i].nl_address.ipv4 == proto->ipv4) @@ -48,24 +48,26 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, return GRUB_ERR_NONE; } /* Build a request packet */ - nb = grub_malloc (2048); + nb = grub_netbuff_alloc (2048); + if (!nb) + return grub_errno; grub_netbuff_reserve(nb, 2048); grub_netbuff_push(nb, sizeof(*arp_header) + 2 * (6 + 6)); arp_header = (struct arphdr *)nb->data; - arp_header->hrd = 0; - arp_header->pro = 0; + arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); + arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); arp_header->hln = 6; - arp_header->pln = 6; - arp_header->op = ARP_REQUEST; + arp_header->pln = 4; + arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); aux = (grub_uint8_t *)arp_header + sizeof(*arp_header); /* Sender hardware address */ grub_memcpy(aux, &inf->hwaddress.mac, 6); aux += 6; /* Sender protocol address */ grub_memcpy(aux, &inf->address.ipv4, 4); - aux += 6; + aux += 4; /* Target hardware address */ - for(i=0; i < 6; i++) + for(i = 0; i < 6; i++) aux[i] = 0x00; aux += 6; /* Target protocol address */ @@ -73,7 +75,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_memset (&target_hw_addr.mac, 0xff, 6); - send_ethernet_packet (inf, nb, target_hw_addr, ARP_ETHERTYPE); + send_ethernet_packet (inf, nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); grub_netbuff_clear(nb); grub_netbuff_reserve(nb, 2048); @@ -81,7 +83,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, start_time = grub_get_time_ms(); do { - grub_net_recv_ethernet_packet (inf, nb, ARP_ETHERTYPE); + grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_ARP); /* Now check cache table again */ entry = arp_find_entry(proto_addr); if (entry) @@ -90,7 +92,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_netbuff_clear(nb); return GRUB_ERR_NONE; } - current_time = grub_get_time_ms(); + current_time = grub_get_time_ms(); if (current_time - start_time > 3000) break; } while (! entry); @@ -99,17 +101,16 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, } grub_err_t -grub_net_arp_receive(struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb) +grub_net_arp_receive (struct grub_net_network_level_interface *inf, + struct grub_net_buff *nb) { struct arphdr *arp_header = (struct arphdr *)nb->data; struct arp_entry *entry; - grub_uint8_t merge = 0; grub_uint8_t *sender_hardware_address, *sender_protocol_address; grub_uint8_t *target_hardware_address, *target_protocol_address; grub_net_network_level_address_t hwaddress; - sender_hardware_address = (grub_uint8_t *)arp_header + sizeof(*arp_header); + sender_hardware_address = (grub_uint8_t *) arp_header + sizeof(*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; @@ -118,40 +119,36 @@ grub_net_arp_receive(struct grub_net_network_level_interface *inf, entry = arp_find_entry(&hwaddress); /* Update sender hardware address */ if (entry) + grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + else { - grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); - merge = 1; - } - /* Am I the protocol address target? */ - if (! grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6)) - { - /* Add sender to cache table */ - if (! merge) - { + /* Add sender to cache table */ if (new_table_entry == -1) - arp_init_table(); + arp_init_table(); entry = &(arp_table[new_table_entry]); entry->avail = 1; grub_memcpy(&entry->nl_address.ipv4, sender_protocol_address, 4); grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); new_table_entry++; - if (new_table_entry == SIZE_ARP_TABLE) - new_table_entry = 0; - } - if (arp_header->op == ARP_REQUEST) - { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); - grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy(aux.mac, sender_protocol_address, 6); - grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy(target_protocol_address, aux.mac, arp_header->pln); - /* Change operation to REPLY and send packet */ - arp_header->op = ARP_REPLY; - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, ARP_ETHERTYPE); - } + if (new_table_entry == ARRAY_SIZE (arp_table)) + new_table_entry = 0; + } + + /* Am I the protocol address target? */ + if (grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { + grub_net_link_level_address_t aux; + /* Swap hardware fields */ + grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); + grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6); + grub_memcpy(aux.mac, sender_protocol_address, 6); + grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); + grub_memcpy(target_protocol_address, aux.mac, arp_header->pln); + /* Change operation to REPLY and send packet */ + arp_header->op = grub_be_to_cpu16 (ARP_REPLY); + grub_memcpy (aux.mac, target_hardware_address, 6); + send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); } return GRUB_ERR_NONE; } diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index 8914a1d95..9e4e66dce 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -1,68 +1,92 @@ + +#include #include #include -#include -#include /* the L2 protocols */ #include +#include +#include +#include +#include +#include +#include +#include + +static int fd; static grub_err_t -card_open (struct grub_net_card *dev) -{ - dev->data_num = socket (AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (dev->data_num < 0) - return grub_error (GRUB_ERR_IO, "couldn't open packet interface"); - return GRUB_ERR_NONE; -} - -static grub_err_t -card_close (struct grub_net_card *dev) -{ - close (dev->data_num); - return GRUB_ERR_NONE; -} - -static grub_err_t -send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *pack) { ssize_t actual; - actual = write (dev->data_num, pack->data, pack->tail - pack->data); + actual = write (fd, pack->data, pack->tail - pack->data); if (actual < 0) return grub_error (GRUB_ERR_IO, "couldn't send packets"); return GRUB_ERR_NONE; } -static grub_err_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +static grub_size_t +get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *pack) { ssize_t actual; grub_netbuff_clear(pack); - actual = read (dev->data_num, pack->data, 1500); + actual = read (fd, pack->data, 1500); if (actual < 0) - return grub_error (GRUB_ERR_IO, "couldn't receive packets"); + { + grub_error (GRUB_ERR_IO, "couldn't receive packets"); + return -1; + } grub_netbuff_put (pack, actual); - return GRUB_ERR_NONE; + return actual; } static struct grub_net_card_driver emudriver = { .name = "emu", - .init = card_open, - .fini = card_close, .send = send_card_buffer, .recv = get_card_packet }; +static struct grub_net_card emucard = +{ + .name = "emu0", + .driver = &emudriver, + .default_address = { + .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, + { .mac = { 0, 1, 2, 3, 4, 5} } + }, + .flags = 0 +}; + GRUB_MOD_INIT(emunet) { - grub_net_card_driver_register (&emudriver); + struct ifreq ifr; + // char fullname[64]; + fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK); + if (fd < 0) + return; + grub_memset (&ifr, 0, sizeof (ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if (ioctl (fd, TUNSETIFF, &ifr) < 0) + { + close (fd); + fd = -1; + return; + } + grub_net_card_register (&emucard); } -GRUB_MODE_FINI(emunet) +GRUB_MOD_FINI(emunet) { - grub_net_card_driver_unregister (&emudriver); + if (fd >= 0) + { + close (fd); + grub_net_card_unregister (&emucard); + } } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index a40e1f795..cbda4c875 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -38,10 +38,10 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, inf->card->driver->recv (inf->card, nb); eth = (struct etherhdr *) nb->data; - type = eth->type; + type = grub_be_to_cpu16 (eth->type); grub_netbuff_pull(nb,sizeof (*eth)); - if (eth->type <=1500) + if (type <= 1500) { llch = (struct llchdr *) nb->data; type = llch->dsap & LLCADDRMASK; @@ -55,14 +55,10 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, } /* ARP packet */ - if (type == ARP_ETHERTYPE) - { - grub_net_arp_receive(inf, nb); - if (ethertype == ARP_ETHERTYPE) - return GRUB_ERR_NONE; - } + if (type == GRUB_NET_ETHERTYPE_ARP) + grub_net_arp_receive(inf, nb); /* IP packet */ - else if(type == IP_ETHERTYPE && ethertype == IP_ETHERTYPE) + if(type == GRUB_NET_ETHERTYPE_IP && ethertype == GRUB_NET_ETHERTYPE_IP) return GRUB_ERR_NONE; return GRUB_ERR_NONE; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 023564a5a..9a96ef532 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -54,7 +54,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, if (err) return err; - return send_ethernet_packet (inf, nb, ll_target_addr, IP_ETHERTYPE); + return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); } static int @@ -84,8 +84,11 @@ ip_filter (struct grub_net_buff *nb, grub_err_t grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf) { - struct grub_net_buff nb; - grub_net_recv_ethernet_packet (inf, &nb, IP_ETHERTYPE); - ip_filter (&nb, inf); + struct grub_net_buff *nb; + nb = grub_netbuff_alloc (2048); + if (!nb) + return grub_errno; + grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_IP); + ip_filter (nb, inf); return GRUB_ERR_NONE; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 5205e1938..54663f4b0 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -92,7 +92,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) *ip = grub_cpu_to_le32 (newip); if (rest) *rest = ptr - 1; - return 0; + return 1; } static int @@ -341,7 +341,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected")); FOR_NET_CARDS (card) - if (grub_strcmp (card->name, args[1])) + if (grub_strcmp (card->name, args[1]) == 0) break; if (card == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found")); @@ -464,7 +464,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_network_level_interface *inter; FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[2])) + if (grub_strcmp (inter->name, args[2]) == 0) break; if (!inter) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index b9e3f49c4..16b60eeb6 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -9,60 +9,15 @@ #include #include -struct { - int block_size; - int size; -} tftp_file; -static int block; - - -static char *get_tok_val(char **tok, char **val, char **str_opt,char *end); -static void process_option(char *tok, char *val); - -static char * -get_tok_val(char **tok, char **val,char **str_opt,char *end) -{ - char *p = *str_opt; - *tok = p; - p += grub_strlen(p) + 1; - - if(p > end) - return NULL; - - *val = p; - p += grub_strlen(p) + 1; - *str_opt = p; - return *tok; -} - -static void -process_option(char *tok, char *val) -{ - if (!grub_strcmp(tok,"blksize")) - { - tftp_file.block_size = grub_strtoul (val,NULL,0); - return; - } - - if (!grub_strcmp(tok,"tsize")) - { - tftp_file.size = grub_strtoul (val,NULL,0); - return; - } - -} - -//void tftp_open (char *options); - -/*send read request*/ static grub_err_t tftp_open (struct grub_file *file, const char *filename) { struct tftphdr *tftph; char *rrq; + char *ptr; int rrqlen; int hdrlen; - struct grub_net_buff nb; + struct grub_net_buff *nb; grub_net_network_level_address_t addr; grub_err_t err; @@ -70,29 +25,28 @@ tftp_open (struct grub_file *file, const char *filename) + sizeof ("tftp,") - 1, &addr); if (err) return err; - - grub_memset (&nb, 0, sizeof (nb)); - grub_netbuff_push (&nb,sizeof (*tftph)); - tftph = (struct tftphdr *) nb.data; + nb = grub_netbuff_alloc (2048); + if (!nb) + return grub_errno; + + grub_netbuff_reserve (nb,2048); + grub_netbuff_push (nb,sizeof (*tftph)); + + tftph = (struct tftphdr *) nb->data; rrq = (char *) tftph->u.rrq; rrqlen = 0; - tftph->opcode = TFTP_RRQ; + tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ); grub_strcpy (rrq, filename); rrqlen += grub_strlen (filename) + 1; rrq += grub_strlen (filename) + 1; - /*passar opcoes como parametro ou usar default?*/ grub_strcpy (rrq,"octet"); rrqlen += grub_strlen ("octet") + 1; rrq += grub_strlen ("octet") + 1; - //grub_strcpy (rrq,"netascii"); - //rrqlen += grub_strlen ("netascii") + 1; - //rrq += grub_strlen ("netascii") + 1; - grub_strcpy (rrq,"blksize"); rrqlen += grub_strlen("blksize") + 1; rrq += grub_strlen ("blksize") + 1; @@ -107,29 +61,53 @@ tftp_open (struct grub_file *file, const char *filename) grub_strcpy (rrq,"0"); rrqlen += grub_strlen ("0") + 1; - rrq += grub_strlen ("0") + 1; + rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - grub_netbuff_unput (&nb,nb.tail - (nb.data+hdrlen)); + grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); - grub_net_send_udp_packet (&addr, - &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + err = grub_net_send_udp_packet (&addr, + nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + if (err) + return err; - grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); - /*Receive OACK*/ - grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb,2048); - file->size = tftp_file.size; + /* Receive OACK. */ + grub_netbuff_clear (nb); + grub_netbuff_reserve (nb,2048); - return grub_net_recv_udp_packet (&addr, &nb, - TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + do + { + err = grub_net_recv_udp_packet (&addr, nb, + TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + if (err) + return err; + } + while (nb->tail == nb->data); + + file->size = 0; + + for (ptr = nb->data; ptr < nb->tail; ) + grub_printf ("%02x ", *ptr); + + for (ptr = nb->data; ptr < nb->tail; ) + { + if (grub_memcmp (ptr, "tsize\0=", sizeof ("tsize\0=") - 1) == 0) + { + file->size = grub_strtoul (ptr + sizeof ("tsize\0=") - 1, 0, 0); + grub_errno = GRUB_ERR_NONE; + } + while (ptr < nb->tail && *ptr) + ptr++; + ptr++; + } + return GRUB_ERR_NONE; } static grub_ssize_t tftp_receive (struct grub_file *file, char *buf, grub_size_t len) { struct tftphdr *tftph; - char *token,*value,*temp; + // char *token,*value,*temp; grub_err_t err; grub_net_network_level_address_t addr; struct grub_net_buff nb; @@ -143,38 +121,21 @@ tftp_receive (struct grub_file *file, char *buf, grub_size_t len) TFTP_CLIENT_PORT, TFTP_SERVER_PORT); tftph = (struct tftphdr *) nb.data; - switch (tftph->opcode) + switch (grub_be_to_cpu16 (tftph->opcode)) { - case TFTP_OACK: - /*process oack packet*/ - temp = (char *) tftph->u.oack.data; - while(get_tok_val(&token,&value,&temp,nb.tail)) - { - process_option(token,value); - } - - //buff_clean - grub_netbuff_clear(&nb); - // grub_printf("OACK---------------------------------------------------------\n"); - //grub_printf("block_size=%d\n",tftp_file.block_size); - // grub_printf("file_size=%d\n",tftp_file.size); - // grub_printf("OACK---------------------------------------------------------\n"); - block = 0; - break; case TFTP_DATA: grub_netbuff_pull (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); - if (tftph->u.data.block == block + 1) - { - block = tftph->u.data.block; + // if (tftph->u.data.block == block + 1) + //{ + // block = tftph->u.data.block; grub_memcpy (buf, nb.data, len); - } - else - grub_netbuff_clear(&nb); - break; + //} + //else + //grub_netbuff_clear(&nb); + break; case TFTP_ERROR: grub_netbuff_clear (&nb); - return grub_error (GRUB_ERR_ACCESS_DENIED, (char *)tftph->u.err.errmsg); - break; + return grub_error (GRUB_ERR_IO, (char *)tftph->u.err.errmsg); } nb.data = nb.tail = nb.end; @@ -182,8 +143,8 @@ tftp_receive (struct grub_file *file, char *buf, grub_size_t len) grub_netbuff_push (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); tftph = (struct tftphdr *) nb.data; - tftph->opcode = TFTP_ACK; - tftph->u.ack.block = block; + tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); + // tftph->u.ack.block = block; return grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); } diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 1475086e4..691fda307 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -3,13 +3,11 @@ #include #include -/* IANA ARP constant to define hardware type as ethernet */ -#define ARPHRD_ETHERNET 1 -/* IANA Ethertype */ -#define ARP_ETHERTYPE 0x806 - -/* Size for cache table */ -#define SIZE_ARP_TABLE 5 +enum +{ +/* IANA ARP constant to define hardware type as ethernet. */ + GRUB_NET_ARPHRD_ETHERNET = 1 +}; /* ARP header operation codes */ #define ARP_REQUEST 1 diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index b4f07992b..7a0235be6 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -38,6 +38,14 @@ struct snaphdr grub_uint16_t type; } __attribute__ ((packed)); +/* IANA Ethertype */ +enum +{ + GRUB_NET_ETHERTYPE_IP = 0x0800, + GRUB_NET_ETHERTYPE_ARP = 0x0806 +}; + + grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 765d8005e..6f748bbf3 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -2,8 +2,6 @@ #define GRUB_NET_IP_HEADER 1 #include -#define IP_ETHERTYPE 0x800 /* IANA Ethertype */ - struct iphdr { grub_uint8_t verhdrlen; grub_uint8_t service; From c5dc16905aea5bce096c5a2061c236712b6e4686 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 6 Oct 2010 19:57:01 +0200 Subject: [PATCH 035/673] Make enable of disk cache statistics code configurable. * configure.ac: --enable-cache-stats added. * config.h.in (DISK_CACHE_STATS): New define. * grub-core/Makefile.core.def (cacheinfo): New command. * include/grub/disk.h(grub_disk_cache_get_performance): New function. * grub-core/commands/cacheinfo.c: New file. * grub-core/commands/minicmd.c (grub_rescue_cmd_info): Updated and moved to cacheinfo.c. * grub-core/kern/disk.c: Use DISK_CACHE_STATS to disable disk cache debug code. * include/grub/disk.h: Likewise. --- ChangeLog | 15 +++++++++ config.h.in | 2 ++ configure.ac | 17 ++++++++++ grub-core/Makefile.core.def | 6 ++++ grub-core/commands/cacheinfo.c | 58 ++++++++++++++++++++++++++++++++++ grub-core/commands/minicmd.c | 20 ------------ grub-core/kern/disk.c | 6 ++-- include/grub/disk.h | 5 +++ 8 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 grub-core/commands/cacheinfo.c diff --git a/ChangeLog b/ChangeLog index cc3c87445..6d54b6301 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2010-10-05 Szymon Janc + + Make enable of disk cache statistics code configurable. + + * configure.ac: --enable-cache-stats added. + * config.h.in (DISK_CACHE_STATS): New define. + * grub-core/Makefile.core.def (cacheinfo): New command. + * include/grub/disk.h(grub_disk_cache_get_performance): New function. + * grub-core/commands/cacheinfo.c: New file. + * grub-core/commands/minicmd.c (grub_rescue_cmd_info): Updated and + moved to cacheinfo.c. + * grub-core/kern/disk.c: Use DISK_CACHE_STATS to disable disk cache + debug code. + * include/grub/disk.h: Likewise. + 2010-10-02 AleÅ¡ Nesrsta * include/grub/scsi.h: diff --git a/config.h.in b/config.h.in index 6d7d95dec..cfe6a94b2 100644 --- a/config.h.in +++ b/config.h.in @@ -32,6 +32,8 @@ #define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@ /* Define to 1 if GCC generates calls to __register_frame_info(). */ #define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@ +/* Define to 1 to enable disk cache statistics. */ +#define DISK_CACHE_STATS @DISK_CACHE_STATS@ #if defined(__i386__) #define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) diff --git a/configure.ac b/configure.ac index 66d4a6877..b3b5652d1 100644 --- a/configure.ac +++ b/configure.ac @@ -669,6 +669,17 @@ AC_ARG_ENABLE([mm-debug], [AC_DEFINE([MM_DEBUG], [1], [Define to 1 if you enable memory manager debugging.])]) +AC_ARG_ENABLE([cache-stats], + AS_HELP_STRING([--enable-cache-stats], + [enable disk cache statistics collection])]) + +if test x$enable_cache_stats = xyes; then + DISK_CACHE_STATS=1 +else + DISK_CACHE_STATS=0 +fi +AC_SUBST([DISK_CACHE_STATS]) + AC_ARG_ENABLE([grub-emu-usb], [AS_HELP_STRING([--enable-grub-emu-usb], [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) @@ -922,6 +933,7 @@ AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) +AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1]) AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1]) @@ -983,6 +995,11 @@ echo With memory debugging: Yes else echo With memory debugging: No fi +if [ x"$enable_cache_stats" = xyes ]; then +echo With disk cache statistics: Yes +else +echo With disk cache statistics: No +fi if [ x"$efiemu_excuse" = x ]; then echo efiemu runtime: Yes else diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8845c26ea..51ae522a6 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1502,3 +1502,9 @@ module = { common = commands/keylayouts.c; enable = videomodules; }; + +module = { + name = cacheinfo; + common = commands/cacheinfo.c; + condition = COND_ENABLE_CACHE_STATS; +}; diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c new file mode 100644 index 000000000..771763c9c --- /dev/null +++ b/grub-core/commands/cacheinfo.c @@ -0,0 +1,58 @@ +/* cacheinfo.c - disk cache statistics */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2010 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 . + */ + +#include +#include +#include +#include +#include + +static grub_err_t +grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + unsigned long hits, misses; + + grub_disk_cache_get_performance (&hits, &misses); + grub_printf ("Disk cache: hits = %lu, misses = %lu ", hits, misses); + if (hits + misses) + { + unsigned long ratio = hits * 10000 / (hits + misses); + grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100); + } + else + grub_printf ("(N/A)\n"); + + return 0; +} + +static grub_command_t cmd_cacheinfo; + +GRUB_MOD_INIT(cacheinfo) +{ + cmd_cacheinfo = + grub_register_command ("cacheinfo", grub_rescue_cmd_info, + 0, N_("Get disk cache info.")); +} + +GRUB_MOD_FINI(cacheinfo) +{ + grub_unregister_command (cmd_cacheinfo); +} diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 5cf109fde..5c90e8ac5 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -88,26 +88,6 @@ grub_mini_cmd_help (struct grub_command *cmd __attribute__ ((unused)), return 0; } -#if 0 -static void -grub_rescue_cmd_info (void) -{ - extern void grub_disk_cache_get_performance (unsigned long *, - unsigned long *); - unsigned long hits, misses; - - grub_disk_cache_get_performance (&hits, &misses); - grub_printf ("Disk cache: hits = %u, misses = %u ", hits, misses); - if (hits + misses) - { - unsigned long ratio = hits * 10000 / (hits + misses); - grub_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100); - } - else - grub_printf ("(N/A)\n"); -} -#endif - /* dump ADDRESS [SIZE] */ static grub_err_t grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)), diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 807ee4277..2d50ea60c 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -50,7 +50,7 @@ grub_err_t (* grub_disk_ata_pass_through) (grub_disk_t, struct grub_disk_ata_pass_through_parms *); -#if 0 +#if DISK_CACHE_STATS static unsigned long grub_disk_cache_hits; static unsigned long grub_disk_cache_misses; @@ -123,13 +123,13 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id, && cache->sector == sector) { cache->lock = 1; -#if 0 +#if DISK_CACHE_STATS grub_disk_cache_hits++; #endif return cache->data; } -#if 0 +#if DISK_CACHE_STATS grub_disk_cache_misses++; #endif diff --git a/include/grub/disk.h b/include/grub/disk.h index 9c5653e00..783640d19 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -160,6 +160,11 @@ grub_err_t EXPORT_FUNC(grub_disk_write) (grub_disk_t disk, grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk); +#if DISK_CACHE_STATS +void +EXPORT_FUNC(grub_disk_cache_get_performance) (unsigned long *hits, unsigned long *misses); +#endif + extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void); extern int EXPORT_VAR(grub_disk_firmware_is_tainted); From 5d49b1e69c82de6a07195dc39e7e601feeedd44d Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 6 Oct 2010 22:09:07 +0200 Subject: [PATCH 036/673] Move last changelog entry from ChangeLog to ChangeLog.cacheinfo. --- ChangeLog | 15 --------------- ChangeLog.cacheinfo | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 15 deletions(-) create mode 100644 ChangeLog.cacheinfo diff --git a/ChangeLog b/ChangeLog index 6d54b6301..cc3c87445 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,18 +1,3 @@ -2010-10-05 Szymon Janc - - Make enable of disk cache statistics code configurable. - - * configure.ac: --enable-cache-stats added. - * config.h.in (DISK_CACHE_STATS): New define. - * grub-core/Makefile.core.def (cacheinfo): New command. - * include/grub/disk.h(grub_disk_cache_get_performance): New function. - * grub-core/commands/cacheinfo.c: New file. - * grub-core/commands/minicmd.c (grub_rescue_cmd_info): Updated and - moved to cacheinfo.c. - * grub-core/kern/disk.c: Use DISK_CACHE_STATS to disable disk cache - debug code. - * include/grub/disk.h: Likewise. - 2010-10-02 AleÅ¡ Nesrsta * include/grub/scsi.h: diff --git a/ChangeLog.cacheinfo b/ChangeLog.cacheinfo new file mode 100644 index 000000000..a26271cca --- /dev/null +++ b/ChangeLog.cacheinfo @@ -0,0 +1,14 @@ +2010-10-05 Szymon Janc + + Make enable of disk cache statistics code configurable. + + * configure.ac: --enable-cache-stats added. + * config.h.in (DISK_CACHE_STATS): New define. + * grub-core/Makefile.core.def (cacheinfo): New command. + * include/grub/disk.h(grub_disk_cache_get_performance): New function. + * grub-core/commands/cacheinfo.c: New file. + * grub-core/commands/minicmd.c (grub_rescue_cmd_info): Updated and + moved to cacheinfo.c. + * grub-core/kern/disk.c: Use DISK_CACHE_STATS to disable disk cache + debug code. + * include/grub/disk.h: Likewise. From 7a6e93788cda1f9ead6b4fdb25ea72b7a434eddd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 4 Dec 2010 00:40:44 +0100 Subject: [PATCH 037/673] ZFS zlib compression support --- grub-core/fs/zfs/zfs.c | 22 ++++++++++++++++++++-- include/grub/zfs/zio.h | 10 +++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 8901af76f..d7bf2bc30 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -51,6 +51,7 @@ #include #include #include +#include #define ZPOOL_PROP_BOOTFS "bootfs" @@ -161,13 +162,30 @@ struct grub_zfs_data grub_disk_addr_t vdev_phys_sector; }; +static grub_err_t +zlib_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) +{ + if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0) + return grub_errno; + return GRUB_ERR_NONE; +} + decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"inherit", NULL}, /* ZIO_COMPRESS_INHERIT */ {"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */ {"off", NULL}, /* ZIO_COMPRESS_OFF */ {"lzjb", lzjb_decompress}, /* ZIO_COMPRESS_LZJB */ {"empty", NULL}, /* ZIO_COMPRESS_EMPTY */ - {"gzip", NULL}, /* ZIO_COMPRESS_GZIP */ + {"gzip-1", zlib_decompress}, /* ZIO_COMPRESS_GZIP1 */ + {"gzip-2", zlib_decompress}, /* ZIO_COMPRESS_GZIP2 */ + {"gzip-3", zlib_decompress}, /* ZIO_COMPRESS_GZIP3 */ + {"gzip-4", zlib_decompress}, /* ZIO_COMPRESS_GZIP4 */ + {"gzip-5", zlib_decompress}, /* ZIO_COMPRESS_GZIP5 */ + {"gzip-6", zlib_decompress}, /* ZIO_COMPRESS_GZIP6 */ + {"gzip-7", zlib_decompress}, /* ZIO_COMPRESS_GZIP7 */ + {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ + {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ }; static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, @@ -525,7 +543,7 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, *buf = NULL; checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; - comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7; + comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; lsize = (BP_IS_HOLE(bp) ? 0 : (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) << SPA_MINBLOCKSHIFT)); diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h index 797d4f9b3..3dafb4028 100644 --- a/include/grub/zfs/zio.h +++ b/include/grub/zfs/zio.h @@ -77,7 +77,15 @@ enum zio_compress { ZIO_COMPRESS_OFF, ZIO_COMPRESS_LZJB, ZIO_COMPRESS_EMPTY, - ZIO_COMPRESS_GZIP, + ZIO_COMPRESS_GZIP1, + ZIO_COMPRESS_GZIP2, + ZIO_COMPRESS_GZIP3, + ZIO_COMPRESS_GZIP4, + ZIO_COMPRESS_GZIP5, + ZIO_COMPRESS_GZIP6, + ZIO_COMPRESS_GZIP7, + ZIO_COMPRESS_GZIP8, + ZIO_COMPRESS_GZIP9, ZIO_COMPRESS_FUNCTIONS }; From c5cf9f53a839f38405fd9fe10999c3231c30322a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 4 Dec 2010 01:59:06 +0100 Subject: [PATCH 038/673] Fix short symlinks --- grub-core/fs/zfs/zfs.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index d7bf2bc30..8f20085fa 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1306,22 +1306,27 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, break; *path = ch; -#if 0 - if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa && ch) + if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) { char *oldpath = path, *oldpathbuf = path_buf; + grub_size_t bonuslen; + bonuslen = (grub_uint8_t *) (&dnode_path->dn.dn + 1) + - (grub_uint8_t *) DN_BONUS (&dnode_path->dn.dn); + if (bonuslen <= sizeof (znode_phys_t)) + err = grub_error (GRUB_ERR_BAD_FS, + "incorrect or unsupported symlink"); path = path_buf - = grub_malloc (sizeof (dnode_path->dn.dn.dn_bonus) - - sizeof (znode_phys_t) + grub_strlen (oldpath) + 1); + = grub_malloc (bonuslen - sizeof (znode_phys_t) + + grub_strlen (oldpath) + 1); if (!path_buf) { grub_free (oldpathbuf); return grub_errno; } - grub_memcpy (path, - (char *) DN_BONUS(&dnode_path->dn.dn) + sizeof (znode_phys_t), - sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t)); - path [sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t)] = 0; + grub_memcpy (path, (char *) DN_BONUS(&dnode_path->dn.dn) + + sizeof (znode_phys_t), + bonuslen - sizeof (znode_phys_t)); + path[bonuslen - sizeof (znode_phys_t)] = 0; grub_memcpy (path + grub_strlen (path), oldpath, grub_strlen (oldpath) + 1); @@ -1339,7 +1344,6 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, grub_free (dn_new); } } -#endif } if (!err) From fe79a8ad9db01795baccfc28525a5d75f03d0959 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 5 Dec 2010 15:35:08 +0100 Subject: [PATCH 039/673] Fix fzap handling --- grub-core/fs/zfs/zfs.c | 4 +++- include/grub/zfs/zap_leaf.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 8f20085fa..c47b4afc9 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -961,7 +961,8 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small"); return 0; } - for (idx = 0; idx < zap->zap_ptrtbl.zt_numblks; idx++) + for (idx = 0; idx < grub_zfs_to_cpu64 (zap->zap_num_leafs, + zap_dnode->endian); idx++) { blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))]; @@ -2553,6 +2554,7 @@ static struct grub_fs grub_zfs_fs = { GRUB_MOD_INIT (zfs) { + COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE); grub_fs_register (&grub_zfs_fs); #ifndef GRUB_UTIL my_mod = mod; diff --git a/include/grub/zfs/zap_leaf.h b/include/grub/zfs/zap_leaf.h index 1ef654054..5adfdc290 100644 --- a/include/grub/zfs/zap_leaf.h +++ b/include/grub/zfs/zap_leaf.h @@ -90,7 +90,7 @@ typedef union zap_leaf_chunk { { grub_uint8_t la_array[ZAP_LEAF_ARRAY_BYTES]; grub_uint64_t la_array64; - }; + } __attribute__ ((packed)); grub_uint16_t la_next; /* next blk or CHAIN_END */ } l_array; struct zap_leaf_free { From 47c3603cc8deeae7bf03bb7fc6756d9c58fe5e00 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 5 Dec 2010 15:41:17 +0100 Subject: [PATCH 040/673] Add missing endianness conversions in fzap code --- grub-core/fs/zfs/zfs.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index c47b4afc9..62d7051ef 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -831,7 +831,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, return grub_error (GRUB_ERR_BAD_FS, "invalid leaf magic"); for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h)], endian); - chunk != CHAIN_END; chunk = le->le_next) + chunk != CHAIN_END; chunk = grub_zfs_to_cpu16 (le->le_next, endian)) { if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) @@ -856,7 +856,8 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, struct zap_leaf_array *la; grub_uint8_t *ip; - if (le->le_int_size != 8 || le->le_value_length != 1) + if (le->le_int_size != 8 || grub_zfs_to_cpu16 (le->le_value_length, + endian) != 1) return grub_error (GRUB_ERR_BAD_FS, "invalid leaf chunk entry"); /* get the uint64_t property value */ @@ -875,9 +876,9 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, /* Verify if this is a fat zap header block */ static grub_err_t -zap_verify (zap_phys_t *zap) +zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) { - if (zap->zap_magic != (grub_uint64_t) ZAP_MAGIC) + if (grub_zfs_to_cpu64 (zap->zap_magic, endian) != (grub_uint64_t) ZAP_MAGIC) return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic"); if (zap->zap_flags != 0) @@ -905,7 +906,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, grub_err_t err; grub_zfs_endian_t leafendian; - err = zap_verify (zap); + err = zap_verify (zap, zap_dnode->endian); if (err) return err; @@ -916,7 +917,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "external pointer tables not supported"); idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift); - blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))]; + blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], zap_dnode->endian); /* Get the leaf block */ if ((1U << blksft) < sizeof (zap_leaf_phys_t)) @@ -945,7 +946,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, grub_err_t err; grub_zfs_endian_t endian; - if (zap_verify (zap)) + if (zap_verify (zap, zap_dnode->endian)) return 0; /* get block id from index */ @@ -964,7 +965,8 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, for (idx = 0; idx < grub_zfs_to_cpu64 (zap->zap_num_leafs, zap_dnode->endian); idx++) { - blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))]; + blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], + zap_dnode->endian); err = dmu_read (zap_dnode, blkid, (void **) &l, &endian, data); if (err) @@ -999,8 +1001,11 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) + 1); - if (zap_leaf_array_get (l, endian, blksft, le->le_name_chunk, - le->le_name_length, buf)) + if (zap_leaf_array_get (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_name_chunk, + endian), + grub_zfs_to_cpu16 (le->le_name_length, + endian), buf)) { grub_free (buf); continue; @@ -1012,7 +1017,9 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, continue; /* get the uint64_t property value */ - la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk).l_array; + la = &ZAP_LEAF_CHUNK (l, blksft, + grub_zfs_to_cpu16 (le->le_value_chunk, + endian)).l_array; val = grub_be_to_cpu64 (la->la_array64); if (hook (buf, val)) return 1; From 069142f4c2cd0eab6528a4abfc955b308c47d113 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 5 Dec 2010 16:08:26 +0100 Subject: [PATCH 041/673] Support long symlinks --- grub-core/fs/zfs/zfs.c | 47 +++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 62d7051ef..bf955a930 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1323,18 +1323,45 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, if (bonuslen <= sizeof (znode_phys_t)) err = grub_error (GRUB_ERR_BAD_FS, "incorrect or unsupported symlink"); - path = path_buf - = grub_malloc (bonuslen - sizeof (znode_phys_t) - + grub_strlen (oldpath) + 1); - if (!path_buf) + if (dnode_path->dn.dn.dn_flags & 1) { - grub_free (oldpathbuf); - return grub_errno; + void *sbuf; + grub_size_t ssize; + err = zio_read (dnode_path->dn.dn.dn_blkptr, + dnode_path->dn.endian, &sbuf, + &ssize, data); + if (err) + { + grub_free (oldpathbuf); + return err; + } + + path = path_buf = grub_malloc (ssize+ grub_strlen (oldpath) + 1); + if (!path_buf) + { + grub_free (oldpathbuf); + grub_free (sbuf); + return grub_errno; + } + grub_memcpy (path, sbuf, ssize); + path[ssize] = 0; + grub_free (sbuf); + } + else + { + path = path_buf + = grub_malloc (bonuslen - sizeof (znode_phys_t) + + grub_strlen (oldpath) + 1); + if (!path_buf) + { + grub_free (oldpathbuf); + return grub_errno; + } + grub_memcpy (path, (char *) DN_BONUS(&dnode_path->dn.dn) + + sizeof (znode_phys_t), + bonuslen - sizeof (znode_phys_t)); + path[bonuslen - sizeof (znode_phys_t)] = 0; } - grub_memcpy (path, (char *) DN_BONUS(&dnode_path->dn.dn) - + sizeof (znode_phys_t), - bonuslen - sizeof (znode_phys_t)); - path[bonuslen - sizeof (znode_phys_t)] = 0; grub_memcpy (path + grub_strlen (path), oldpath, grub_strlen (oldpath) + 1); From e5c63d9d4183e40f155e84f3313b9f1490064659 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 5 Dec 2010 18:13:32 +0100 Subject: [PATCH 042/673] Fix handling of nvlist array --- grub-core/fs/zfs/zfs.c | 48 ++++++++++++++++++++++++-------------- grub-core/fs/zfs/zfsinfo.c | 2 +- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index bf955a930..670326a42 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1812,13 +1812,28 @@ grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name) grub_size_t nelm, size; int found; - found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair, + found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair, &size, &nelm); if (! found) return -1; return nelm; } +static int +get_nvlist_size (char *beg, char *limit) +{ + char *ptr; + grub_uint32_t encode_size; + + ptr = beg + 8; + + while (ptr < limit + && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) ptr))) + ptr += encode_size; /* goto the next nvpair */ + ptr += 8; + return (ptr > limit) ? -1 : (ptr - beg); +} + char * grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name, grub_size_t index) @@ -1829,8 +1844,9 @@ grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name, grub_size_t size; unsigned i; grub_size_t nelm; + int elemsize = 0; - found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair, + found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair, &size, &nelm); if (!found) return 0; @@ -1844,33 +1860,31 @@ grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name, for (i = 0; i < index; i++) { - grub_uint32_t encode_size; + int r; + r = get_nvlist_size (nvpairptr, nvpair + size); - /* skip the header, nvl_version, and nvl_nvflag */ - nvpairptr = nvpairptr + 4 * 2; - - while (nvpairptr < nvpair + size - && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) nvpairptr))) - nvlist += encode_size; /* goto the next nvpair */ - - nvlist = nvlist + 4 * 2; /* skip the ending 2 zeros - 8 bytes */ + if (r < 0) + { + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist array"); + return NULL; + } + nvpairptr += r; } - if (nvpairptr >= nvpair + size - || nvpairptr + grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2)) - >= nvpair + size) + elemsize = get_nvlist_size (nvpairptr, nvpair + size); + + if (elemsize < 0) { grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist array"); return 0; } - ret = grub_zalloc (grub_be_to_cpu32 (*(grub_uint32_t *) (nvpairptr + 4 * 2)) - + 3 * sizeof (grub_uint32_t)); + ret = grub_zalloc (elemsize + sizeof (grub_uint32_t)); if (!ret) return 0; grub_memcpy (ret, nvlist, sizeof (grub_uint32_t)); - grub_memcpy (ret + sizeof (grub_uint32_t), nvpairptr, size); + grub_memcpy (ret + sizeof (grub_uint32_t), nvpairptr, elemsize); return ret; } diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index 33065892a..735b8e983 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -139,7 +139,6 @@ print_vdev_info (char *nvlist, int tab) } grub_printf ("Mirror VDEV with %d children\n", nelm); print_state (nvlist, tab); - for (i = 0; i < nelm; i++) { char *child; @@ -159,6 +158,7 @@ print_vdev_info (char *nvlist, int tab) grub_free (child); } + return GRUB_ERR_NONE; } print_tabs (tab); From fdfde32aa4f1d4ce00d86cf481401cf215b8861e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 5 Dec 2010 21:17:24 +0100 Subject: [PATCH 043/673] striped zpool support --- Makefile.util.def | 1 + grub-core/fs/zfs/zfs.c | 659 +++++++++++++++++++++++++---------------- util/grub-fstest.c | 8 + 3 files changed, 412 insertions(+), 256 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 2dd7fe1e9..0e2e0afa8 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -71,6 +71,7 @@ library = { common = grub-core/fs/ufs.c; common = grub-core/fs/xfs.c; common = grub-core/fs/zfs/zfs.c; + common = grub-core/fs/zfs/zfsinfo.c; common = grub-core/fs/zfs/zfs_lzjb.c; common = grub-core/fs/zfs/zfs_sha256.c; common = grub-core/fs/zfs/zfs_fletcher.c; diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 670326a42..3163e2e78 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -138,6 +138,15 @@ typedef struct dnode_end grub_zfs_endian_t endian; } dnode_end_t; +struct grub_zfs_device_desc +{ + enum { DEVICE_LEAF } type; + grub_disk_t disk; + grub_uint64_t id; + grub_disk_addr_t vdev_phys_sector; + uberblock_t current_uberblock; +}; + struct grub_zfs_data { /* cache for a file block of the currently zfs_open()-ed file */ @@ -152,14 +161,16 @@ struct grub_zfs_data grub_uint64_t dnode_end; grub_zfs_endian_t dnode_endian; - uberblock_t current_uberblock; - grub_disk_t disk; - dnode_end_t mos; dnode_end_t mdn; dnode_end_t dnode; - grub_disk_addr_t vdev_phys_sector; + struct grub_zfs_device_desc *devices_attached; + unsigned n_devices_attached; + unsigned n_devices_allocated; + + int mounted; + grub_uint64_t guid; }; static grub_err_t @@ -408,7 +419,7 @@ get_psize (blkptr_t * bp, grub_zfs_endian_t endian) } static grub_uint64_t -dva_get_offset (dva_t * dva, grub_zfs_endian_t endian) +dva_get_offset (const dva_t *dva, grub_zfs_endian_t endian) { grub_dprintf ("zfs", "dva=%llx, %llx\n", (unsigned long long) dva->dva_word[0], @@ -417,6 +428,356 @@ dva_get_offset (dva_t * dva, grub_zfs_endian_t endian) endian) << SPA_MINBLOCKSHIFT; } +static grub_err_t +zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist) +{ + grub_err_t err; + + *nvlist = grub_malloc (VDEV_PHYS_SIZE); + /* Read in the vdev name-value pair list (112K). */ + err = grub_disk_read (diskdesc->disk, diskdesc->vdev_phys_sector, 0, + VDEV_PHYS_SIZE, *nvlist); + if (err) + { + grub_free (*nvlist); + *nvlist = 0; + return err; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +fill_vdev_info (char *nvlist, struct grub_zfs_device_desc *diskdesc) +{ + char *type = 0; + + type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE); + + if (!type) + return grub_errno; + if (grub_strcmp (type, VDEV_TYPE_DISK) == 0) + { + diskdesc->type = DEVICE_LEAF; + if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &diskdesc->id)) + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported", + type); +} + +/* + * Check the disk label information and retrieve needed vdev name-value pairs. + * + */ +static grub_err_t +check_pool_label (struct grub_zfs_data *data, + struct grub_zfs_device_desc *diskdesc, + grub_uint64_t *id) +{ + grub_uint64_t pool_state, txg = 0; + char *nvlist; +#if 0 + char *nv; +#endif + grub_uint64_t diskguid, poolguid; + grub_uint64_t version; + int found; + grub_err_t err; + + err = zfs_fetch_nvlist (diskdesc, &nvlist); + if (err) + return err; + + grub_dprintf ("zfs", "check 2 passed\n"); + + found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE, + &pool_state); + if (! found) + { + grub_free (nvlist); + if (! grub_errno) + grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_STATE " not found"); + return grub_errno; + } + grub_dprintf ("zfs", "check 3 passed\n"); + + if (pool_state == POOL_STATE_DESTROYED) + { + grub_free (nvlist); + return grub_error (GRUB_ERR_BAD_FS, "zpool is marked as destroyed"); + } + grub_dprintf ("zfs", "check 4 passed\n"); + + found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_TXG, &txg); + if (!found) + { + grub_free (nvlist); + if (! grub_errno) + grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_TXG " not found"); + return grub_errno; + } + grub_dprintf ("zfs", "check 6 passed\n"); + + /* not an active device */ + if (txg == 0) + { + grub_free (nvlist); + return grub_error (GRUB_ERR_BAD_FS, "zpool isn't active"); + } + grub_dprintf ("zfs", "check 7 passed\n"); + + found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_VERSION, + &version); + if (! found) + { + grub_free (nvlist); + if (! grub_errno) + grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_VERSION " not found"); + return grub_errno; + } + grub_dprintf ("zfs", "check 8 passed\n"); + + if (version > SPA_VERSION) + { + grub_free (nvlist); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "too new version %llu > %llu", + (unsigned long long) version, + (unsigned long long) SPA_VERSION); + } + grub_dprintf ("zfs", "check 9 passed\n"); + + { + char *nv; + nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE); + + if (!nv) + { + grub_free (nvlist); + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev tree"); + } + err = fill_vdev_info (nv, diskdesc); + if (err) + { + grub_free (nvlist); + return err; + } + } + grub_dprintf ("zfs", "check 10 passed\n"); + + found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID, &diskguid); + if (! found) + { + grub_free (nvlist); + if (! grub_errno) + grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_GUID " not found"); + return grub_errno; + } + + found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, + &poolguid); + if (! found) + { + grub_free (nvlist); + if (! grub_errno) + grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_GUID " not found"); + return grub_errno; + } + + grub_dprintf ("zfs", "check 11 passed\n"); + + if (data->mounted && data->guid != poolguid) + return grub_error (GRUB_ERR_BAD_FS, "another zpool"); + else + data->guid = poolguid; + grub_free (nvlist); + + data->n_devices_attached++; + if (data->n_devices_attached > data->n_devices_allocated) + { + void *tmp; + data->n_devices_allocated = 2 * data->n_devices_attached + 1; + data->devices_attached + = grub_realloc (tmp = data->devices_attached, + data->n_devices_allocated + * sizeof (data->devices_attached[0])); + if (!data->devices_attached) + { + data->devices_attached = tmp; + return grub_errno; + } + } + + data->devices_attached[data->n_devices_attached - 1] = *diskdesc; + if (id) + *id = diskdesc->id; + + return GRUB_ERR_NONE; +} + +static grub_err_t +scan_disk (grub_disk_t disk, struct grub_zfs_data *data, + grub_uint64_t *id) +{ + int label = 0; + uberblock_phys_t *ub_array, *ubbest = NULL; + vdev_boot_header_t *bh; + grub_err_t err; + int vdevnum; + struct grub_zfs_device_desc desc; + + ub_array = grub_malloc (VDEV_UBERBLOCK_RING); + if (!ub_array) + return grub_errno; + + bh = grub_malloc (VDEV_BOOT_HEADER_SIZE); + if (!bh) + { + grub_free (ub_array); + return grub_errno; + } + + vdevnum = VDEV_LABELS; + + desc.disk = disk; + + /* Don't check back labels on CDROM. */ + if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN) + vdevnum = VDEV_LABELS / 2; + + for (label = 0; ubbest == NULL && label < vdevnum; label++) + { + grub_dprintf ("zfs", "label %d\n", label); + + desc.vdev_phys_sector + = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT) + + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT) + + (label < VDEV_LABELS / 2 ? 0 : grub_disk_get_size (disk) + - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)); + + /* Read in the uberblock ring (128K). */ + err = grub_disk_read (disk, desc.vdev_phys_sector + + (VDEV_PHYS_SIZE >> SPA_MINBLOCKSHIFT), + 0, VDEV_UBERBLOCK_RING, (char *) ub_array); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + grub_dprintf ("zfs", "label ok %d\n", label); + + ubbest = find_bestub (ub_array, desc.vdev_phys_sector); + if (!ubbest) + { + grub_dprintf ("zfs", "No uberblock found\n"); + grub_errno = GRUB_ERR_NONE; + continue; + } + + grub_memmove (&(desc.current_uberblock), + &ubbest->ubp_uberblock, sizeof (uberblock_t)); + + err = check_pool_label (data, &desc, id); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } +#if 0 + if (find_best_root && + vdev_uberblock_compare (&ubbest->ubp_uberblock, + &(current_uberblock)) <= 0) + continue; +#endif + grub_free (ub_array); + grub_free (bh); + return GRUB_ERR_NONE; + } + + grub_free (ub_array); + grub_free (bh); + + return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label"); +} + +static grub_err_t +scan_devices (struct grub_zfs_data *data, grub_uint64_t id) +{ + grub_device_t dev_found = NULL; + auto int hook (const char *name); + int hook (const char *name) + { + grub_device_t dev; + grub_err_t err; + grub_uint64_t f_id = -1; + dev = grub_device_open (name); + if (!dev) + return 0; + if (!dev->disk) + { + grub_device_close (dev); + return 0; + } + err = scan_disk (dev->disk, data, &f_id); + if (err == GRUB_ERR_BAD_FS) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (err) + { + grub_device_close (dev); + grub_print_error (); + return 0; + } + if (f_id != id) + { + grub_device_close (dev); + return 0; + } + + dev_found = dev; + return 1; + } + grub_device_iterate (hook); + if (!dev_found) + return grub_error (GRUB_ERR_BAD_FS, + "couldn't find device 0x%" PRIxGRUB_UINT64_T, id); + return GRUB_ERR_NONE; +} + +static grub_err_t +read_dva (const dva_t *dva, + grub_zfs_endian_t endian, struct grub_zfs_data *data, + void *buf, grub_size_t len) +{ + grub_uint64_t offset, sector; + unsigned i; + grub_err_t err; + int try = 0; + + for (try = 0; try < 1; try++) + { + for (i = 0; i < data->n_devices_attached; i++) + if (data->devices_attached[i].id == DVA_GET_VDEV (dva)) + { + /* read in a data block */ + offset = dva_get_offset (dva, endian); + sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); + return grub_disk_read (data->devices_attached[i].disk, sector, + 0, len, buf); + } + err = scan_devices (data, DVA_GET_VDEV (dva)); + if (err) + return err; + } + return grub_error (GRUB_ERR_BAD_FS, + "couldn't find device 0x%" PRIxGRUB_UINT64_T, + DVA_GET_VDEV (dva)); +} /* * Read a block of data based on the gang block address dva, @@ -428,7 +789,6 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, struct grub_zfs_data *data) { zio_gbh_phys_t *zio_gb; - grub_uint64_t offset, sector; unsigned i; grub_err_t err; zio_cksum_t zc; @@ -440,13 +800,8 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, return grub_errno; grub_dprintf ("zfs", endian == LITTLE_ENDIAN ? "little-endian gang\n" :"big-endian gang\n"); - offset = dva_get_offset (dva, endian); - sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); - grub_dprintf ("zfs", "offset=%llx\n", (unsigned long long) offset); - /* read in the gang block header */ - err = grub_disk_read (data->disk, sector, 0, SPA_GANGBLOCKSIZE, - (char *) zio_gb); + err = read_dva (dva, endian, data, zio_gb, SPA_GANGBLOCKSIZE); if (err) { grub_free (zio_gb); @@ -499,20 +854,13 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, /* pick a good dva from the block pointer */ for (i = 0; i < SPA_DVAS_PER_BP; i++) { - grub_uint64_t offset, sector; - if (bp->blk_dva[i].dva_word[0] == 0 && bp->blk_dva[i].dva_word[1] == 0) continue; if ((grub_zfs_to_cpu64 (bp->blk_dva[i].dva_word[1], endian)>>63) & 1) err = zio_read_gang (bp, endian, &bp->blk_dva[i], buf, data); else - { - /* read in a data block */ - offset = dva_get_offset (&bp->blk_dva[i], endian); - sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); - err = grub_disk_read (data->disk, sector, 0, psize, buf); - } + err = read_dva (&bp->blk_dva[i], endian, data, buf, psize); if (!err) return GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE; @@ -1888,128 +2236,6 @@ grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name, return ret; } -static grub_err_t -zfs_fetch_nvlist (struct grub_zfs_data * data, char **nvlist) -{ - grub_err_t err; - - *nvlist = grub_malloc (VDEV_PHYS_SIZE); - /* Read in the vdev name-value pair list (112K). */ - err = grub_disk_read (data->disk, data->vdev_phys_sector, 0, - VDEV_PHYS_SIZE, *nvlist); - if (err) - { - grub_free (*nvlist); - *nvlist = 0; - return err; - } - return GRUB_ERR_NONE; -} - -/* - * Check the disk label information and retrieve needed vdev name-value pairs. - * - */ -static grub_err_t -check_pool_label (struct grub_zfs_data *data) -{ - grub_uint64_t pool_state, txg = 0; - char *nvlist; -#if 0 - char *nv; -#endif - grub_uint64_t diskguid; - grub_uint64_t version; - int found; - grub_err_t err; - - err = zfs_fetch_nvlist (data, &nvlist); - if (err) - return err; - - grub_dprintf ("zfs", "check 2 passed\n"); - - found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE, - &pool_state); - if (! found) - { - grub_free (nvlist); - if (! grub_errno) - grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_STATE " not found"); - return grub_errno; - } - grub_dprintf ("zfs", "check 3 passed\n"); - - if (pool_state == POOL_STATE_DESTROYED) - { - grub_free (nvlist); - return grub_error (GRUB_ERR_BAD_FS, "zpool is marked as destroyed"); - } - grub_dprintf ("zfs", "check 4 passed\n"); - - found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_TXG, &txg); - if (!found) - { - grub_free (nvlist); - if (! grub_errno) - grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_POOL_TXG " not found"); - return grub_errno; - } - grub_dprintf ("zfs", "check 6 passed\n"); - - /* not an active device */ - if (txg == 0) - { - grub_free (nvlist); - return grub_error (GRUB_ERR_BAD_FS, "zpool isn't active"); - } - grub_dprintf ("zfs", "check 7 passed\n"); - - found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_VERSION, - &version); - if (! found) - { - grub_free (nvlist); - if (! grub_errno) - grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_VERSION " not found"); - return grub_errno; - } - grub_dprintf ("zfs", "check 8 passed\n"); - - if (version > SPA_VERSION) - { - grub_free (nvlist); - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "too new version %llu > %llu", - (unsigned long long) version, - (unsigned long long) SPA_VERSION); - } - grub_dprintf ("zfs", "check 9 passed\n"); -#if 0 - if (nvlist_lookup_value (nvlist, ZPOOL_CONFIG_VDEV_TREE, &nv, - DATA_TYPE_NVLIST, NULL)) - { - grub_free (vdev); - return (GRUB_ERR_BAD_FS); - } - grub_dprintf ("zfs", "check 10 passed\n"); -#endif - - found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID, &diskguid); - if (! found) - { - grub_free (nvlist); - if (! grub_errno) - grub_error (GRUB_ERR_BAD_FS, ZPOOL_CONFIG_GUID " not found"); - return grub_errno; - } - grub_dprintf ("zfs", "check 11 passed\n"); - - grub_free (nvlist); - - return GRUB_ERR_NONE; -} - static void zfs_unmount (struct grub_zfs_data *data) { @@ -2028,13 +2254,11 @@ static struct grub_zfs_data * zfs_mount (grub_device_t dev) { struct grub_zfs_data *data = 0; - int label = 0; - uberblock_phys_t *ub_array, *ubbest = NULL; - vdev_boot_header_t *bh; + grub_err_t err; objset_phys_t *osp = 0; grub_size_t ospsize; - grub_err_t err; - int vdevnum; + grub_zfs_endian_t ub_endian = UNKNOWN_ENDIAN; + uberblock_t *ub; if (! dev->disk) { @@ -2042,118 +2266,56 @@ zfs_mount (grub_device_t dev) return 0; } - data = grub_malloc (sizeof (*data)); + data = grub_zalloc (sizeof (*data)); if (!data) return 0; - grub_memset (data, 0, sizeof (*data)); #if 0 /* if it's our first time here, zero the best uberblock out */ if (data->best_drive == 0 && data->best_part == 0 && find_best_root) grub_memset (¤t_uberblock, 0, sizeof (uberblock_t)); #endif - data->disk = dev->disk; - - ub_array = grub_malloc (VDEV_UBERBLOCK_RING); - if (!ub_array) + data->n_devices_allocated = 16; + data->devices_attached = grub_malloc (sizeof (data->devices_attached[0]) + * data->n_devices_allocated); + data->n_devices_attached = 0; + err = scan_disk (dev->disk, data, NULL); + if (err) { zfs_unmount (data); - return 0; + return NULL; } - bh = grub_malloc (VDEV_BOOT_HEADER_SIZE); - if (!bh) + ub = &(data->devices_attached[0].current_uberblock); + ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, + LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? LITTLE_ENDIAN : BIG_ENDIAN); + + err = zio_read (&ub->ub_rootbp, ub_endian, + (void **) &osp, &ospsize, data); + if (err) { zfs_unmount (data); - grub_free (ub_array); - return 0; + return NULL; } - vdevnum = VDEV_LABELS; - - /* Don't check back labels on CDROM. */ - if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) - vdevnum = VDEV_LABELS / 2; - - for (label = 0; ubbest == NULL && label < vdevnum; label++) + if (ospsize < OBJSET_PHYS_SIZE_V14) { - grub_zfs_endian_t ub_endian = UNKNOWN_ENDIAN; - grub_dprintf ("zfs", "label %d\n", label); - - data->vdev_phys_sector - = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT) - + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT) - + (label < VDEV_LABELS / 2 ? 0 : grub_disk_get_size (dev->disk) - - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)); - - /* Read in the uberblock ring (128K). */ - err = grub_disk_read (data->disk, data->vdev_phys_sector - + (VDEV_PHYS_SIZE >> SPA_MINBLOCKSHIFT), - 0, VDEV_UBERBLOCK_RING, (char *) ub_array); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - grub_dprintf ("zfs", "label ok %d\n", label); - - ubbest = find_bestub (ub_array, data->vdev_phys_sector); - if (!ubbest) - { - grub_dprintf ("zfs", "No uberblock found\n"); - grub_errno = GRUB_ERR_NONE; - continue; - } - ub_endian = (grub_zfs_to_cpu64 (ubbest->ubp_uberblock.ub_magic, - LITTLE_ENDIAN) == UBERBLOCK_MAGIC - ? LITTLE_ENDIAN : BIG_ENDIAN); - err = zio_read (&ubbest->ubp_uberblock.ub_rootbp, - ub_endian, - (void **) &osp, &ospsize, data); - if (err) - { - grub_dprintf ("zfs", "couldn't zio_read\n"); - grub_errno = GRUB_ERR_NONE; - continue; - } - - if (ospsize < OBJSET_PHYS_SIZE_V14) - { - grub_dprintf ("zfs", "osp too small\n"); - grub_free (osp); - continue; - } - grub_dprintf ("zfs", "ubbest %p\n", ubbest); - - err = check_pool_label (data); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } -#if 0 - if (find_best_root && - vdev_uberblock_compare (&ubbest->ubp_uberblock, - &(current_uberblock)) <= 0) - continue; -#endif - /* Got the MOS. Save it at the memory addr MOS. */ - grub_memmove (&(data->mos.dn), &osp->os_meta_dnode, DNODE_SIZE); - data->mos.endian = (grub_zfs_to_cpu64 (ubbest->ubp_uberblock.ub_rootbp.blk_prop, ub_endian) >> 63) & 1; - grub_memmove (&(data->current_uberblock), - &ubbest->ubp_uberblock, sizeof (uberblock_t)); - grub_free (ub_array); - grub_free (bh); + grub_error (GRUB_ERR_BAD_FS, "OSP too small"); grub_free (osp); - return data; + zfs_unmount (data); + return NULL; } - grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label"); - zfs_unmount (data); - grub_free (ub_array); - grub_free (bh); + + /* Got the MOS. Save it at the memory addr MOS. */ + grub_memmove (&(data->mos.dn), &osp->os_meta_dnode, DNODE_SIZE); + data->mos.endian = (grub_zfs_to_cpu64 (ub->ub_rootbp.blk_prop, + ub_endian) >> 63) & 1; grub_free (osp); - return 0; + data->mounted = 1; + + return data; } grub_err_t @@ -2165,7 +2327,7 @@ grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist) zfs = zfs_mount (dev); if (!zfs) return grub_errno; - err = zfs_fetch_nvlist (zfs, nvlist); + err = zfs_fetch_nvlist (&zfs->devices_attached[0], nvlist); zfs_unmount (zfs); return err; } @@ -2181,7 +2343,7 @@ zfs_label (grub_device_t device, char **label) if (! data) return grub_errno; - err = zfs_fetch_nvlist (data, &nvlist); + err = zfs_fetch_nvlist (data->devices_attached, &nvlist); if (err) { zfs_unmount (data); @@ -2197,11 +2359,7 @@ zfs_label (grub_device_t device, char **label) static grub_err_t zfs_uuid (grub_device_t device, char **uuid) { - char *nvlist; - int found; struct grub_zfs_data *data; - grub_uint64_t guid; - grub_err_t err; *uuid = 0; @@ -2209,18 +2367,7 @@ zfs_uuid (grub_device_t device, char **uuid) if (! data) return grub_errno; - err = zfs_fetch_nvlist (data, &nvlist); - if (err) - { - zfs_unmount (data); - return err; - } - - found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid); - if (! found) - return grub_errno; - grub_free (nvlist); - *uuid = grub_xasprintf ("%016llx", (long long unsigned) guid); + *uuid = grub_xasprintf ("%016llx", (long long unsigned) data->guid); zfs_unmount (data); if (! *uuid) return grub_errno; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 2fcde4ab0..122465d7a 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -60,6 +60,7 @@ execute_command (char *name, int n, char **args) #define CMD_HEX 4 #define CMD_CRC 6 #define CMD_BLOCKLIST 7 +#define CMD_ZFSINFO 8 #define BUF_SIZE 32256 @@ -309,6 +310,9 @@ fstest (int n, char **args) case CMD_LS: execute_command ("ls", n, args); break; + case CMD_ZFSINFO: + execute_command ("zfsinfo", n, args); + break; case CMD_CP: cmd_cp (args[0], args[1]); break; @@ -454,6 +458,10 @@ argp_parser (int key, char *arg, struct argp_state *state) { cmd = CMD_LS; } + else if (!grub_strcmp (arg, "zfsinfo")) + { + cmd = CMD_ZFSINFO; + } else if (!grub_strcmp (arg, "cp")) { cmd = CMD_CP; From 8ff84951c5c8d09011caec8bf77c67e55414ec30 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 6 Dec 2010 02:31:22 +0100 Subject: [PATCH 044/673] ZFS mirror support --- grub-core/fs/zfs/zfs.c | 299 +++++++++++++++++++++++++++++------------ include/grub/zfs/zfs.h | 12 +- 2 files changed, 221 insertions(+), 90 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 3163e2e78..b5f25473f 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -140,11 +140,19 @@ typedef struct dnode_end struct grub_zfs_device_desc { - enum { DEVICE_LEAF } type; - grub_disk_t disk; + enum { DEVICE_LEAF, DEVICE_MIRROR } type; grub_uint64_t id; + grub_uint64_t guid; + + /* Valid only for non-leafs. */ + unsigned n_children; + struct grub_zfs_device_desc *children; + + /* Valid only for leaf devices. */ + grub_device_t dev; grub_disk_addr_t vdev_phys_sector; uberblock_t current_uberblock; + int original; }; struct grub_zfs_data @@ -169,6 +177,8 @@ struct grub_zfs_data unsigned n_devices_attached; unsigned n_devices_allocated; + uberblock_t current_uberblock; + int mounted; grub_uint64_t guid; }; @@ -434,8 +444,11 @@ zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist) grub_err_t err; *nvlist = grub_malloc (VDEV_PHYS_SIZE); + if (!diskdesc->dev) + return grub_error (GRUB_ERR_BAD_FS, "member drive unknown"); + /* Read in the vdev name-value pair list (112K). */ - err = grub_disk_read (diskdesc->disk, diskdesc->vdev_phys_sector, 0, + err = grub_disk_read (diskdesc->dev->disk, diskdesc->vdev_phys_sector, 0, VDEV_PHYS_SIZE, *nvlist); if (err) { @@ -447,41 +460,129 @@ zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist) } static grub_err_t -fill_vdev_info (char *nvlist, struct grub_zfs_device_desc *diskdesc) +fill_vdev_info_real (const char *nvlist, + struct grub_zfs_device_desc *fill, + struct grub_zfs_device_desc *insert) { - char *type = 0; + char *type; type = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_TYPE); if (!type) return grub_errno; + + if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &(fill->id))) + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + + if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "guid", &(fill->guid))) + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + if (grub_strcmp (type, VDEV_TYPE_DISK) == 0) { - diskdesc->type = DEVICE_LEAF; - if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &diskdesc->id)) - return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + fill->type = DEVICE_LEAF; + + if (!fill->dev && fill->guid == insert->guid) + { + fill->dev = insert->dev; + fill->vdev_phys_sector = insert->vdev_phys_sector; + fill->current_uberblock = insert->current_uberblock; + fill->original = insert->original; + } return GRUB_ERR_NONE; } + + if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) + { + int nelm, i; + + fill->type = DEVICE_MIRROR; + + nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, ZPOOL_CONFIG_CHILDREN); + + if (nelm <= 0) + return grub_error (GRUB_ERR_BAD_FS, "incorrect mirror VDEV"); + + fill->n_children = nelm; + + fill->children = grub_zalloc (fill->n_children + * sizeof (fill->children[0])); + + for (i = 0; i < nelm; i++) + { + char *child; + grub_err_t err; + + child = grub_zfs_nvlist_lookup_nvlist_array + (nvlist, ZPOOL_CONFIG_CHILDREN, i); + + err = fill_vdev_info_real (child, &fill->children[i], insert); + + grub_free (child); + + if (err) + return err; + } + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported", type); } +static grub_err_t +fill_vdev_info (struct grub_zfs_data *data, + char *nvlist, struct grub_zfs_device_desc *diskdesc) +{ + grub_uint64_t id; + unsigned i; + + if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &id)) + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + + for (i = 0; i < data->n_devices_attached; i++) + if (data->devices_attached[i].id == id) + return fill_vdev_info_real (nvlist, &data->devices_attached[i], + diskdesc); + + data->n_devices_attached++; + if (data->n_devices_attached > data->n_devices_allocated) + { + void *tmp; + data->n_devices_allocated = 2 * data->n_devices_attached + 1; + data->devices_attached + = grub_realloc (tmp = data->devices_attached, + data->n_devices_allocated + * sizeof (data->devices_attached[0])); + if (!data->devices_attached) + { + data->devices_attached = tmp; + return grub_errno; + } + } + + grub_memset (&data->devices_attached[data->n_devices_attached - 1], + 0, sizeof (data->devices_attached[data->n_devices_attached - 1])); + + return fill_vdev_info_real (nvlist, + &data->devices_attached[data->n_devices_attached - 1], + diskdesc); +} + /* * Check the disk label information and retrieve needed vdev name-value pairs. * */ static grub_err_t check_pool_label (struct grub_zfs_data *data, - struct grub_zfs_device_desc *diskdesc, - grub_uint64_t *id) + struct grub_zfs_device_desc *diskdesc) { grub_uint64_t pool_state, txg = 0; char *nvlist; #if 0 char *nv; #endif - grub_uint64_t diskguid, poolguid; + grub_uint64_t poolguid; grub_uint64_t version; int found; grub_err_t err; @@ -549,25 +650,8 @@ check_pool_label (struct grub_zfs_data *data, } grub_dprintf ("zfs", "check 9 passed\n"); - { - char *nv; - nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE); - - if (!nv) - { - grub_free (nvlist); - return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev tree"); - } - err = fill_vdev_info (nv, diskdesc); - if (err) - { - grub_free (nvlist); - return err; - } - } - grub_dprintf ("zfs", "check 10 passed\n"); - - found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID, &diskguid); + found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_GUID, + &(diskdesc->guid)); if (! found) { grub_free (nvlist); @@ -592,34 +676,33 @@ check_pool_label (struct grub_zfs_data *data, return grub_error (GRUB_ERR_BAD_FS, "another zpool"); else data->guid = poolguid; + + { + char *nv; + nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE); + + if (!nv) + { + grub_free (nvlist); + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev tree"); + } + err = fill_vdev_info (data, nv, diskdesc); + if (err) + { + grub_free (nvlist); + return err; + } + } + grub_dprintf ("zfs", "check 10 passed\n"); + grub_free (nvlist); - data->n_devices_attached++; - if (data->n_devices_attached > data->n_devices_allocated) - { - void *tmp; - data->n_devices_allocated = 2 * data->n_devices_attached + 1; - data->devices_attached - = grub_realloc (tmp = data->devices_attached, - data->n_devices_allocated - * sizeof (data->devices_attached[0])); - if (!data->devices_attached) - { - data->devices_attached = tmp; - return grub_errno; - } - } - - data->devices_attached[data->n_devices_attached - 1] = *diskdesc; - if (id) - *id = diskdesc->id; - return GRUB_ERR_NONE; } static grub_err_t -scan_disk (grub_disk_t disk, struct grub_zfs_data *data, - grub_uint64_t *id) +scan_disk (grub_device_t dev, struct grub_zfs_data *data, + int original) { int label = 0; uberblock_phys_t *ub_array, *ubbest = NULL; @@ -641,24 +724,23 @@ scan_disk (grub_disk_t disk, struct grub_zfs_data *data, vdevnum = VDEV_LABELS; - desc.disk = disk; + desc.dev = dev; + desc.original = original; /* Don't check back labels on CDROM. */ - if (grub_disk_get_size (disk) == GRUB_DISK_SIZE_UNKNOWN) + if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) vdevnum = VDEV_LABELS / 2; for (label = 0; ubbest == NULL && label < vdevnum; label++) { - grub_dprintf ("zfs", "label %d\n", label); - desc.vdev_phys_sector = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT) + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT) - + (label < VDEV_LABELS / 2 ? 0 : grub_disk_get_size (disk) + + (label < VDEV_LABELS / 2 ? 0 : grub_disk_get_size (dev->disk) - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)); /* Read in the uberblock ring (128K). */ - err = grub_disk_read (disk, desc.vdev_phys_sector + err = grub_disk_read (dev->disk, desc.vdev_phys_sector + (VDEV_PHYS_SIZE >> SPA_MINBLOCKSHIFT), 0, VDEV_UBERBLOCK_RING, (char *) ub_array); if (err) @@ -678,8 +760,11 @@ scan_disk (grub_disk_t disk, struct grub_zfs_data *data, grub_memmove (&(desc.current_uberblock), &ubbest->ubp_uberblock, sizeof (uberblock_t)); + if (original) + grub_memmove (&(data->current_uberblock), + &ubbest->ubp_uberblock, sizeof (uberblock_t)); - err = check_pool_label (data, &desc, id); + err = check_pool_label (data, &desc); if (err) { grub_errno = GRUB_ERR_NONE; @@ -711,7 +796,6 @@ scan_devices (struct grub_zfs_data *data, grub_uint64_t id) { grub_device_t dev; grub_err_t err; - grub_uint64_t f_id = -1; dev = grub_device_open (name); if (!dev) return 0; @@ -720,7 +804,7 @@ scan_devices (struct grub_zfs_data *data, grub_uint64_t id) grub_device_close (dev); return 0; } - err = scan_disk (dev->disk, data, &f_id); + err = scan_disk (dev, data, 0); if (err == GRUB_ERR_BAD_FS) { grub_device_close (dev); @@ -733,11 +817,6 @@ scan_devices (struct grub_zfs_data *data, grub_uint64_t id) grub_print_error (); return 0; } - if (f_id != id) - { - grub_device_close (dev); - return 0; - } dev_found = dev; return 1; @@ -749,6 +828,36 @@ scan_devices (struct grub_zfs_data *data, grub_uint64_t id) return GRUB_ERR_NONE; } +static grub_err_t +read_device (grub_uint64_t sector, struct grub_zfs_device_desc *desc, + grub_size_t len, void *buf) +{ + switch (desc->type) + { + case DEVICE_LEAF: + if (!desc->dev) + return grub_error (GRUB_ERR_BAD_FS, "member drive unknown"); + /* read in a data block */ + return grub_disk_read (desc->dev->disk, sector, 0, len, buf); + case DEVICE_MIRROR: + { + grub_err_t err; + unsigned i; + for (i = 0; i < desc->n_children; i++) + { + err = read_device (sector, &desc->children[i], + len, buf); + if (!err) + break; + grub_errno = GRUB_ERR_NONE; + } + return (grub_errno = err); + } + default: + return grub_error (GRUB_ERR_BAD_FS, "unsupported device type"); + } +} + static grub_err_t read_dva (const dva_t *dva, grub_zfs_endian_t endian, struct grub_zfs_data *data, @@ -758,18 +867,15 @@ read_dva (const dva_t *dva, unsigned i; grub_err_t err; int try = 0; + offset = dva_get_offset (dva, endian); + sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); for (try = 0; try < 1; try++) { for (i = 0; i < data->n_devices_attached; i++) if (data->devices_attached[i].id == DVA_GET_VDEV (dva)) - { - /* read in a data block */ - offset = dva_get_offset (dva, endian); - sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); - return grub_disk_read (data->devices_attached[i].disk, sector, - 0, len, buf); - } + return read_device (sector, &data->devices_attached[i], + len, buf); err = scan_devices (data, DVA_GET_VDEV (dva)); if (err) return err; @@ -2026,11 +2132,12 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, */ static int -nvlist_find_value (char *nvlist, char *name, int valtype, char **val, +nvlist_find_value (const char *nvlist, const char *name, + int valtype, char **val, grub_size_t *size_out, grub_size_t *nelm_out) { int name_len, type, encode_size; - char *nvpair, *nvp_name; + const char *nvpair, *nvp_name; /* Verify if the 1st and 2nd byte in the nvlist are valid. */ /* NOTE: independently of what endianness header announces all @@ -2072,7 +2179,7 @@ nvlist_find_value (char *nvlist, char *name, int valtype, char **val, if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype) { - *val = nvpair; + *val = (char *) nvpair; *size_out = encode_size; if (nelm_out) *nelm_out = nelm; @@ -2085,7 +2192,8 @@ nvlist_find_value (char *nvlist, char *name, int valtype, char **val, } int -grub_zfs_nvlist_lookup_uint64 (char *nvlist, char *name, grub_uint64_t * out) +grub_zfs_nvlist_lookup_uint64 (const char *nvlist, const char *name, + grub_uint64_t * out) { char *nvpair; grub_size_t size; @@ -2105,7 +2213,7 @@ grub_zfs_nvlist_lookup_uint64 (char *nvlist, char *name, grub_uint64_t * out) } char * -grub_zfs_nvlist_lookup_string (char *nvlist, char *name) +grub_zfs_nvlist_lookup_string (const char *nvlist, const char *name) { char *nvpair; char *ret; @@ -2133,7 +2241,7 @@ grub_zfs_nvlist_lookup_string (char *nvlist, char *name) } char * -grub_zfs_nvlist_lookup_nvlist (char *nvlist, char *name) +grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name) { char *nvpair; char *ret; @@ -2154,7 +2262,8 @@ grub_zfs_nvlist_lookup_nvlist (char *nvlist, char *name) } int -grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name) +grub_zfs_nvlist_lookup_nvlist_array_get_nelm (const char *nvlist, + const char *name) { char *nvpair; grub_size_t nelm, size; @@ -2168,9 +2277,9 @@ grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name) } static int -get_nvlist_size (char *beg, char *limit) +get_nvlist_size (const char *beg, const char *limit) { - char *ptr; + const char *ptr; grub_uint32_t encode_size; ptr = beg + 8; @@ -2183,7 +2292,7 @@ get_nvlist_size (char *beg, char *limit) } char * -grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name, +grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name, grub_size_t index) { char *nvpair, *nvpairptr; @@ -2236,9 +2345,29 @@ grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name, return ret; } +static void +unmount_device (struct grub_zfs_device_desc *desc) +{ + unsigned i; + switch (desc->type) + { + case DEVICE_LEAF: + if (!desc->original && desc->dev) + grub_device_close (desc->dev); + return; + case DEVICE_MIRROR: + for (i = 0; i < desc->n_children; i++) + unmount_device (&desc->children[i]); + return; + } +} + static void zfs_unmount (struct grub_zfs_data *data) { + unsigned i; + for (i = 0; i < data->n_devices_attached; i++) + unmount_device (&data->devices_attached[i]); grub_free (data->dnode_buf); grub_free (data->dnode_mdn); grub_free (data->file_buf); @@ -2279,14 +2408,14 @@ zfs_mount (grub_device_t dev) data->devices_attached = grub_malloc (sizeof (data->devices_attached[0]) * data->n_devices_allocated); data->n_devices_attached = 0; - err = scan_disk (dev->disk, data, NULL); + err = scan_disk (dev, data, 1); if (err) { zfs_unmount (data); return NULL; } - ub = &(data->devices_attached[0].current_uberblock); + ub = &(data->current_uberblock); ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC ? LITTLE_ENDIAN : BIG_ENDIAN); diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index 057692573..e1759dbbd 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -112,12 +112,14 @@ grub_err_t grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist); grub_err_t grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename, grub_uint64_t *mdnobj); -char *grub_zfs_nvlist_lookup_string (char *nvlist, char *name); -char *grub_zfs_nvlist_lookup_nvlist (char *nvlist, char *name); -int grub_zfs_nvlist_lookup_uint64 (char *nvlist, char *name, +char *grub_zfs_nvlist_lookup_string (const char *nvlist, const char *name); +char *grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name); +int grub_zfs_nvlist_lookup_uint64 (const char *nvlist, const char *name, grub_uint64_t *out); -char *grub_zfs_nvlist_lookup_nvlist_array (char *nvlist, char *name, +char *grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, + const char *name, grub_size_t index); -int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (char *nvlist, char *name); +int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (const char *nvlist, + const char *name); #endif /* ! GRUB_ZFS_HEADER */ From 925d998e6f9eb04c92465246b6fe458128bafb65 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 6 Dec 2010 07:03:58 +0100 Subject: [PATCH 045/673] Fix a warining --- grub-core/fs/zfs/zfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index b5f25473f..b23490c92 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -843,6 +843,9 @@ read_device (grub_uint64_t sector, struct grub_zfs_device_desc *desc, { grub_err_t err; unsigned i; + if (desc->n_children <= 0) + return grub_error (GRUB_ERR_BAD_FS, + "non-positive number of mirror children"); for (i = 0; i < desc->n_children; i++) { err = read_device (sector, &desc->children[i], From c3b87afcd47d0ad5e4fa8f14c551ce3593c649f4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 6 Dec 2010 20:28:02 +0100 Subject: [PATCH 046/673] Recognize vdev file --- grub-core/fs/zfs/zfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index b23490c92..1dab363b2 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -477,7 +477,8 @@ fill_vdev_info_real (const char *nvlist, if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "guid", &(fill->guid))) return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); - if (grub_strcmp (type, VDEV_TYPE_DISK) == 0) + if (grub_strcmp (type, VDEV_TYPE_DISK) == 0 + || grub_strcmp (type, VDEV_TYPE_FILE) == 0) { fill->type = DEVICE_LEAF; From 39db1a3f75047d1a665c7d1c194a134b31b1ee0a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 6 Dec 2010 23:46:01 +0100 Subject: [PATCH 047/673] First attempt on RAIDZ. Right now works only with right phase of the moon. --- grub-core/fs/zfs/zfs.c | 122 +++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 34 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 1dab363b2..23e9c7b36 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -140,7 +140,7 @@ typedef struct dnode_end struct grub_zfs_device_desc { - enum { DEVICE_LEAF, DEVICE_MIRROR } type; + enum { DEVICE_LEAF, DEVICE_MIRROR, DEVICE_RAIDZ } type; grub_uint64_t id; grub_uint64_t guid; @@ -148,6 +148,9 @@ struct grub_zfs_device_desc unsigned n_children; struct grub_zfs_device_desc *children; + /* Valid only for RAIDZ. */ + unsigned nparity; + /* Valid only for leaf devices. */ grub_device_t dev; grub_disk_addr_t vdev_phys_sector; @@ -290,13 +293,13 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, || (actual_cksum.zc_word[2] != zc.zc_word[2]) || (actual_cksum.zc_word[3] != zc.zc_word[3])) { - grub_dprintf ("zfs", "checksum %d verification failed\n", checksum); - grub_dprintf ("zfs", "actual checksum %16llx %16llx %16llx %16llx\n", + grub_dprintf ("zfs", "checksum %s verification failed\n", ci->ci_name); + grub_dprintf ("zfs", "actual checksum %016llx %016llx %016llx %016llx\n", (unsigned long long) actual_cksum.zc_word[0], (unsigned long long) actual_cksum.zc_word[1], (unsigned long long) actual_cksum.zc_word[2], (unsigned long long) actual_cksum.zc_word[3]); - grub_dprintf ("zfs", "expected checksum %16llx %16llx %16llx %16llx\n", + grub_dprintf ("zfs", "expected checksum %016llx %016llx %016llx %016llx\n", (unsigned long long) zc.zc_word[0], (unsigned long long) zc.zc_word[1], (unsigned long long) zc.zc_word[2], @@ -493,21 +496,34 @@ fill_vdev_info_real (const char *nvlist, return GRUB_ERR_NONE; } - if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) + if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0 + || grub_strcmp (type, VDEV_TYPE_RAIDZ) == 0) { int nelm, i; - fill->type = DEVICE_MIRROR; + if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) + fill->type = DEVICE_MIRROR; + else + { + grub_uint64_t par; + fill->type = DEVICE_RAIDZ; + if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "nparity", &par)) + return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity"); + fill->nparity = par; + } nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, ZPOOL_CONFIG_CHILDREN); if (nelm <= 0) return grub_error (GRUB_ERR_BAD_FS, "incorrect mirror VDEV"); - fill->n_children = nelm; - - fill->children = grub_zalloc (fill->n_children - * sizeof (fill->children[0])); + if (!fill->children) + { + fill->n_children = nelm; + + fill->children = grub_zalloc (fill->n_children + * sizeof (fill->children[0])); + } for (i = 0; i < nelm; i++) { @@ -789,9 +805,8 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, } static grub_err_t -scan_devices (struct grub_zfs_data *data, grub_uint64_t id) +scan_devices (struct grub_zfs_data *data) { - grub_device_t dev_found = NULL; auto int hook (const char *name); int hook (const char *name) { @@ -819,27 +834,29 @@ scan_devices (struct grub_zfs_data *data, grub_uint64_t id) return 0; } - dev_found = dev; - return 1; + return 0; } grub_device_iterate (hook); - if (!dev_found) - return grub_error (GRUB_ERR_BAD_FS, - "couldn't find device 0x%" PRIxGRUB_UINT64_T, id); return GRUB_ERR_NONE; } static grub_err_t -read_device (grub_uint64_t sector, struct grub_zfs_device_desc *desc, +read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_size_t len, void *buf) { switch (desc->type) { case DEVICE_LEAF: - if (!desc->dev) - return grub_error (GRUB_ERR_BAD_FS, "member drive unknown"); - /* read in a data block */ - return grub_disk_read (desc->dev->disk, sector, 0, len, buf); + { + grub_uint64_t sector; + sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); + if (!desc->dev) + { + return grub_error (GRUB_ERR_BAD_FS, "member drive unknown"); + } + /* read in a data block */ + return grub_disk_read (desc->dev->disk, sector, 0, len, buf); + } case DEVICE_MIRROR: { grub_err_t err; @@ -849,7 +866,7 @@ read_device (grub_uint64_t sector, struct grub_zfs_device_desc *desc, "non-positive number of mirror children"); for (i = 0; i < desc->n_children; i++) { - err = read_device (sector, &desc->children[i], + err = read_device (offset, &desc->children[i], len, buf); if (!err) break; @@ -857,9 +874,41 @@ read_device (grub_uint64_t sector, struct grub_zfs_device_desc *desc, } return (grub_errno = err); } - default: - return grub_error (GRUB_ERR_BAD_FS, "unsupported device type"); + case DEVICE_RAIDZ: + { + grub_uint64_t sector; + grub_uint64_t high; + grub_uint32_t devn; + if (desc->n_children <= 0) + return grub_error (GRUB_ERR_BAD_FS, + "non-positive number of mirror children"); + offset += 512; + + sector = offset >> 9; + high = grub_divmod64 (sector, desc->n_children, &devn); + + while (len > 0) + { + grub_size_t csize; + grub_err_t err; + + csize = 0x200 * desc->n_children - (offset & 0x1ff); + if (csize > len) + csize = len; + + err = read_device (high << 9, &desc->children[devn], + csize, buf); + if (err) + return err; + len -= csize; + buf = (grub_uint8_t *) buf + csize; + devn = (devn + 1) % desc->n_children; + high++; + } + } + return GRUB_ERR_NONE; } + return grub_error (GRUB_ERR_BAD_FS, "unsupported device type"); } static grub_err_t @@ -867,26 +916,30 @@ read_dva (const dva_t *dva, grub_zfs_endian_t endian, struct grub_zfs_data *data, void *buf, grub_size_t len) { - grub_uint64_t offset, sector; + grub_uint64_t offset; unsigned i; grub_err_t err; int try = 0; offset = dva_get_offset (dva, endian); - sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); - for (try = 0; try < 1; try++) + for (try = 0; try < 2; try++) { for (i = 0; i < data->n_devices_attached; i++) if (data->devices_attached[i].id == DVA_GET_VDEV (dva)) - return read_device (sector, &data->devices_attached[i], - len, buf); - err = scan_devices (data, DVA_GET_VDEV (dva)); + { + err = read_device (offset, &data->devices_attached[i], + len, buf); + if (!err) + return GRUB_ERR_NONE; + break; + } + if (try == 1) + break; + err = scan_devices (data); if (err) return err; } - return grub_error (GRUB_ERR_BAD_FS, - "couldn't find device 0x%" PRIxGRUB_UINT64_T, - DVA_GET_VDEV (dva)); + return err; } /* @@ -2359,6 +2412,7 @@ unmount_device (struct grub_zfs_device_desc *desc) if (!desc->original && desc->dev) grub_device_close (desc->dev); return; + case DEVICE_RAIDZ: case DEVICE_MIRROR: for (i = 0; i < desc->n_children; i++) unmount_device (&desc->children[i]); From bfff320cdfd27c197dec74cdff9c258098acadb3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 7 Dec 2010 11:45:37 +0100 Subject: [PATCH 048/673] Apparently functioning raidz. Still mostly a guesswork so may break --- grub-core/fs/zfs/zfs.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 23e9c7b36..e41067c38 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -842,7 +842,7 @@ scan_devices (struct grub_zfs_data *data) static grub_err_t read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, - grub_size_t len, void *buf) + grub_uint32_t asize, grub_size_t len, void *buf) { switch (desc->type) { @@ -866,7 +866,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, "non-positive number of mirror children"); for (i = 0; i < desc->n_children; i++) { - err = read_device (offset, &desc->children[i], + err = read_device (offset, &desc->children[i], asize, len, buf); if (!err) break; @@ -877,35 +877,35 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, case DEVICE_RAIDZ: { grub_uint64_t sector; - grub_uint64_t high; - grub_uint32_t devn; - if (desc->n_children <= 0) - return grub_error (GRUB_ERR_BAD_FS, - "non-positive number of mirror children"); - offset += 512; + grub_uint32_t bsize; + unsigned c = 0; + bsize = (asize + desc->nparity) / desc->n_children; sector = offset >> 9; - high = grub_divmod64 (sector, desc->n_children, &devn); - while (len > 0) { grub_size_t csize; + grub_uint64_t high; + grub_uint32_t devn; grub_err_t err; - - csize = 0x200 * desc->n_children - (offset & 0x1ff); + high = grub_divmod64 (sector + (asize > 2) + c, desc->n_children, + &devn); + csize = bsize << 9; if (csize > len) csize = len; - + grub_dprintf ("zfs", "RAIDZ mapping 0x%" PRIxGRUB_UINT64_T + "+%d+%u -> (0x%" PRIxGRUB_UINT64_T ", 0x%x)\n", + sector,(asize > 2), c, high, devn); err = read_device (high << 9, &desc->children[devn], - csize, buf); + bsize, csize, buf); if (err) return err; + c++; + buf = (char *) buf + csize; len -= csize; - buf = (grub_uint8_t *) buf + csize; - devn = (devn + 1) % desc->n_children; - high++; } - } + return GRUB_ERR_NONE; + } return GRUB_ERR_NONE; } return grub_error (GRUB_ERR_BAD_FS, "unsupported device type"); @@ -928,7 +928,7 @@ read_dva (const dva_t *dva, if (data->devices_attached[i].id == DVA_GET_VDEV (dva)) { err = read_device (offset, &data->devices_attached[i], - len, buf); + dva->dva_word[0] & 0xffffff, len, buf); if (!err) return GRUB_ERR_NONE; break; From eb03b5527161d9537e914870858d232e1fa277a9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 14:56:02 +0100 Subject: [PATCH 049/673] fix ZFS label handling in non-single disk configs --- grub-core/fs/zfs/zfs.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index e41067c38..cafe915c5 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -179,6 +179,7 @@ struct grub_zfs_data struct grub_zfs_device_desc *devices_attached; unsigned n_devices_attached; unsigned n_devices_allocated; + struct grub_zfs_device_desc *device_original; uberblock_t current_uberblock; @@ -463,7 +464,8 @@ zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist) } static grub_err_t -fill_vdev_info_real (const char *nvlist, +fill_vdev_info_real (struct grub_zfs_data *data, + const char *nvlist, struct grub_zfs_device_desc *fill, struct grub_zfs_device_desc *insert) { @@ -492,6 +494,8 @@ fill_vdev_info_real (const char *nvlist, fill->current_uberblock = insert->current_uberblock; fill->original = insert->original; } + if (!data->device_original) + data->device_original = fill; return GRUB_ERR_NONE; } @@ -533,7 +537,7 @@ fill_vdev_info_real (const char *nvlist, child = grub_zfs_nvlist_lookup_nvlist_array (nvlist, ZPOOL_CONFIG_CHILDREN, i); - err = fill_vdev_info_real (child, &fill->children[i], insert); + err = fill_vdev_info_real (data, child, &fill->children[i], insert); grub_free (child); @@ -559,7 +563,7 @@ fill_vdev_info (struct grub_zfs_data *data, for (i = 0; i < data->n_devices_attached; i++) if (data->devices_attached[i].id == id) - return fill_vdev_info_real (nvlist, &data->devices_attached[i], + return fill_vdev_info_real (data, nvlist, &data->devices_attached[i], diskdesc); data->n_devices_attached++; @@ -581,7 +585,7 @@ fill_vdev_info (struct grub_zfs_data *data, grub_memset (&data->devices_attached[data->n_devices_attached - 1], 0, sizeof (data->devices_attached[data->n_devices_attached - 1])); - return fill_vdev_info_real (nvlist, + return fill_vdev_info_real (data, nvlist, &data->devices_attached[data->n_devices_attached - 1], diskdesc); } @@ -2514,7 +2518,7 @@ grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist) zfs = zfs_mount (dev); if (!zfs) return grub_errno; - err = zfs_fetch_nvlist (&zfs->devices_attached[0], nvlist); + err = zfs_fetch_nvlist (zfs->device_original, nvlist); zfs_unmount (zfs); return err; } @@ -2530,7 +2534,7 @@ zfs_label (grub_device_t device, char **label) if (! data) return grub_errno; - err = zfs_fetch_nvlist (data->devices_attached, &nvlist); + err = zfs_fetch_nvlist (data->device_original, &nvlist); if (err) { zfs_unmount (data); From ea0df4e9530965c4ec04982656f27e074aeefac8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Dec 2010 15:01:33 +0100 Subject: [PATCH 050/673] ZFS mtime support --- grub-core/fs/zfs/zfs.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index cafe915c5..327e99a90 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2565,6 +2565,29 @@ zfs_uuid (grub_device_t device, char **uuid) return GRUB_ERR_NONE; } +static grub_err_t +zfs_mtime (grub_device_t device, grub_int32_t *mt) +{ + struct grub_zfs_data *data; + grub_zfs_endian_t ub_endian = UNKNOWN_ENDIAN; + uberblock_t *ub; + + *mt = 0; + + data = zfs_mount (device); + if (! data) + return grub_errno; + + ub = &(data->current_uberblock); + ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, + LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? LITTLE_ENDIAN : BIG_ENDIAN); + + *mt = grub_zfs_to_cpu64 (ub->ub_timestamp, ub_endian); + zfs_unmount (data); + return GRUB_ERR_NONE; +} + /* * zfs_open() locates a file in the rootpool by following the * MOS and places the dnode of the file in the memory address DNODE. @@ -2934,7 +2957,7 @@ static struct grub_fs grub_zfs_fs = { .close = grub_zfs_close, .label = zfs_label, .uuid = zfs_uuid, - .mtime = 0, + .mtime = zfs_mtime, .next = 0 }; From e03f549b3e11018b0ec0f44465f6bf5ca98ca993 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 16:22:19 +0000 Subject: [PATCH 051/673] Preferred resolution detection for VBE. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): New function. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. (grub_vbe_edid_checksum): Likewise. (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the Flat Panel extension, in line with the X.org VESA driver. (grub_video_vbe_setup): When the mode is "auto", try to get the preferred mode from VBE, and use the largest mode that is no larger than the preferred mode (some BIOSes expose a preferred mode that is not in their mode list!). If this fails, fall back to 640x480 as a safe conservative choice. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. (struct grub_vbe_edid_info): Likewise. (grub_vbe_bios_get_flat_panel_info): Add prototype. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This is more appropriate on a wider range of platforms than 640x480. --- ChangeLog.vbe-autodetect | 25 ++++++ grub-core/video/i386/pc/vbe.c | 150 +++++++++++++++++++++++++++++++++- include/grub/i386/pc/vbe.h | 84 +++++++++++++++++++ util/grub.d/00_header.in | 2 +- 4 files changed, 256 insertions(+), 5 deletions(-) create mode 100644 ChangeLog.vbe-autodetect diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect new file mode 100644 index 000000000..7d16ebee2 --- /dev/null +++ b/ChangeLog.vbe-autodetect @@ -0,0 +1,25 @@ +2010-12-14 Colin Watson + + Preferred resolution detection for VBE. + + * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): + New function. + (grub_vbe_bios_get_ddc_capabilities): Likewise. + (grub_vbe_bios_read_edid): Likewise. + (grub_vbe_edid_checksum): Likewise. + (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the + Flat Panel extension, in line with the X.org VESA driver. + (grub_video_vbe_setup): When the mode is "auto", try to get the + preferred mode from VBE, and use the largest mode that is no larger + than the preferred mode (some BIOSes expose a preferred mode that is + not in their mode list!). If this fails, fall back to 640x480 as a + safe conservative choice. + * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New + structure. + (struct grub_vbe_edid_info): Likewise. + (grub_vbe_bios_get_flat_panel_info): Add prototype. + (grub_vbe_bios_get_ddc_capabilities): Likewise. + (grub_vbe_bios_read_edid): Likewise. + + * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This + is more appropriate on a wider range of platforms than 640x480. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 2ddb4ca80..1794addae 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -273,6 +273,56 @@ grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset, return regs.eax & 0xffff; } +/* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f11; + regs.ebx = 0x0001; + regs.es = (((grub_addr_t) flat_panel_info) & 0xffff0000) >> 4; + regs.edi = ((grub_addr_t) flat_panel_info) & 0xffff; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f15; + regs.ebx = 0x0000; + regs.ecx = 0x0000; + regs.es = 0x0000; + regs.edi = 0x0000; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + *level = regs.ebx & 0xff; + return regs.eax & 0xffff; +} + +/* Call VESA BIOS 0x4f15 to read EDID information, return status. */ +grub_vbe_status_t +grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_info) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x4f15; + regs.ebx = 0x0001; + regs.ecx = 0x0000; + regs.edx = 0x0000; + regs.es = (((grub_addr_t) edid_info) & 0xffff0000) >> 4; + regs.edi = ((grub_addr_t) edid_info) & 0xffff; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return regs.eax & 0xffff; +} + grub_err_t grub_vbe_probe (struct grub_vbe_info_block *info_block) @@ -327,6 +377,70 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) return GRUB_ERR_NONE; } +static grub_err_t +grub_vbe_edid_checksum (struct grub_vbe_edid_info *edid_info) +{ + const char *edid_bytes = (const char *) edid_info; + int i; + char checksum = 0; + + /* Check EDID checksum. */ + for (i = 0; i < 128; ++i) + checksum += edid_bytes[i]; + + if (checksum != 0) + return grub_error (GRUB_ERR_BAD_DEVICE, + "invalid EDID checksum %d", checksum); + + grub_errno = GRUB_ERR_NONE; + return grub_errno; +} + +static grub_err_t +grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) +{ + grub_vbe_status_t status; + grub_uint8_t ddc_level; + struct grub_vbe_edid_info edid_info; + struct grub_vbe_flat_panel_info flat_panel_info; + + if (controller_info.version >= 0x200 + && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) + == GRUB_VBE_STATUS_OK) + { + status = grub_vbe_bios_read_edid (&edid_info); + /* Bit 1 in the Feature Support field indicates that the first + Detailed Timing Description is the preferred timing mode. */ + if (status == GRUB_VBE_STATUS_OK + && grub_vbe_edid_checksum (&edid_info) == GRUB_ERR_NONE + && edid_info.version == 1 /* we don't understand later versions */ + && (edid_info.feature_support + & GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE) + && edid_info.detailed_timings[0].pixel_clock) + { + *width = edid_info.detailed_timings[0].horizontal_active_lo + | (((unsigned int) + (edid_info.detailed_timings[0].horizontal_hi & 0xf0)) + << 4); + *height = edid_info.detailed_timings[0].vertical_active_lo + | (((unsigned int) + (edid_info.detailed_timings[0].vertical_hi & 0xf0)) + << 4); + return GRUB_ERR_NONE; + } + } + + status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info); + if (status == GRUB_VBE_STATUS_OK) + { + *width = flat_panel_info.horizontal_size; + *height = flat_panel_info.vertical_size; + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot get preferred mode"); +} + grub_err_t grub_vbe_set_video_mode (grub_uint32_t vbe_mode, struct grub_vbe_mode_info_block *vbe_mode_info) @@ -695,11 +809,28 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, struct grub_vbe_mode_info_block best_vbe_mode_info; grub_uint32_t best_vbe_mode = 0; int depth; + int preferred_mode = 0; /* 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; + if (width == 0 && height == 0) + { + grub_vbe_get_preferred_mode (&width, &height); + if (grub_errno == GRUB_ERR_NONE) + preferred_mode = 1; + else + { + /* Fall back to 640x480. This is conservative, but the largest + mode supported by the graphics card may not be safe for the + display device. */ + grub_errno = GRUB_ERR_NONE; + width = 640; + height = 480; + } + } + /* Walk thru mode list and try to find matching mode. */ for (p = vbe_mode_list; *p != 0xFFFF; p++) { @@ -742,10 +873,21 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Unsupported bitdepth . */ continue; - if (((vbe_mode_info.x_resolution != width) - || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0) - /* Non matching resolution. */ - continue; + if (preferred_mode) + { + if (vbe_mode_info.x_resolution > width + || vbe_mode_info.y_resolution > height) + /* Resolution exceeds that of preferred mode. */ + continue; + } + else + { + if (((vbe_mode_info.x_resolution != width) + || (vbe_mode_info.y_resolution != height)) + && width != 0 && height != 0) + /* Non matching resolution. */ + continue; + } /* Check if user requested RGB or index color mode. */ if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0) diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index fba3ee642..5be34fdec 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -169,6 +169,81 @@ struct grub_vbe_palette_data grub_uint8_t alignment; } __attribute__ ((packed)); +struct grub_vbe_flat_panel_info +{ + grub_uint16_t horizontal_size; + grub_uint16_t vertical_size; + grub_uint16_t panel_type; + grub_uint8_t red_bpp; + grub_uint8_t green_bpp; + grub_uint8_t blue_bpp; + grub_uint8_t reserved_bpp; + grub_uint32_t reserved_offscreen_mem_size; + grub_vbe_farptr_t reserved_offscreen_mem_ptr; + + grub_uint8_t reserved[14]; +} __attribute__ ((packed)); + +struct grub_vbe_edid_info +{ + grub_uint8_t header[8]; + grub_uint16_t manufacturer_id; + grub_uint16_t product_id; + grub_uint32_t serial_number; + grub_uint8_t week_of_manufacture; + grub_uint8_t year_of_manufacture; + grub_uint8_t version; + grub_uint8_t revision; + + grub_uint8_t video_input_definition; + grub_uint8_t max_horizontal_image_size; + grub_uint8_t max_vertical_image_size; + grub_uint8_t display_gamma; + grub_uint8_t feature_support; +#define GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) + + grub_uint8_t red_green_lo; + grub_uint8_t blue_white_lo; + grub_uint8_t red_x_hi; + grub_uint8_t red_y_hi; + grub_uint8_t green_x_hi; + grub_uint8_t green_y_hi; + grub_uint8_t blue_x_hi; + grub_uint8_t blue_y_hi; + grub_uint8_t white_x_hi; + grub_uint8_t white_y_hi; + + grub_uint8_t established_timings_1; + grub_uint8_t established_timings_2; + grub_uint8_t manufacturer_reserved_timings; + + grub_uint16_t standard_timings[8]; + + struct { + grub_uint16_t pixel_clock; + /* Only valid if the pixel clock is non-null. */ + grub_uint8_t horizontal_active_lo; + grub_uint8_t horizontal_blanking_lo; + grub_uint8_t horizontal_hi; + grub_uint8_t vertical_active_lo; + grub_uint8_t vertical_blanking_lo; + grub_uint8_t vertical_hi; + grub_uint8_t horizontal_sync_offset_lo; + grub_uint8_t horizontal_sync_pulse_width_lo; + grub_uint8_t vertical_sync_lo; + grub_uint8_t sync_hi; + grub_uint8_t horizontal_image_size_lo; + grub_uint8_t vertical_image_size_lo; + grub_uint8_t image_size_hi; + grub_uint8_t horizontal_border; + grub_uint8_t vertical_border; + grub_uint8_t flags; + } detailed_timings[4]; + + grub_uint8_t extension_flag; + grub_uint8_t checksum; +} __attribute__ ((packed)); + /* Prototypes for helper functions. */ /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */ grub_vbe_status_t @@ -197,6 +272,15 @@ grub_vbe_bios_get_scanline_length (grub_uint32_t *length); grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x, grub_uint32_t *y); +/* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info); +/* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ +grub_vbe_status_t +grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level); +/* Call VESA BIOS 0x4f15 to read EDID information, return status. */ +grub_vbe_status_t +grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_data); grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index a596e9c4a..55c686296 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -36,7 +36,7 @@ done if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi -if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi +if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=auto ; fi if [ "x${GRUB_DEFAULT_BUTTON}" = "x" ] ; then GRUB_DEFAULT_BUTTON="$GRUB_DEFAULT" ; fi if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_entry}' ; fi From 25d884a52a1819792bc97cac9890d44a72446b7c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 17:06:32 +0000 Subject: [PATCH 052/673] move generic parts of EDID handling (structure, checksumming) to generic location --- ChangeLog.vbe-autodetect | 7 ++-- grub-core/video/i386/pc/vbe.c | 27 +++------------ grub-core/video/video.c | 19 +++++++++++ include/grub/i386/pc/vbe.h | 64 ++--------------------------------- include/grub/video.h | 62 +++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 87 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 7d16ebee2..0d96fc0a2 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -2,11 +2,11 @@ Preferred resolution detection for VBE. + * grub-core/video/video.c (grub_video_edid_checksum): New function. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): - New function. + Likewise. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. - (grub_vbe_edid_checksum): Likewise. (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the Flat Panel extension, in line with the X.org VESA driver. (grub_video_vbe_setup): When the mode is "auto", try to get the @@ -14,9 +14,10 @@ than the preferred mode (some BIOSes expose a preferred mode that is not in their mode list!). If this fails, fall back to 640x480 as a safe conservative choice. + * include/grub/video.h (struct grub_vbe_edid_info): New structure. + (grub_video_edid_checksum): Add prototype. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. - (struct grub_vbe_edid_info): Likewise. (grub_vbe_bios_get_flat_panel_info): Add prototype. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 1794addae..e2dcc151e 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -308,7 +308,7 @@ grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_info) +grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_info) { struct grub_bios_int_registers regs; @@ -377,31 +377,12 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) return GRUB_ERR_NONE; } -static grub_err_t -grub_vbe_edid_checksum (struct grub_vbe_edid_info *edid_info) -{ - const char *edid_bytes = (const char *) edid_info; - int i; - char checksum = 0; - - /* Check EDID checksum. */ - for (i = 0; i < 128; ++i) - checksum += edid_bytes[i]; - - if (checksum != 0) - return grub_error (GRUB_ERR_BAD_DEVICE, - "invalid EDID checksum %d", checksum); - - grub_errno = GRUB_ERR_NONE; - return grub_errno; -} - static grub_err_t grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) { grub_vbe_status_t status; grub_uint8_t ddc_level; - struct grub_vbe_edid_info edid_info; + struct grub_video_edid_info edid_info; struct grub_vbe_flat_panel_info flat_panel_info; if (controller_info.version >= 0x200 @@ -412,10 +393,10 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) /* Bit 1 in the Feature Support field indicates that the first Detailed Timing Description is the preferred timing mode. */ if (status == GRUB_VBE_STATUS_OK - && grub_vbe_edid_checksum (&edid_info) == GRUB_ERR_NONE + && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE && edid_info.version == 1 /* we don't understand later versions */ && (edid_info.feature_support - & GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE) + & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE) && edid_info.detailed_timings[0].pixel_clock) { *width = edid_info.detailed_timings[0].horizontal_active_lo diff --git a/grub-core/video/video.c b/grub-core/video/video.c index 7a1a446e4..f3ecab94d 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -374,6 +374,25 @@ grub_video_get_active_render_target (struct grub_video_render_target **target) return grub_video_adapter_active->get_active_render_target (target); } +grub_err_t +grub_video_edid_checksum (struct grub_video_edid_info *edid_info) +{ + const char *edid_bytes = (const char *) edid_info; + int i; + char checksum = 0; + + /* Check EDID checksum. */ + for (i = 0; i < 128; ++i) + checksum += edid_bytes[i]; + + if (checksum != 0) + return grub_error (GRUB_ERR_BAD_DEVICE, + "invalid EDID checksum %d", checksum); + + grub_errno = GRUB_ERR_NONE; + return grub_errno; +} + /* Parse x[x]*/ static grub_err_t parse_modespec (const char *current_mode, int *width, int *height, int *depth) diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 5be34fdec..0422558db 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -19,6 +19,8 @@ #ifndef GRUB_VBE_MACHINE_HEADER #define GRUB_VBE_MACHINE_HEADER 1 +#include + /* Default video mode to be used. */ #define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101 @@ -184,66 +186,6 @@ struct grub_vbe_flat_panel_info grub_uint8_t reserved[14]; } __attribute__ ((packed)); -struct grub_vbe_edid_info -{ - grub_uint8_t header[8]; - grub_uint16_t manufacturer_id; - grub_uint16_t product_id; - grub_uint32_t serial_number; - grub_uint8_t week_of_manufacture; - grub_uint8_t year_of_manufacture; - grub_uint8_t version; - grub_uint8_t revision; - - grub_uint8_t video_input_definition; - grub_uint8_t max_horizontal_image_size; - grub_uint8_t max_vertical_image_size; - grub_uint8_t display_gamma; - grub_uint8_t feature_support; -#define GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) - - grub_uint8_t red_green_lo; - grub_uint8_t blue_white_lo; - grub_uint8_t red_x_hi; - grub_uint8_t red_y_hi; - grub_uint8_t green_x_hi; - grub_uint8_t green_y_hi; - grub_uint8_t blue_x_hi; - grub_uint8_t blue_y_hi; - grub_uint8_t white_x_hi; - grub_uint8_t white_y_hi; - - grub_uint8_t established_timings_1; - grub_uint8_t established_timings_2; - grub_uint8_t manufacturer_reserved_timings; - - grub_uint16_t standard_timings[8]; - - struct { - grub_uint16_t pixel_clock; - /* Only valid if the pixel clock is non-null. */ - grub_uint8_t horizontal_active_lo; - grub_uint8_t horizontal_blanking_lo; - grub_uint8_t horizontal_hi; - grub_uint8_t vertical_active_lo; - grub_uint8_t vertical_blanking_lo; - grub_uint8_t vertical_hi; - grub_uint8_t horizontal_sync_offset_lo; - grub_uint8_t horizontal_sync_pulse_width_lo; - grub_uint8_t vertical_sync_lo; - grub_uint8_t sync_hi; - grub_uint8_t horizontal_image_size_lo; - grub_uint8_t vertical_image_size_lo; - grub_uint8_t image_size_hi; - grub_uint8_t horizontal_border; - grub_uint8_t vertical_border; - grub_uint8_t flags; - } detailed_timings[4]; - - grub_uint8_t extension_flag; - grub_uint8_t checksum; -} __attribute__ ((packed)); - /* Prototypes for helper functions. */ /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */ grub_vbe_status_t @@ -280,7 +222,7 @@ grub_vbe_status_t grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level); /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_data); +grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_data); grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); diff --git a/include/grub/video.h b/include/grub/video.h index 97bd85bd1..2cf1424c4 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -210,6 +210,66 @@ struct grub_video_palette_data grub_uint8_t a; /* Reserved bits value (0-255). */ }; +struct grub_video_edid_info +{ + grub_uint8_t header[8]; + grub_uint16_t manufacturer_id; + grub_uint16_t product_id; + grub_uint32_t serial_number; + grub_uint8_t week_of_manufacture; + grub_uint8_t year_of_manufacture; + grub_uint8_t version; + grub_uint8_t revision; + + grub_uint8_t video_input_definition; + grub_uint8_t max_horizontal_image_size; + grub_uint8_t max_vertical_image_size; + grub_uint8_t display_gamma; + grub_uint8_t feature_support; +#define GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) + + grub_uint8_t red_green_lo; + grub_uint8_t blue_white_lo; + grub_uint8_t red_x_hi; + grub_uint8_t red_y_hi; + grub_uint8_t green_x_hi; + grub_uint8_t green_y_hi; + grub_uint8_t blue_x_hi; + grub_uint8_t blue_y_hi; + grub_uint8_t white_x_hi; + grub_uint8_t white_y_hi; + + grub_uint8_t established_timings_1; + grub_uint8_t established_timings_2; + grub_uint8_t manufacturer_reserved_timings; + + grub_uint16_t standard_timings[8]; + + struct { + grub_uint16_t pixel_clock; + /* Only valid if the pixel clock is non-null. */ + grub_uint8_t horizontal_active_lo; + grub_uint8_t horizontal_blanking_lo; + grub_uint8_t horizontal_hi; + grub_uint8_t vertical_active_lo; + grub_uint8_t vertical_blanking_lo; + grub_uint8_t vertical_hi; + grub_uint8_t horizontal_sync_offset_lo; + grub_uint8_t horizontal_sync_pulse_width_lo; + grub_uint8_t vertical_sync_lo; + grub_uint8_t sync_hi; + grub_uint8_t horizontal_image_size_lo; + grub_uint8_t vertical_image_size_lo; + grub_uint8_t image_size_hi; + grub_uint8_t horizontal_border; + grub_uint8_t vertical_border; + grub_uint8_t flags; + } detailed_timings[4]; + + grub_uint8_t extension_flag; + grub_uint8_t checksum; +} __attribute__ ((packed)); + typedef enum grub_video_driver_id { GRUB_VIDEO_DRIVER_NONE, @@ -423,6 +483,8 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); +grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); + grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modemask, unsigned int modevalue); From 129185cfaae5969be4e49f5d898ed553b18d8502 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 18:03:34 +0000 Subject: [PATCH 053/673] move more EDID-handling functions to generic code, and make videoinfo display EDID information --- ChangeLog.vbe-autodetect | 15 +++++++++--- grub-core/commands/videoinfo.c | 31 ++++++++++++++++++++++++ grub-core/video/i386/pc/vbe.c | 36 +++++++++++++--------------- grub-core/video/video.c | 43 ++++++++++++++++++++++++++++++++++ include/grub/video.h | 6 +++++ 5 files changed, 108 insertions(+), 23 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 0d96fc0a2..355ce00f6 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -3,24 +3,33 @@ Preferred resolution detection for VBE. * grub-core/video/video.c (grub_video_edid_checksum): New function. + (grub_video_get_edid): Likewise. + (grub_video_edid_preferred_mode): Likewise. Try EDID followed by + the Flat Panel extension, in line with the X.org VESA driver. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): - Likewise. + New function. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. - (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the - Flat Panel extension, in line with the X.org VESA driver. + (grub_vbe_get_preferred_mode): Likewise. (grub_video_vbe_setup): When the mode is "auto", try to get the preferred mode from VBE, and use the largest mode that is no larger than the preferred mode (some BIOSes expose a preferred mode that is not in their mode list!). If this fails, fall back to 640x480 as a safe conservative choice. + (grub_video_vbe_get_edid): New function. + (grub_video_vbe_adapter): Add get_edid. * include/grub/video.h (struct grub_vbe_edid_info): New structure. (grub_video_edid_checksum): Add prototype. + (grub_video_get_edid): Likewise. + (grub_video_edid_preferred_mode): Likewise. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. (grub_vbe_bios_get_flat_panel_info): Add prototype. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. + * grub-core/commands/videoinfo.c (print_edid): New function. + (grub_cmd_videoinfo): Print EDID if available. + * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This is more appropriate on a wider range of platforms than 640x480. diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 10f77915b..56df943ec 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -77,6 +77,30 @@ hook (const struct grub_video_mode_info *info) return 0; } +static void +print_edid (struct grub_video_edid_info *edid_info) +{ + unsigned int edid_width, edid_height; + + if (grub_video_edid_checksum (edid_info)) + { + grub_printf (" EDID checksum invalid\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + + grub_printf (" EDID version: %u.%u\n", + edid_info->version, edid_info->revision); + if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height) + == GRUB_ERR_NONE) + grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height); + else + { + grub_printf (" No preferred mode available\n"); + grub_errno = GRUB_ERR_NONE; + } +} + static grub_err_t grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) @@ -120,6 +144,8 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), FOR_VIDEO_ADAPTERS (adapter) { + struct grub_video_edid_info edid_info; + grub_printf ("Adapter '%s':\n", adapter->name); if (!adapter->iterate) @@ -143,6 +169,11 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), adapter->iterate (hook); + if (adapter->get_edid (&edid_info) == GRUB_ERR_NONE) + print_edid (&edid_info); + else + grub_errno = GRUB_ERR_NONE; + if (adapter->id != id) { if (adapter->fini ()) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index e2dcc151e..c6bb733a9 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -389,26 +389,12 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) == GRUB_VBE_STATUS_OK) { - status = grub_vbe_bios_read_edid (&edid_info); - /* Bit 1 in the Feature Support field indicates that the first - Detailed Timing Description is the preferred timing mode. */ - if (status == GRUB_VBE_STATUS_OK - && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE - && edid_info.version == 1 /* we don't understand later versions */ - && (edid_info.feature_support - & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE) - && edid_info.detailed_timings[0].pixel_clock) - { - *width = edid_info.detailed_timings[0].horizontal_active_lo - | (((unsigned int) - (edid_info.detailed_timings[0].horizontal_hi & 0xf0)) - << 4); - *height = edid_info.detailed_timings[0].vertical_active_lo - | (((unsigned int) - (edid_info.detailed_timings[0].vertical_hi & 0xf0)) - << 4); - return GRUB_ERR_NONE; - } + if (grub_video_get_edid (&edid_info) == GRUB_ERR_NONE + && grub_video_edid_preferred_mode (&edid_info, width, height) + == GRUB_ERR_NONE) + return GRUB_ERR_NONE; + + grub_errno = GRUB_ERR_NONE; } status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info); @@ -978,6 +964,15 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, return grub_video_fb_get_info_and_fini (mode_info, framebuf); } +static grub_err_t +grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) +{ + if (grub_vbe_bios_read_edid (edid_info) != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); + + return GRUB_ERR_NONE; +} + static void grub_video_vbe_print_adapter_specific_info (void) { @@ -1022,6 +1017,7 @@ static struct grub_video_adapter grub_video_vbe_adapter = .set_active_render_target = grub_video_fb_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, .iterate = grub_video_vbe_iterate, + .get_edid = grub_video_vbe_get_edid, .print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info, .next = 0 diff --git a/grub-core/video/video.c b/grub-core/video/video.c index f3ecab94d..84e98bb67 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -393,6 +393,49 @@ grub_video_edid_checksum (struct grub_video_edid_info *edid_info) return grub_errno; } +grub_err_t +grub_video_get_edid (struct grub_video_edid_info *edid_info) +{ + if (! grub_video_adapter_active) + return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); + + if (! grub_video_adapter_active->get_edid) + return grub_error (GRUB_ERR_BAD_DEVICE, + "EDID information unavailable for this video mode"); + + if (grub_video_adapter_active->get_edid (edid_info) != GRUB_ERR_NONE) + return grub_errno; + if (grub_video_edid_checksum (edid_info) != GRUB_ERR_NONE) + return grub_errno; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, + unsigned int *width, unsigned int *height) +{ + /* Bit 1 in the Feature Support field indicates that the first + Detailed Timing Description is the preferred timing mode. */ + if (edid_info->version == 1 /* we don't understand later versions */ + && (edid_info->feature_support + & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE) + && edid_info->detailed_timings[0].pixel_clock) + { + *width = edid_info->detailed_timings[0].horizontal_active_lo + | (((unsigned int) + (edid_info->detailed_timings[0].horizontal_hi & 0xf0)) + << 4); + *height = edid_info->detailed_timings[0].vertical_active_lo + | (((unsigned int) + (edid_info->detailed_timings[0].vertical_hi & 0xf0)) + << 4); + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_BAD_DEVICE, "no preferred mode available"); +} + /* Parse x[x]*/ static grub_err_t parse_modespec (const char *current_mode, int *width, int *height, int *depth) diff --git a/include/grub/video.h b/include/grub/video.h index 2cf1424c4..2251ed5f4 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -371,6 +371,8 @@ struct grub_video_adapter int (*iterate) (int (*hook) (const struct grub_video_mode_info *info)); + grub_err_t (*get_edid) (struct grub_video_edid_info *edid_info); + void (*print_adapter_specific_info) (void); }; typedef struct grub_video_adapter *grub_video_adapter_t; @@ -484,6 +486,10 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); +grub_err_t grub_video_get_edid (struct grub_video_edid_info *edid_info); +grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, + unsigned int *width, + unsigned int *height); grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modemask, From ef429417b2297c508685d9b1cc43e0bee74f0f44 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 18:08:27 +0000 Subject: [PATCH 054/673] mention struct grub_video_adapter change --- ChangeLog.vbe-autodetect | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 355ce00f6..d8034b885 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -19,6 +19,7 @@ (grub_video_vbe_get_edid): New function. (grub_video_vbe_adapter): Add get_edid. * include/grub/video.h (struct grub_vbe_edid_info): New structure. + (struct grub_video_adapter): Add get_edid. (grub_video_edid_checksum): Add prototype. (grub_video_get_edid): Likewise. (grub_video_edid_preferred_mode): Likewise. From 015e21571c2ecaacb7eb59c2cfde566d1290c445 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 19:03:28 +0000 Subject: [PATCH 055/673] check that adapter->get_edid is non-NULL --- grub-core/commands/videoinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 56df943ec..9bd0a0e78 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -169,7 +169,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), adapter->iterate (hook); - if (adapter->get_edid (&edid_info) == GRUB_ERR_NONE) + if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE) print_edid (&edid_info); else grub_errno = GRUB_ERR_NONE; From 70e8145a7b52759fcf94fe16fa3ea287d83eb904 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 16:10:26 +0100 Subject: [PATCH 056/673] Plan9 support --- grub-core/Makefile.core.def | 7 + grub-core/loader/i386/pc/plan9.c | 219 +++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 grub-core/loader/i386/pc/plan9.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 37c0ce970..ae604b3c6 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1146,6 +1146,13 @@ module = { enable = x86; }; +module = { + name = plan9; + i386_pc = loader/i386/pc/plan9.c; + enable = i386_pc; +}; + + module = { name = linux16; i386_pc = loader/i386/pc/linux.c; diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c new file mode 100644 index 000000000..aa96ae83c --- /dev/null +++ b/grub-core/loader/i386/pc/plan9.c @@ -0,0 +1,219 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static grub_dl_t my_mod; +static struct grub_relocator *rel; +static grub_uint32_t eip = 0xffffffff; + +#define GRUB_PLAN9_TARGET 0x100000 +#define GRUB_PLAN9_CONFIG_ADDR 0x001200 +#define GRUB_PLAN9_CONFIG_PATH_SIZE 0x000040 +#define GRUB_PLAN9_CONFIG_MAGIC "ZORT 0\r\n" + +struct grub_plan9_header +{ + grub_uint32_t magic; +#define GRUB_PLAN9_MAGIC 0x1eb + grub_uint32_t text_size; + grub_uint32_t data_size; + grub_uint32_t bss_size; + grub_uint32_t zero1; + grub_uint32_t entry_addr; + grub_uint32_t zero2; + grub_uint32_t zero3; +}; + +static grub_err_t +grub_plan9_boot (void) +{ + struct grub_relocator32_state state = { + .eax = 0, + .eip = eip, + .ebx = 0, + .ecx = 0, + .edx = 0, + .edi = 0, + .esp = 0, + .ebp = 0, + .esi = 0 + /* grub_uint32_t ebp; + grub_uint32_t esi; +*/ + }; + grub_video_set_mode ("text", 0, 0); + + return grub_relocator32_boot (rel, state); +} + +static grub_err_t +grub_plan9_unload (void) +{ + grub_relocator_unload (rel); + rel = NULL; + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + grub_err_t err; + void *mem; + grub_uint8_t *ptr; + grub_size_t memsize, padsize; + struct grub_plan9_header hdr; + char *config, *configptr; + grub_size_t configsize; + int i; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + + grub_dl_ref (my_mod); + + rel = grub_relocator_new (); + if (!rel) + goto fail; + + file = grub_file_open (argv[0]); + if (! file) + goto fail; + + if (grub_file_read (file, &hdr, sizeof (hdr)) != (grub_ssize_t) sizeof (hdr)) + goto fail; + + if (grub_be_to_cpu32 (hdr.magic) != GRUB_PLAN9_MAGIC + || hdr.zero1 || hdr.zero2 || hdr.zero3) + { + grub_error (GRUB_ERR_BAD_OS, "unsupported Plan9"); + goto fail; + } + + memsize = sizeof (hdr); + memsize += ALIGN_UP (grub_be_to_cpu32 (hdr.text_size), 16); + memsize += ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), 16); + memsize += ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), 16); + eip = grub_be_to_cpu32 (hdr.entry_addr) & 0xfffffff; + + /* path */ + configsize = GRUB_PLAN9_CONFIG_PATH_SIZE; + /* magic */ + configsize += sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1; + for (i = 1; i < argc; i++) + configsize += grub_strlen (argv[i]) + 1; + /* Terminating \0. */ + configsize++; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_PLAN9_CONFIG_ADDR, + configsize); + if (err) + goto fail; + config = get_virtual_current_address (ch); + } + + grub_memset (config, 0, GRUB_PLAN9_CONFIG_PATH_SIZE); + configptr = config + GRUB_PLAN9_CONFIG_PATH_SIZE; + grub_memcpy (configptr, GRUB_PLAN9_CONFIG_MAGIC, + sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1); + configptr += sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1; + for (i = 1; i < argc; i++) + { + configptr = grub_stpcpy (configptr, argv[i]); + *configptr++ = '\n'; + } + *configptr = 0; + + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_PLAN9_TARGET, + memsize); + if (err) + goto fail; + mem = get_virtual_current_address (ch); + } + + ptr = mem; + grub_memcpy (ptr, &hdr, sizeof (hdr)); + ptr += sizeof (hdr); + + if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.text_size)) + != (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size)) + goto fail; + ptr += grub_be_to_cpu32 (hdr.text_size); + padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.text_size), 16) + - grub_be_to_cpu32 (hdr.text_size); + + grub_memset (ptr, 0, padsize); + ptr += padsize; + + if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.data_size)) + != (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size)) + goto fail; + ptr += grub_be_to_cpu32 (hdr.data_size); + padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), 16) + - grub_be_to_cpu32 (hdr.data_size); + + grub_memset (ptr, 0, padsize); + ptr += padsize; + grub_memset (ptr, 0, ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), 16)); + + grub_loader_set (grub_plan9_boot, grub_plan9_unload, 1); + return GRUB_ERR_NONE; + + fail: + + if (file) + grub_file_close (file); + + grub_plan9_unload (); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(plan9) +{ + cmd = grub_register_command ("plan9", grub_cmd_plan9, + 0, N_("Load Plan9 kernel.")); + my_mod = mod; +} + +GRUB_MOD_FINI(plan9) +{ + grub_unregister_command (cmd); +} From 239ab5f0480cb232ccb987856f21d4875629702e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 17:02:25 +0100 Subject: [PATCH 057/673] Fix Plan9 alignment --- grub-core/loader/i386/pc/plan9.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index aa96ae83c..aaceb2825 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -36,6 +36,7 @@ static struct grub_relocator *rel; static grub_uint32_t eip = 0xffffffff; #define GRUB_PLAN9_TARGET 0x100000 +#define GRUB_PLAN9_ALIGN 4096 #define GRUB_PLAN9_CONFIG_ADDR 0x001200 #define GRUB_PLAN9_CONFIG_PATH_SIZE 0x000040 #define GRUB_PLAN9_CONFIG_MAGIC "ZORT 0\r\n" @@ -121,10 +122,10 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), goto fail; } - memsize = sizeof (hdr); - memsize += ALIGN_UP (grub_be_to_cpu32 (hdr.text_size), 16); - memsize += ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), 16); - memsize += ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), 16); + memsize = ALIGN_UP (grub_be_to_cpu32 (hdr.text_size) + sizeof (hdr), + GRUB_PLAN9_ALIGN); + memsize += ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), GRUB_PLAN9_ALIGN); + memsize += ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), GRUB_PLAN9_ALIGN); eip = grub_be_to_cpu32 (hdr.entry_addr) & 0xfffffff; /* path */ @@ -174,8 +175,9 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), != (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size)) goto fail; ptr += grub_be_to_cpu32 (hdr.text_size); - padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.text_size), 16) - - grub_be_to_cpu32 (hdr.text_size); + padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.text_size) + sizeof (hdr), + GRUB_PLAN9_ALIGN) - grub_be_to_cpu32 (hdr.text_size) + - sizeof (hdr); grub_memset (ptr, 0, padsize); ptr += padsize; @@ -184,12 +186,12 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), != (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size)) goto fail; ptr += grub_be_to_cpu32 (hdr.data_size); - padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), 16) + padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), GRUB_PLAN9_ALIGN) - grub_be_to_cpu32 (hdr.data_size); grub_memset (ptr, 0, padsize); ptr += padsize; - grub_memset (ptr, 0, ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), 16)); + grub_memset (ptr, 0, ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), GRUB_PLAN9_ALIGN)); grub_loader_set (grub_plan9_boot, grub_plan9_unload, 1); return GRUB_ERR_NONE; From 3c50773923e086199748c7d431c2d0c1fd419bbd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Dec 2010 20:51:32 +0100 Subject: [PATCH 058/673] Ignore fields zero1 and zero3 --- grub-core/loader/i386/pc/plan9.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index aaceb2825..7b777d0b3 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -48,10 +48,10 @@ struct grub_plan9_header grub_uint32_t text_size; grub_uint32_t data_size; grub_uint32_t bss_size; - grub_uint32_t zero1; + grub_uint32_t sectiona; grub_uint32_t entry_addr; - grub_uint32_t zero2; - grub_uint32_t zero3; + grub_uint32_t zero; + grub_uint32_t sectionb; }; static grub_err_t @@ -116,7 +116,7 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), goto fail; if (grub_be_to_cpu32 (hdr.magic) != GRUB_PLAN9_MAGIC - || hdr.zero1 || hdr.zero2 || hdr.zero3) + || hdr.zero) { grub_error (GRUB_ERR_BAD_OS, "unsupported Plan9"); goto fail; From ac9ef7eef97d4c217a849e185ca5e06c560b9c83 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 20 Dec 2010 01:18:21 +0100 Subject: [PATCH 059/673] plan9 subpartition support --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 ++ grub-core/partmap/plan.c | 118 ++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 grub-core/partmap/plan.c diff --git a/Makefile.util.def b/Makefile.util.def index 74984e2e9..2b9d28cf0 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -91,6 +91,7 @@ library = { common = grub-core/partmap/gpt.c; common = grub-core/partmap/msdos.c; common = grub-core/partmap/sun.c; + common = grub-core/partmap/plan.c; common = grub-core/partmap/sunpc.c; common = grub-core/partmap/bsdlabel.c; common = grub-core/script/function.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index ae604b3c6..9151e434b 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1308,6 +1308,11 @@ module = { common = partmap/sun.c; }; +module = { + name = part_plan; + common = partmap/plan.c; +}; + module = { name = part_bsd; common = partmap/bsdlabel.c; diff --git a/grub-core/partmap/plan.c b/grub-core/partmap/plan.c new file mode 100644 index 000000000..c62d04b73 --- /dev/null +++ b/grub-core/partmap/plan.c @@ -0,0 +1,118 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct grub_partition_map grub_plan_partition_map; + +static grub_err_t +plan_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) +{ + struct grub_partition p; + int ptr = 0; + grub_err_t err; + + p.partmap = &grub_plan_partition_map; + p.msdostype = 0; + + for (p.number = 0; ; p.number++) + { + char sig[sizeof ("part ") - 1]; + char c; + + p.offset = (ptr >> GRUB_DISK_SECTOR_BITS) + 1; + p.index = ptr & (GRUB_DISK_SECTOR_SIZE - 1); + + err = grub_disk_read (disk, 1, ptr, sizeof (sig), sig); + if (err) + return err; + if (grub_memcmp (sig, "part ", sizeof ("part ") - 1) != 0) + break; + ptr += sizeof (sig); + do + { + err = grub_disk_read (disk, 1, ptr, 1, &c); + if (err) + return err; + ptr++; + } + while (grub_isdigit (c) || grub_isalpha (c)); + if (c != ' ') + break; + p.start = 0; + while (1) + { + err = grub_disk_read (disk, 1, ptr, 1, &c); + if (err) + return err; + ptr++; + if (!grub_isdigit (c)) + break; + p.start = p.start * 10 + (c - '0'); + } + if (c != ' ') + break; + p.len = 0; + while (1) + { + err = grub_disk_read (disk, 1, ptr, 1, &c); + if (err) + return err; + ptr++; + if (!grub_isdigit (c)) + break; + p.len = p.len * 10 + (c - '0'); + } + if (c != '\n') + break; + p.len -= p.start; + if (hook (disk, &p)) + return grub_errno; + } + if (p.number == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a plan partition table"); + + return GRUB_ERR_NONE; +} + +/* Partition map type. */ +static struct grub_partition_map grub_plan_partition_map = + { + .name = "plan", + .iterate = plan_partition_map_iterate, + }; + +GRUB_MOD_INIT(part_plan) +{ + grub_partition_map_register (&grub_plan_partition_map); +} + +GRUB_MOD_FINI(part_plan) +{ + grub_partition_map_unregister (&grub_plan_partition_map); +} + From da94d203d9f421259aca4548d9862d138c5d7188 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Dec 2010 00:04:31 +0100 Subject: [PATCH 060/673] Generate partmaps for plan9 --- grub-core/loader/i386/pc/plan9.c | 279 +++++++++++++++++++++++++++---- include/grub/disk.h | 2 - include/grub/misc.h | 1 + include/grub/mm.h | 17 ++ include/grub/msdos_partition.h | 2 + 5 files changed, 271 insertions(+), 30 deletions(-) diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 7b777d0b3..2418bf1a1 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -67,9 +69,6 @@ grub_plan9_boot (void) .esp = 0, .ebp = 0, .esi = 0 - /* grub_uint32_t ebp; - grub_uint32_t esi; -*/ }; grub_video_set_mode ("text", 0, 0); @@ -90,14 +89,218 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { grub_file_t file = 0; - grub_err_t err; void *mem; - grub_uint8_t *ptr; grub_size_t memsize, padsize; struct grub_plan9_header hdr; char *config, *configptr; grub_size_t configsize; int i; + char *pmap = NULL; + grub_size_t pmapalloc = 256; + grub_size_t pmapptr = 0; + int noslash = 1; + char prefixes[5][10] = {"dos", "plan9", "ntfs", "linux", "linuxswap"}; + int prefixescnt[5]; + + auto int fill_partition (grub_disk_t disk, + const grub_partition_t partition); + int fill_partition (grub_disk_t disk, + const grub_partition_t partition) + { + if (!noslash) + { + if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap)) + return 1; + pmap[pmapptr++] = '/'; + } + noslash = 0; + + if (grub_strcmp (partition->partmap->name, "plan") == 0) + { + unsigned ptr = partition->index + sizeof ("part ") - 1; + grub_err_t err; + disk->partition = partition->parent; + do + { + if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap)) + return 1; + err = grub_disk_read (disk, 1, ptr, 1, pmap + pmapptr); + if (err) + { + disk->partition = 0; + return err; + } + ptr++; + pmapptr++; + } + while (grub_isalpha (pmap[pmapptr - 1]) + || grub_isdigit (pmap[pmapptr - 1])); + pmapptr--; + } + else + { + char name[50]; + int c = 0; + if (grub_strcmp (partition->partmap->name, "msdos") == 0) + { + switch (partition->msdostype) + { + case GRUB_PC_PARTITION_TYPE_PLAN9: + c = 1; + break; + case GRUB_PC_PARTITION_TYPE_NTFS: + c = 2; + break; + case GRUB_PC_PARTITION_TYPE_MINIX: + case GRUB_PC_PARTITION_TYPE_LINUX_MINIX: + case GRUB_PC_PARTITION_TYPE_EXT2FS: + c = 3; + break; + case GRUB_PC_PARTITION_TYPE_LINUX_SWAP: + c = 4; + break; + } + } + + if (prefixescnt[c] == 0) + grub_strcpy (name, prefixes[c]); + else + grub_snprintf (name, sizeof (name), "%s.%d", prefixes[c], + prefixescnt[c]); + prefixescnt[c]++; + if (grub_extend_alloc (pmapptr + grub_strlen (name) + 1, + &pmapalloc, (void **) &pmap)) + return 1; + grub_strcpy (pmap + pmapptr, name); + pmapptr += grub_strlen (name); + } + if (grub_extend_alloc (pmapptr + 2 + 25 + 5 + 25, &pmapalloc, + (void **) &pmap)) + return 1; + pmap[pmapptr++] = ' '; + grub_snprintf (pmap + pmapptr, 25 + 5 + 25, + "%" PRIuGRUB_UINT64_T " %" PRIuGRUB_UINT64_T, + grub_partition_get_start (partition), + grub_partition_get_start (partition) + + grub_partition_get_len (partition)); + pmapptr += grub_strlen (pmap + pmapptr); + return 0; + } + + auto int fill_disk (const char *name); + int fill_disk (const char *name) + { + grub_device_t dev; + int file_disk; + char *plan9name = NULL; + + dev = grub_device_open (name); + if (!dev) + { + grub_print_error (); + return 0; + } + if (!dev->disk) + { + grub_device_close (dev); + return 0; + } + file_disk = file->device->disk && dev->disk->id == file->device->disk->id + && dev->disk->dev->id == file->device->disk->dev->id; + switch (dev->disk->dev->id) + { + case GRUB_DISK_DEVICE_BIOSDISK_ID: + if (dev->disk->id & 0x80) + plan9name = grub_xasprintf ("sdB%u", + (unsigned) (dev->disk->id & 0x7f)); + else + plan9name = grub_xasprintf ("fd%u", + (unsigned) (dev->disk->id & 0x7f)); + break; + /* Shouldn't happen as Plan9 doesn't work on these platforms. */ + case GRUB_DISK_DEVICE_OFDISK_ID: + case GRUB_DISK_DEVICE_EFIDISK_ID: + + /* Plan9 doesn't see those. */ + case GRUB_DISK_DEVICE_LOOPBACK_ID: + case GRUB_DISK_DEVICE_RAID_ID: + case GRUB_DISK_DEVICE_LVM_ID: + case GRUB_DISK_DEVICE_HOST_ID: + case GRUB_DISK_DEVICE_MEMDISK_ID: + case GRUB_DISK_DEVICE_LUKS_ID: + + /* Not sure how to handle those. */ + case GRUB_DISK_DEVICE_PXE_ID: + case GRUB_DISK_DEVICE_NAND_ID: + if (!file_disk) + { + grub_device_close (dev); + return 0; + } + + /* if it's the disk the kernel is loaded from we need to name + it nevertheless. */ + plan9name = grub_strdup ("sdZ0"); + break; + + case GRUB_DISK_DEVICE_ATA_ID: + { + int unit; + if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1) + unit = 0; + else + unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0); + plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2); + } + break; + case GRUB_DISK_DEVICE_SCSI_ID: + if (((dev->disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xff) + == GRUB_SCSI_SUBSYSTEM_ATAPI) + { + int unit; + if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1) + unit = 0; + else + unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0); + plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2); + break; + } + + /* FIXME: how does Plan9 number controllers? + We probably need save the SCSI devices and sort them */ + plan9name + = grub_xasprintf ("sd0%u", (unsigned) + ((dev->disk->id >> GRUB_SCSI_ID_BUS_SHIFT) & 0xf)); + break; + } + if (!plan9name) + { + grub_print_error (); + return 0; + } + if (grub_extend_alloc (pmapptr + grub_strlen (plan9name) + + sizeof ("part="), &pmapalloc, + (void **) &pmap)) + { + grub_free (plan9name); + return 1; + } + grub_strcpy (pmap + pmapptr, plan9name); + pmapptr += grub_strlen (plan9name); + grub_free (plan9name); + grub_strcpy (pmap + pmapptr, "part="); + pmapptr += sizeof ("part=") - 1; + + noslash = 1; + grub_memset (prefixescnt, 0, sizeof (prefixescnt)); + if (grub_partition_iterate (dev->disk, fill_partition)) + return 1; + if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap)) + return 1; + pmap[pmapptr++] = '\n'; + + return 0; + } if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); @@ -112,6 +315,18 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), if (! file) goto fail; + pmap = grub_malloc (pmapalloc); + if (!pmap) + goto fail; + + if (grub_disk_dev_iterate (fill_disk)) + goto fail; + + if (grub_extend_alloc (pmapptr + 1, &pmapalloc, + (void **) &pmap)) + goto fail; + pmap[pmapptr] = 0; + if (grub_file_read (file, &hdr, sizeof (hdr)) != (grub_ssize_t) sizeof (hdr)) goto fail; @@ -134,11 +349,13 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), configsize += sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1; for (i = 1; i < argc; i++) configsize += grub_strlen (argv[i]) + 1; + configsize += pmapptr; /* Terminating \0. */ configsize++; { grub_relocator_chunk_t ch; + grub_err_t err; err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_PLAN9_CONFIG_ADDR, configsize); if (err) @@ -156,10 +373,12 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), configptr = grub_stpcpy (configptr, argv[i]); *configptr++ = '\n'; } - *configptr = 0; + configptr = grub_stpcpy (configptr, pmap); { grub_relocator_chunk_t ch; + grub_err_t err; + err = grub_relocator_alloc_chunk_addr (rel, &ch, GRUB_PLAN9_TARGET, memsize); if (err) @@ -167,36 +386,40 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), mem = get_virtual_current_address (ch); } - ptr = mem; - grub_memcpy (ptr, &hdr, sizeof (hdr)); - ptr += sizeof (hdr); + { + grub_uint8_t *ptr; + ptr = mem; + grub_memcpy (ptr, &hdr, sizeof (hdr)); + ptr += sizeof (hdr); - if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.text_size)) - != (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size)) - goto fail; - ptr += grub_be_to_cpu32 (hdr.text_size); - padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.text_size) + sizeof (hdr), - GRUB_PLAN9_ALIGN) - grub_be_to_cpu32 (hdr.text_size) - - sizeof (hdr); + if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.text_size)) + != (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size)) + goto fail; + ptr += grub_be_to_cpu32 (hdr.text_size); + padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.text_size) + sizeof (hdr), + GRUB_PLAN9_ALIGN) - grub_be_to_cpu32 (hdr.text_size) + - sizeof (hdr); - grub_memset (ptr, 0, padsize); - ptr += padsize; + grub_memset (ptr, 0, padsize); + ptr += padsize; - if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.data_size)) - != (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size)) - goto fail; - ptr += grub_be_to_cpu32 (hdr.data_size); - padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), GRUB_PLAN9_ALIGN) - - grub_be_to_cpu32 (hdr.data_size); - - grub_memset (ptr, 0, padsize); - ptr += padsize; - grub_memset (ptr, 0, ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), GRUB_PLAN9_ALIGN)); + if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.data_size)) + != (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size)) + goto fail; + ptr += grub_be_to_cpu32 (hdr.data_size); + padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), GRUB_PLAN9_ALIGN) + - grub_be_to_cpu32 (hdr.data_size); + grub_memset (ptr, 0, padsize); + ptr += padsize; + grub_memset (ptr, 0, ALIGN_UP(grub_be_to_cpu32 (hdr.bss_size), + GRUB_PLAN9_ALIGN)); + } grub_loader_set (grub_plan9_boot, grub_plan9_unload, 1); return GRUB_ERR_NONE; fail: + grub_free (pmap); if (file) grub_file_close (file); diff --git a/include/grub/disk.h b/include/grub/disk.h index 66db1149a..b72b26f46 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -38,10 +38,8 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_ATA_ID, GRUB_DISK_DEVICE_MEMDISK_ID, GRUB_DISK_DEVICE_NAND_ID, - GRUB_DISK_DEVICE_UUID_ID, GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, - GRUB_DISK_DEVICE_FILE_ID, GRUB_DISK_DEVICE_LUKS_ID }; diff --git a/include/grub/misc.h b/include/grub/misc.h index 6fcaa148b..b26a70cd0 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -353,4 +353,5 @@ extern int EXPORT_VAR(grub_no_autoload); #define grub_no_autoload 0 #endif + #endif /* ! GRUB_MISC_HEADER */ diff --git a/include/grub/mm.h b/include/grub/mm.h index cc115907a..5810fff41 100644 --- a/include/grub/mm.h +++ b/include/grub/mm.h @@ -72,4 +72,21 @@ void *EXPORT_FUNC(grub_debug_memalign) (const char *file, int line, grub_size_t align, grub_size_t size); #endif /* MM_DEBUG && ! GRUB_UTIL */ +#include + +static inline grub_err_t +grub_extend_alloc (grub_size_t sz, grub_size_t *allocated, void **ptr) +{ + void *n; + if (sz < *allocated) + return GRUB_ERR_NONE; + + *allocated = 2 * sz; + n = grub_realloc (*ptr, *allocated); + if (!n) + return grub_errno; + *ptr = n; + return GRUB_ERR_NONE; +} + #endif /* ! GRUB_MM_H */ diff --git a/include/grub/msdos_partition.h b/include/grub/msdos_partition.h index a6e3fda49..9c8ac3e8a 100644 --- a/include/grub/msdos_partition.h +++ b/include/grub/msdos_partition.h @@ -42,9 +42,11 @@ #define GRUB_PC_PARTITION_TYPE_FAT32_LBA 0xc #define GRUB_PC_PARTITION_TYPE_FAT16_LBA 0xe #define GRUB_PC_PARTITION_TYPE_WIN95_EXTENDED 0xf +#define GRUB_PC_PARTITION_TYPE_PLAN9 0x39 #define GRUB_PC_PARTITION_TYPE_EZD 0x55 #define GRUB_PC_PARTITION_TYPE_MINIX 0x80 #define GRUB_PC_PARTITION_TYPE_LINUX_MINIX 0x81 +#define GRUB_PC_PARTITION_TYPE_LINUX_SWAP 0x82 #define GRUB_PC_PARTITION_TYPE_EXT2FS 0x83 #define GRUB_PC_PARTITION_TYPE_LINUX_EXTENDED 0x85 #define GRUB_PC_PARTITION_TYPE_VSTAFS 0x9e From 645b8cd99f6a83df1c0780b0bfdf8685cd21adb9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Dec 2010 00:22:11 +0100 Subject: [PATCH 061/673] Allow override Plan9 device names --- grub-core/loader/i386/pc/plan9.c | 161 ++++++++++++++++++------------- 1 file changed, 93 insertions(+), 68 deletions(-) diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 2418bf1a1..228ea6159 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -32,6 +32,7 @@ #include #include #include +#include static grub_dl_t my_mod; static struct grub_relocator *rel; @@ -43,6 +44,14 @@ static grub_uint32_t eip = 0xffffffff; #define GRUB_PLAN9_CONFIG_PATH_SIZE 0x000040 #define GRUB_PLAN9_CONFIG_MAGIC "ZORT 0\r\n" +static const struct grub_arg_option options[] = + { + {"map", 'm', GRUB_ARG_OPTION_REPEATABLE, + N_("Override guessed mapping of Plan9 devices."), "GRUBDEVICE=PLAN9DEVICE", + ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + struct grub_plan9_header { grub_uint32_t magic; @@ -85,8 +94,7 @@ grub_plan9_unload (void) } static grub_err_t -grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) +grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) { grub_file_t file = 0; void *mem; @@ -94,7 +102,6 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), struct grub_plan9_header hdr; char *config, *configptr; grub_size_t configsize; - int i; char *pmap = NULL; grub_size_t pmapalloc = 256; grub_size_t pmapptr = 0; @@ -193,6 +200,7 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), grub_device_t dev; int file_disk; char *plan9name = NULL; + unsigned i; dev = grub_device_open (name); if (!dev) @@ -207,55 +215,50 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), } file_disk = file->device->disk && dev->disk->id == file->device->disk->id && dev->disk->dev->id == file->device->disk->dev->id; - switch (dev->disk->dev->id) - { - case GRUB_DISK_DEVICE_BIOSDISK_ID: - if (dev->disk->id & 0x80) - plan9name = grub_xasprintf ("sdB%u", - (unsigned) (dev->disk->id & 0x7f)); - else - plan9name = grub_xasprintf ("fd%u", - (unsigned) (dev->disk->id & 0x7f)); + for (i = 0; ctxt->state[0].args && ctxt->state[0].args[i]; i++) + if (grub_strncmp (name, ctxt->state[0].args[i], grub_strlen (name)) == 0 + && ctxt->state[0].args[i][grub_strlen (name)] == '=') break; - /* Shouldn't happen as Plan9 doesn't work on these platforms. */ - case GRUB_DISK_DEVICE_OFDISK_ID: - case GRUB_DISK_DEVICE_EFIDISK_ID: - - /* Plan9 doesn't see those. */ - case GRUB_DISK_DEVICE_LOOPBACK_ID: - case GRUB_DISK_DEVICE_RAID_ID: - case GRUB_DISK_DEVICE_LVM_ID: - case GRUB_DISK_DEVICE_HOST_ID: - case GRUB_DISK_DEVICE_MEMDISK_ID: - case GRUB_DISK_DEVICE_LUKS_ID: - - /* Not sure how to handle those. */ - case GRUB_DISK_DEVICE_PXE_ID: - case GRUB_DISK_DEVICE_NAND_ID: - if (!file_disk) - { - grub_device_close (dev); - return 0; - } - - /* if it's the disk the kernel is loaded from we need to name - it nevertheless. */ - plan9name = grub_strdup ("sdZ0"); - break; - - case GRUB_DISK_DEVICE_ATA_ID: + if (ctxt->state[0].args && ctxt->state[0].args[i]) + plan9name = grub_strdup (ctxt->state[0].args[i] + grub_strlen (name) + 1); + else + switch (dev->disk->dev->id) { - int unit; - if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1) - unit = 0; + case GRUB_DISK_DEVICE_BIOSDISK_ID: + if (dev->disk->id & 0x80) + plan9name = grub_xasprintf ("sdB%u", + (unsigned) (dev->disk->id & 0x7f)); else - unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0); - plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2); - } - break; - case GRUB_DISK_DEVICE_SCSI_ID: - if (((dev->disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xff) - == GRUB_SCSI_SUBSYSTEM_ATAPI) + plan9name = grub_xasprintf ("fd%u", + (unsigned) (dev->disk->id & 0x7f)); + break; + /* Shouldn't happen as Plan9 doesn't work on these platforms. */ + case GRUB_DISK_DEVICE_OFDISK_ID: + case GRUB_DISK_DEVICE_EFIDISK_ID: + + /* Plan9 doesn't see those. */ + case GRUB_DISK_DEVICE_LOOPBACK_ID: + case GRUB_DISK_DEVICE_RAID_ID: + case GRUB_DISK_DEVICE_LVM_ID: + case GRUB_DISK_DEVICE_HOST_ID: + case GRUB_DISK_DEVICE_MEMDISK_ID: + case GRUB_DISK_DEVICE_LUKS_ID: + + /* Not sure how to handle those. */ + case GRUB_DISK_DEVICE_PXE_ID: + case GRUB_DISK_DEVICE_NAND_ID: + if (!file_disk) + { + grub_device_close (dev); + return 0; + } + + /* if it's the disk the kernel is loaded from we need to name + it nevertheless. */ + plan9name = grub_strdup ("sdZ0"); + break; + + case GRUB_DISK_DEVICE_ATA_ID: { int unit; if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1) @@ -263,16 +266,30 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), else unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, 0, 0); plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2); - break; } + break; + case GRUB_DISK_DEVICE_SCSI_ID: + if (((dev->disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xff) + == GRUB_SCSI_SUBSYSTEM_ATAPI) + { + int unit; + if (grub_strlen (dev->disk->name) < sizeof ("ata0") - 1) + unit = 0; + else + unit = grub_strtoul (dev->disk->name + sizeof ("ata0") - 1, + 0, 0); + plan9name = grub_xasprintf ("sd%c%d", 'C' + unit / 2, unit % 2); + break; + } - /* FIXME: how does Plan9 number controllers? - We probably need save the SCSI devices and sort them */ - plan9name - = grub_xasprintf ("sd0%u", (unsigned) - ((dev->disk->id >> GRUB_SCSI_ID_BUS_SHIFT) & 0xf)); - break; - } + /* FIXME: how does Plan9 number controllers? + We probably need save the SCSI devices and sort them */ + plan9name + = grub_xasprintf ("sd0%u", (unsigned) + ((dev->disk->id >> GRUB_SCSI_ID_BUS_SHIFT) + & 0xf)); + break; + } if (!plan9name) { grub_print_error (); @@ -347,8 +364,11 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), configsize = GRUB_PLAN9_CONFIG_PATH_SIZE; /* magic */ configsize += sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1; - for (i = 1; i < argc; i++) - configsize += grub_strlen (argv[i]) + 1; + { + int i; + for (i = 1; i < argc; i++) + configsize += grub_strlen (argv[i]) + 1; + } configsize += pmapptr; /* Terminating \0. */ configsize++; @@ -368,11 +388,14 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), grub_memcpy (configptr, GRUB_PLAN9_CONFIG_MAGIC, sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1); configptr += sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1; - for (i = 1; i < argc; i++) - { - configptr = grub_stpcpy (configptr, argv[i]); - *configptr++ = '\n'; - } + { + int i; + for (i = 1; i < argc; i++) + { + configptr = grub_stpcpy (configptr, argv[i]); + *configptr++ = '\n'; + } + } configptr = grub_stpcpy (configptr, pmap); { @@ -429,16 +452,18 @@ grub_cmd_plan9 (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } -static grub_command_t cmd; +static grub_extcmd_t cmd; GRUB_MOD_INIT(plan9) { - cmd = grub_register_command ("plan9", grub_cmd_plan9, - 0, N_("Load Plan9 kernel.")); + cmd = grub_register_extcmd ("plan9", grub_cmd_plan9, + GRUB_COMMAND_OPTIONS_AT_START, + N_("KERNEL ARGS"), N_("Load Plan9 kernel."), + options); my_mod = mod; } GRUB_MOD_FINI(plan9) { - grub_unregister_command (cmd); + grub_unregister_extcmd (cmd); } From 5c61fc9f48fee403037fc4399832f8c96d789f6a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 21 Dec 2010 00:37:03 +0100 Subject: [PATCH 062/673] supply boot file to plan9 --- grub-core/loader/i386/pc/plan9.c | 54 ++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 228ea6159..02d1d63cd 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -108,12 +108,15 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) int noslash = 1; char prefixes[5][10] = {"dos", "plan9", "ntfs", "linux", "linuxswap"}; int prefixescnt[5]; + char *bootdisk = NULL, *bootpart = NULL, *bootpath = NULL; auto int fill_partition (grub_disk_t disk, const grub_partition_t partition); int fill_partition (grub_disk_t disk, const grub_partition_t partition) { + int file_disk = 0; + int pstart, pend; if (!noslash) { if (grub_extend_alloc (pmapptr + 1, &pmapalloc, (void **) &pmap)) @@ -122,6 +125,10 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) } noslash = 0; + file_disk = file->device->disk && disk->id == file->device->disk->id + && disk->dev->id == file->device->disk->dev->id; + + pstart = pmapptr; if (grub_strcmp (partition->partmap->name, "plan") == 0) { unsigned ptr = partition->index + sizeof ("part ") - 1; @@ -180,7 +187,8 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) return 1; grub_strcpy (pmap + pmapptr, name); pmapptr += grub_strlen (name); - } + } + pend = pmapptr; if (grub_extend_alloc (pmapptr + 2 + 25 + 5 + 25, &pmapalloc, (void **) &pmap)) return 1; @@ -190,6 +198,15 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) grub_partition_get_start (partition), grub_partition_get_start (partition) + grub_partition_get_len (partition)); + if (file_disk && grub_partition_get_start (partition) + == grub_partition_get_start (file->device->disk->partition) + && grub_partition_get_len (partition) + == grub_partition_get_len (file->device->disk->partition)) + { + grub_free (bootpart); + bootpart = grub_strndup (pmap + pstart, pend - pstart); + } + pmapptr += grub_strlen (pmap + pmapptr); return 0; } @@ -198,9 +215,9 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) int fill_disk (const char *name) { grub_device_t dev; - int file_disk; char *plan9name = NULL; unsigned i; + int file_disk = 0; dev = grub_device_open (name); if (!dev) @@ -304,7 +321,13 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) } grub_strcpy (pmap + pmapptr, plan9name); pmapptr += grub_strlen (plan9name); - grub_free (plan9name); + if (!file_disk) + grub_free (plan9name); + else + { + grub_free (bootdisk); + bootdisk = plan9name; + } grub_strcpy (pmap + pmapptr, "part="); pmapptr += sizeof ("part=") - 1; @@ -344,6 +367,25 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) goto fail; pmap[pmapptr] = 0; + { + char *file_name = grub_strchr (argv[0], ')'); + if (file_name) + file_name++; + else + file_name = argv[0]; + if (*file_name) + file_name++; + + if (bootpart) + bootpath = grub_xasprintf ("%s!%s!%s", bootdisk, bootpart, file_name); + else + bootpath = grub_xasprintf ("%s!%s", bootdisk, file_name); + grub_free (bootdisk); + grub_free (bootpart); + } + if (!bootpath) + goto fail; + if (grub_file_read (file, &hdr, sizeof (hdr)) != (grub_ssize_t) sizeof (hdr)) goto fail; @@ -369,6 +411,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) for (i = 1; i < argc; i++) configsize += grub_strlen (argv[i]) + 1; } + configsize += (sizeof ("bootfile=") - 1) + grub_strlen (bootpath) + 1; configsize += pmapptr; /* Terminating \0. */ configsize++; @@ -384,10 +427,15 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) } grub_memset (config, 0, GRUB_PLAN9_CONFIG_PATH_SIZE); + grub_strncpy (config, bootpath, GRUB_PLAN9_CONFIG_PATH_SIZE - 1); + configptr = config + GRUB_PLAN9_CONFIG_PATH_SIZE; grub_memcpy (configptr, GRUB_PLAN9_CONFIG_MAGIC, sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1); configptr += sizeof (GRUB_PLAN9_CONFIG_MAGIC) - 1; + configptr = grub_stpcpy (configptr, "bootfile="); + configptr = grub_stpcpy (configptr, bootpath); + *configptr++ = '\n'; { int i; for (i = 1; i < argc; i++) From c7336d912c656c4b7c7162e8dee6f5001e732be5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 16:07:53 +0100 Subject: [PATCH 063/673] splitting generic ata from pata. --- commands/hdparm.c | 95 +++-- disk/ahci.c | 289 ++++++++++----- disk/ata.c | 829 ++++++++++++++------------------------------ disk/ata_pthru.c | 520 ++++++++++++++++++++++++--- disk/scsi.c | 38 +- disk/usbms.c | 12 +- include/grub/ata.h | 122 ++++--- include/grub/disk.h | 13 +- include/grub/scsi.h | 16 +- kern/disk.c | 4 - 10 files changed, 1095 insertions(+), 843 deletions(-) diff --git a/commands/hdparm.c b/commands/hdparm.c index a3f8bbff0..02ae8f36b 100644 --- a/commands/hdparm.c +++ b/commands/hdparm.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -61,60 +62,60 @@ enum grub_ata_smart_commands static int quiet = 0; static grub_err_t -grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd, +grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd, grub_uint8_t features, grub_uint8_t sectors, void * buffer, int size) { struct grub_disk_ata_pass_through_parms apt; grub_memset (&apt, 0, sizeof (apt)); - apt.taskfile[GRUB_ATA_REG_CMD] = cmd; - apt.taskfile[GRUB_ATA_REG_FEATURES] = features; - apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors; + apt.taskfile.cmd = cmd; + apt.taskfile.features = features; + apt.taskfile.sectors = sectors; apt.buffer = buffer; apt.size = size; - if (grub_disk_ata_pass_through (disk, &apt)) + if (ata->dev->readwrite (ata, &apt)) return grub_errno; return GRUB_ERR_NONE; } static int -grub_hdparm_do_check_powermode_cmd (grub_disk_t disk) +grub_hdparm_do_check_powermode_cmd (grub_ata_t ata) { struct grub_disk_ata_pass_through_parms apt; grub_memset (&apt, 0, sizeof (apt)); - apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE; + apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE; - if (grub_disk_ata_pass_through (disk, &apt)) + if (ata->dev->readwrite (ata, &apt)) return -1; - return apt.taskfile[GRUB_ATA_REG_SECTORS]; + return apt.taskfile.sectors; } static int -grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features) +grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features) { struct grub_disk_ata_pass_through_parms apt; grub_memset (&apt, 0, sizeof (apt)); - apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART; - apt.taskfile[GRUB_ATA_REG_FEATURES] = features; - apt.taskfile[GRUB_ATA_REG_LBAMID] = 0x4f; - apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2; + apt.taskfile.cmd = GRUB_ATA_CMD_SMART; + apt.taskfile.features = features; + apt.taskfile.lba_mid = 0x4f; + apt.taskfile.lba_high = 0xc2; - if (grub_disk_ata_pass_through (disk, &apt)) + if (ata->dev->readwrite (ata, &apt)) return -1; if (features == GRUB_ATA_FEAT_SMART_STATUS) { - if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0x4f - && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2) + if ( apt.taskfile.lba_mid == 0x4f + && apt.taskfile.lba_high == 0xc2) return 0; /* Good SMART status. */ - else if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0xf4 - && apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c) + else if ( apt.taskfile.lba_mid == 0xf4 + && apt.taskfile.lba_high == 0x2c) return 1; /* Bad SMART status. */ else return -1; @@ -124,12 +125,12 @@ grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features) static grub_err_t grub_hdparm_simple_cmd (const char * msg, - grub_disk_t disk, grub_uint8_t cmd) + grub_ata_t ata, grub_uint8_t cmd) { if (! quiet && msg) grub_printf ("%s", msg); - grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0); + grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0); if (! quiet && msg) grub_printf ("%s\n", ! err ? "" : ": not supported"); @@ -138,7 +139,7 @@ grub_hdparm_simple_cmd (const char * msg, static grub_err_t grub_hdparm_set_val_cmd (const char * msg, int val, - grub_disk_t disk, grub_uint8_t cmd, + grub_ata_t ata, grub_uint8_t cmd, grub_uint8_t features, grub_uint8_t sectors) { if (! quiet && msg && *msg) @@ -149,7 +150,7 @@ grub_hdparm_set_val_cmd (const char * msg, int val, grub_printf ("Disable %s", msg); } - grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors, + grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, features, sectors, NULL, 0); if (! quiet && msg) @@ -273,6 +274,7 @@ static grub_err_t grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? { struct grub_arg_list *state = cmd->state; + struct grub_ata *ata; /* Check command line. */ if (argc != 1) @@ -283,9 +285,6 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name"); args[0][len - 1] = 0; - if (! grub_disk_ata_pass_through) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available"); - int i = 0; int apm = get_int_arg (&state[i++]); int power = state[i++].set; @@ -311,15 +310,37 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed"); } + switch (disk->dev->id) + { + case GRUB_DISK_DEVICE_ATA_ID: + ata = disk->data; + break; + case GRUB_DISK_DEVICE_SCSI_ID: + if (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF) + == GRUB_SCSI_SUBSYSTEM_PATA + || (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF) + == GRUB_SCSI_SUBSYSTEM_AHCI)) + { + ata = ((struct grub_scsi *) disk->data)->data; + break; + } + default: + return grub_error (GRUB_ERR_IO, "not an ATA device"); + } + + /* Change settings. */ if (aam >= 0) grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1), - disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam); + ata, GRUB_ATA_CMD_SET_FEATURES, + (aam ? 0x42 : 0xc2), aam); if (apm >= 0) grub_hdparm_set_val_cmd ("Advanced Power Management", - (apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES, - (apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0)); + (apm != 255 ? apm : -1), ata, + GRUB_ATA_CMD_SET_FEATURES, + (apm != 255 ? 0x05 : 0x85), + (apm != 255 ? apm : 0)); if (standby_tout >= 0) { @@ -330,28 +351,28 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? grub_printf (")"); } /* The IDLE cmd sets disk to idle mode and configures standby timer. */ - grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout); + grub_hdparm_set_val_cmd ("", -1, ata, GRUB_ATA_CMD_IDLE, 0, standby_tout); } if (enable_smart >= 0) { if (! quiet) grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis")); - int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ? + int err = grub_hdparm_do_smart_cmd (ata, (enable_smart ? GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE)); if (! quiet) grub_printf ("%s\n", err ? ": not supported" : ""); } if (sec_freeze) - grub_hdparm_simple_cmd ("Freeze security settings", disk, + grub_hdparm_simple_cmd ("Freeze security settings", ata, GRUB_ATA_CMD_SECURITY_FREEZE_LOCK); /* Print/dump IDENTIFY. */ if (ident || dumpid) { char buf[GRUB_DISK_SECTOR_SIZE]; - if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE, + if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE, 0, 0, buf, sizeof (buf))) grub_printf ("Cannot read ATA IDENTIFY data\n"); else @@ -367,7 +388,7 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? if (power) { grub_printf ("Disk power mode is: "); - int mode = grub_hdparm_do_check_powermode_cmd (disk); + int mode = grub_hdparm_do_check_powermode_cmd (ata); if (mode < 0) grub_printf ("unknown\n"); else @@ -383,7 +404,7 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? { if (! quiet) grub_printf ("SMART status is: "); - int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS); + int err = grub_hdparm_do_smart_cmd (ata, GRUB_ATA_FEAT_SMART_STATUS); if (! quiet) grub_printf ("%s\n", (err < 0 ? "unknown" : err == 0 ? "OK" : "*BAD*")); @@ -392,11 +413,11 @@ grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? /* Change power mode. */ if (standby_now) - grub_hdparm_simple_cmd ("Set disk to standby mode", disk, + grub_hdparm_simple_cmd ("Set disk to standby mode", ata, GRUB_ATA_CMD_STANDBY_IMMEDIATE); if (sleep_now) - grub_hdparm_simple_cmd ("Set disk to sleep mode", disk, + grub_hdparm_simple_cmd ("Set disk to sleep mode", ata, GRUB_ATA_CMD_SLEEP); grub_disk_close (disk); diff --git a/disk/ahci.c b/disk/ahci.c index 1372fd651..946db82e1 100644 --- a/disk/ahci.c +++ b/disk/ahci.c @@ -21,39 +21,79 @@ #include #include #include +#include #include +#include +#include struct grub_ahci_cmd_head { - grub_uint32_t unused[8]; + grub_uint32_t config; + grub_uint32_t transfered; + grub_uint64_t command_table_base; + grub_uint32_t unused[4]; +}; + +struct grub_ahci_prdt_entry +{ + grub_uint64_t data_base; + grub_uint32_t unused; + grub_uint32_t size; +}; + +struct grub_ahci_cmd_table +{ + grub_uint8_t cfis[0x40]; + grub_uint8_t command[16]; + grub_uint32_t reserved[0xc]; + struct grub_ahci_prdt_entry prdt[1]; }; struct grub_ahci_hba_port { grub_uint64_t command_list_base; - grub_uint32_t unused[12]; + grub_uint64_t fis_base; + grub_uint32_t intstatus; + grub_uint32_t inten; + grub_uint32_t command; + grub_uint32_t unused1[6]; grub_uint32_t sata_active; grub_uint32_t command_issue; - grub_uint32_t unused[16]; + grub_uint32_t unused2[17]; }; struct grub_ahci_hba { grub_uint32_t cap; -#define GRUB_AHCI_HBA_CAP_MASK 0x1f grub_uint32_t global_control; -#define GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN 0x80000000 + grub_uint32_t intr_status; grub_uint32_t ports_implemented; - grub_uint32_t unused1[7]; + grub_uint32_t unused1[6]; grub_uint32_t bios_handoff; -#define GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED 1 -#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNED 2 -#define GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED 8 -#define GRUB_AHCI_BIOS_HANDOFF_RWC 8 grub_uint32_t unused2[53]; struct grub_ahci_hba_port ports[32]; }; +enum + { + GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f + }; + +enum + { + GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002, + GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000, + }; + +enum + { + GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED = 1, + GRUB_AHCI_BIOS_HANDOFF_OS_OWNED = 2, + GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED = 8, + GRUB_AHCI_BIOS_HANDOFF_RWC = 8 + }; + + struct grub_ahci_device { struct grub_ahci_device *next; @@ -62,19 +102,41 @@ struct grub_ahci_device int num; struct grub_pci_dma_chunk *command_list_chunk; volatile struct grub_ahci_cmd_head *command_list; + struct grub_pci_dma_chunk *command_table_chunk; + volatile struct grub_ahci_cmd_table *command_table; }; +enum + { + GRUB_AHCI_CONFIG_READ = 0, + GRUB_AHCI_CONFIG_CFIS_LENGTH_MASK = 0x1f, + GRUB_AHCI_CONFIG_ATAPI = 0x20, + GRUB_AHCI_CONFIG_WRITE = 0x40, + GRUB_AHCI_CONFIG_PREFETCH = 0x80, + GRUB_AHCI_CONFIG_RESET = 0x100, + GRUB_AHCI_CONFIG_BIST = 0x200, + GRUB_AHCI_CONFIG_CLEAR_R_OK = 0x400, + GRUB_AHCI_CONFIG_PMP_MASK = 0xf000, + GRUB_AHCI_CONFIG_PRDT_LENGTH_MASK = 0xffff0000, + }; +#define GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT 0 +#define GRUB_AHCI_CONFIG_PMP_SHIFT 12 +#define GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT 16 +#define GRUB_AHCI_INTERRUPT_ON_COMPLETE 0x80000000 + +#define GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH 0x200000 + static struct grub_ahci_device *grub_ahci_devices; static int numdevs; static int NESTED_FUNC_ATTR grub_ahci_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__ ((unused))) + grub_pci_id_t pciid __attribute__ ((unused))) { grub_pci_address_t addr; grub_uint32_t class; grub_uint32_t bar; - int nports; + unsigned i, nports; volatile struct grub_ahci_hba *hba; /* Read class. */ @@ -88,8 +150,8 @@ grub_ahci_pciinit (grub_pci_device_t dev, addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); bar = grub_pci_read (addr); - if (bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK - | GRUB_PCI_ADDR_MEM_PREFETCH) + if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_MEM_PREFETCH)) != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) return 0; @@ -98,7 +160,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - nports = hba->cap & GRUB_AHCI_HBA_CAP_MASK; + nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) { @@ -122,11 +184,13 @@ grub_ahci_pciinit (grub_pci_device_t dev, } else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + grub_dprintf ("ahci", "%d AHCI ports\n", nports); for (i = 0; i < nports; i++) { struct grub_ahci_device *adev; struct grub_pci_dma_chunk *command_list; + struct grub_pci_dma_chunk *command_table; if (!(hba->ports_implemented & (1 << i))) continue; @@ -136,18 +200,34 @@ grub_ahci_pciinit (grub_pci_device_t dev, if (!command_list) return 1; - adev = grub_malloc (sizeof (*adev)); - if (!adev) + command_table = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_table)); + if (!command_table) { grub_dma_free (command_list); return 1; } + adev = grub_malloc (sizeof (*adev)); + if (!adev) + { + grub_dma_free (command_list); + grub_dma_free (command_table); + return 1; + } + + grub_dprintf ("ahci", "found device ahci%d (port %d)\n", numdevs, i); + adev->hba = hba; adev->port = i; adev->num = numdevs++; adev->command_list_chunk = command_list; adev->command_list = grub_dma_get_virt (command_list); + adev->command_table_chunk = command_table; + adev->command_table = grub_dma_get_virt (command_table); + adev->command_list->command_table_base + = grub_dma_get_phys (command_table); + adev->hba->ports[i].command_list_base = grub_dma_get_phys (command_list); grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), GRUB_AS_LIST (adev)); @@ -167,12 +247,12 @@ grub_ahci_initialize (void) static int -grub_ahci_iterate (int (*hook) (int bus, int luns)) +grub_ahci_iterate (int (*hook) (int id, int bus)) { struct grub_ahci_device *dev; FOR_LIST_ELEMENTS(dev, grub_ahci_devices) - if (hook (dev->num, 1)) + if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num)) return 1; return 0; @@ -195,95 +275,130 @@ find_free_cmd_slot (struct grub_ahci_device *dev) } #endif -static grub_err_t -grub_ahci_packet (struct grub_ahci_device *dev, char *packet, - grub_size_t size) +enum + { + GRUB_AHCI_FIS_REG_H2D = 0x27 + }; + +static const int register_map[11] = { 3 /* Features */, + 12 /* Sectors */, + 4 /* LBA low */, + 5 /* LBA mid */, + 6 /* LBA high */, + 7 /* Device */, + 2 /* CMD register */, + 13 /* Sectors 48 */, + 8 /* LBA48 low */, + 9 /* LBA48 mid */, + 10 /* LBA48 high */ }; + +static grub_err_t +grub_ahci_readwrite (grub_ata_t disk, + struct grub_disk_ata_pass_through_parms *parms) { + struct grub_ahci_device *dev = (struct grub_ahci_device *) disk->data; + struct grub_pci_dma_chunk *bufc; + grub_uint64_t endtime; + unsigned i; + + grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n", + (unsigned long long) parms->size, + (unsigned long long) parms->cmdsize); + + if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size"); + + if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer"); + + bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); + + /* FIXME: support port multipliers. */ + dev->command_list[0].config + = (4 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) + | GRUB_AHCI_CONFIG_CLEAR_R_OK + | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT) + | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) + | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0) + | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ); + dev->command_list[0].transfered = 0; + dev->command_list[0].command_table_base + = grub_dma_get_phys (dev->command_table_chunk); + grub_memset ((char *) dev->command_list[0].unused, 0, + sizeof (dev->command_list[0].unused)); + grub_memset ((char *) &dev->command_table[0], 0, + sizeof (dev->command_table[0])); + if (parms->cmdsize) + grub_memcpy ((char *) dev->command_table[0].command, parms->cmd, + parms->cmdsize); + + dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D; + for (i = 0; i < sizeof (parms->taskfile.raw); i++) + dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; + + dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); + dev->command_table[0].prdt[0].unused = 0; + dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) + | GRUB_AHCI_INTERRUPT_ON_COMPLETE; + + if (parms->write) + grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); + + grub_dprintf ("ahci", "AHCI command schedulded\n"); + dev->hba->ports[dev->port].inten = (1 << 5); + dev->hba->ports[dev->port].intstatus = (1 << 5); + dev->hba->ports[dev->port].command_issue |= 1; + dev->hba->ports[dev->port].command |= 1; + + endtime = grub_get_time_ms () + 1000; + while (!(dev->hba->ports[dev->port].intstatus & (1 << 5))) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "AHCI timeout\n"); + dev->hba->ports[dev->port].command &= ~1; + /* FIXME: free resources. */ + return grub_error (GRUB_ERR_IO, "AHCI transfer timeouted"); + } + + grub_dprintf ("ahci", "AHCI command completed succesfully\n"); + dev->hba->ports[dev->port].command &= ~1; + + if (!parms->write) + grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size); + grub_dma_free (bufc); return GRUB_ERR_NONE; } static grub_err_t -grub_ahci_read (struct grub_scsi *scsi, - grub_size_t cmdsize __attribute__((unused)), - char *cmd, grub_size_t size, char *buf) -{ - struct grub_ahci_device *dev = (struct grub_ahci_device *) scsi->data; - - grub_dprintf("ahci", "grub_ahci_read (size=%llu)\n", (unsigned long long) size); - - if (grub_atapi_packet (dev, cmd, size)) - return grub_errno; - - grub_size_t nread = 0; - while (nread < size) - { - /* Wait for !BSY, DRQ, I/O, !C/D. */ - if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_DATA_IN, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - /* Get byte count for this DRQ assertion. */ - unsigned cnt = grub_ata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 - | grub_ata_regget (dev, GRUB_ATAPI_REG_CNTLOW); - grub_dprintf("ata", "DRQ count=%u\n", cnt); - - /* Count of last transfer may be uneven. */ - if (! (0 < cnt && cnt <= size - nread && (! (cnt & 1) || cnt == size - nread))) - return grub_error (GRUB_ERR_READ_ERROR, "invalid ATAPI transfer count"); - - /* Read the data. */ - grub_ata_pio_read (dev, buf + nread, cnt); - - if (cnt & 1) - buf[nread + cnt - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); - - nread += cnt; - } - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_ahci_write (struct grub_scsi *scsi __attribute__((unused)), - grub_size_t cmdsize __attribute__((unused)), - char *cmd __attribute__((unused)), - grub_size_t size __attribute__((unused)), - char *buf __attribute__((unused))) -{ - // XXX: scsi.mod does not use write yet. - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "AHCI write not implemented"); -} - -static grub_err_t -grub_ahci_open (int devnum, struct grub_scsi *scsi) +grub_ahci_open (int id, int devnum, struct grub_ata *ata) { struct grub_ahci_device *dev; + if (id != GRUB_SCSI_SUBSYSTEM_AHCI) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device"); + FOR_LIST_ELEMENTS(dev, grub_ahci_devices) { if (dev->num == devnum) break; } - grub_dprintf ("ata", "opening AHCI dev `ahci%d'\n", devnum); - if (! dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device"); - scsi->data = dev; + grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num); + + ata->data = dev; return GRUB_ERR_NONE; } - -static struct grub_scsi_dev grub_ahci_dev = +static struct grub_ata_dev grub_ahci_dev = { - .name = "ahci", - .id = GRUB_SCSI_SUBSYSTEM_AHCI, .iterate = grub_ahci_iterate, .open = grub_ahci_open, - .read = grub_ahci_read, - .write = grub_ahci_write + .readwrite = grub_ahci_readwrite, }; @@ -291,8 +406,8 @@ static struct grub_scsi_dev grub_ahci_dev = GRUB_MOD_INIT(ahci) { /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) + // grub_disk_firmware_is_tainted = 1; + if (0 && grub_disk_firmware_fini) { grub_disk_firmware_fini (); grub_disk_firmware_fini = NULL; @@ -302,10 +417,10 @@ GRUB_MOD_INIT(ahci) grub_ahci_initialize (); /* AHCI devices are handled by scsi.mod. */ - grub_scsi_dev_register (&grub_ahci_dev); + grub_ata_dev_register (&grub_ahci_dev); } GRUB_MOD_FINI(ahci) { - grub_scsi_dev_unregister (&grub_ahci_dev); + grub_ata_dev_unregister (&grub_ahci_dev); } diff --git a/disk/ata.c b/disk/ata.c index cfd58a6d5..3d9de23dd 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -21,76 +21,9 @@ #include #include #include -#include -#include #include -#include -/* At the moment, only two IDE ports are supported. */ -static const grub_port_t grub_ata_ioaddress[] = { GRUB_ATA_CH0_PORT1, - GRUB_ATA_CH1_PORT1 }; -static const grub_port_t grub_ata_ioaddress2[] = { GRUB_ATA_CH0_PORT2, - GRUB_ATA_CH1_PORT2 }; - -static struct grub_ata_device *grub_ata_devices; - -/* Wait for !BSY. */ -grub_err_t -grub_ata_wait_not_busy (struct grub_ata_device *dev, int milliseconds) -{ - /* ATA requires 400ns (after a write to CMD register) or - 1 PIO cycle (after a DRQ block transfer) before - first check of BSY. */ - grub_millisleep (1); - - int i = 1; - grub_uint8_t sts; - while ((sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS)) - & GRUB_ATA_STATUS_BUSY) - { - if (i >= milliseconds) - { - grub_dprintf ("ata", "timeout: %dms, status=0x%x\n", - milliseconds, sts); - return grub_error (GRUB_ERR_TIMEOUT, "ATA timeout"); - } - - grub_millisleep (1); - i++; - } - - return GRUB_ERR_NONE; -} - -static inline void -grub_ata_wait (void) -{ - grub_millisleep (50); -} - -/* Wait for !BSY, DRQ. */ -grub_err_t -grub_ata_wait_drq (struct grub_ata_device *dev, int rw, - int milliseconds) -{ - if (grub_ata_wait_not_busy (dev, milliseconds)) - return grub_errno; - - /* !DRQ implies error condition. */ - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - != GRUB_ATA_STATUS_DRQ) - { - grub_dprintf ("ata", "ata error: status=0x%x, error=0x%x\n", - sts, grub_ata_regget (dev, GRUB_ATA_REG_ERROR)); - if (! rw) - return grub_error (GRUB_ERR_READ_ERROR, "ATA read error"); - else - return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error"); - } - - return GRUB_ERR_NONE; -} +static grub_ata_dev_t grub_ata_dev_list; /* Byteorder has to be changed before strings can be read. */ static void @@ -105,30 +38,8 @@ grub_ata_strncpy (char *dst, char *src, grub_size_t len) dst[len] = '\0'; } -void -grub_ata_pio_read (struct grub_ata_device *dev, char *buf, grub_size_t size) -{ - grub_uint16_t *buf16 = (grub_uint16_t *) buf; - unsigned int i; - - /* Read in the data, word by word. */ - for (i = 0; i < size / 2; i++) - buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); -} - static void -grub_ata_pio_write (struct grub_ata_device *dev, char *buf, grub_size_t size) -{ - grub_uint16_t *buf16 = (grub_uint16_t *) buf; - unsigned int i; - - /* Write the data, word by word. */ - for (i = 0; i < size / 2; i++) - grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); -} - -static void -grub_ata_dumpinfo (struct grub_ata_device *dev, char *info) +grub_ata_dumpinfo (struct grub_ata *dev, char *info) { char text[41]; @@ -148,31 +59,27 @@ grub_ata_dumpinfo (struct grub_ata_device *dev, char *info) } static grub_err_t -grub_atapi_identify (struct grub_ata_device *dev) +grub_atapi_identify (struct grub_ata *dev) { + struct grub_disk_ata_pass_through_parms parms; char *info; + grub_err_t err; info = grub_malloc (GRUB_DISK_SECTOR_SIZE); if (! info) return grub_errno; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); - grub_ata_wait (); - if (grub_ata_check_ready (dev)) - { - grub_free (info); - return grub_errno; - } + grub_memset (&parms, 0, sizeof (parms)); + parms.taskfile.disk = 0; + parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE; - grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE); - grub_ata_wait (); + err = dev->dev->readwrite (dev, &parms); + if (err) + return err; - if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD)) - { - grub_free (info); - return grub_errno; - } - grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE); + if (parms.size != GRUB_DISK_SECTOR_SIZE) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "device cannot be identified"); dev->atapi = 1; @@ -184,96 +91,35 @@ grub_atapi_identify (struct grub_ata_device *dev) } static grub_err_t -grub_atapi_wait_drq (struct grub_ata_device *dev, - grub_uint8_t ireason, - int milliseconds) -{ - /* Wait for !BSY, DRQ, ireason */ - if (grub_ata_wait_not_busy (dev, milliseconds)) - return grub_errno; - - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - grub_uint8_t irs = grub_ata_regget (dev, GRUB_ATAPI_REG_IREASON); - - /* OK if DRQ is asserted and interrupt reason is as expected. */ - if ((sts & GRUB_ATA_STATUS_DRQ) - && (irs & GRUB_ATAPI_IREASON_MASK) == ireason) - return GRUB_ERR_NONE; - - /* !DRQ implies error condition. */ - grub_dprintf ("ata", "atapi error: status=0x%x, ireason=0x%x, error=0x%x\n", - sts, irs, grub_ata_regget (dev, GRUB_ATA_REG_ERROR)); - - if (! (sts & GRUB_ATA_STATUS_DRQ) - && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_ERROR) - { - if (ireason == GRUB_ATAPI_IREASON_CMD_OUT) - return grub_error (GRUB_ERR_READ_ERROR, "ATA PACKET command error"); - else - return grub_error (GRUB_ERR_READ_ERROR, "ATAPI read error"); - } - - return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error"); -} - -static grub_err_t -grub_atapi_packet (struct grub_ata_device *dev, char *packet, - grub_size_t size) -{ - grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); - if (grub_ata_check_ready (dev)) - return grub_errno; - - /* Send ATA PACKET command. */ - grub_ata_regset (dev, GRUB_ATA_REG_FEATURES, 0); - grub_ata_regset (dev, GRUB_ATAPI_REG_IREASON, 0); - grub_ata_regset (dev, GRUB_ATAPI_REG_CNTHIGH, size >> 8); - grub_ata_regset (dev, GRUB_ATAPI_REG_CNTLOW, size & 0xFF); - - grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_PACKET); - - /* Wait for !BSY, DRQ, !I/O, C/D. */ - if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_CMD_OUT, GRUB_ATA_TOUT_STD)) - return grub_errno; - - /* Write the packet. */ - grub_ata_pio_write (dev, packet, 12); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_ata_identify (struct grub_ata_device *dev) +grub_ata_identify (struct grub_ata *dev) { + struct grub_disk_ata_pass_through_parms parms; char *info; grub_uint16_t *info16; + grub_err_t err; info = grub_malloc (GRUB_DISK_SECTOR_SIZE); if (! info) return grub_errno; info16 = (grub_uint16_t *) info; + grub_memset (&parms, 0, sizeof (parms)); + parms.buffer = info; + parms.taskfile.disk = 0; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4); - grub_ata_wait (); - if (grub_ata_check_ready (dev)) + parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; + + err = dev->dev->readwrite (dev, &parms); + if (err) + return err; + + if (parms.size != GRUB_DISK_SECTOR_SIZE) { + grub_uint8_t sts = parms.taskfile.status; grub_free (info); - return grub_errno; - } - - grub_ata_regset (dev, GRUB_ATA_REG_CMD, GRUB_ATA_CMD_IDENTIFY_DEVICE); - grub_ata_wait (); - - if (grub_ata_wait_drq (dev, 0, GRUB_ATA_TOUT_STD)) - { - grub_free (info); - grub_errno = GRUB_ERR_NONE; - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR - && (grub_ata_regget (dev, GRUB_ATA_REG_ERROR) & 0x04 /* ABRT */)) + && (parms.taskfile.error & 0x04 /* ABRT */)) /* Device without ATA IDENTIFY, try ATAPI. */ return grub_atapi_identify (dev); @@ -287,19 +133,6 @@ grub_ata_identify (struct grub_ata_device *dev) "device cannot be identified"); } - grub_ata_pio_read (dev, info, GRUB_DISK_SECTOR_SIZE); - - /* Re-check status to avoid bogus identify data due to stuck DRQ. */ - grub_uint8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - if (sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - { - grub_dprintf ("ata", "bad status=0x%x\n", sts); - grub_free (info); - /* No device, return error but don't print message. */ - grub_errno = GRUB_ERR_NONE; - return GRUB_ERR_UNKNOWN_DEVICE; - } - /* Now it is certain that this is not an ATAPI device. */ dev->atapi = 0; @@ -335,196 +168,12 @@ grub_ata_identify (struct grub_ata_device *dev) } static grub_err_t -check_device (struct grub_ata_device *dev) -{ - grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); - grub_ata_wait (); - - /* Try to detect if the port is in use by writing to it, - waiting for a while and reading it again. If the value - was preserved, there is a device connected. */ - grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A); - grub_ata_wait (); - grub_uint8_t sec = grub_ata_regget (dev, GRUB_ATA_REG_SECTORS); - grub_dprintf ("ata", "sectors=0x%x\n", sec); - if (sec != 0x5A) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected"); - - /* The above test may detect a second (slave) device - connected to a SATA controller which supports only one - (master) device. It is not safe to use the status register - READY bit to check for controller channel existence. Some - ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */ - - /* Use the IDENTIFY DEVICE command to query the device. */ - return grub_ata_identify (dev); -} - -static grub_err_t -grub_ata_device_initialize (int port, int device, int addr, int addr2) -{ - struct grub_ata_device *dev; - struct grub_ata_device **devp; - grub_err_t err; - - grub_dprintf ("ata", "detecting device %d,%d (0x%x, 0x%x)\n", - port, device, addr, addr2); - - dev = grub_malloc (sizeof(*dev)); - if (! dev) - return grub_errno; - - /* Setup the device information. */ - dev->port = port; - dev->device = device; - dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; - dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; - dev->next = NULL; - - /* Register the device. */ - for (devp = &grub_ata_devices; *devp; devp = &(*devp)->next); - *devp = dev; - - err = check_device (dev); - if (err) - grub_print_error (); - - return 0; -} - -static int NESTED_FUNC_ATTR -grub_ata_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid) -{ - static int compat_use[2] = { 0 }; - grub_pci_address_t addr; - grub_uint32_t class; - grub_uint32_t bar1; - grub_uint32_t bar2; - int rega; - int regb; - int i; - static int controller = 0; - int cs5536 = 0; - int nports = 2; - - /* Read class. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - /* AMD CS5536 Southbridge. */ - if (pciid == GRUB_CS5536_PCIID) - { - cs5536 = 1; - nports = 1; - } - - /* Check if this class ID matches that of a PCI IDE Controller. */ - if (!cs5536 && (class >> 16 != 0x0101)) - return 0; - - for (i = 0; i < nports; i++) - { - /* Set to 0 when the channel operated in compatibility mode. */ - int compat; - - /* We don't support non-compatibility mode for CS5536. */ - if (cs5536) - compat = 0; - else - compat = (class >> (8 + 2 * i)) & 1; - - rega = 0; - regb = 0; - - /* If the channel is in compatibility mode, just assign the - default registers. */ - if (compat == 0 && !compat_use[i]) - { - rega = grub_ata_ioaddress[i]; - regb = grub_ata_ioaddress2[i]; - compat_use[i] = 1; - } - else if (compat) - { - /* Read the BARs, which either contain a mmapped IO address - or the IO port address. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES - + sizeof (grub_uint64_t) * i); - bar1 = grub_pci_read (addr); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES - + sizeof (grub_uint64_t) * i - + sizeof (grub_uint32_t)); - bar2 = grub_pci_read (addr); - - /* Check if the BARs describe an IO region. */ - if ((bar1 & 1) && (bar2 & 1)) - { - rega = bar1 & ~3; - regb = bar2 & ~3; - } - } - - grub_dprintf ("ata", - "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n", - grub_pci_get_bus (dev), grub_pci_get_device (dev), - grub_pci_get_function (dev), compat, rega, regb); - - if (rega && regb) - { - grub_errno = GRUB_ERR_NONE; - grub_ata_device_initialize (controller * 2 + i, 0, rega, regb); - - /* Most errors raised by grub_ata_device_initialize() are harmless. - They just indicate this particular drive is not responding, most - likely because it doesn't exist. We might want to ignore specific - error types here, instead of printing them. */ - if (grub_errno) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - } - - grub_ata_device_initialize (controller * 2 + i, 1, rega, regb); - - /* Likewise. */ - if (grub_errno) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - } - } - } - - controller++; - - return 0; -} - -static grub_err_t -grub_ata_initialize (void) -{ - grub_pci_iterate (grub_ata_pciinit); - return 0; -} - -static void -grub_ata_setlba (struct grub_ata_device *dev, grub_disk_addr_t sector, - grub_size_t size) -{ - grub_ata_regset (dev, GRUB_ATA_REG_SECTORS, size); - grub_ata_regset (dev, GRUB_ATA_REG_LBALOW, sector & 0xFF); - grub_ata_regset (dev, GRUB_ATA_REG_LBAMID, (sector >> 8) & 0xFF); - grub_ata_regset (dev, GRUB_ATA_REG_LBAHIGH, (sector >> 16) & 0xFF); -} - -static grub_err_t -grub_ata_setaddress (struct grub_ata_device *dev, - grub_ata_addressing_t addressing, +grub_ata_setaddress (struct grub_ata *dev, + struct grub_disk_ata_pass_through_parms *parms, grub_disk_addr_t sector, grub_size_t size) { - switch (addressing) + switch (dev->addr) { case GRUB_ATA_CHS: { @@ -544,14 +193,11 @@ grub_ata_setaddress (struct grub_ata_device *dev, return grub_error (GRUB_ERR_OUT_OF_RANGE, "sector %d cannot be addressed " "using CHS addressing", sector); - - grub_ata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4) | head); - if (grub_ata_check_ready (dev)) - return grub_errno; - - grub_ata_regset (dev, GRUB_ATA_REG_SECTNUM, sect); - grub_ata_regset (dev, GRUB_ATA_REG_CYLLSB, cylinder & 0xFF); - grub_ata_regset (dev, GRUB_ATA_REG_CYLMSB, cylinder >> 8); + + parms->taskfile.disk = head; + parms->taskfile.sectnum = sect; + parms->taskfile.cyllsb = cylinder & 0xFF; + parms->taskfile.cylmsb = cylinder >> 8; break; } @@ -559,26 +205,31 @@ grub_ata_setaddress (struct grub_ata_device *dev, case GRUB_ATA_LBA: if (size == 256) size = 0; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, - 0xE0 | (dev->device << 4) | ((sector >> 24) & 0x0F)); - if (grub_ata_check_ready (dev)) - return grub_errno; + parms->taskfile.disk = ((sector >> 24) & 0x0F); - grub_ata_setlba (dev, sector, size); + parms->taskfile.sectors = size; + parms->taskfile.lba_low = sector & 0xFF; + parms->taskfile.lba_mid = (sector >> 8) & 0xFF; + parms->taskfile.lba_high = (sector >> 16) & 0xFF; break; case GRUB_ATA_LBA48: if (size == 65536) size = 0; - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | (dev->device << 4)); - if (grub_ata_check_ready (dev)) - return grub_errno; + parms->taskfile.disk = 0; /* Set "Previous". */ - grub_ata_setlba (dev, sector >> 24, size >> 8); + parms->taskfile.sectors = size & 0xFF; + parms->taskfile.lba_low = sector & 0xFF; + parms->taskfile.lba_mid = (sector >> 8) & 0xFF; + parms->taskfile.lba_high = (sector >> 16) & 0xFF; + /* Set "Current". */ - grub_ata_setlba (dev, sector, size); + parms->taskfile.sectors48 = (size >> 8) & 0xFF; + parms->taskfile.lba48_low = (sector >> 24) & 0xFF; + parms->taskfile.lba48_mid = (sector >> 32) & 0xFF; + parms->taskfile.lba48_high = (sector >> 40) & 0xFF; break; } @@ -590,14 +241,15 @@ static grub_err_t grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf, int rw) { - struct grub_ata_device *dev = (struct grub_ata_device *) disk->data; + struct grub_ata *ata = disk->data; - grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n", (unsigned long long) size, rw); - - grub_ata_addressing_t addressing = dev->addr; + grub_ata_addressing_t addressing = ata->addr; grub_size_t batch; int cmd, cmd_write; + grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n", + (unsigned long long) size, rw); + if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0) { batch = 65536; @@ -608,7 +260,10 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, { if (addressing == GRUB_ATA_LBA48) addressing = GRUB_ATA_LBA; - batch = 256; + if (addressing != GRUB_ATA_CHS) + batch = 256; + else + batch = 1; cmd = GRUB_ATA_CMD_READ_SECTORS; cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; } @@ -616,44 +271,25 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t nsectors = 0; while (nsectors < size) { + struct grub_disk_ata_pass_through_parms parms; + grub_err_t err; + if (size - nsectors < batch) batch = size - nsectors; grub_dprintf("ata", "rw=%d, sector=%llu, batch=%llu\n", rw, (unsigned long long) sector, (unsigned long long) batch); - - /* Send read/write command. */ - if (grub_ata_setaddress (dev, addressing, sector, batch)) - return grub_errno; - - grub_ata_regset (dev, GRUB_ATA_REG_CMD, (! rw ? cmd : cmd_write)); - - unsigned sect; - for (sect = 0; sect < batch; sect++) - { - /* Wait for !BSY, DRQ. */ - if (grub_ata_wait_drq (dev, rw, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - /* Transfer data. */ - if (! rw) - grub_ata_pio_read (dev, buf, GRUB_DISK_SECTOR_SIZE); - else - grub_ata_pio_write (dev, buf, GRUB_DISK_SECTOR_SIZE); - - buf += GRUB_DISK_SECTOR_SIZE; - } - - if (rw) - { - /* Check for write error. */ - if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) - & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error"); - } - + grub_memset (&parms, 0, sizeof (parms)); + grub_ata_setaddress (ata, &parms, sector, batch); + parms.taskfile.cmd = (! rw ? cmd : cmd_write); + parms.buffer = buf; + parms.size = batch * GRUB_DISK_SECTOR_SIZE; + + err = ata->dev->readwrite (ata, &parms); + if (err) + return err; + if (parms.size != batch * GRUB_DISK_SECTOR_SIZE) + return grub_error (GRUB_ERR_READ_ERROR, "incomplete read"); + buf += GRUB_DISK_SECTOR_SIZE * batch; sector += batch; nsectors += batch; } @@ -663,76 +299,118 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, -static int -grub_ata_iterate (int (*hook) (const char *name)) +static inline void +grub_ata_real_close (struct grub_ata *ata) { - struct grub_ata_device *dev; + if (ata->dev->close) + ata->dev->close (ata); +} - for (dev = grub_ata_devices; dev; dev = dev->next) +static struct grub_ata * +grub_ata_real_open (int id, int bus) +{ + struct grub_ata *ata; + grub_ata_dev_t p; + + ata = grub_malloc (sizeof (*ata)); + if (!ata) + return NULL; + for (p = grub_ata_dev_list; p; p = p->next) { - char devname[10]; grub_err_t err; - - err = check_device (dev); - if (err) + if (p->open (id, bus, ata)) { grub_errno = GRUB_ERR_NONE; continue; } - - if (dev->atapi) - continue; - - grub_snprintf (devname, sizeof (devname), - "ata%d", dev->port * 2 + dev->device); - - if (hook (devname)) - return 1; + ata->dev = p; + /* Use the IDENTIFY DEVICE command to query the device. */ + err = grub_ata_identify (ata); + if (err) + { + grub_free (ata); + return NULL; + } + return ata; } + grub_free (ata); + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device"); + return NULL; +} +static int +grub_ata_iterate (int (*hook_in) (const char *name)) +{ + auto int hook (int id, int bus); + int hook (int id, int bus) + { + struct grub_ata *ata; + int ret; + char devname[40]; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + grub_snprintf (devname, sizeof (devname), + "%s%d", grub_scsi_names[id], bus); + ret = hook_in (devname); + grub_ata_real_close (ata); + return ret; + } + + grub_ata_dev_t p; + + for (p = grub_ata_dev_list; p; p = p->next) + if (p->iterate && p->iterate (hook)) + return 1; return 0; } static grub_err_t grub_ata_open (const char *name, grub_disk_t disk) { - struct grub_ata_device *dev; - grub_err_t err; + unsigned id, bus; + struct grub_ata *ata; - for (dev = grub_ata_devices; dev; dev = dev->next) - { - char devname[10]; - grub_snprintf (devname, sizeof (devname), - "ata%d", dev->port * 2 + dev->device); - if (grub_strcmp (name, devname) == 0) - break; - } + for (id = 0; id < GRUB_SCSI_NUM_SUBSYSTEMS; id++) + if (grub_strncmp (grub_scsi_names[id], name, + grub_strlen (grub_scsi_names[id])) == 0 + && grub_isdigit (name[grub_strlen (grub_scsi_names[id])])) + break; + if (id == GRUB_SCSI_NUM_SUBSYSTEMS) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); + bus = grub_strtoul (name + grub_strlen (grub_scsi_names[id]), 0, 0); + ata = grub_ata_real_open (id, bus); + if (!ata) + return grub_errno; - if (! dev) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - - if (dev->atapi) + if (ata->atapi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); - err = check_device (dev); + disk->total_sectors = ata->size; - if (err) - return err; - - disk->total_sectors = dev->size; - - disk->id = (unsigned long) dev; + disk->id = grub_make_scsi_id (id, bus, 0); disk->has_partitions = 1; - disk->data = dev; + disk->data = ata; return 0; } static void -grub_ata_close (grub_disk_t disk __attribute__((unused))) +grub_ata_close (grub_disk_t disk) { - + struct grub_ata *ata = disk->data; + grub_ata_real_close (ata); } static grub_err_t @@ -767,70 +445,35 @@ static struct grub_disk_dev grub_atadisk_dev = /* ATAPI code. */ -static int -grub_atapi_iterate (int (*hook) (int bus, int luns)) -{ - struct grub_ata_device *dev; - - for (dev = grub_ata_devices; dev; dev = dev->next) - { - grub_err_t err; - - err = check_device (dev); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - - if (! dev->atapi) - continue; - - if (hook (dev->port * 2 + dev->device, 1)) - return 1; - } - - return 0; - -} - static grub_err_t -grub_atapi_read (struct grub_scsi *scsi, - grub_size_t cmdsize __attribute__((unused)), - char *cmd, grub_size_t size, char *buf) +grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf) { - struct grub_ata_device *dev = (struct grub_ata_device *) scsi->data; + struct grub_ata *dev = scsi->data; + struct grub_disk_ata_pass_through_parms parms; + grub_err_t err; grub_dprintf("ata", "grub_atapi_read (size=%llu)\n", (unsigned long long) size); + grub_memset (&parms, 0, sizeof (parms)); - if (grub_atapi_packet (dev, cmd, size)) - return grub_errno; + parms.taskfile.disk = 0; + parms.taskfile.features = 0; + parms.taskfile.atapi_ireason = 0; + parms.taskfile.atapi_cnthigh = size >> 8; + parms.taskfile.atapi_cntlow = size & 0xff; + parms.taskfile.cmd = GRUB_ATA_CMD_PACKET; + parms.cmd = cmd; + parms.cmdsize = cmdsize; - grub_size_t nread = 0; - while (nread < size) - { - /* Wait for !BSY, DRQ, I/O, !C/D. */ - if (grub_atapi_wait_drq (dev, GRUB_ATAPI_IREASON_DATA_IN, GRUB_ATA_TOUT_DATA)) - return grub_errno; - - /* Get byte count for this DRQ assertion. */ - unsigned cnt = grub_ata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 - | grub_ata_regget (dev, GRUB_ATAPI_REG_CNTLOW); - grub_dprintf("ata", "DRQ count=%u\n", cnt); - - /* Count of last transfer may be uneven. */ - if (! (0 < cnt && cnt <= size - nread && (! (cnt & 1) || cnt == size - nread))) - return grub_error (GRUB_ERR_READ_ERROR, "invalid ATAPI transfer count"); - - /* Read the data. */ - grub_ata_pio_read (dev, buf + nread, cnt); - - if (cnt & 1) - buf[nread + cnt - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); - - nread += cnt; - } + parms.size = size; + parms.buffer = buf; + + err = dev->dev->readwrite (dev, &parms); + if (err) + return err; + if (parms.size != size) + return grub_error (GRUB_ERR_READ_ERROR, "incomplete ATAPI read"); return GRUB_ERR_NONE; } @@ -846,64 +489,98 @@ grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)), } static grub_err_t -grub_atapi_open (int devnum, struct grub_scsi *scsi) +grub_atapi_open (int id, int bus, struct grub_scsi *scsi) { - struct grub_ata_device *dev; - struct grub_ata_device *devfnd = 0; - grub_err_t err; + struct grub_ata *ata; - for (dev = grub_ata_devices; dev; dev = dev->next) - { - if (dev->port * 2 + dev->device == devnum) - { - devfnd = dev; - break; - } - } - - grub_dprintf ("ata", "opening ATAPI dev `ata%d'\n", devnum); - - if (! devfnd) + ata = grub_ata_real_open (id, bus); + if (!ata) + return grub_errno; + + if (! ata->atapi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); - err = check_device (devfnd); - if (err) - return err; - - if (! devfnd->atapi) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); - - scsi->data = devfnd; + scsi->data = ata; return GRUB_ERR_NONE; } +static int +grub_atapi_iterate (int (*hook_in) (int id, int bus, int luns)) +{ + auto int hook (int id, int bus); + int hook (int id, int bus) + { + struct grub_ata *ata; + int ret; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (!ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + ret = hook_in (id, bus, 1); + grub_ata_real_close (ata); + return ret; + } + + grub_ata_dev_t p; + + for (p = grub_ata_dev_list; p; p = p->next) + if (p->iterate && p->iterate (hook)) + return 1; + return 0; +} + +static void +grub_atapi_close (grub_scsi_t disk) +{ + struct grub_ata *ata = disk->data; + grub_ata_real_close (ata); +} + + +void +grub_ata_dev_register (grub_ata_dev_t dev) +{ + dev->next = grub_ata_dev_list; + grub_ata_dev_list = dev; +} + +void +grub_ata_dev_unregister (grub_ata_dev_t dev) +{ + grub_ata_dev_t *p, q; + + for (p = &grub_ata_dev_list, q = *p; q; p = &(q->next), q = q->next) + if (q == dev) + { + *p = q->next; + break; + } +} static struct grub_scsi_dev grub_atapi_dev = { - .name = "ata", - .id = GRUB_SCSI_SUBSYSTEM_ATAPI, .iterate = grub_atapi_iterate, .open = grub_atapi_open, + .close = grub_atapi_close, .read = grub_atapi_read, - .write = grub_atapi_write + .write = grub_atapi_write, + .next = 0 }; GRUB_MOD_INIT(ata) { - /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) - { - grub_disk_firmware_fini (); - grub_disk_firmware_fini = NULL; - } - - /* ATA initialization. */ - grub_ata_initialize (); - grub_disk_dev_register (&grub_atadisk_dev); /* ATAPI devices are handled by scsi.mod. */ diff --git a/disk/ata_pthru.c b/disk/ata_pthru.c index f52725a49..b6edf78d6 100644 --- a/disk/ata_pthru.c +++ b/disk/ata_pthru.c @@ -18,90 +18,496 @@ */ #include +#include #include #include #include +#include +#include +#include +/* At the moment, only two IDE ports are supported. */ +static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1, + GRUB_ATA_CH1_PORT1 }; +static const grub_port_t grub_pata_ioaddress2[] = { GRUB_ATA_CH0_PORT2, + GRUB_ATA_CH1_PORT2 }; -/* ATA pass through support, used by hdparm.mod. */ -static grub_err_t -grub_ata_pass_through (grub_disk_t disk, - struct grub_disk_ata_pass_through_parms *parms) +struct grub_pata_device { - if (disk->dev->id != GRUB_DISK_DEVICE_ATA_ID) - return grub_error (GRUB_ERR_BAD_DEVICE, - "device not accessed via ata.mod"); + /* IDE port to use. */ + int port; - struct grub_ata_device *dev = (struct grub_ata_device *) disk->data; + /* IO addresses on which the registers for this device can be + found. */ + grub_port_t ioaddress; + grub_port_t ioaddress2; - if (! (parms->size == 0 || parms->size == GRUB_DISK_SECTOR_SIZE)) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "ATA multi-sector read and DATA OUT not implemented"); + /* Two devices can be connected to a single cable. Use this field + to select device 0 (commonly known as "master") or device 1 + (commonly known as "slave"). */ + int device; - grub_dprintf ("ata", "ata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n", - parms->taskfile[GRUB_ATA_REG_CMD], - parms->taskfile[GRUB_ATA_REG_FEATURES], - parms->taskfile[GRUB_ATA_REG_SECTORS]); - grub_dprintf ("ata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n", - parms->taskfile[GRUB_ATA_REG_LBAHIGH], - parms->taskfile[GRUB_ATA_REG_LBAMID], - parms->taskfile[GRUB_ATA_REG_LBALOW], parms->size); + struct grub_pata_device *next; +}; - /* Set registers. */ - grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4 - | (parms->taskfile[GRUB_ATA_REG_DISK] & 0xf)); - if (grub_ata_check_ready (dev)) - return grub_errno; +static struct grub_pata_device *grub_pata_devices; - int i; - for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++) - grub_ata_regset (dev, i, parms->taskfile[i]); +static inline void +grub_pata_regset (struct grub_pata_device *dev, int reg, int val) +{ + grub_outb (val, dev->ioaddress + reg); +} - /* Start command. */ - grub_ata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile[GRUB_ATA_REG_CMD]); +static inline grub_uint8_t +grub_pata_regget (struct grub_pata_device *dev, int reg) +{ + return grub_inb (dev->ioaddress + reg); +} - /* Wait for !BSY. */ - if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) - return grub_errno; +static inline void +grub_pata_regset2 (struct grub_pata_device *dev, int reg, int val) +{ + grub_outb (val, dev->ioaddress2 + reg); +} - /* Check status. */ - grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS); - grub_dprintf ("ata", "status=0x%x\n", sts); +static inline grub_uint8_t +grub_pata_regget2 (struct grub_pata_device *dev, int reg) +{ + return grub_inb (dev->ioaddress2 + reg); +} - /* Transfer data. */ - if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_DRQ) +/* Wait for !BSY. */ +static grub_err_t +grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds) +{ + /* ATA requires 400ns (after a write to CMD register) or + 1 PIO cycle (after a DRQ block transfer) before + first check of BSY. */ + grub_millisleep (1); + + int i = 1; + grub_uint8_t sts; + while ((sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS)) + & GRUB_ATA_STATUS_BUSY) { - if (parms->size != GRUB_DISK_SECTOR_SIZE) - return grub_error (GRUB_ERR_READ_ERROR, "DRQ unexpected"); - grub_ata_pio_read (dev, parms->buffer, GRUB_DISK_SECTOR_SIZE); + if (i >= milliseconds) + { + grub_dprintf ("pata", "timeout: %dms, status=0x%x\n", + milliseconds, sts); + return grub_error (GRUB_ERR_TIMEOUT, "PATA timeout"); + } + + grub_millisleep (1); + i++; } - /* Return registers. */ - for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++) - parms->taskfile[i] = grub_ata_regget (dev, i); - - grub_dprintf ("ata", "status=0x%x, error=0x%x, sectors=0x%x\n", - parms->taskfile[GRUB_ATA_REG_STATUS], - parms->taskfile[GRUB_ATA_REG_ERROR], - parms->taskfile[GRUB_ATA_REG_SECTORS]); - - if (parms->taskfile[GRUB_ATA_REG_STATUS] - & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) - return grub_error (GRUB_ERR_READ_ERROR, "ATA passthrough failed"); - return GRUB_ERR_NONE; } +static inline grub_err_t +grub_pata_check_ready (struct grub_pata_device *dev) +{ + if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY) + return grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_STD); + + return GRUB_ERR_NONE; +} + +static inline void +grub_pata_wait (void) +{ + grub_millisleep (50); +} + +static void +grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) +{ + grub_uint16_t *buf16 = (grub_uint16_t *) buf; + unsigned int i; + + /* Read in the data, word by word. */ + for (i = 0; i < size / 2; i++) + buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); + if (size & 1) + buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + + GRUB_ATA_REG_DATA)); +} + +static void +grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size) +{ + grub_uint16_t *buf16 = (grub_uint16_t *) buf; + unsigned int i; + + /* Write the data, word by word. */ + for (i = 0; i < size / 2; i++) + grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); +} + +/* ATA pass through support, used by hdparm.mod. */ +static grub_err_t +grub_pata_readwrite (struct grub_ata *disk, + struct grub_disk_ata_pass_through_parms *parms) +{ + struct grub_pata_device *dev = (struct grub_pata_device *) disk->data; + grub_size_t nread = 0; + + if (! (parms->cmdsize == 0 || parms->cmdsize == 12)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "ATAPI non-12 byte commands not supported"); + + grub_dprintf ("pata", "pata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n", + parms->taskfile.cmd, + parms->taskfile.features, + parms->taskfile.sectors); + grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n", + parms->taskfile.lba_high, + parms->taskfile.lba_mid, + parms->taskfile.lba_low, parms->size); + + /* Set registers. */ + grub_pata_regset (dev, GRUB_ATA_REG_DISK, (parms->cmdsize ? 0 : 0xE0) + | dev->device << 4 + | (parms->taskfile.disk & 0xf)); + if (grub_pata_check_ready (dev)) + return grub_errno; + + int i; + for (i = GRUB_ATA_REG_SECTORS; i <= GRUB_ATA_REG_LBAHIGH; i++) + grub_pata_regset (dev, i, + parms->taskfile.raw[7 + (i - GRUB_ATA_REG_SECTORS)]); + for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++) + grub_pata_regset (dev, i, parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES]); + + /* Start command. */ + grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd); + + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + /* Check status. */ + grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS); + grub_dprintf ("pata", "status=0x%x\n", sts); + + if (parms->cmdsize) + { + grub_uint8_t irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON); + /* OK if DRQ is asserted and interrupt reason is as expected. */ + if (!((sts & GRUB_ATA_STATUS_DRQ) + && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_CMD_OUT)) + return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error"); + /* Write the packet. */ + grub_pata_pio_write (dev, parms->cmd, parms->cmdsize); + } + + /* Transfer data. */ + while (nread < parms->size + && ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) + == GRUB_ATA_STATUS_DRQ) + && (!parms->cmdsize + || ((grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON) + & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_DATA_IN))) + { + unsigned cnt; + if (parms->cmdsize) + { + cnt = grub_pata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 + | grub_pata_regget (dev, GRUB_ATAPI_REG_CNTLOW); + grub_dprintf("pata", "DRQ count=%u\n", cnt); + + /* Count of last transfer may be uneven. */ + if (! (0 < cnt && cnt <= parms->size - nread + && (! (cnt & 1) || cnt == parms->size - nread))) + return grub_error (GRUB_ERR_READ_ERROR, + "invalid ATAPI transfer count"); + } + else + cnt = GRUB_DISK_SECTOR_SIZE; + if (cnt > parms->size - nread) + cnt = parms->size - nread; + + if (parms->write) + grub_pata_pio_write (dev, (char *) parms->buffer + nread, cnt); + else + grub_pata_pio_read (dev, (char *) parms->buffer + nread, cnt); + + nread += cnt; + } + if (parms->write) + { + /* Check for write error. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) + & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) + return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error"); + } + parms->size = nread; + + /* Return registers. */ + for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++) + parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES] = grub_pata_regget (dev, i); + + grub_dprintf ("pata", "status=0x%x, error=0x%x, sectors=0x%x\n", + parms->taskfile.status, + parms->taskfile.error, + parms->taskfile.sectors); + + if (parms->taskfile.status + & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) + return grub_error (GRUB_ERR_READ_ERROR, "PATA passthrough failed"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +check_device (struct grub_pata_device *dev) +{ + grub_pata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); + grub_pata_wait (); + + /* Try to detect if the port is in use by writing to it, + waiting for a while and reading it again. If the value + was preserved, there is a device connected. */ + grub_pata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A); + grub_pata_wait (); + grub_uint8_t sec = grub_pata_regget (dev, GRUB_ATA_REG_SECTORS); + grub_dprintf ("ata", "sectors=0x%x\n", sec); + if (sec != 0x5A) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected"); + + /* The above test may detect a second (slave) device + connected to a SATA controller which supports only one + (master) device. It is not safe to use the status register + READY bit to check for controller channel existence. Some + ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */ + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_pata_device_initialize (int port, int device, int addr, int addr2) +{ + struct grub_pata_device *dev; + struct grub_pata_device **devp; + grub_err_t err; + + grub_dprintf ("pata", "detecting device %d,%d (0x%x, 0x%x)\n", + port, device, addr, addr2); + + dev = grub_malloc (sizeof(*dev)); + if (! dev) + return grub_errno; + + /* Setup the device information. */ + dev->port = port; + dev->device = device; + dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; + dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; + dev->next = NULL; + + /* Register the device. */ + for (devp = &grub_pata_devices; *devp; devp = &(*devp)->next); + *devp = dev; + + err = check_device (dev); + if (err) + grub_print_error (); + + return 0; +} + +static int NESTED_FUNC_ATTR +grub_pata_pciinit (grub_pci_device_t dev, + grub_pci_id_t pciid) +{ + static int compat_use[2] = { 0 }; + grub_pci_address_t addr; + grub_uint32_t class; + grub_uint32_t bar1; + grub_uint32_t bar2; + int rega; + int regb; + int i; + static int controller = 0; + int cs5536 = 0; + int nports = 2; + + /* Read class. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + /* AMD CS5536 Southbridge. */ + if (pciid == GRUB_CS5536_PCIID) + { + cs5536 = 1; + nports = 1; + } + + /* Check if this class ID matches that of a PCI IDE Controller. */ + if (!cs5536 && (class >> 16 != 0x0101)) + return 0; + + for (i = 0; i < nports; i++) + { + /* Set to 0 when the channel operated in compatibility mode. */ + int compat; + + /* We don't support non-compatibility mode for CS5536. */ + if (cs5536) + compat = 0; + else + compat = (class >> (8 + 2 * i)) & 1; + + rega = 0; + regb = 0; + + /* If the channel is in compatibility mode, just assign the + default registers. */ + if (compat == 0 && !compat_use[i]) + { + rega = grub_pata_ioaddress[i]; + regb = grub_pata_ioaddress2[i]; + compat_use[i] = 1; + } + else if (compat) + { + /* Read the BARs, which either contain a mmapped IO address + or the IO port address. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES + + sizeof (grub_uint64_t) * i); + bar1 = grub_pci_read (addr); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES + + sizeof (grub_uint64_t) * i + + sizeof (grub_uint32_t)); + bar2 = grub_pci_read (addr); + + /* Check if the BARs describe an IO region. */ + if ((bar1 & 1) && (bar2 & 1)) + { + rega = bar1 & ~3; + regb = bar2 & ~3; + } + } + + grub_dprintf ("pata", + "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n", + grub_pci_get_bus (dev), grub_pci_get_device (dev), + grub_pci_get_function (dev), compat, rega, regb); + + if (rega && regb) + { + grub_errno = GRUB_ERR_NONE; + grub_pata_device_initialize (controller * 2 + i, 0, rega, regb); + + /* Most errors raised by grub_ata_device_initialize() are harmless. + They just indicate this particular drive is not responding, most + likely because it doesn't exist. We might want to ignore specific + error types here, instead of printing them. */ + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + grub_pata_device_initialize (controller * 2 + i, 1, rega, regb); + + /* Likewise. */ + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + } + } + + controller++; + + return 0; +} + +static grub_err_t +grub_pata_initialize (void) +{ + grub_pci_iterate (grub_pata_pciinit); + return 0; +} + +static grub_err_t +grub_pata_open (int id, int devnum, struct grub_ata *ata) +{ + struct grub_pata_device *dev; + struct grub_pata_device *devfnd = 0; + grub_err_t err; + + if (id != GRUB_SCSI_SUBSYSTEM_PATA) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a PATA device"); + + for (dev = grub_pata_devices; dev; dev = dev->next) + { + if (dev->port * 2 + dev->device == devnum) + { + devfnd = dev; + break; + } + } + + grub_dprintf ("pata", "opening PATA dev `ata%d'\n", devnum); + + if (! devfnd) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such PATA device"); + + err = check_device (devfnd); + if (err) + return err; + + ata->data = devfnd; + + return GRUB_ERR_NONE; +} + +static int +grub_pata_iterate (int (*hook) (int id, int bus)) +{ + struct grub_pata_device *dev; + + for (dev = grub_pata_devices; dev; dev = dev->next) + if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device)) + return 1; + + return 0; +} + + +static struct grub_ata_dev grub_pata_dev = + { + .iterate = grub_pata_iterate, + .open = grub_pata_open, + .readwrite = grub_pata_readwrite, + }; + + GRUB_MOD_INIT(ata_pthru) { - /* Register ATA pass through function. */ - grub_disk_ata_pass_through = grub_ata_pass_through; + /* To prevent two drivers operating on the same disks. */ + grub_disk_firmware_is_tainted = 1; + if (grub_disk_firmware_fini) + { + grub_disk_firmware_fini (); + grub_disk_firmware_fini = NULL; + } + + /* ATA initialization. */ + grub_pata_initialize (); + + grub_ata_dev_register (&grub_pata_dev); } GRUB_MOD_FINI(ata_pthru) { - if (grub_disk_ata_pass_through == grub_ata_pass_through) - grub_disk_ata_pass_through = NULL; + grub_ata_dev_unregister (&grub_pata_dev); } diff --git a/disk/scsi.c b/disk/scsi.c index 60192bef5..f0594e7c7 100644 --- a/disk/scsi.c +++ b/disk/scsi.c @@ -30,6 +30,12 @@ static grub_scsi_dev_t grub_scsi_dev_list; +char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5] = { + [GRUB_SCSI_SUBSYSTEM_USBMS] = "usb", + [GRUB_SCSI_SUBSYSTEM_PATA] = "ata", + [GRUB_SCSI_SUBSYSTEM_AHCI] = "ahci" +}; + void grub_scsi_dev_register (grub_scsi_dev_t dev) { @@ -318,9 +324,9 @@ grub_scsi_iterate (int (*hook) (const char *name)) { grub_scsi_dev_t p; - auto int scsi_iterate (int bus, int luns); + auto int scsi_iterate (int id, int bus, int luns); - int scsi_iterate (int bus, int luns) + int scsi_iterate (int id, int bus, int luns) { int i; @@ -329,7 +335,7 @@ grub_scsi_iterate (int (*hook) (const char *name)) { char *sname; int ret; - sname = grub_xasprintf ("%s%d", p->name, bus); + sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus); if (!sname) return 1; ret = hook (sname); @@ -343,7 +349,7 @@ grub_scsi_iterate (int (*hook) (const char *name)) { char *sname; int ret; - sname = grub_xasprintf ("%s%d%c", p->name, bus, 'a' + i); + sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i); if (!sname) return 1; ret = hook (sname); @@ -370,6 +376,7 @@ grub_scsi_open (const char *name, grub_disk_t disk) int lun, bus; grub_uint64_t maxtime; const char *nameend; + unsigned id; nameend = name + grub_strlen (name) - 1; /* Try to detect a LUN ('a'-'z'), otherwise just use the first @@ -394,15 +401,25 @@ grub_scsi_open (const char *name, grub_disk_t disk) if (! scsi) return grub_errno; + for (id = 0; id < ARRAY_SIZE (grub_scsi_names); id++) + if (grub_strncmp (grub_scsi_names[id], name, nameend - name) == 0) + break; + + if (id == ARRAY_SIZE (grub_scsi_names)) + { + grub_free (scsi); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk"); + } + for (p = grub_scsi_dev_list; p; p = p->next) { - if (grub_strncmp (p->name, name, nameend - name) != 0) - continue; + if (p->open (id, bus, scsi)) + { + grub_errno = GRUB_ERR_NONE; + continue; + } - if (p->open (bus, scsi)) - continue; - - disk->id = grub_make_scsi_id (p->id, bus, lun); + disk->id = grub_make_scsi_id (id, bus, lun); disk->data = scsi; scsi->dev = p; scsi->lun = lun; @@ -484,7 +501,6 @@ grub_scsi_open (const char *name, grub_disk_t disk) } grub_free (scsi); - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk"); } diff --git a/disk/usbms.c b/disk/usbms.c index 225761e0f..0ff2e6235 100644 --- a/disk/usbms.c +++ b/disk/usbms.c @@ -205,7 +205,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) static int -grub_usbms_iterate (int (*hook) (int bus, int luns)) +grub_usbms_iterate (int (*hook) (int id, int bus, int luns)) { unsigned i; @@ -214,7 +214,7 @@ grub_usbms_iterate (int (*hook) (int bus, int luns)) for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) if (grub_usbms_devices[i]) { - if (hook (i, grub_usbms_devices[i]->luns)) + if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns)) return 1; } @@ -384,8 +384,12 @@ grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } static grub_err_t -grub_usbms_open (int devnum, struct grub_scsi *scsi) +grub_usbms_open (int id, int devnum, struct grub_scsi *scsi) { + if (id != GRUB_SCSI_SUBSYSTEM_USBMS) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "not USB Mass Storage device"); + grub_usb_poll_devices (); if (!grub_usbms_devices[devnum]) @@ -400,8 +404,6 @@ grub_usbms_open (int devnum, struct grub_scsi *scsi) static struct grub_scsi_dev grub_usbms_dev = { - .name = "usb", - .id = GRUB_SCSI_SUBSYSTEM_USBMS, .iterate = grub_usbms_iterate, .open = grub_usbms_open, .read = grub_usbms_read, diff --git a/include/grub/ata.h b/include/grub/ata.h index 9e3aaf0e6..b1c6ead26 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -97,21 +97,64 @@ enum grub_ata_timeout_milliseconds GRUB_ATA_TOUT_DATA = 10000 /* 10s DATA I/O timeout. */ }; -struct grub_ata_device +typedef union { - /* IDE port to use. */ - int port; + grub_uint8_t raw[11]; + struct + { + union + { + grub_uint8_t features; + grub_uint8_t error; + }; + union + { + grub_uint8_t sectors; + grub_uint8_t atapi_ireason; + }; + union + { + grub_uint8_t lba_low; + grub_uint8_t sectnum; + }; + union + { + grub_uint8_t lba_mid; + grub_uint8_t cyllsb; + grub_uint8_t atapi_cntlow; + }; + union + { + grub_uint8_t lba_high; + grub_uint8_t cylmsb; + grub_uint8_t atapi_cnthigh; + }; + grub_uint8_t disk; + union + { + grub_uint8_t cmd; + grub_uint8_t status; + }; + grub_uint8_t sectors48; + grub_uint8_t lba48_low; + grub_uint8_t lba48_mid; + grub_uint8_t lba48_high; + }; +} grub_ata_regs_t; - /* IO addresses on which the registers for this device can be - found. */ - grub_port_t ioaddress; - grub_port_t ioaddress2; - - /* Two devices can be connected to a single cable. Use this field - to select device 0 (commonly known as "master") or device 1 - (commonly known as "slave"). */ - int device; +/* ATA pass through parameters and function. */ +struct grub_disk_ata_pass_through_parms +{ + grub_ata_regs_t taskfile; + void * buffer; + grub_size_t size; + int write; + void *cmd; + int cmdsize; +}; +struct grub_ata +{ /* Addressing methods available for accessing this device. If CHS is only available, use that. Otherwise use LBA, except for the high sectors. In that case use LBA48. */ @@ -128,47 +171,36 @@ struct grub_ata_device /* Set to 0 for ATA, set to 1 for ATAPI. */ int atapi; - struct grub_ata_device *next; + void *data; + + struct grub_ata_dev *dev; }; -grub_err_t EXPORT_FUNC(grub_ata_wait_not_busy) (struct grub_ata_device *dev, - int milliseconds); -grub_err_t EXPORT_FUNC(grub_ata_wait_drq) (struct grub_ata_device *dev, - int rw, int milliseconds); -void EXPORT_FUNC(grub_ata_pio_read) (struct grub_ata_device *dev, - char *buf, grub_size_t size); +typedef struct grub_ata *grub_ata_t; -static inline void -grub_ata_regset (struct grub_ata_device *dev, int reg, int val) +struct grub_ata_dev { - grub_outb (val, dev->ioaddress + reg); -} + /* Call HOOK with each device name, until HOOK returns non-zero. */ + int (*iterate) (int (*hook) (int id, int bus)); -static inline grub_uint8_t -grub_ata_regget (struct grub_ata_device *dev, int reg) -{ - return grub_inb (dev->ioaddress + reg); -} + /* Open the device named NAME, and set up SCSI. */ + grub_err_t (*open) (int id, int bus, struct grub_ata *scsi); -static inline void -grub_ata_regset2 (struct grub_ata_device *dev, int reg, int val) -{ - grub_outb (val, dev->ioaddress2 + reg); -} + /* Close the scsi device SCSI. */ + void (*close) (struct grub_ata *ata); -static inline grub_uint8_t -grub_ata_regget2 (struct grub_ata_device *dev, int reg) -{ - return grub_inb (dev->ioaddress2 + reg); -} + /* Read SIZE bytes from the device SCSI into BUF after sending the + command CMD of size CMDSIZE. */ + grub_err_t (*readwrite) (struct grub_ata *ata, + struct grub_disk_ata_pass_through_parms *parms); -static inline grub_err_t -grub_ata_check_ready (struct grub_ata_device *dev) -{ - if (grub_ata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY) - return grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_STD); + /* The next scsi device. */ + struct grub_ata_dev *next; +}; - return GRUB_ERR_NONE; -} +typedef struct grub_ata_dev *grub_ata_dev_t; + +void grub_ata_dev_register (grub_ata_dev_t dev); +void grub_ata_dev_unregister (grub_ata_dev_t dev); #endif /* ! GRUB_ATA_HEADER */ diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..ac3fb6497 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -165,16 +165,5 @@ grub_uint64_t EXPORT_FUNC(grub_disk_get_size) (grub_disk_t disk); extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void); extern int EXPORT_VAR(grub_disk_firmware_is_tainted); - -/* ATA pass through parameters and function. */ -struct grub_disk_ata_pass_through_parms -{ - grub_uint8_t taskfile[8]; - void * buffer; - int size; -}; - -extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t, - struct grub_disk_ata_pass_through_parms *); - + #endif /* ! GRUB_DISK_HEADER */ diff --git a/include/grub/scsi.h b/include/grub/scsi.h index 289cd8e4a..081189fb0 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -29,10 +29,13 @@ struct grub_scsi; enum { GRUB_SCSI_SUBSYSTEM_USBMS, - GRUB_SCSI_SUBSYSTEM_ATAPI, - GRUB_SCSI_SUBSYSTEM_AHCI + GRUB_SCSI_SUBSYSTEM_PATA, + GRUB_SCSI_SUBSYSTEM_AHCI, + GRUB_SCSI_NUM_SUBSYSTEMS }; +extern char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5]; + #define GRUB_SCSI_ID_SUBSYSTEM_SHIFT 24 #define GRUB_SCSI_ID_BUS_SHIFT 8 #define GRUB_SCSI_ID_LUN_SHIFT 0 @@ -46,16 +49,11 @@ grub_make_scsi_id (int subsystem, int bus, int lun) struct grub_scsi_dev { - /* The device name. */ - const char *name; - - grub_uint8_t id; - /* Call HOOK with each device name, until HOOK returns non-zero. */ - int (*iterate) (int (*hook) (int bus, int luns)); + int (*iterate) (int (*hook) (int id, int bus, int luns)); /* Open the device named NAME, and set up SCSI. */ - grub_err_t (*open) (int bus, struct grub_scsi *scsi); + grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi); /* Close the scsi device SCSI. */ void (*close) (struct grub_scsi *scsi); diff --git a/kern/disk.c b/kern/disk.c index ccd5f200f..84c48e65c 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -46,10 +46,6 @@ static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; void (*grub_disk_firmware_fini) (void); int grub_disk_firmware_is_tainted; -grub_err_t (* grub_disk_ata_pass_through) (grub_disk_t, - struct grub_disk_ata_pass_through_parms *); - - #if 0 static unsigned long grub_disk_cache_hits; static unsigned long grub_disk_cache_misses; From faec81d97dd6b3cb58b631f4fcf426786f1db54f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 16:54:33 +0100 Subject: [PATCH 064/673] Add missing buffer specifications --- grub-core/disk/ata.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 04b81cd27..9f62546e1 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -72,6 +72,8 @@ grub_atapi_identify (struct grub_ata *dev) grub_memset (&parms, 0, sizeof (parms)); parms.taskfile.disk = 0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE; + parms.size = GRUB_DISK_SECTOR_SIZE; + parms.buffer = info; err = dev->dev->readwrite (dev, &parms); if (err) @@ -105,6 +107,7 @@ grub_ata_identify (struct grub_ata *dev) info16 = (grub_uint16_t *) info; grub_memset (&parms, 0, sizeof (parms)); parms.buffer = info; + parms.size = GRUB_DISK_SECTOR_SIZE; parms.taskfile.disk = 0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; From 22a7cc9a6f5e61de79b34f09c97a71a12dd370a2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 17:09:56 +0100 Subject: [PATCH 065/673] fix 3rd argument to scsi_iterate --- grub-core/disk/ata.c | 2 +- grub-core/disk/scsi.c | 4 ++-- grub-core/disk/usbms.c | 2 +- include/grub/scsi.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 9f62546e1..6f7f44227 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -508,7 +508,7 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi) } static int -grub_atapi_iterate (int (*hook_in) (int id, int bus, int luns)) +grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns)) { auto int hook (int id, int bus); int hook (int id, int bus) diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index b989a98ad..015e5dce6 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -324,9 +324,9 @@ grub_scsi_iterate (int (*hook) (const char *name)) { grub_scsi_dev_t p; - auto int scsi_iterate (int id, int bus, int luns); + auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns); - int scsi_iterate (int id, int bus, int luns) + int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns) { int i; diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index 4e1af7be3..8041c6c95 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -205,7 +205,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) static int -grub_usbms_iterate (int (*hook) (int id, int bus, int luns)) +grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns)) { unsigned i; diff --git a/include/grub/scsi.h b/include/grub/scsi.h index 3deb18f1b..5b6ccc9f4 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -50,7 +50,7 @@ grub_make_scsi_id (int subsystem, int bus, int lun) struct grub_scsi_dev { /* Call HOOK with each device name, until HOOK returns non-zero. */ - int (*iterate) (int (*hook) (int id, int bus, int luns)); + int (*iterate) (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns)); /* Open the device named NAME, and set up SCSI. */ grub_err_t (*open) (int id, int bus, struct grub_scsi *scsi); From 8f5ac9e57050652378a9d54d9082ab331a775946 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 17:10:41 +0100 Subject: [PATCH 066/673] fix ATAPI support --- grub-core/disk/ata.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 6f7f44227..5015f8507 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -113,13 +113,12 @@ grub_ata_identify (struct grub_ata *dev) parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; err = dev->dev->readwrite (dev, &parms); - if (err) - return err; - if (parms.size != GRUB_DISK_SECTOR_SIZE) + if (err || parms.size != GRUB_DISK_SECTOR_SIZE) { grub_uint8_t sts = parms.taskfile.status; grub_free (info); + grub_errno = GRUB_ERR_NONE; if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR && (parms.taskfile.error & 0x04 /* ABRT */)) @@ -503,6 +502,7 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); scsi->data = ata; + scsi->luns = 1; return GRUB_ERR_NONE; } From ee2b985ef68f5522796057ef6d3055ad7d6dc5a1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 17:11:21 +0100 Subject: [PATCH 067/673] rearrange wait_not_busy --- grub-core/disk/pata.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index b6edf78d6..a24237a83 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -182,17 +182,18 @@ grub_pata_readwrite (struct grub_ata *disk, /* Start command. */ grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd); - /* Wait for !BSY. */ - if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) - return grub_errno; - /* Check status. */ grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS); grub_dprintf ("pata", "status=0x%x\n", sts); if (parms->cmdsize) { - grub_uint8_t irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON); + grub_uint8_t irs; + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + + irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON); /* OK if DRQ is asserted and interrupt reason is as expected. */ if (!((sts & GRUB_ATA_STATUS_DRQ) && (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_CMD_OUT)) @@ -210,6 +211,11 @@ grub_pata_readwrite (struct grub_ata *disk, & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_DATA_IN))) { unsigned cnt; + + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + if (parms->cmdsize) { cnt = grub_pata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8 @@ -246,6 +252,10 @@ grub_pata_readwrite (struct grub_ata *disk, } parms->size = nread; + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + /* Return registers. */ for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++) parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES] = grub_pata_regget (dev, i); From 908a8fc37a51aea0dd22d53494772456a210b900 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Dec 2010 19:48:55 +0100 Subject: [PATCH 068/673] Fix several AHCI problems --- grub-core/disk/ahci.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 946db82e1..1e28b3dc5 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -56,10 +56,12 @@ struct grub_ahci_hba_port grub_uint32_t intstatus; grub_uint32_t inten; grub_uint32_t command; - grub_uint32_t unused1[6]; + grub_uint32_t unused1[3]; + grub_uint32_t status; + grub_uint32_t unused2[2]; grub_uint32_t sata_active; grub_uint32_t command_issue; - grub_uint32_t unused2[17]; + grub_uint32_t unused3[17]; }; struct grub_ahci_hba @@ -195,6 +197,10 @@ grub_ahci_pciinit (grub_pci_device_t dev, if (!(hba->ports_implemented & (1 << i))) continue; + /* FIXME: support hotplugging. */ + if (!hba->ports[i].status) + continue; + command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head)); if (!command_list) @@ -333,8 +339,11 @@ grub_ahci_readwrite (grub_ata_t disk, parms->cmdsize); dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D; + dev->command_table[0].cfis[1] = 0x80; for (i = 0; i < sizeof (parms->taskfile.raw); i++) - dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; + dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; + + dev->command_table[0].cfis[7] |= (parms->cmdsize ? 0 : 0xE0); dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); dev->command_table[0].prdt[0].unused = 0; @@ -345,12 +354,12 @@ grub_ahci_readwrite (grub_ata_t disk, grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); grub_dprintf ("ahci", "AHCI command schedulded\n"); - dev->hba->ports[dev->port].inten = (1 << 5); - dev->hba->ports[dev->port].intstatus = (1 << 5); + dev->hba->ports[dev->port].inten = (1 << 2) | (1 << 5); + dev->hba->ports[dev->port].intstatus = (1 << 2) | (1 << 5); dev->hba->ports[dev->port].command_issue |= 1; dev->hba->ports[dev->port].command |= 1; - endtime = grub_get_time_ms () + 1000; + endtime = grub_get_time_ms () + 1000; while (!(dev->hba->ports[dev->port].intstatus & (1 << 5))) if (grub_get_time_ms () > endtime) { @@ -362,6 +371,7 @@ grub_ahci_readwrite (grub_ata_t disk, grub_dprintf ("ahci", "AHCI command completed succesfully\n"); dev->hba->ports[dev->port].command &= ~1; + dev->hba->ports[dev->port].command_issue &= ~1; if (!parms->write) grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size); @@ -379,10 +389,8 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device"); FOR_LIST_ELEMENTS(dev, grub_ahci_devices) - { - if (dev->num == devnum) - break; - } + if (dev->num == devnum) + break; if (! dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device"); From 51f7e1acb7355d15d83ff3f916cc80cc1827b96b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 02:53:20 +0100 Subject: [PATCH 069/673] DMA ATA commands support --- grub-core/disk/ahci.c | 1 + grub-core/disk/ata.c | 28 +++++++++++++++++++++++----- grub-core/disk/pata.c | 1 + include/grub/ata.h | 8 ++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 1e28b3dc5..4b5d195f2 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -398,6 +398,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num); ata->data = dev; + ata->dma = 0; return GRUB_ERR_NONE; } diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 5015f8507..b33abf90d 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -255,8 +255,16 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0) { batch = 65536; - cmd = GRUB_ATA_CMD_READ_SECTORS_EXT; - cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT; + if (ata->dma) + { + cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT; + } + else + { + cmd = GRUB_ATA_CMD_READ_SECTORS_EXT; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_EXT; + } } else { @@ -266,9 +274,17 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, batch = 256; else batch = 1; - cmd = GRUB_ATA_CMD_READ_SECTORS; - cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; - } + if (ata->dma) + { + cmd = GRUB_ATA_CMD_READ_SECTORS_DMA; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS_DMA; + } + else + { + cmd = GRUB_ATA_CMD_READ_SECTORS; + cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; + } + } grub_size_t nsectors = 0; while (nsectors < size) @@ -285,6 +301,8 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; parms.size = batch * GRUB_DISK_SECTOR_SIZE; + if (ata->dma) + parms.dma = 1; err = ata->dev->readwrite (ata, &parms); if (err) diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index a24237a83..186caf6a2 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -474,6 +474,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata) return err; ata->data = devfnd; + ata->dma = 0; return GRUB_ERR_NONE; } diff --git a/include/grub/ata.h b/include/grub/ata.h index b1c6ead26..bea74c180 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -82,6 +82,9 @@ enum grub_ata_commands GRUB_ATA_CMD_PACKET = 0xa0, GRUB_ATA_CMD_READ_SECTORS = 0x20, GRUB_ATA_CMD_READ_SECTORS_EXT = 0x24, + GRUB_ATA_CMD_READ_SECTORS_DMA = 0xc8, + GRUB_ATA_CMD_READ_SECTORS_DMA_EXT = 0x25, + GRUB_ATA_CMD_SECURITY_FREEZE_LOCK = 0xf5, GRUB_ATA_CMD_SET_FEATURES = 0xef, GRUB_ATA_CMD_SLEEP = 0xe6, @@ -89,6 +92,8 @@ enum grub_ata_commands GRUB_ATA_CMD_STANDBY_IMMEDIATE = 0xe0, GRUB_ATA_CMD_WRITE_SECTORS = 0x30, GRUB_ATA_CMD_WRITE_SECTORS_EXT = 0x34, + GRUB_ATA_CMD_WRITE_SECTORS_DMA_EXT = 0x35, + GRUB_ATA_CMD_WRITE_SECTORS_DMA = 0xca, }; enum grub_ata_timeout_milliseconds @@ -151,6 +156,7 @@ struct grub_disk_ata_pass_through_parms int write; void *cmd; int cmdsize; + int dma; }; struct grub_ata @@ -171,6 +177,8 @@ struct grub_ata /* Set to 0 for ATA, set to 1 for ATAPI. */ int atapi; + int dma; + void *data; struct grub_ata_dev *dev; From 060d0c7ac2fbf763cc07efcb498c04c03b4cf197 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:06:07 +0100 Subject: [PATCH 070/673] working AHCI (at last) --- grub-core/disk/ahci.c | 182 +++++++++++++++++++++++++++++++++++------- 1 file changed, 152 insertions(+), 30 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 4b5d195f2..4d5ee692c 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -44,8 +44,8 @@ struct grub_ahci_prdt_entry struct grub_ahci_cmd_table { grub_uint8_t cfis[0x40]; - grub_uint8_t command[16]; - grub_uint32_t reserved[0xc]; + grub_uint8_t command[0x10]; + grub_uint8_t reserved[0x30]; struct grub_ahci_prdt_entry prdt[1]; }; @@ -56,14 +56,27 @@ struct grub_ahci_hba_port grub_uint32_t intstatus; grub_uint32_t inten; grub_uint32_t command; - grub_uint32_t unused1[3]; + grub_uint32_t unused1; + grub_uint32_t task_file_data; + grub_uint32_t sig; grub_uint32_t status; - grub_uint32_t unused2[2]; + grub_uint32_t unused2; + grub_uint32_t sata_error; grub_uint32_t sata_active; grub_uint32_t command_issue; - grub_uint32_t unused3[17]; + grub_uint32_t unused3; + grub_uint32_t fbs; + grub_uint32_t unused4[15]; }; +enum grub_ahci_hba_port_command + { + GRUB_AHCI_HBA_PORT_CMD_ST = 0x01, + GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10, + GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000, + GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000, + }; + struct grub_ahci_hba { grub_uint32_t cap; @@ -76,6 +89,11 @@ struct grub_ahci_hba struct grub_ahci_hba_port ports[32]; }; +struct grub_ahci_received_fis +{ + char raw[4096]; +}; + enum { GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f @@ -83,6 +101,7 @@ enum enum { + GRUB_AHCI_HBA_GLOBAL_CONTROL_RESET = 0x00000001, GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002, GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000, }; @@ -106,8 +125,14 @@ struct grub_ahci_device volatile struct grub_ahci_cmd_head *command_list; struct grub_pci_dma_chunk *command_table_chunk; volatile struct grub_ahci_cmd_table *command_table; + struct grub_pci_dma_chunk *rfis; }; +static grub_err_t +grub_ahci_readwrite_real (struct grub_ahci_device *dev, + struct grub_disk_ata_pass_through_parms *parms); + + enum { GRUB_AHCI_CONFIG_READ = 0, @@ -160,10 +185,6 @@ grub_ahci_pciinit (grub_pci_device_t dev, hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, sizeof (hba)); - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - - nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; - if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) { grub_uint64_t endtime; @@ -186,6 +207,11 @@ grub_ahci_pciinit (grub_pci_device_t dev, } else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + + nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; + grub_dprintf ("ahci", "%d AHCI ports\n", nports); for (i = 0; i < nports; i++) @@ -197,8 +223,9 @@ grub_ahci_pciinit (grub_pci_device_t dev, if (!(hba->ports_implemented & (1 << i))) continue; + grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status); /* FIXME: support hotplugging. */ - if (!hba->ports[i].status) + if ((hba->ports[i].status & 0xf) != 0x3) continue; command_list = grub_memalign_dma32 (1024, @@ -224,6 +251,26 @@ grub_ahci_pciinit (grub_pci_device_t dev, grub_dprintf ("ahci", "found device ahci%d (port %d)\n", numdevs, i); + hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); + hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + + hba->ports[i].fbs = 2; + + adev->rfis = grub_memalign_dma32 (4096, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (adev->rfis), 0, + sizeof (struct grub_ahci_received_fis)); + hba->ports[i].fis_base = grub_dma_get_phys (adev->rfis); + hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; + while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); + hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + + hba->ports[i].command = (hba->ports[i].command & 0x0fffffff) + | (1 << 28) | 2 | 4; + adev->hba = hba; adev->port = i; adev->num = numdevs++; @@ -299,13 +346,26 @@ static const int register_map[11] = { 3 /* Features */, 10 /* LBA48 high */ }; static grub_err_t -grub_ahci_readwrite (grub_ata_t disk, - struct grub_disk_ata_pass_through_parms *parms) +grub_ahci_readwrite_real (struct grub_ahci_device *dev, + struct grub_disk_ata_pass_through_parms *parms) { - struct grub_ahci_device *dev = (struct grub_ahci_device *) disk->data; struct grub_pci_dma_chunk *bufc; grub_uint64_t endtime; unsigned i; + grub_err_t err = GRUB_ERR_NONE; + + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + + if ((dev->hba->ports[dev->port].task_file_data & 0x80)) + { + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + } + + dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n", (unsigned long long) parms->size, @@ -319,14 +379,19 @@ grub_ahci_readwrite (grub_ata_t disk, bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); + dev->hba->ports[dev->port].command |= 8; + + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); /* FIXME: support port multipliers. */ dev->command_list[0].config - = (4 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) - | GRUB_AHCI_CONFIG_CLEAR_R_OK + = (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) + // | GRUB_AHCI_CONFIG_CLEAR_R_OK | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT) | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0) - | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ); + | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ) + | (parms->taskfile.cmd == 8 ? (1 << 8) : 0); dev->command_list[0].transfered = 0; dev->command_list[0].command_table_base = grub_dma_get_phys (dev->command_table_chunk); @@ -344,40 +409,97 @@ grub_ahci_readwrite (grub_ata_t disk, dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; dev->command_table[0].cfis[7] |= (parms->cmdsize ? 0 : 0xE0); + grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n", + dev->command_table[0].cfis[0], dev->command_table[0].cfis[1], + dev->command_table[0].cfis[2], dev->command_table[0].cfis[3], + dev->command_table[0].cfis[4], dev->command_table[0].cfis[5], + dev->command_table[0].cfis[6], dev->command_table[0].cfis[7]); + grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n", + dev->command_table[0].cfis[8], dev->command_table[0].cfis[9], + dev->command_table[0].cfis[10], dev->command_table[0].cfis[11], + dev->command_table[0].cfis[12], dev->command_table[0].cfis[13], + dev->command_table[0].cfis[14], dev->command_table[0].cfis[15]); dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); dev->command_table[0].prdt[0].unused = 0; dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) | GRUB_AHCI_INTERRUPT_ON_COMPLETE; + grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%x)\n", + dev->command_table[0].prdt[0].data_base, + dev->command_table[0].prdt[0].unused, + dev->command_table[0].prdt[0].size, + (char *) &dev->command_table[0].prdt[0] + - (char *) &dev->command_table[0]); + if (parms->write) grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); grub_dprintf ("ahci", "AHCI command schedulded\n"); - dev->hba->ports[dev->port].inten = (1 << 2) | (1 << 5); - dev->hba->ports[dev->port].intstatus = (1 << 2) | (1 << 5); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5); + dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); dev->hba->ports[dev->port].command_issue |= 1; - dev->hba->ports[dev->port].command |= 1; + grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); endtime = grub_get_time_ms () + 1000; - while (!(dev->hba->ports[dev->port].intstatus & (1 << 5))) + while ((dev->hba->ports[dev->port].command_issue & 1)) if (grub_get_time_ms () > endtime) { - grub_dprintf ("ahci", "AHCI timeout\n"); - dev->hba->ports[dev->port].command &= ~1; - /* FIXME: free resources. */ - return grub_error (GRUB_ERR_IO, "AHCI transfer timeouted"); + grub_dprintf ("ahci", "AHCI status <%x %x %x>\n", + dev->hba->ports[dev->port].command_issue, + dev->hba->ports[dev->port].intstatus, + dev->hba->ports[dev->port].task_file_data); + err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted"); + break; } - grub_dprintf ("ahci", "AHCI command completed succesfully\n"); - dev->hba->ports[dev->port].command &= ~1; - dev->hba->ports[dev->port].command_issue &= ~1; + grub_dprintf ("ahci", "AHCI command completed <%x %x %x %x %x, %x %x>\n", + dev->hba->ports[dev->port].command_issue, + dev->hba->ports[dev->port].intstatus, + dev->hba->ports[dev->port].task_file_data, + dev->command_list[0].transfered, + dev->hba->ports[dev->port].sata_error, + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]); + grub_dprintf ("ahci", + "last PIO FIS %08x %08x %08x %08x %08x %08x %08x %08x\n", + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x08], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x09], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0a], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0b], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0c], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0d], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0e], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0f]); + grub_dprintf ("ahci", + "last REG FIS %08x %08x %08x %08x %08x %08x %08x %08x\n", + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x10], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x11], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x12], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x13], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x14], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x15], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x16], + ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x17]); if (!parms->write) grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size); grub_dma_free (bufc); - return GRUB_ERR_NONE; + return err; +} + +static grub_err_t +grub_ahci_readwrite (grub_ata_t disk, + struct grub_disk_ata_pass_through_parms *parms) +{ + return grub_ahci_readwrite_real (disk->data, parms); } static grub_err_t @@ -415,8 +537,8 @@ static struct grub_ata_dev grub_ahci_dev = GRUB_MOD_INIT(ahci) { /* To prevent two drivers operating on the same disks. */ - // grub_disk_firmware_is_tainted = 1; - if (0 && grub_disk_firmware_fini) + grub_disk_firmware_is_tainted = 1; + if (grub_disk_firmware_fini) { grub_disk_firmware_fini (); grub_disk_firmware_fini = NULL; From 188ac234bd37cd6c0fbf649d1f09cb1a0f114f5e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:12:49 +0100 Subject: [PATCH 071/673] use DMA for AHCI commands --- grub-core/disk/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 4d5ee692c..d9b95df37 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -520,7 +520,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num); ata->data = dev; - ata->dma = 0; + ata->dma = 1; return GRUB_ERR_NONE; } From a934071d76d66b4b1a36ec73240249363392351f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:22:12 +0100 Subject: [PATCH 072/673] Remove unused pata ioaddress2 --- grub-core/disk/pata.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 186caf6a2..940a9a5f0 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -29,8 +29,6 @@ /* At the moment, only two IDE ports are supported. */ static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1, GRUB_ATA_CH1_PORT1 }; -static const grub_port_t grub_pata_ioaddress2[] = { GRUB_ATA_CH0_PORT2, - GRUB_ATA_CH1_PORT2 }; struct grub_pata_device { @@ -40,7 +38,6 @@ struct grub_pata_device /* IO addresses on which the registers for this device can be found. */ grub_port_t ioaddress; - grub_port_t ioaddress2; /* Two devices can be connected to a single cable. Use this field to select device 0 (commonly known as "master") or device 1 @@ -64,18 +61,6 @@ grub_pata_regget (struct grub_pata_device *dev, int reg) return grub_inb (dev->ioaddress + reg); } -static inline void -grub_pata_regset2 (struct grub_pata_device *dev, int reg, int val) -{ - grub_outb (val, dev->ioaddress2 + reg); -} - -static inline grub_uint8_t -grub_pata_regget2 (struct grub_pata_device *dev, int reg) -{ - return grub_inb (dev->ioaddress2 + reg); -} - /* Wait for !BSY. */ static grub_err_t grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds) @@ -298,14 +283,14 @@ check_device (struct grub_pata_device *dev) } static grub_err_t -grub_pata_device_initialize (int port, int device, int addr, int addr2) +grub_pata_device_initialize (int port, int device, int addr) { struct grub_pata_device *dev; struct grub_pata_device **devp; grub_err_t err; - grub_dprintf ("pata", "detecting device %d,%d (0x%x, 0x%x)\n", - port, device, addr, addr2); + grub_dprintf ("pata", "detecting device %d,%d (0x%x)\n", + port, device, addr); dev = grub_malloc (sizeof(*dev)); if (! dev) @@ -315,7 +300,6 @@ grub_pata_device_initialize (int port, int device, int addr, int addr2) dev->port = port; dev->device = device; dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; - dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; dev->next = NULL; /* Register the device. */ @@ -339,7 +323,6 @@ grub_pata_pciinit (grub_pci_device_t dev, grub_uint32_t bar1; grub_uint32_t bar2; int rega; - int regb; int i; static int controller = 0; int cs5536 = 0; @@ -372,14 +355,12 @@ grub_pata_pciinit (grub_pci_device_t dev, compat = (class >> (8 + 2 * i)) & 1; rega = 0; - regb = 0; /* If the channel is in compatibility mode, just assign the default registers. */ if (compat == 0 && !compat_use[i]) { rega = grub_pata_ioaddress[i]; - regb = grub_pata_ioaddress2[i]; compat_use[i] = 1; } else if (compat) @@ -398,19 +379,18 @@ grub_pata_pciinit (grub_pci_device_t dev, if ((bar1 & 1) && (bar2 & 1)) { rega = bar1 & ~3; - regb = bar2 & ~3; } } grub_dprintf ("pata", - "PCI dev (%d,%d,%d) compat=%d rega=0x%x regb=0x%x\n", + "PCI dev (%d,%d,%d) compat=%d rega=0x%x\n", grub_pci_get_bus (dev), grub_pci_get_device (dev), - grub_pci_get_function (dev), compat, rega, regb); + grub_pci_get_function (dev), compat, rega); - if (rega && regb) + if (rega) { grub_errno = GRUB_ERR_NONE; - grub_pata_device_initialize (controller * 2 + i, 0, rega, regb); + grub_pata_device_initialize (controller * 2 + i, 0, rega); /* Most errors raised by grub_ata_device_initialize() are harmless. They just indicate this particular drive is not responding, most @@ -422,7 +402,7 @@ grub_pata_pciinit (grub_pci_device_t dev, grub_errno = GRUB_ERR_NONE; } - grub_pata_device_initialize (controller * 2 + i, 1, rega, regb); + grub_pata_device_initialize (controller * 2 + i, 1, rega); /* Likewise. */ if (grub_errno) From d9675dbee3525def248571a7937e69fdec7afab0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 03:47:51 +0100 Subject: [PATCH 073/673] Move 0xE0 to callers rather than to have it in drivers --- grub-core/commands/hdparm.c | 4 ++++ grub-core/disk/ahci.c | 1 - grub-core/disk/ata.c | 10 +++++----- grub-core/disk/pata.c | 5 ++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index 0154ece57..800bfa06d 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -72,6 +72,8 @@ grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd, apt.taskfile.cmd = cmd; apt.taskfile.features = features; apt.taskfile.sectors = sectors; + apt.taskfile.disk = 0xE0; + apt.buffer = buffer; apt.size = size; @@ -88,6 +90,7 @@ grub_hdparm_do_check_powermode_cmd (grub_ata_t ata) grub_memset (&apt, 0, sizeof (apt)); apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE; + apt.taskfile.disk = 0xE0; if (ata->dev->readwrite (ata, &apt)) return -1; @@ -105,6 +108,7 @@ grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features) apt.taskfile.features = features; apt.taskfile.lba_mid = 0x4f; apt.taskfile.lba_high = 0xc2; + apt.taskfile.disk = 0xE0; if (ata->dev->readwrite (ata, &apt)) return -1; diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index d9b95df37..3160523ce 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -408,7 +408,6 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, for (i = 0; i < sizeof (parms->taskfile.raw); i++) dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; - dev->command_table[0].cfis[7] |= (parms->cmdsize ? 0 : 0xE0); grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n", dev->command_table[0].cfis[0], dev->command_table[0].cfis[1], dev->command_table[0].cfis[2], dev->command_table[0].cfis[3], diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index b33abf90d..494325aa5 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -70,7 +70,7 @@ grub_atapi_identify (struct grub_ata *dev) return grub_errno; grub_memset (&parms, 0, sizeof (parms)); - parms.taskfile.disk = 0; + parms.taskfile.disk = 0xE0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_PACKET_DEVICE; parms.size = GRUB_DISK_SECTOR_SIZE; parms.buffer = info; @@ -108,7 +108,7 @@ grub_ata_identify (struct grub_ata *dev) grub_memset (&parms, 0, sizeof (parms)); parms.buffer = info; parms.size = GRUB_DISK_SECTOR_SIZE; - parms.taskfile.disk = 0; + parms.taskfile.disk = 0xE0; parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE; @@ -196,7 +196,7 @@ grub_ata_setaddress (struct grub_ata *dev, "sector %d cannot be addressed " "using CHS addressing", sector); - parms->taskfile.disk = head; + parms->taskfile.disk = 0xE0 | head; parms->taskfile.sectnum = sect; parms->taskfile.cyllsb = cylinder & 0xFF; parms->taskfile.cylmsb = cylinder >> 8; @@ -207,7 +207,7 @@ grub_ata_setaddress (struct grub_ata *dev, case GRUB_ATA_LBA: if (size == 256) size = 0; - parms->taskfile.disk = ((sector >> 24) & 0x0F); + parms->taskfile.disk = 0xE0 | ((sector >> 24) & 0x0F); parms->taskfile.sectors = size; parms->taskfile.lba_low = sector & 0xFF; @@ -219,7 +219,7 @@ grub_ata_setaddress (struct grub_ata *dev, if (size == 65536) size = 0; - parms->taskfile.disk = 0; + parms->taskfile.disk = 0xE0; /* Set "Previous". */ parms->taskfile.sectors = size & 0xFF; diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 940a9a5f0..f9111bc5f 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -151,9 +151,8 @@ grub_pata_readwrite (struct grub_ata *disk, parms->taskfile.lba_low, parms->size); /* Set registers. */ - grub_pata_regset (dev, GRUB_ATA_REG_DISK, (parms->cmdsize ? 0 : 0xE0) - | dev->device << 4 - | (parms->taskfile.disk & 0xf)); + grub_pata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4) + | (parms->taskfile.disk & 0xef)); if (grub_pata_check_ready (dev)) return grub_errno; From d1e517eb20c2e5e14bdd8eea7168538f9f15a67c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 12:11:54 +0100 Subject: [PATCH 074/673] extend --disk-module to AHCI and USB --- grub-core/bus/usb/ohci.c | 8 ++++++-- grub-core/disk/ahci.c | 38 ++++++++++++++++++++++++++++++++++++++ util/grub-install.in | 14 +++++++++++--- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 8adaee6e0..577f35259 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -1422,18 +1422,22 @@ static struct grub_usb_controller_dev usb_controller = .detect_dev = grub_ohci_detect_dev }; +static void *fini_hnd; + GRUB_MOD_INIT(ohci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32); COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16); grub_ohci_inithw (); grub_usb_controller_dev_register (&usb_controller); - grub_loader_register_preboot_hook (grub_ohci_fini_hw, grub_ohci_restore_hw, - GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw, + grub_ohci_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(ohci) { grub_ohci_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); grub_usb_controller_dev_unregister (&usb_controller); } diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 3160523ce..61ca7e4d6 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -25,6 +25,7 @@ #include #include #include +#include struct grub_ahci_cmd_head { @@ -296,6 +297,34 @@ grub_ahci_initialize (void) return grub_errno; } +static grub_err_t +grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_ahci_device *dev, *next; + + for (dev = grub_ahci_devices; dev; dev = next) + { + next = dev->next; + dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_FR)); + dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + grub_dma_free (dev->command_list_chunk); + grub_dma_free (dev->command_table_chunk); + grub_dma_free (dev->rfis); + + grub_free (dev); + } + grub_ahci_devices = NULL; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ahci_restore_hw (void) +{ + return grub_ahci_initialize (); +} + @@ -533,6 +562,8 @@ static struct grub_ata_dev grub_ahci_dev = +static void *fini_hnd; + GRUB_MOD_INIT(ahci) { /* To prevent two drivers operating on the same disks. */ @@ -548,9 +579,16 @@ GRUB_MOD_INIT(ahci) /* AHCI devices are handled by scsi.mod. */ grub_ata_dev_register (&grub_ahci_dev); + + fini_hnd = grub_loader_register_preboot_hook (grub_ahci_fini_hw, + grub_ahci_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(ahci) { + grub_ahci_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); + grub_ata_dev_unregister (&grub_ahci_dev); } diff --git a/util/grub-install.in b/util/grub-install.in index b9e833360..6259b1c4a 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -77,7 +77,7 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then disk_module= else - disk_module=ata + disk_module=native fi # Usage: usage @@ -114,7 +114,7 @@ Install GRUB on your drive. EOF if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then cat < Date: Sat, 25 Dec 2010 13:44:31 +0100 Subject: [PATCH 075/673] avoid throwing data away on pxefs_open. Reported by : Seth Goldberg --- grub-core/net/i386/pc/pxe.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index fd1447b40..c07aa78f9 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -117,7 +117,7 @@ grub_pxefs_open (struct grub_file *file, const char *name) struct grub_pxe_data *data; grub_file_t file_int, bufio; - data = grub_malloc (sizeof (*data)); + data = grub_zalloc (sizeof (*data) + grub_strlen (name) + 1); if (!data) return grub_errno; @@ -135,7 +135,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) err = grub_net_resolve_address (file->device->net->name + sizeof ("pxe,") - 1, &addr); if (err) - return err; + { + grub_free (data); + return err; + } } else { @@ -144,7 +147,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) } err = grub_net_route_address (addr, &gateway, &interf); if (err) - return err; + { + grub_free (data); + return err; + } data->server_ip = addr.ipv4; data->gateway_ip = gateway.ipv4; } @@ -160,7 +166,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) grub_strcpy ((char *)&c.c1.filename[0], name); grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry); if (c.c1.status) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + { + grub_free (data); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + } file->size = c.c1.file_size; @@ -168,11 +177,10 @@ grub_pxefs_open (struct grub_file *file, const char *name) c.c2.packet_size = grub_pxe_blksize; grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry); if (c.c2.status) - return grub_error (GRUB_ERR_BAD_FS, "open fails"); - - data = grub_zalloc (sizeof (struct grub_pxe_data) + grub_strlen (name) + 1); - if (! data) - return grub_errno; + { + grub_free (data); + return grub_error (GRUB_ERR_BAD_FS, "open fails"); + } data->block_size = c.c2.packet_size; grub_strcpy (data->filename, name); From 3c51ecb82b7ab1a94a296c530bd5f4ffdb7a2eab Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 15:47:23 +0100 Subject: [PATCH 076/673] Fix adressing mode mismatch --- grub-core/disk/ata.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 494325aa5..3fecb98dd 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -173,9 +173,10 @@ static grub_err_t grub_ata_setaddress (struct grub_ata *dev, struct grub_disk_ata_pass_through_parms *parms, grub_disk_addr_t sector, - grub_size_t size) + grub_size_t size, + grub_ata_addressing_t addressing) { - switch (dev->addr) + switch (addressing) { case GRUB_ATA_CHS: { @@ -297,7 +298,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_dprintf("ata", "rw=%d, sector=%llu, batch=%llu\n", rw, (unsigned long long) sector, (unsigned long long) batch); grub_memset (&parms, 0, sizeof (parms)); - grub_ata_setaddress (ata, &parms, sector, batch); + grub_ata_setaddress (ata, &parms, sector, batch, addressing); parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; parms.size = batch * GRUB_DISK_SECTOR_SIZE; From c76ae9b4da785c43dba8478768dd346f5c0b4d59 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 17:40:00 +0100 Subject: [PATCH 077/673] set parms.write on disk write --- grub-core/disk/ata.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 3fecb98dd..c7cde3166 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -302,6 +302,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; parms.size = batch * GRUB_DISK_SECTOR_SIZE; + parms.write = rw; if (ata->dma) parms.dma = 1; From 9797178671d1044cf9fc13648152ea2ea5e76e41 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Dec 2010 18:02:43 +0100 Subject: [PATCH 078/673] Accept ports in state 1 --- grub-core/disk/ahci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 61ca7e4d6..b348ce3d0 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -220,13 +220,15 @@ grub_ahci_pciinit (grub_pci_device_t dev, struct grub_ahci_device *adev; struct grub_pci_dma_chunk *command_list; struct grub_pci_dma_chunk *command_table; + grub_uint32_t st; if (!(hba->ports_implemented & (1 << i))) continue; grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status); /* FIXME: support hotplugging. */ - if ((hba->ports[i].status & 0xf) != 0x3) + st = hba->ports[i].status; + if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1) continue; command_list = grub_memalign_dma32 (1024, From 406a552051bdda5fa07de20a10ccfa7910ca946b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Dec 2010 10:43:04 +0100 Subject: [PATCH 079/673] Add plan9 to OS support table --- docs/grub.texi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/grub.texi b/docs/grub.texi index 54a2d8791..6878a645a 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3305,6 +3305,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab BIOS @tab Coreboot @item BIOS chainloading @tab yes @tab no (1) @item NTLDR @tab yes @tab no (1) +@item Plan9 @tab yes @tab no (1) @item FreeBSD bootloader @tab yes @tab crashes (1) @item 32-bit kFreeBSD @tab yes @tab crashes (2,6) @item 64-bit kFreeBSD @tab yes @tab crashes (2,6) @@ -3329,6 +3330,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab Multiboot @tab Qemu @item BIOS chainloading @tab no (1) @tab no (1) @item NTLDR @tab no (1) @tab no (1) +@item Plan9 @tab no (1) @tab no (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1) @item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6) @item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6) @@ -3353,6 +3355,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab 32-bit EFI @tab 64-bit EFI @item BIOS chainloading @tab no (1) @tab no (1) @item NTLDR @tab no (1) @tab no (1) +@item Plan9 @tab no (1) @tab no (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1) @item 32-bit kFreeBSD @tab headless @tab headless @item 64-bit kFreeBSD @tab headless @tab headless @@ -3377,6 +3380,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item @tab IEEE1275 @item BIOS chainloading @tab no (1) @item NTLDR @tab no (1) +@item Plan9 @tab no (1) @item FreeBSD bootloader @tab crashes (1) @item 32-bit kFreeBSD @tab crashes (6) @item 64-bit kFreeBSD @tab crashes (6) From fb7ab4a99ba343167d3d0c5a8affa38c8dc057bf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 3 Jan 2011 15:54:59 +0100 Subject: [PATCH 080/673] add missing == 0 --- grub-core/net/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 54663f4b0..d3b4c74db 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -199,7 +199,7 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1])) + if (grub_strcmp (inter->name, args[1]) == 0) break; if (inter == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("address not found")); @@ -730,7 +730,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1])) + if (grub_strcmp (inter->name, args[1]) == 0) break; if (!inter) From 7a1d4deec9267fc56ed50507b5a7fa9d96e3b610 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 3 Jan 2011 15:59:20 +0100 Subject: [PATCH 081/673] Fix finalisation/restore --- grub-core/disk/ahci.c | 255 +++++++++++++++++++++++++++++++----------- 1 file changed, 192 insertions(+), 63 deletions(-) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index b348ce3d0..c67dbbe7e 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -157,6 +157,98 @@ enum static struct grub_ahci_device *grub_ahci_devices; static int numdevs; +static int +init_port (struct grub_ahci_device *dev) +{ + struct grub_pci_dma_chunk *command_list; + struct grub_pci_dma_chunk *command_table; + grub_uint64_t endtime; + + command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head)); + if (!command_list) + return 1; + + command_table = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_table)); + if (!command_table) + { + grub_dma_free (command_list); + return 1; + } + + grub_dprintf ("ahci", "found device ahci%d (port %d)\n", dev->num, dev->port); + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + goto out; + } + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + goto out; + } + + dev->hba->ports[dev->port].fbs = 2; + + dev->rfis = grub_memalign_dma32 (4096, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (dev->rfis), 0, + sizeof (struct grub_ahci_received_fis)); + dev->hba->ports[dev->port].fis_base = grub_dma_get_phys (dev->rfis); + dev->hba->ports[dev->port].command_list_base + = grub_dma_get_phys (command_list); + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't start FR\n"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + goto out; + } + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't start CR\n"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_CR; + goto out_stop_fr; + } + + dev->hba->ports[dev->port].command + = (dev->hba->ports[dev->port].command & 0x0fffffff) | (1 << 28) | 2 | 4; + + dev->command_list_chunk = command_list; + dev->command_list = grub_dma_get_virt (command_list); + dev->command_table_chunk = command_table; + dev->command_table = grub_dma_get_virt (command_table); + dev->command_list->command_table_base + = grub_dma_get_phys (command_table); + + return 0; + out_stop_fr: + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + break; + } + out: + grub_dma_free (command_list); + grub_dma_free (command_table); + grub_dma_free (dev->rfis); + return 1; +} + static int NESTED_FUNC_ATTR grub_ahci_pciinit (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) @@ -209,7 +301,50 @@ grub_ahci_pciinit (grub_pci_device_t dev, else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) + grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); + else + grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + + /* + { + grub_uint64_t endtime; + hba->global_control |= 1; + endtime = grub_get_time_ms () + 1000; + while (hba->global_control & 1) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't reset AHCI\n"); + return 0; + } + } + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + */ nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; @@ -218,8 +353,6 @@ grub_ahci_pciinit (grub_pci_device_t dev, for (i = 0; i < nports; i++) { struct grub_ahci_device *adev; - struct grub_pci_dma_chunk *command_list; - struct grub_pci_dma_chunk *command_table; grub_uint32_t st; if (!(hba->ports_implemented & (1 << i))) @@ -231,60 +364,20 @@ grub_ahci_pciinit (grub_pci_device_t dev, if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1) continue; - command_list = grub_memalign_dma32 (1024, - sizeof (struct grub_ahci_cmd_head)); - if (!command_list) - return 1; - - command_table = grub_memalign_dma32 (1024, - sizeof (struct grub_ahci_cmd_table)); - if (!command_table) - { - grub_dma_free (command_list); - return 1; - } - adev = grub_malloc (sizeof (*adev)); if (!adev) - { - grub_dma_free (command_list); - grub_dma_free (command_table); - return 1; - } - - grub_dprintf ("ahci", "found device ahci%d (port %d)\n", numdevs, i); - - hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; - while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); - hba->ports[i].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - while ((hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); - - hba->ports[i].fbs = 2; - - adev->rfis = grub_memalign_dma32 (4096, - sizeof (struct grub_ahci_received_fis)); - grub_memset ((char *) grub_dma_get_virt (adev->rfis), 0, - sizeof (struct grub_ahci_received_fis)); - hba->ports[i].fis_base = grub_dma_get_phys (adev->rfis); - hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; - while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_FR)); - hba->ports[i].command |= GRUB_AHCI_HBA_PORT_CMD_ST; - while (!(hba->ports[i].command & GRUB_AHCI_HBA_PORT_CMD_CR)); - - hba->ports[i].command = (hba->ports[i].command & 0x0fffffff) - | (1 << 28) | 2 | 4; + return 1; adev->hba = hba; adev->port = i; adev->num = numdevs++; - adev->command_list_chunk = command_list; - adev->command_list = grub_dma_get_virt (command_list); - adev->command_table_chunk = command_table; - adev->command_table = grub_dma_get_virt (command_table); - adev->command_list->command_table_base - = grub_dma_get_phys (command_table); - adev->hba->ports[i].command_list_base = grub_dma_get_phys (command_list); + if (init_port (adev)) + { + grub_free (adev); + return 1; + } + grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), GRUB_AS_LIST (adev)); } @@ -302,29 +395,53 @@ grub_ahci_initialize (void) static grub_err_t grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) { - struct grub_ahci_device *dev, *next; + struct grub_ahci_device *dev; - for (dev = grub_ahci_devices; dev; dev = next) + for (dev = grub_ahci_devices; dev; dev = dev->next) { - next = dev->next; - dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; - while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_FR)); - dev->hba->ports[dev->num].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - while ((dev->hba->ports[dev->num].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + grub_uint64_t endtime; + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + break; + } + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + break; + } grub_dma_free (dev->command_list_chunk); grub_dma_free (dev->command_table_chunk); grub_dma_free (dev->rfis); - - grub_free (dev); + dev->command_list_chunk = NULL; + dev->command_table_chunk = NULL; + dev->rfis = NULL; } - grub_ahci_devices = NULL; return GRUB_ERR_NONE; } static grub_err_t grub_ahci_restore_hw (void) { - return grub_ahci_initialize (); + struct grub_ahci_device **pdev; + + for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next)) + if (init_port (*pdev)) + { + struct grub_ahci_device *odev; + odev = *pdev; + *pdev = (*pdev)->next; + grub_free (odev); + } + return GRUB_ERR_NONE; } @@ -391,9 +508,21 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, if ((dev->hba->ports[dev->port].task_file_data & 0x80)) { dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + break; + } dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; - while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)); + endtime = grub_get_time_ms () + 1000; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't start CR\n"); + break; + } } dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; From 92bb078645e55f116ebb253be5292cd10b6ffbb9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 8 Jan 2011 19:51:08 +0100 Subject: [PATCH 082/673] grub-fuse --- Makefile.util.def | 15 ++ config.h.in | 4 + configure.ac | 37 ++++ docs/man/grub-fuse.h2m | 2 + util/grub-fuse.c | 455 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 513 insertions(+) create mode 100644 docs/man/grub-fuse.h2m create mode 100644 util/grub-fuse.c diff --git a/Makefile.util.def b/Makefile.util.def index 74984e2e9..369d312f6 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -212,6 +212,21 @@ program = { ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; }; +program = { + name = grub-fuse; + mansection = 1; + common_nodist = grub_fstest_init.c; + common = util/grub-fuse.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + ldadd = libgrubmods.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)' '-lfuse'; + condition = COND_GRUB_FUSE; +}; + program = { name = grub-mkfont; mansection = 1; diff --git a/config.h.in b/config.h.in index 6d7d95dec..3974ad7d5 100644 --- a/config.h.in +++ b/config.h.in @@ -1,3 +1,7 @@ +#undef _LARGEFILE_SOURCE +#undef _FILE_OFFSET_BITS +#define _LARGEFILE_SOURCE +#define _FILE_OFFSET_BITS 64 #if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) #include #define NESTED_FUNC_ATTR diff --git a/configure.ac b/configure.ac index 8bb585a78..e9e31e7fb 100644 --- a/configure.ac +++ b/configure.ac @@ -856,6 +856,37 @@ AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) +AC_ARG_ENABLE([grub-mkfont], + [AS_HELP_STRING([--enable-grub-mkfont], + [build and install the `grub-mkfont' utility (default=guessed)])]) +if test x"$enable_grub_mkfont" = xno ; then + grub_mkfont_excuse="explicitly disabled" +fi + +if test x"$grub_fuse_excuse" = x ; then + AC_CHECK_LIB([fuse], [fuse_main_real], [], + [grub_fuse_excuse="need FUSE library"]) +fi + +if test x"$grub_fuse_excuse" = x ; then + # Check for fuse headers. + SAVED_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" + AC_CHECK_HEADERS([fuse/fuse.h], [], + [grub_fuse_excuse=["need FUSE headers"]]) + CPPFLAGS="$SAVED_CPPFLAGS" +fi + +if test x"$enable_grub_fuse" = xyes && test x"$grub_fuse_excuse" != x ; then + AC_MSG_ERROR([grub-fuse was explicitly requested but can't be compiled]) +fi +if test x"$grub_fuse_excuse" = x ; then +enable_grub_fuse=yes +else +enable_grub_fuse=no +fi +AC_SUBST([enable_grub_fuse]) + AC_ARG_ENABLE([device-mapper], [AS_HELP_STRING([--enable-device-mapper], [enable Linux device-mapper support (default=guessed)])]) @@ -952,6 +983,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) +AM_CONDITIONAL([COND_GRUB_FUSE], [test x$enable_grub_fuse = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) @@ -1027,5 +1059,10 @@ echo grub-mkfont: Yes else echo grub-mkfont: No "($grub_mkfont_excuse)" fi +if [ x"$grub_fuse_excuse" = x ]; then +echo grub-fuse: Yes +else +echo grub-fuse: No "($grub_fuse_excuse)" +fi echo "*******************************************************" ] diff --git a/docs/man/grub-fuse.h2m b/docs/man/grub-fuse.h2m new file mode 100644 index 000000000..0e234ddc1 --- /dev/null +++ b/docs/man/grub-fuse.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-fuse \- export GRUB filesystem with FUSE. diff --git a/util/grub-fuse.c b/util/grub-fuse.c new file mode 100644 index 000000000..7f0ad0d0f --- /dev/null +++ b/util/grub-fuse.c @@ -0,0 +1,455 @@ +/* grub-fstest.c - debug tool for filesystem driver */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009,2010 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 . + */ +#define FUSE_USE_VERSION 26 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "progname.h" +#include "argp.h" + +static char *root = NULL; +static char **images = NULL; +static char *debug_str = NULL; +static char **fuse_args = NULL; +static int fuse_argc = 0; +static int num_disks = 0; + +static grub_err_t +execute_command (char *name, int n, char **args) +{ + grub_command_t cmd; + + cmd = grub_command_find (name); + if (! cmd) + grub_util_error (_("can\'t find command %s"), name); + + return (cmd->func) (cmd, n, args); +} + +static int +fuse_getattr (const char *path, struct stat *st) +{ + char *filename, *pathname, *path2; + const char *pathname_t; + grub_fs_t fs; + grub_device_t dev; + struct grub_dirhook_info file_info; + int file_exists = 0; + + /* A hook for iterating directories. */ + auto int find_file (const char *cur_filename, + const struct grub_dirhook_info *info); + int find_file (const char *cur_filename, + const struct grub_dirhook_info *info) + { + if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename) + : grub_strcmp (cur_filename, filename)) == 0) + { + file_info = *info; + file_exists = 1; + return 1; + } + return 0; + } + + if (path[0] == '/' && path[1] == 0) + { + st->st_dev = 0; + st->st_ino = 0; + st->st_mode = 0555 | S_IFDIR; + st->st_uid = 0; + st->st_gid = 0; + st->st_rdev = 0; + st->st_size = 0; + st->st_blksize = 512; + st->st_blocks = (st->st_blksize + 511) >> 9; + st->st_atime = st->st_mtime = st->st_ctime = 0; + return 0; + } + + file_exists = 0; + dev = grub_device_open (0); + if (! dev) + return -1; + + fs = grub_fs_probe (dev); + if (! fs) + { + grub_device_close (dev); + return -1; + } + + pathname_t = grub_strchr (path, ')'); + if (! pathname_t) + pathname_t = path; + else + pathname_t++; + pathname = xstrdup (pathname_t); + + /* Remove trailing '/'. */ + while (*pathname && pathname[grub_strlen (pathname) - 1] == '/') + pathname[grub_strlen (pathname) - 1] = 0; + + /* Split into path and filename. */ + filename = grub_strrchr (pathname, '/'); + if (! filename) + { + path2 = grub_strdup ("/"); + filename = pathname; + } + else + { + filename++; + path2 = grub_strdup (pathname); + path2[filename - pathname] = 0; + } + + /* It's the whole device. */ + (fs->dir) (dev, path2, find_file); + + grub_device_close (dev); + grub_free (path2); + if (!file_exists) + return -1; + st->st_dev = 0; + st->st_ino = 0; + st->st_mode = file_info.dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); + st->st_uid = 0; + st->st_gid = 0; + st->st_rdev = 0; + if (!file_info.dir) + { + grub_file_t file; + file = grub_file_open (path); + if (! file) + { + grub_print_error (); + return -1; + } + st->st_size = file->size; + grub_file_close (file); + } + else + st->st_size = 0; + st->st_blksize = 512; + st->st_blocks = (st->st_size + 511) >> 9; + st->st_atime = st->st_mtime = st->st_ctime = file_info.mtimeset + ? file_info.mtime : 0; + return 0; +} + +static int +fuse_opendir (const char *path, struct fuse_file_info *fi) +{ + return 0; +} + +/* FIXME */ +static grub_file_t files[65536]; +static int first_fd = 1; + +static int +fuse_open (const char *path, struct fuse_file_info *fi __attribute__ ((unused))) +{ + grub_file_t file; + file = grub_file_open (path); + if (! file) + { + grub_print_error (); + return -1; + } + files[first_fd++] = file; + fi->fh = first_fd; + files[first_fd++] = file; + return 0; +} + +static int +fuse_read (const char *path, char *buf, size_t sz, off_t off, + struct fuse_file_info *fi) +{ + grub_file_t file = files[fi->fh]; + + if (off > file->size) + return -1; + + file->offset = off; + + return grub_file_read (file, buf, sz); +} + +static int +fuse_release (const char *path, struct fuse_file_info *fi) +{ + grub_file_close (files[fi->fh]); + files[fi->fh] = NULL; + return 0; +} + +static int +fuse_readdir (const char *path, void *buf, + fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi) +{ + char *pathname; + grub_fs_t fs; + grub_device_t dev; + + auto int call_fill (const char *filename, + const struct grub_dirhook_info *info); + int call_fill (const char *filename, const struct grub_dirhook_info *info) + { + fill (buf, filename, NULL, 0); + return 0; + } + + dev = grub_device_open (0); + if (! dev) + { + return 1; + } + + fs = grub_fs_probe (dev); + if (! fs) + { + grub_device_close (dev); + return 1; + } + + pathname = xstrdup (path); + + /* Remove trailing '/'. */ + while (pathname [0] && pathname[1] + && pathname[grub_strlen (pathname) - 1] == '/') + pathname[grub_strlen (pathname) - 1] = 0; + + (fs->dir) (dev, pathname, call_fill); + grub_device_close (dev); + free (pathname); + return 0; +} + +struct fuse_operations grub_opers = { + .getattr = fuse_getattr, + .open = fuse_open, + .release = fuse_release, + .opendir = fuse_opendir, + .readdir = fuse_readdir, + .read = fuse_read +}; + +static void +fuse_init (void) +{ + int i; + + for (i = 0; i < num_disks; i++) + { + char *argv[2]; + char *host_file; + char *loop_name; + loop_name = grub_xasprintf ("loop%d", i); + if (!loop_name) + grub_util_error (grub_errmsg); + + host_file = grub_xasprintf ("(host)%s", images[i]); + if (!host_file) + grub_util_error (grub_errmsg); + + argv[0] = loop_name; + argv[1] = host_file; + + if (execute_command ("loopback", 2, argv)) + grub_util_error (_("loopback command fails")); + + grub_free (loop_name); + grub_free (host_file); + } + + grub_lvm_fini (); + grub_mdraid09_fini (); + grub_mdraid1x_fini (); + grub_raid_fini (); + grub_raid_init (); + grub_mdraid09_init (); + grub_mdraid1x_init (); + grub_lvm_init (); + + fuse_main (fuse_argc, fuse_args, &grub_opers, NULL); + + for (i = 0; i < num_disks; i++) + { + char *argv[2]; + char *loop_name; + + loop_name = grub_xasprintf ("loop%d", i); + if (!loop_name) + grub_util_error (grub_errmsg); + + argv[0] = "-d"; + argv[1] = loop_name; + + execute_command ("loopback", 2, argv); + + grub_free (loop_name); + } +} + +static struct argp_option options[] = { + {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, + {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, + {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, + {0, 0, 0, 0, 0, 0} +}; + +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); +} +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + char *p; + + switch (key) + { + case 'r': + root = arg; + return 0; + + case 'd': + debug_str = arg; + return 0; + + case 'v': + verbosity++; + return 0; + + case ARGP_KEY_ARG: + if (arg[0] != '-') + break; + + default: + if (!arg) + return 0; + + fuse_args = xrealloc (fuse_args, (fuse_argc + 1) * sizeof (fuse_args[0])); + fuse_args[fuse_argc] = xstrdup (arg); + fuse_argc++; + return 0; + } + + if (arg[0] != '/') + { + fprintf (stderr, "%s", _("Must use absolute path.\n")); + argp_usage (state); + } + images = xrealloc (images, (num_disks + 1) * sizeof (images[0])); + images[num_disks] = xstrdup (arg); + num_disks++; + + return 0; +} + +struct argp argp = { + options, argp_parser, N_("IMAGE1 [IMAGE2 ...] MOUNTPOINT"), + N_("Debug tool for filesystem driver."), + NULL, NULL, NULL +}; + +int +main (int argc, char *argv[]) +{ + char *default_root, *alloc_root; + + set_program_name (argv[0]); + + grub_util_init_nls (); + + fuse_args = xrealloc (fuse_args, (fuse_argc + 1) * sizeof (fuse_args[0])); + fuse_args[fuse_argc] = xstrdup (argv[0]); + fuse_argc++; + + argp_parse (&argp, argc, argv, 0, 0, 0); + + if (num_disks < 2) + grub_util_error ("need an image and mountpoint"); + fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0])); + fuse_args[fuse_argc] = images[num_disks - 1]; + fuse_argc++; + num_disks--; + fuse_args[fuse_argc] = NULL; + + /* Initialize all modules. */ + grub_init_all (); + + if (debug_str) + grub_env_set ("debug", debug_str); + + default_root = (num_disks == 1) ? "loop0" : "md0"; + alloc_root = 0; + if (root) + { + if ((*root >= '0') && (*root <= '9')) + { + alloc_root = xmalloc (strlen (default_root) + strlen (root) + 2); + + sprintf (alloc_root, "%s,%s", default_root, root); + root = alloc_root; + } + } + else + root = default_root; + + grub_env_set ("root", root); + + if (alloc_root) + free (alloc_root); + + /* Do it. */ + fuse_init (); + + /* Free resources. */ + grub_fini_all (); + + return 0; +} From 89644ef113f00c03b18d075243debf5417e00549 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Tue, 11 Jan 2011 21:20:54 +0100 Subject: [PATCH 083/673] Rename grub-fuse to grub-mount (with Vladimir's blessing) --- Makefile.util.def | 4 ++-- configure.ac | 6 +++--- docs/man/grub-fuse.h2m | 2 -- docs/man/grub-mount.h2m | 2 ++ util/{grub-fuse.c => grub-mount.c} | 0 5 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 docs/man/grub-fuse.h2m create mode 100644 docs/man/grub-mount.h2m rename util/{grub-fuse.c => grub-mount.c} (100%) diff --git a/Makefile.util.def b/Makefile.util.def index 369d312f6..3009ff76a 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -213,10 +213,10 @@ program = { }; program = { - name = grub-fuse; + name = grub-mount; mansection = 1; common_nodist = grub_fstest_init.c; - common = util/grub-fuse.c; + common = util/grub-mount.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; diff --git a/configure.ac b/configure.ac index e9e31e7fb..b71aea910 100644 --- a/configure.ac +++ b/configure.ac @@ -878,7 +878,7 @@ if test x"$grub_fuse_excuse" = x ; then fi if test x"$enable_grub_fuse" = xyes && test x"$grub_fuse_excuse" != x ; then - AC_MSG_ERROR([grub-fuse was explicitly requested but can't be compiled]) + AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled]) fi if test x"$grub_fuse_excuse" = x ; then enable_grub_fuse=yes @@ -1060,9 +1060,9 @@ else echo grub-mkfont: No "($grub_mkfont_excuse)" fi if [ x"$grub_fuse_excuse" = x ]; then -echo grub-fuse: Yes +echo grub-mount: Yes else -echo grub-fuse: No "($grub_fuse_excuse)" +echo grub-mount: No "($grub_fuse_excuse)" fi echo "*******************************************************" ] diff --git a/docs/man/grub-fuse.h2m b/docs/man/grub-fuse.h2m deleted file mode 100644 index 0e234ddc1..000000000 --- a/docs/man/grub-fuse.h2m +++ /dev/null @@ -1,2 +0,0 @@ -[NAME] -grub-fuse \- export GRUB filesystem with FUSE. diff --git a/docs/man/grub-mount.h2m b/docs/man/grub-mount.h2m new file mode 100644 index 000000000..73e7246a3 --- /dev/null +++ b/docs/man/grub-mount.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mount \- export GRUB filesystem with FUSE. diff --git a/util/grub-fuse.c b/util/grub-mount.c similarity index 100% rename from util/grub-fuse.c rename to util/grub-mount.c From 13fc463f17281442f13c5ed3dc586f22efaaa2af Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sat, 15 Jan 2011 14:18:16 -0600 Subject: [PATCH 084/673] Make new grub_vbe_bios_* functions static. --- ChangeLog.vbe-autodetect | 5 +---- grub-core/video/i386/pc/vbe.c | 6 +++--- include/grub/i386/pc/vbe.h | 9 --------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index d8034b885..46aacef7b 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -1,4 +1,4 @@ -2010-12-14 Colin Watson +2011-01-15 Colin Watson Preferred resolution detection for VBE. @@ -25,9 +25,6 @@ (grub_video_edid_preferred_mode): Likewise. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. - (grub_vbe_bios_get_flat_panel_info): Add prototype. - (grub_vbe_bios_get_ddc_capabilities): Likewise. - (grub_vbe_bios_read_edid): Likewise. * grub-core/commands/videoinfo.c (print_edid): New function. (grub_cmd_videoinfo): Print EDID if available. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index c6bb733a9..29b67beeb 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -274,7 +274,7 @@ grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset, } /* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ -grub_vbe_status_t +static grub_vbe_status_t grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info) { struct grub_bios_int_registers regs; @@ -289,7 +289,7 @@ grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_i } /* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ -grub_vbe_status_t +static grub_vbe_status_t grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) { struct grub_bios_int_registers regs; @@ -307,7 +307,7 @@ grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) } /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ -grub_vbe_status_t +static grub_vbe_status_t grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_info) { struct grub_bios_int_registers regs; diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 0422558db..09ad7eb64 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -214,15 +214,6 @@ grub_vbe_bios_get_scanline_length (grub_uint32_t *length); grub_vbe_status_t grub_vbe_bios_get_display_start (grub_uint32_t *x, grub_uint32_t *y); -/* Call VESA BIOS 0x4f11 to get flat panel information, return status. */ -grub_vbe_status_t -grub_vbe_bios_get_flat_panel_info (struct grub_vbe_flat_panel_info *flat_panel_info); -/* Call VESA BIOS 0x4f15 to get DDC availability, return status. */ -grub_vbe_status_t -grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level); -/* Call VESA BIOS 0x4f15 to read EDID information, return status. */ -grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_data); grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); From 4f8ba1461b82f886557293c26da82fe590d556cd Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 17 Jan 2011 11:56:36 +0000 Subject: [PATCH 085/673] Use low memory scratch area for EDID and FP calls. --- grub-core/video/i386/pc/vbe.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 29b67beeb..ea60c6074 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -383,7 +383,12 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) grub_vbe_status_t status; grub_uint8_t ddc_level; struct grub_video_edid_info edid_info; - struct grub_vbe_flat_panel_info flat_panel_info; + struct grub_vbe_flat_panel_info *flat_panel_info; + + /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ + flat_panel_info = (struct grub_vbe_flat_panel_info *) + (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + sizeof (struct grub_video_edid_info)); + grub_memset (flat_panel_info, 0, sizeof (*flat_panel_info)); if (controller_info.version >= 0x200 && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) @@ -397,7 +402,7 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) grub_errno = GRUB_ERR_NONE; } - status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info); + status = grub_vbe_bios_get_flat_panel_info (flat_panel_info); if (status == GRUB_VBE_STATUS_OK) { *width = flat_panel_info.horizontal_size; @@ -967,9 +972,18 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, static grub_err_t grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) { - if (grub_vbe_bios_read_edid (edid_info) != GRUB_VBE_STATUS_OK) + struct grub_video_edid_info *edid_info_lowmem; + + /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ + edid_info_lowmem = + (struct grub_video_edid_info *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (edid_info_lowmem, 0, sizeof (*edid_info_lowmem)); + + if (grub_vbe_bios_read_edid (edid_info_lowmem) != GRUB_VBE_STATUS_OK) return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); + grub_memcpy (edid_info, edid_info_lowmem, sizeof (*edid_info)); + return GRUB_ERR_NONE; } From cb918eddf4fd5c2d2d07ac5da6fa8074604b3e5f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 17 Jan 2011 12:05:12 +0000 Subject: [PATCH 086/673] fix FP info handling --- grub-core/video/i386/pc/vbe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index ea60c6074..c2b35a851 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -405,8 +405,8 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) status = grub_vbe_bios_get_flat_panel_info (flat_panel_info); if (status == GRUB_VBE_STATUS_OK) { - *width = flat_panel_info.horizontal_size; - *height = flat_panel_info.vertical_size; + *width = flat_panel_info->horizontal_size; + *height = flat_panel_info->vertical_size; return GRUB_ERR_NONE; } From 9b300caf8455dd0b8c3910330b063ff5777f0a36 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 17 Jan 2011 12:07:47 +0000 Subject: [PATCH 087/673] grub_video_get_edid is not usable from grub_vbe_get_preferred_mode, as a video adapter has not necessarily yet been set. Use grub_video_vbe_get_edid and grub_video_edid_checksum directly instead. Remove grub_video_get_edid as it now has no users. Reported by: Marjo Mercado. --- ChangeLog.vbe-autodetect | 4 +--- grub-core/video/i386/pc/vbe.c | 39 ++++++++++++++++++----------------- grub-core/video/video.c | 18 ---------------- include/grub/video.h | 1 - 4 files changed, 21 insertions(+), 41 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 46aacef7b..3341e8cc3 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -1,9 +1,8 @@ -2011-01-15 Colin Watson +2011-01-17 Colin Watson Preferred resolution detection for VBE. * grub-core/video/video.c (grub_video_edid_checksum): New function. - (grub_video_get_edid): Likewise. (grub_video_edid_preferred_mode): Likewise. Try EDID followed by the Flat Panel extension, in line with the X.org VESA driver. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): @@ -21,7 +20,6 @@ * include/grub/video.h (struct grub_vbe_edid_info): New structure. (struct grub_video_adapter): Add get_edid. (grub_video_edid_checksum): Add prototype. - (grub_video_get_edid): Likewise. (grub_video_edid_preferred_mode): Likewise. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index c2b35a851..f94b06060 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -377,6 +377,24 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) return GRUB_ERR_NONE; } +static grub_err_t +grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) +{ + struct grub_video_edid_info *edid_info_lowmem; + + /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ + edid_info_lowmem = + (struct grub_video_edid_info *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (edid_info_lowmem, 0, sizeof (*edid_info_lowmem)); + + if (grub_vbe_bios_read_edid (edid_info_lowmem) != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); + + grub_memcpy (edid_info, edid_info_lowmem, sizeof (*edid_info)); + + return GRUB_ERR_NONE; +} + static grub_err_t grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) { @@ -394,7 +412,8 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) && (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff) == GRUB_VBE_STATUS_OK) { - if (grub_video_get_edid (&edid_info) == GRUB_ERR_NONE + if (grub_video_vbe_get_edid (&edid_info) == GRUB_ERR_NONE + && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE && grub_video_edid_preferred_mode (&edid_info, width, height) == GRUB_ERR_NONE) return GRUB_ERR_NONE; @@ -969,24 +988,6 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, return grub_video_fb_get_info_and_fini (mode_info, framebuf); } -static grub_err_t -grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info) -{ - struct grub_video_edid_info *edid_info_lowmem; - - /* Use low memory scratch area as temporary storage for VESA BIOS calls. */ - edid_info_lowmem = - (struct grub_video_edid_info *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - grub_memset (edid_info_lowmem, 0, sizeof (*edid_info_lowmem)); - - if (grub_vbe_bios_read_edid (edid_info_lowmem) != GRUB_VBE_STATUS_OK) - return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available"); - - grub_memcpy (edid_info, edid_info_lowmem, sizeof (*edid_info)); - - return GRUB_ERR_NONE; -} - static void grub_video_vbe_print_adapter_specific_info (void) { diff --git a/grub-core/video/video.c b/grub-core/video/video.c index 84e98bb67..01bdd1ff3 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -393,24 +393,6 @@ grub_video_edid_checksum (struct grub_video_edid_info *edid_info) return grub_errno; } -grub_err_t -grub_video_get_edid (struct grub_video_edid_info *edid_info) -{ - if (! grub_video_adapter_active) - return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated"); - - if (! grub_video_adapter_active->get_edid) - return grub_error (GRUB_ERR_BAD_DEVICE, - "EDID information unavailable for this video mode"); - - if (grub_video_adapter_active->get_edid (edid_info) != GRUB_ERR_NONE) - return grub_errno; - if (grub_video_edid_checksum (edid_info) != GRUB_ERR_NONE) - return grub_errno; - - return GRUB_ERR_NONE; -} - grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, unsigned int *width, unsigned int *height) diff --git a/include/grub/video.h b/include/grub/video.h index 2251ed5f4..f42730a7d 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -486,7 +486,6 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); -grub_err_t grub_video_get_edid (struct grub_video_edid_info *edid_info); grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, unsigned int *width, unsigned int *height); From 09573499ff62ebbeabfedc45dd8106ba715cbdf3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 29 Mar 2011 02:02:55 +0200 Subject: [PATCH 088/673] Initial variable sector size support --- grub-core/disk/efi/efidisk.c | 17 ++++--- grub-core/disk/i386/pc/biosdisk.c | 52 +++++++++++---------- grub-core/disk/scsi.c | 36 +++++---------- grub-core/kern/disk.c | 77 +++++++++++++++++++++++-------- grub-core/kern/emu/hostdisk.c | 37 ++++++++++----- grub-core/partmap/msdos.c | 22 ++++++--- include/grub/disk.h | 10 ++-- 7 files changed, 155 insertions(+), 96 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 08094fa5c..20fea956f 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -536,8 +536,13 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) and total sectors should be replaced with total blocks. */ grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", m, (unsigned long long) m->last_block, m->block_size); - disk->total_sectors = (m->last_block - * (m->block_size >> GRUB_DISK_SECTOR_BITS)); + disk->total_sectors = m->last_block; + if (m->blocksize & (m->blocksize - 1) || !m->blocksize) + return grub_error (GRUB_ERR_IO, "invalid sector size %d", + m->blocksize); + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < m->blocksize; + disk->log_sector_size++); disk->data = d; grub_dprintf ("efidisk", "opening %s succeeded\n", name); @@ -571,8 +576,8 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, (unsigned long) size, (unsigned long long) sector, disk->name); status = efi_call_5 (dio->read, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS, - (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS, + (grub_efi_uint64_t) sector << disk->log_sector_size, + (grub_efi_uintn_t) size << disk->log_sector_size, buf); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error"); @@ -599,8 +604,8 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, (unsigned long) size, (unsigned long long) sector, disk->name); status = efi_call_5 (dio->write, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS, - (grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS, + (grub_efi_uint64_t) sector << disk->log_sector_size, + (grub_efi_uintn_t) size << disk->log_sector_size, (void *) buf); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error"); diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 069bb0b59..6e48fff43 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -338,7 +338,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) if ((cd_drive) && (drive == cd_drive)) { data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM; - data->sectors = 32; + data->sectors = 8; + disk->log_sector_size = 11; /* TODO: get the correct size. */ total_sectors = GRUB_DISK_SIZE_UNKNOWN; } @@ -347,6 +348,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) /* HDD */ int version; + disk->log_sector_size = 9; + version = grub_biosdisk_check_int13_extensions (drive); if (version) { @@ -367,6 +370,15 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) correctly but returns zero. So if it is zero, compute it by C/H/S returned by the LBA BIOS call. */ total_sectors = drp->cylinders * drp->heads * drp->sectors; + if (drp->bytes_per_sector + && !(drp->bytes_per_sector & (drp->bytes_per_sector - 1)) + && drp->bytes_per_sector >= 512 + && drp->bytes_per_sector <= 16384) + { + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < drp->bytes_per_sector; + disk->log_sector_size++); + } } } } @@ -429,7 +441,7 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + (data->sectors - << GRUB_DISK_SECTOR_BITS)); + << disk->log_sector_size)); dap->length = sizeof (*dap); dap->reserved = 0; dap->blocks = size; @@ -443,9 +455,6 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, if (cmd) return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom"); - dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2; - dap->block >>= 2; - for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++) if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap)) break; @@ -501,10 +510,12 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, /* Return the number of sectors which can be read safely at a time. */ static grub_size_t -get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors) +get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector) { grub_size_t size; grub_uint32_t offset; + struct grub_biosdisk_data *data = disk->data; + grub_uint32_t sectors = data->sectors; /* OFFSET = SECTOR % SECTORS */ grub_divmod64 (sector, sectors, &offset); @@ -512,8 +523,8 @@ get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors) size = sectors - offset; /* Limit the max to 0x7f because of Phoenix EDD. */ - if (size > 0x7f) - size = 0x7f; + if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size)) + size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size); return size; } @@ -522,21 +533,11 @@ static grub_err_t grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { - struct grub_biosdisk_data *data = disk->data; - while (size) { grub_size_t len; - grub_size_t cdoff = 0; - len = get_safe_sectors (sector, data->sectors); - - if (data->flags & GRUB_BIOSDISK_FLAG_CDROM) - { - cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS; - len = ALIGN_UP (sector + len, 4) - (sector & ~3); - sector &= ~3; - } + len = get_safe_sectors (disk, sector); if (len > size) len = size; @@ -545,9 +546,10 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, GRUB_MEMORY_MACHINE_SCRATCH_SEG)) return grub_errno; - grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff), - len << GRUB_DISK_SECTOR_BITS); - buf += len << GRUB_DISK_SECTOR_BITS; + grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, + len << disk->log_sector_size); + + buf += len << disk->log_sector_size; sector += len; size -= len; } @@ -568,18 +570,18 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, { grub_size_t len; - len = get_safe_sectors (sector, data->sectors); + len = get_safe_sectors (disk, sector); if (len > size) len = size; grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf, - len << GRUB_DISK_SECTOR_BITS); + len << disk->log_sector_size); if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len, GRUB_MEMORY_MACHINE_SCRATCH_SEG)) return grub_errno; - buf += len << GRUB_DISK_SECTOR_BITS; + buf += len << disk->log_sector_size; sector += len; size -= len; } diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index a40de278f..0d4734dc0 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -463,15 +463,20 @@ grub_scsi_open (const char *name, grub_disk_t disk) return err; } - /* SCSI blocks can be something else than 512, although GRUB - wants 512 byte blocks. */ - disk->total_sectors = ((grub_uint64_t)scsi->size - * (grub_uint64_t)scsi->blocksize) - >> GRUB_DISK_SECTOR_BITS; + disk->total_sectors = scsi->size; + if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize) + { + grub_free (scsi); + return grub_error (GRUB_ERR_IO, "invalid sector size %d", + scsi->blocksize); + } + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < scsi->blocksize; + disk->log_sector_size++); grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n", scsi->size, scsi->blocksize); - grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n", + grub_dprintf ("scsi", "Disk total sectors = %llu\n", (unsigned long long) disk->total_sectors); return GRUB_ERR_NONE; @@ -501,25 +506,6 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, scsi = disk->data; - /* SCSI sectors are variable in size. GRUB uses 512 byte - sectors. */ - if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE) - { - unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS; - if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported SCSI block size"); - - grub_uint32_t sector_mod = 0; - sector = grub_divmod64 (sector, spb, §or_mod); - - if (! (sector_mod == 0 && size % spb == 0)) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unaligned SCSI read not supported"); - - size /= spb; - } - /* Depending on the type, select a read function. */ switch (scsi->devtype) { diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 807ee4277..af56527ad 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -247,6 +247,7 @@ grub_disk_open (const char *name) disk = (grub_disk_t) grub_zalloc (sizeof (*disk)); if (! disk) return 0; + disk->log_sector_size = GRUB_DISK_SECTOR_BITS; p = find_part_sep (name); if (p) @@ -266,7 +267,6 @@ grub_disk_open (const char *name) if (! disk->name) goto fail; - for (dev = grub_disk_dev_list; dev; dev = dev->next) { if ((dev->open) (raw, disk) == GRUB_ERR_NONE) @@ -282,6 +282,14 @@ grub_disk_open (const char *name) grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk"); goto fail; } + if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + || disk->log_sector_size < GRUB_DISK_SECTOR_BITS) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "sector sizes of %d bytes aren't supported yet", + (1 << disk->log_sector_size)); + goto fail; + } disk->dev = dev; @@ -373,14 +381,23 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, *sector += start; } - if (disk->total_sectors <= *sector - || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS) > disk->total_sectors - *sector) + if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN + && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector + || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors + << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - *sector)) return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk"); return GRUB_ERR_NONE; } +static inline grub_disk_addr_t +transform_sector (grub_disk_t disk, grub_disk_addr_t sector) +{ + return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); +} + /* Read data from the disk. */ grub_err_t grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, @@ -433,27 +450,39 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, else { /* Otherwise read data from the disk actually. */ - if (start_sector + GRUB_DISK_CACHE_SIZE > disk->total_sectors - || (disk->dev->read) (disk, start_sector, - GRUB_DISK_CACHE_SIZE, tmp_buf) + if ((disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN + && start_sector + GRUB_DISK_CACHE_SIZE + > (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) + || (disk->dev->read) (disk, transform_sector (disk, start_sector), + 1 << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), tmp_buf) != GRUB_ERR_NONE) { /* Uggh... Failed. Instead, just read necessary data. */ unsigned num; char *p; + grub_disk_addr_t aligned_sector; grub_errno = GRUB_ERR_NONE; - num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + - 1)); + real_offset += ((sector - aligned_sector) + << GRUB_DISK_SECTOR_BITS); + num = ((size + real_offset + (1 << (disk->log_sector_size)) + - 1) >> (disk->log_sector_size)); - p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS); + p = grub_realloc (tmp_buf, num << disk->log_sector_size); if (!p) goto finish; tmp_buf = p; - if ((disk->dev->read) (disk, sector, num, tmp_buf)) + if ((disk->dev->read) (disk, transform_sector (disk, + aligned_sector), + num, tmp_buf)) { grub_error_push (); grub_dprintf ("disk", "%s read failed\n", disk->name); @@ -528,25 +557,31 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, const void *buf) { unsigned real_offset; + grub_disk_addr_t aligned_sector; grub_dprintf ("disk", "Writing `%s'...\n", disk->name); if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) return -1; - real_offset = offset; + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - 1)); + real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); + sector = aligned_sector; while (size) { - if (real_offset != 0 || (size < GRUB_DISK_SECTOR_SIZE && size != 0)) + if (real_offset != 0 || (size < (1U << disk->log_sector_size) + && size != 0)) { - char tmp_buf[GRUB_DISK_SECTOR_SIZE]; + char tmp_buf[1 << disk->log_sector_size]; grub_size_t len; grub_partition_t part; part = disk->partition; disk->partition = 0; - if (grub_disk_read (disk, sector, 0, GRUB_DISK_SECTOR_SIZE, tmp_buf) + if (grub_disk_read (disk, sector, + 0, (1 << disk->log_sector_size), tmp_buf) != GRUB_ERR_NONE) { disk->partition = part; @@ -554,7 +589,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, } disk->partition = part; - len = GRUB_DISK_SECTOR_SIZE - real_offset; + len = (1 << disk->log_sector_size) - real_offset; if (len > size) len = size; @@ -565,7 +600,7 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE) goto finish; - sector++; + sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); buf = (char *) buf + len; size -= len; real_offset = 0; @@ -575,8 +610,8 @@ grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t len; grub_size_t n; - len = size & ~(GRUB_DISK_SECTOR_SIZE - 1); - n = size >> GRUB_DISK_SECTOR_BITS; + len = size & ~((1 << disk->log_sector_size) - 1); + n = size >> disk->log_sector_size; if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE) goto finish; @@ -599,6 +634,8 @@ grub_disk_get_size (grub_disk_t disk) { if (disk->partition) return grub_partition_get_len (disk->partition); + else if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN) + return disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); else - return disk->total_sectors; + return GRUB_DISK_SIZE_UNKNOWN; } diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 73d023ce9..f082ada89 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -42,6 +42,7 @@ #ifdef __linux__ # include /* ioctl */ +# include # if !defined(__GLIBC__) || \ ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) /* Maybe libc doesn't have large file support. */ @@ -264,6 +265,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) # else unsigned long long nr; # endif + int sector_size; int fd; fd = open (map[drive].device, O_RDONLY); @@ -295,16 +297,28 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) goto fail; } + if (ioctl (fd, BLKSSZGET, §or_size)) + { + close (fd); + goto fail; + } + close (fd); + if (sector_size & (sector_size - 1) || !sector_size) + goto fail; + for (disk->log_sector_size = 0; + (1 << disk->log_sector_size) < sector_size; + disk->log_sector_size++); + # if defined (__APPLE__) disk->total_sectors = nr; # elif defined(__NetBSD__) disk->total_sectors = label.d_secperunit; # else - disk->total_sectors = nr / 512; + disk->total_sectors = nr >> disk->log_sector_size; - if (nr % 512) + if (nr & ((1 << disk->log_sector_size) - 1)) grub_util_error ("unaligned device size"); # endif @@ -321,7 +335,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) if (stat (map[drive].device, &st) < 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device); - disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS; + disk->total_sectors = st.st_size >> disk->log_sector_size; grub_util_info ("the size of %s is %lu", name, disk->total_sectors); @@ -760,7 +774,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, loff_t *, res, uint, wh); - offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS; + offset = (loff_t) sector << disk->log_sector_size; if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) { grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device); @@ -770,7 +784,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) } #else { - off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS; + off_t offset = (off_t) sector << disk->log_sector_size; if (lseek (fd, offset, SEEK_SET) != offset) { @@ -870,20 +884,21 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, sectors that are read together with the MBR in one read. It should only remap the MBR, so we split the read in two parts. -jochen */ - if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) + if (nread (fd, buf, (1 << disk->log_sector_size)) + != (1 << disk->log_sector_size)) { grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device); close (fd); return grub_errno; } - buf += GRUB_DISK_SECTOR_SIZE; + buf += (1 << disk->log_sector_size); size--; } #endif /* __linux__ */ - if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS) - != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (nread (fd, buf, size << disk->log_sector_size) + != (ssize_t) (size << disk->log_sector_size)) grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device); return grub_errno; @@ -916,8 +931,8 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, if (fd < 0) return grub_errno; - if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS) - != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (nwrite (fd, buf, size << disk->log_sector_size) + != (ssize_t) (size << disk->log_sector_size)) grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device); return grub_errno; diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index 31a0a0707..c2e726bd7 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -90,8 +90,11 @@ grub_partition_msdos_iterate (grub_disk_t disk, { e = mbr.entries + p.index; - p.start = p.offset + grub_le_to_cpu32 (e->start) - delta; - p.len = grub_le_to_cpu32 (e->length); + p.start = p.offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - delta; + p.len = grub_le_to_cpu32 (e->length) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); p.msdostype = e->type; grub_dprintf ("partition", @@ -126,7 +129,9 @@ grub_partition_msdos_iterate (grub_disk_t disk, if (grub_msdos_partition_is_extended (e->type)) { - p.offset = ext_offset + grub_le_to_cpu32 (e->start); + p.offset = ext_offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); if (! ext_offset) ext_offset = p.offset; @@ -204,8 +209,11 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, e = mbr.entries + i; if (!grub_msdos_partition_is_empty (e->type) - && end > offset + grub_le_to_cpu32 (e->start)) - end = offset + grub_le_to_cpu32 (e->start); + && end > offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) + end = offset + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); /* If this is a GPT partition, this MBR is just a dummy. */ if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0) @@ -219,7 +227,9 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, if (grub_msdos_partition_is_extended (e->type)) { - offset = ext_offset + grub_le_to_cpu32 (e->start); + offset = ext_offset + + (grub_le_to_cpu32 (e->start) + << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); if (! ext_offset) ext_offset = offset; diff --git a/include/grub/disk.h b/include/grub/disk.h index 66db1149a..b46d6670a 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -100,6 +100,9 @@ struct grub_disk /* The total number of sectors. */ grub_uint64_t total_sectors; + /* Logarithm of sector size. */ + unsigned int log_sector_size; + /* The id used by the disk cache manager. */ unsigned long id; @@ -132,9 +135,10 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t; /* The maximum number of disk caches. */ #define GRUB_DISK_CACHE_NUM 1021 -/* The size of a disk cache in sector units. */ -#define GRUB_DISK_CACHE_SIZE 8 -#define GRUB_DISK_CACHE_BITS 3 +/* The size of a disk cache in 512B units. Must be at least as big as the + largest supported sector size, currently 16K. */ +#define GRUB_DISK_CACHE_BITS 6 +#define GRUB_DISK_CACHE_SIZE (1 << GRUB_DISK_CACHE_BITS) /* Return value of grub_disk_get_size() in case disk size is unknown. */ #define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL From 421284f2998aa3e9134372379a2bd03de08a2740 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 30 Mar 2011 10:19:08 +0100 Subject: [PATCH 089/673] * docs/grub.texi (Simple configuration): Update GRUB_GFXMODE documentation. --- ChangeLog.vbe-autodetect | 2 ++ docs/grub.texi | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 3341e8cc3..6308e5793 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -29,3 +29,5 @@ * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This is more appropriate on a wider range of platforms than 640x480. + * docs/grub.texi (Simple configuration): Update GRUB_GFXMODE + documentation. diff --git a/docs/grub.texi b/docs/grub.texi index 54a2d8791..885bb4731 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1140,7 +1140,8 @@ listed in @file{/boot/grub/video.lst}. Set the resolution used on the @samp{gfxterm} graphical terminal. Note that you can only use modes which your graphics card supports via VESA BIOS Extensions (VBE), so for example native LCD panel resolutions may not be -available. The default is @samp{640x480}. +available. The default is @samp{auto}, which tries to select a preferred +resolution. @item GRUB_BACKGROUND Set a background image for use with the @samp{gfxterm} graphical terminal. From 6dc14451f4769d68d96c40f66644fe52e5a29d39 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:12:44 -0300 Subject: [PATCH 090/673] Iterate sockets to see if we expect this packet. Let the App layer to remove its own header. Add packet to socket list if it contains data. Undesired packets are freed. --- grub-core/net/udp.c | 62 ++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index a73431f83..16b2011ff 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -5,63 +5,51 @@ #include grub_err_t -grub_net_send_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *nb, grub_uint16_t srcport, - grub_uint16_t destport) +grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb) { struct udphdr *udph; - struct grub_net_network_level_interface *inf; - grub_err_t err; - grub_net_network_level_address_t gateway; - - err = grub_net_route_address (*target, &gateway, &inf); - if (err) - return err; grub_netbuff_push (nb,sizeof(*udph)); udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (srcport); - udph->dst = grub_cpu_to_be16 (destport); + udph->src = grub_cpu_to_be16 (socket->in_port); + udph->dst = grub_cpu_to_be16 (socket->out_port); /* No chechksum. */ udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - return grub_net_send_ip_packet (inf, target, nb); + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb); } grub_err_t -grub_net_recv_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *buf, - grub_uint16_t srcport, grub_uint16_t destport) +grub_net_recv_udp_packet (struct grub_net_buff *nb) { - grub_err_t err; - struct grub_net_packet *pkt; - struct grub_net_network_level_interface *inf; - grub_net_network_level_address_t gateway; + //grub_err_t err; + struct udphdr *udph; + grub_net_socket_t sock; + udph = (struct udphdr *) nb->data; + grub_netbuff_pull (nb, sizeof (*udph)); - err = grub_net_route_address (*target, &gateway, &inf); - if (err) - return err; - - (void) srcport; - - err = grub_net_recv_ip_packets (inf); - - FOR_NET_NL_PACKETS(inf, pkt) + FOR_NET_SOCKETS(sock) { - struct udphdr *udph; - struct grub_net_buff *nb = pkt->nb; - udph = (struct udphdr *) nb->data; - if (grub_be_to_cpu16 (udph->dst) == destport) + if (grub_be_to_cpu16 (udph->dst) == sock->in_port) { - grub_net_remove_packet (pkt); - grub_netbuff_pull (nb, sizeof(*udph)); - grub_memcpy (buf, nb, sizeof (buf)); - + if (sock->status == 0) + sock->out_port = udph->src; + + + /* App protocol remove its own reader. */ + sock->app->read (sock,nb); + + /* If there is data, puts packet in socket list */ + if ((nb->tail - nb->data) > 0) + grub_net_put_packet (sock->packs, nb); + else + grub_netbuff_free (nb); return GRUB_ERR_NONE; } } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } From d5e0a358f1252bb4af4002a9589e89ec70f0944c Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:14:16 -0300 Subject: [PATCH 091/673] Correctly match network. --- grub-core/net/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 54663f4b0..ab6b39261 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -105,7 +105,7 @@ match_net (const grub_net_network_level_netaddress_t *net, { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { - grub_int32_t mask = (1 << net->ipv4.masksize) - 1; + grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize); return ((grub_be_to_cpu32 (net->ipv4.base) & mask) == (grub_be_to_cpu32 (addr->ipv4) & mask)); } From fbdee79b1729f432e4673a5088b20509be5e032b Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:22:41 -0300 Subject: [PATCH 092/673] Add generic functions to read and seek in network file. Allocate socket with network and adress information. --- grub-core/net/net.c | 164 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index ab6b39261..8c9229915 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -17,8 +17,12 @@ */ #include +#include +#include +#include #include #include +#include #include #include #include @@ -40,6 +44,7 @@ struct grub_net_route struct grub_net_route *grub_net_routes = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; +struct grub_net_card_driver *grub_net_card_drivers = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static inline void @@ -538,6 +543,7 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), } grub_net_app_level_t grub_net_app_level_list; +struct grub_net_socket *grub_net_sockets; static grub_net_t grub_net_open_real (const char *name) @@ -570,6 +576,159 @@ grub_net_open_real (const char *name) return NULL; } +static grub_err_t +grub_net_file_open_real (struct grub_file *file, const char *name) +{ + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + grub_net_socket_t socket; + static int port = 25300; + + err = grub_net_resolve_address (file->device->net->name + + sizeof (file->device->net->protocol->name) + 1, &addr); + if (err) + return err; + + err = grub_net_route_address (addr, &gateway, &inf); + if (err) + return err; + + if ((socket = (grub_net_socket_t) grub_malloc (sizeof (*socket))) == NULL) + return GRUB_ERR_OUT_OF_MEMORY; + + socket->inf = inf; + socket->out_nla = addr; + socket->in_port = port++; + socket->status = 0; + socket->app = file->device->net->protocol; + socket->packs = NULL; + file->device->net->socket = socket; + grub_net_socket_register (socket); + + if ((err = file->device->net->protocol->open (file,name))) + goto fail; + + return GRUB_ERR_NONE; +fail: + grub_net_socket_unregister (socket); + grub_free (socket); + return err; + +} + +static grub_err_t +receive_packets (struct grub_net_card *card) +{ + /* Maybe should be better have a fixed number of packets for each card + and just mark them as used and not used. */ + struct grub_net_buff *nb; + nb = grub_netbuff_alloc (1500); + if (!nb) + return grub_errno; + + card->driver->recv (card, nb); + return GRUB_ERR_NONE; +} + +void +grub_net_pool_cards (unsigned time) +{ + struct grub_net_card *card; + grub_uint64_t start_time; + FOR_NET_CARDS (card) + { + start_time = grub_get_time_ms (); + while( (grub_get_time_ms () - start_time) < time) + receive_packets (card); + } +} + +static grub_ssize_t +process_packets (grub_file_t file, void *buf, grub_size_t len, + void *NESTED_FUNC_ATTR (hook) (void *dest, const void *src, grub_size_t n)) +{ + grub_net_socket_t sock = file->device->net->socket; + struct grub_net_buff *nb; + char *ptr = (char *) buf; + grub_size_t amount, total = 0; + int try = 0; + while (try <= 3) + { + while (sock->packs->first) + { + try = 0; + nb = sock->packs->first->nb; + amount = (grub_size_t)(len <= (grub_size_t) (nb->tail - nb->data))? len :(grub_size_t)(nb->tail - nb->data); + len -= amount; + total += amount; + hook (ptr, nb->data, amount); + ptr += amount; + if (amount == (grub_size_t) (nb->tail - nb->data)) + { + grub_netbuff_free (nb); + grub_net_remove_packet (sock->packs->first); + } + else + nb->data += amount; + + if (!len) + return total; + } + if (sock->status == 1) + { + try++; + grub_net_pool_cards (200); + } + else + return total; + } + return total; +} + + +/* Read from the packets list*/ +static grub_ssize_t +grub_net_read_real (grub_file_t file, void *buf, grub_size_t len ) +{ + auto void *NESTED_FUNC_ATTR memcpy_hook (void *dest, const void *src, grub_size_t n); + void *NESTED_FUNC_ATTR memcpy_hook (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), + grub_size_t n __attribute__ ((unused))) + { + return grub_memcpy (dest, src, n); + } + return process_packets (file, buf, len, memcpy_hook); +} + +/* Read from the packets list*/ +static grub_err_t +grub_net_seek_real (struct grub_file *file, grub_off_t offset) +{ + grub_net_socket_t sock = file->device->net->socket; + struct grub_net_buff *nb; + grub_size_t len = offset - file->offset; + + if (!len) + return GRUB_ERR_NONE; + + /* We cant seek backwards past the current packet. */ + if (file->offset > offset) + { + nb = sock->packs->first->nb; + return grub_netbuff_push (nb, file->offset - offset); + } + + auto void *NESTED_FUNC_ATTR dummy (void *dest, const void *src, grub_size_t n); + void *NESTED_FUNC_ATTR dummy (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), + grub_size_t n __attribute__ ((unused))) + { + return NULL; + } + process_packets (file, NULL, len, dummy); + return GRUB_ERR_NONE; +} + static char * grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), const char *val __attribute__ ((unused))) @@ -857,6 +1016,9 @@ GRUB_MOD_INIT(net) N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); grub_net_open = grub_net_open_real; + grub_file_net_open = grub_net_file_open_real; + grub_file_net_read = grub_net_read_real; + grub_file_net_seek = grub_net_seek_real; } GRUB_MOD_FINI(net) @@ -869,4 +1031,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_getdhcp); grub_net_open = NULL; + grub_file_net_read = NULL; + grub_file_net_open = NULL; } From 6ccb7a35e61a2853549dc90fe00981aebc09571b Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:26:27 -0300 Subject: [PATCH 093/673] Remove unused file. --- grub-core/net/device.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 grub-core/net/device.c diff --git a/grub-core/net/device.c b/grub-core/net/device.c deleted file mode 100644 index e69de29bb..000000000 From 6d5c2ed68a8b5f126c2eec349e39496af86d63ab Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:27:06 -0300 Subject: [PATCH 094/673] Use nb in all function declarations for consistency. --- grub-core/net/netbuff.c | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index cc366ae09..be9fc9de2 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -22,43 +22,43 @@ #include -grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_put (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->tail += len; - if (net_buff->tail > net_buff->end) + nb->tail += len; + if (nb->tail > nb->end) return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_unput (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->tail -= len; - if (net_buff->tail < net_buff->head) + nb->tail -= len; + if (nb->tail < nb->head) return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_push (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->data -= len; - if (net_buff->data < net_buff->head) + nb->data -= len; + if (nb->data < nb->head) return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_pull (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->data += len; - if (net_buff->data > net_buff->end) + nb->data += len; + if (nb->data > nb->end) return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range."); return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len) +grub_err_t grub_netbuff_reserve (struct grub_net_buff *nb ,grub_size_t len) { - net_buff->data += len; - net_buff->tail += len; - if ((net_buff->tail > net_buff->end) || (net_buff->data > net_buff->end)) + nb->data += len; + nb->tail += len; + if ((nb->tail > nb->end) || (nb->data > nb->end)) return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range."); return GRUB_ERR_NONE; } @@ -73,22 +73,23 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) len = ALIGN_UP (len,NETBUFF_ALIGN); data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); + if (!data) + return NULL; nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); nb->head = nb->data = nb->tail = data; - nb->end = (char *) nb; - + nb->end = (char *) nb; return nb; } -grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff) +grub_err_t grub_netbuff_free (struct grub_net_buff *nb) { - grub_free (net_buff->head); + grub_free (nb->head); return 0; } -grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff) +grub_err_t grub_netbuff_clear (struct grub_net_buff *nb) { - net_buff->data = net_buff->tail = net_buff->head; + nb->data = nb->tail = nb->head; return 0; } From 59b361a2df22426b6d34870bdbcc312641414369 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:39:06 -0300 Subject: [PATCH 095/673] Use bootp packet to set prefix and card address. --- grub-core/kern/ieee1275/init.c | 19 +++++- grub-core/kern/ieee1275/openfw.c | 1 + grub-core/net/drivers/ieee1275/ofnet.c | 89 +++++++++++++++++--------- include/grub/ieee1275/ofnet.h | 6 +- 4 files changed, 77 insertions(+), 38 deletions(-) diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 682a8b5a4..ad34ea188 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -74,7 +76,22 @@ grub_machine_set_prefix (void) char bootpath[64]; /* XXX check length */ char *filename; char *prefix; - + grub_bootp_t bootp_pckt; + char addr[GRUB_NET_MAX_STR_ADDR_LEN]; + + /* Set the net prefix when possible. */ + if (grub_getbootp && (bootp_pckt = grub_getbootp())) + { + grub_uint32_t n = bootp_pckt->siaddr; + grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + ((n >> 24) & 0xff), ((n >> 16) & 0xff), + ((n >> 8) & 0xff), ((n >> 0) & 0xff)); + prefix = grub_xasprintf ("(tftp,%s)%s", addr,grub_prefix); + grub_env_set ("prefix", prefix); + grub_free (prefix); + return; + } + if (grub_prefix[0]) { grub_env_set ("prefix", grub_prefix); diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 3c228f574..fed4f7e76 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -28,6 +28,7 @@ #include #include +grub_bootp_t (*grub_getbootp) (void); enum grub_ieee1275_parse_type { GRUB_PARSE_FILENAME, diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index ce5276efe..10de81bc7 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -78,12 +78,11 @@ bootp_response_properties[] = { .name = "bootpreply-packet", .offset = 0x2a }, }; - -grub_bootp_t -grub_getbootp( void ) +static grub_bootp_t +grub_getbootp_real ( void ) { - grub_bootp_t packet = grub_malloc(sizeof *packet); - void *bootp_response = NULL; + grub_bootp_t packet = grub_malloc (sizeof *packet); + char *bootp_response; grub_ssize_t size; unsigned int i; @@ -94,30 +93,27 @@ grub_getbootp( void ) break; if (size < 0) - { - grub_printf("Error to get bootp\n"); return NULL; - } + bootp_response = grub_malloc (size); if (grub_ieee1275_get_property (grub_ieee1275_chosen, bootp_response_properties[i].name, bootp_response , size, 0) < 0) - { - grub_printf("Error to get bootp\n"); return NULL; - } - packet = (void *) ((int)bootp_response - + bootp_response_properties[i].offset); + grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet)); + grub_free (bootp_response); return packet; } +static void grub_ofnet_findcards (void) { struct grub_net_card *card; + grub_ieee1275_phandle_t devhandle; + grub_net_link_level_address_t lla; int i = 0; - auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) @@ -128,53 +124,82 @@ void grub_ofnet_findcards (void) card = grub_malloc (sizeof (struct grub_net_card)); struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); ofdata->path = grub_strdup (alias->path); - card->data = ofdata; + + grub_ieee1275_finddevice (ofdata->path, &devhandle); + + if (grub_ieee1275_get_integer_property + (devhandle, "max-frame-size", &(ofdata->mtu), sizeof (ofdata->mtu), 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + + if (grub_ieee1275_get_property (devhandle, "mac-address", &(lla.mac), 6, 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + + lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + card->default_address = lla; + + card->data = ofdata; + card->flags = 0; card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); grub_net_card_register (card); } return 0; } - /*Look at all nodes for devices of the type network*/ + /* Look at all nodes for devices of the type network. */ grub_ieee1275_devices_iterate (search_net_devices); - } +static void grub_ofnet_probecards (void) { struct grub_net_card *card; struct grub_net_card_driver *driver; + struct grub_net_network_level_interface *inter; + grub_bootp_t bootp_pckt; + grub_net_network_level_address_t addr; + grub_net_network_level_netaddress_t net; - /*Assign correspondent driver for each device. */ + /* Assign correspondent driver for each device. */ FOR_NET_CARDS (card) { FOR_NET_CARD_DRIVERS (driver) { if (driver->init(card) == GRUB_ERR_NONE) - { - card->driver = driver; - continue; - } + { + card->driver = driver; + bootp_pckt = grub_getbootp (); + if (bootp_pckt) + { + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = bootp_pckt->yiaddr; + grub_net_add_addr ("bootp_cli_addr", card, addr, card->default_address, 0); + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, "bootp_cli_addr") == 0) + break; + net.type = addr.type; + net.ipv4.base = addr.ipv4; + net.ipv4.masksize = 24; + grub_net_add_route ("bootp-router", net, inter); + } + grub_free (bootp_pckt); + break; + } } } } -GRUB_MOD_INIT(ofnet) +GRUB_MOD_INIT (ofnet) { + grub_getbootp = grub_getbootp_real; grub_net_card_driver_register (&ofdriver); - grub_ofnet_findcards(); - grub_ofnet_probecards(); - - /*init tftp stack - will be handled by module subsystem in the future*/ - tftp_ini (); - /*get bootp packet - won't be needed in the future*/ - bootp_pckt = grub_getbootp (); - grub_disknet_init(); + grub_ofnet_findcards (); + grub_ofnet_probecards (); } -GRUB_MODE_FINI(ofnet) +GRUB_MOD_FINI (ofnet) { grub_net_card_driver_unregister (&ofdriver); + grub_getbootp = NULL; } diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index ba4c62630..9a0ae29e3 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -60,14 +60,10 @@ struct grub_bootp { unsigned char chaddr [16]; /* Client hardware address */ char sname [64]; /* Server name */ char file [128]; /* Boot filename */ -// grub_uint32_t filesize ; /*File size (testing)*/ unsigned char vend [64]; }; typedef struct grub_bootp* grub_bootp_t; -char * grub_get_filestr(const char * ); -char * grub_ip2str (grub_uint32_t ip); -void grub_get_netinfo (grub_ofnet_t netinfo,grub_bootp_t packet); -grub_bootp_t grub_getbootp (void); +extern grub_bootp_t (*EXPORT_VAR (grub_getbootp)) (void); #endif /* ! GRUB_NET_HEADER */ From 457d1104f6137887a04c479ee43b5168b7733987 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:40:44 -0300 Subject: [PATCH 096/673] Add ofnet.h to Makefile.am --- grub-core/Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 050075ef8..0fdb4b1db 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -113,6 +113,7 @@ endif if COND_i386_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -148,6 +149,7 @@ endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -155,6 +157,7 @@ endif if COND_sparc64_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h From 09375846b9ea73269302e97affc85dbb3a43f1b8 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:41:37 -0300 Subject: [PATCH 097/673] Add mtu to ieee1275 driver data. --- include/grub/ieee1275/ieee1275.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 94a69d73d..87294610d 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -68,6 +68,7 @@ struct grub_ofnetcard_data { char *path; grub_ieee1275_ihandle_t handle; + grub_uint32_t mtu; }; /* Maps a device alias to a pathname. */ @@ -201,8 +202,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); -void EXPORT_FUNC(grub_ofnet_findcards) (void); -void EXPORT_FUNC(grub_ofnet_probecards) (void); char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path); #endif /* ! GRUB_IEEE1275_HEADER */ From 25f1579b4348935084a7f349b1ee6c345fe83d39 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 1 Apr 2011 05:42:34 -0300 Subject: [PATCH 098/673] Adapt protocols to new network struct. --- Makefile.util.def | 1 + grub-core/kern/file.c | 29 ++++++- grub-core/kern/fs.c | 2 +- grub-core/net/arp.c | 100 ++++++++++++------------ grub-core/net/ethernet.c | 18 ++--- grub-core/net/i386/pc/pxe.c | 2 +- grub-core/net/ip.c | 36 +++++---- grub-core/net/tftp.c | 151 ++++++++++++++++++------------------ include/grub/net.h | 125 ++++++++++++++++++++++------- include/grub/net/arp.h | 3 +- include/grub/net/device.h | 7 -- include/grub/net/ethernet.h | 4 +- include/grub/net/ip.h | 2 +- include/grub/net/tftp.h | 12 ++- include/grub/net/udp.h | 12 +-- 15 files changed, 296 insertions(+), 208 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 579fd0714..0f7643b58 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -37,6 +37,7 @@ library = { common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; common = grub-core/net/net.c; + common = grub-core/net/netbuff.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/loopback.c; common = grub-core/disk/lvm.c; diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index c93fbf737..85ba8536c 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -20,10 +20,15 @@ #include #include #include +#include #include #include #include +grub_ssize_t (*grub_file_net_read) (grub_file_t file, void *buf, grub_size_t len) = NULL; +grub_err_t (*grub_file_net_open) (struct grub_file *file, const char *name) = NULL; +grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; + grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX]; @@ -85,6 +90,13 @@ grub_file_open (const char *name) file->device = device; + if (device->net && grub_file_net_open) + { + if (grub_file_net_open (file, file_name)) + goto fail; + return file; + } + if (device->disk && file_name[0] != '/') /* This is a block list. */ file->fs = &grub_fs_blocklist; @@ -130,7 +142,7 @@ grub_file_open (const char *name) grub_ssize_t grub_file_read (grub_file_t file, void *buf, grub_size_t len) { - grub_ssize_t res; + grub_ssize_t res = 0; if (file->offset > file->size) { @@ -148,8 +160,12 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (len == 0) return 0; - - res = (file->fs->read) (file, buf, len); + if (file->device->disk) + res = (file->fs->read) (file, buf, len); + else + if (grub_file_net_read && file->device->net) + res = grub_file_net_read (file, buf, len); + if (res > 0) file->offset += res; @@ -159,6 +175,9 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) grub_err_t grub_file_close (grub_file_t file) { + if (file->device->net) + return grub_errno; + if (file->fs->close) (file->fs->close) (file); @@ -179,8 +198,12 @@ grub_file_seek (grub_file_t file, grub_off_t offset) "attempt to seek outside of the file"); return -1; } + + if (file->device->net && grub_file_net_seek) + grub_file_net_seek (file, offset); old = file->offset; file->offset = offset; + return old; } diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index c4d6efa96..7166648be 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -95,7 +95,7 @@ grub_fs_probe (grub_device_t device) } } else if (device->net) - return device->net->protocol; + return NULL; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); return 0; diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index c7b5d0573..8778a6e51 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -35,36 +35,40 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_net_link_level_address_t *hw_addr) { struct arp_entry *entry; - struct grub_net_buff *nb; + struct grub_net_buff nb; struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; - grub_uint8_t *aux, i; + char *aux, arp_data[128]; + int i; - /* Check cache table */ + /* Check cache table. */ entry = arp_find_entry (proto_addr); if (entry) { *hw_addr = entry->ll_address; return GRUB_ERR_NONE; } - /* Build a request packet */ - nb = grub_netbuff_alloc (2048); - if (!nb) - return grub_errno; - grub_netbuff_reserve(nb, 2048); - grub_netbuff_push(nb, sizeof(*arp_header) + 2 * (6 + 6)); - arp_header = (struct arphdr *)nb->data; + /* Build a request packet. */ + nb.head = arp_data; + nb.end = arp_data + sizeof (arp_data); + grub_netbuff_clear (&nb); + + grub_netbuff_reserve (&nb,128); + grub_netbuff_push (&nb, sizeof(*arp_header) + 2 * (6 + 4)); + arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); + /* FIXME Add support to ipv6 address. */ arp_header->hln = 6; arp_header->pln = 4; arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); - aux = (grub_uint8_t *)arp_header + sizeof(*arp_header); - /* Sender hardware address */ - grub_memcpy(aux, &inf->hwaddress.mac, 6); + aux = (char *) arp_header + sizeof (*arp_header); + /* Sender hardware address. */ + grub_memcpy (aux, &inf->hwaddress.mac, 6); + aux += 6; /* Sender protocol address */ - grub_memcpy(aux, &inf->address.ipv4, 4); + grub_memcpy (aux, &inf->address.ipv4, 4); aux += 4; /* Target hardware address */ for(i = 0; i < 6; i++) @@ -72,49 +76,40 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, aux += 6; /* Target protocol address */ grub_memcpy(aux, &proto_addr->ipv4, 4); - grub_memset (&target_hw_addr.mac, 0xff, 6); - send_ethernet_packet (inf, nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); - grub_netbuff_clear(nb); - grub_netbuff_reserve(nb, 2048); - - grub_uint64_t start_time, current_time; - start_time = grub_get_time_ms(); - do + send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); + for (i = 0; i < 3; i++) { - grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_ARP); - /* Now check cache table again */ - entry = arp_find_entry(proto_addr); + entry = arp_find_entry (proto_addr); if (entry) - { - grub_memcpy(hw_addr, &entry->ll_address, sizeof (*hw_addr)); - grub_netbuff_clear(nb); - return GRUB_ERR_NONE; - } - current_time = grub_get_time_ms(); - if (current_time - start_time > 3000) - break; - } while (! entry); - grub_netbuff_clear(nb); + { + grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr)); + return GRUB_ERR_NONE; + } + grub_net_pool_cards (200); + + } + return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address."); } grub_err_t -grub_net_arp_receive (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb) +grub_net_arp_receive (struct grub_net_buff *nb) { struct arphdr *arp_header = (struct arphdr *)nb->data; struct arp_entry *entry; grub_uint8_t *sender_hardware_address, *sender_protocol_address; grub_uint8_t *target_hardware_address, *target_protocol_address; grub_net_network_level_address_t hwaddress; + struct grub_net_network_level_interface *inf; sender_hardware_address = (grub_uint8_t *) arp_header + sizeof(*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4); + /* Check if the sender is in the cache table */ entry = arp_find_entry(&hwaddress); /* Update sender hardware address */ @@ -134,21 +129,24 @@ grub_net_arp_receive (struct grub_net_network_level_interface *inf, new_table_entry = 0; } - /* Am I the protocol address target? */ - if (grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6) == 0 - && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + FOR_NET_NETWORK_LEVEL_INTERFACES(inf) { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln); - grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy(aux.mac, sender_protocol_address, 6); - grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy(target_protocol_address, aux.mac, arp_header->pln); - /* Change operation to REPLY and send packet */ - arp_header->op = grub_be_to_cpu16 (ARP_REPLY); - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + /* Am I the protocol address target? */ + if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { + grub_net_link_level_address_t aux; + /* Swap hardware fields */ + grub_memcpy (target_hardware_address, sender_hardware_address, arp_header->hln); + grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); + grub_memcpy (aux.mac, sender_protocol_address, 6); + grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln); + grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); + /* Change operation to REPLY and send packet */ + arp_header->op = grub_be_to_cpu16 (ARP_REPLY); + grub_memcpy (aux.mac, target_hardware_address, 6); + send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + } } return GRUB_ERR_NONE; } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index cbda4c875..c96a65602 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -23,23 +23,20 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, eth->type = grub_cpu_to_be16 (ethertype); - return inf->card->driver->send (inf->card,nb); + return inf->card->driver->send (inf->card, nb); } grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb, - grub_uint16_t ethertype) +grub_net_recv_ethernet_packet (struct grub_net_buff *nb) { struct etherhdr *eth; struct llchdr *llch; struct snaphdr *snaph; grub_uint16_t type; - inf->card->driver->recv (inf->card, nb); eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); - grub_netbuff_pull(nb,sizeof (*eth)); + grub_netbuff_pull (nb, sizeof (*eth)); if (type <= 1500) { @@ -56,10 +53,13 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, /* ARP packet */ if (type == GRUB_NET_ETHERTYPE_ARP) - grub_net_arp_receive(inf, nb); + { + grub_net_arp_receive (nb); + grub_netbuff_free (nb); + } /* IP packet */ - if(type == GRUB_NET_ETHERTYPE_IP && ethertype == GRUB_NET_ETHERTYPE_IP) - return GRUB_ERR_NONE; + if (type == GRUB_NET_ETHERTYPE_IP) + grub_net_recv_ip_packets (nb); return GRUB_ERR_NONE; } diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index c07aa78f9..8e7f75ed8 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -292,7 +292,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)), return GRUB_ERR_NONE; } -static struct grub_fs grub_pxefs_fs = +static struct grub_net_app_protocol grub_pxefs_fs = { .name = "pxe", .dir = grub_pxefs_dir, diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 9a96ef532..d6684c29e 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, grub_net_link_level_address_t ll_target_addr; grub_err_t err; - grub_netbuff_push(nb,sizeof(*iph)); + grub_netbuff_push (nb, sizeof(*iph)); iph = (struct iphdr *) nb->data; iph->verhdrlen = ((4 << 4) | 5); @@ -49,17 +50,15 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, iph->chksum = 0 ; iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - /* Determine link layer target address via ARP */ - err = grub_net_arp_resolve(inf, target, &ll_target_addr); + /* Determine link layer target address via ARP. */ + err = grub_net_arp_resolve (inf, target, &ll_target_addr); if (err) return err; - return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); } - +/* static int -ip_filter (struct grub_net_buff *nb, - struct grub_net_network_level_interface *inf) +ip_filter (struct grub_net_buff *nb) { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; @@ -80,15 +79,22 @@ ip_filter (struct grub_net_buff *nb, } return 1; } - +*/ grub_err_t -grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf) +grub_net_recv_ip_packets (struct grub_net_buff *nb) { - struct grub_net_buff *nb; - nb = grub_netbuff_alloc (2048); - if (!nb) - return grub_errno; - grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_IP); - ip_filter (nb, inf); + struct iphdr *iph = (struct iphdr *) nb->data; + grub_netbuff_pull (nb, sizeof (*iph)); + + switch (iph->protocol) + { + case IP_UDP: + return grub_net_recv_udp_packet (nb); + break; + default: + grub_netbuff_free (nb); + break; + } + return GRUB_ERR_NONE; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 16b60eeb6..cafb30585 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -14,26 +14,23 @@ tftp_open (struct grub_file *file, const char *filename) { struct tftphdr *tftph; char *rrq; - char *ptr; + int i; int rrqlen; - int hdrlen; - struct grub_net_buff *nb; - grub_net_network_level_address_t addr; + int hdrlen; + char open_data[1500]; + struct grub_net_buff nb; + tftp_data_t data = grub_malloc (sizeof *data); grub_err_t err; + + file->device->net->socket->data = (void *) data; + nb.head = open_data; + nb.end = open_data + sizeof (open_data); + grub_netbuff_clear (&nb); - err = grub_net_resolve_address (file->device->net->name - + sizeof ("tftp,") - 1, &addr); - if (err) - return err; + grub_netbuff_reserve (&nb,1500); + grub_netbuff_push (&nb,sizeof (*tftph)); - nb = grub_netbuff_alloc (2048); - if (!nb) - return grub_errno; - - grub_netbuff_reserve (nb,2048); - grub_netbuff_push (nb,sizeof (*tftph)); - - tftph = (struct tftphdr *) nb->data; + tftph = (struct tftphdr *) nb.data; rrq = (char *) tftph->u.rrq; rrqlen = 0; @@ -64,89 +61,93 @@ tftp_open (struct grub_file *file, const char *filename) rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen)); + grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); - err = grub_net_send_udp_packet (&addr, - nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + file->device->net->socket->out_port = TFTP_SERVER_PORT; + + err = grub_net_send_udp_packet (file->device->net->socket, &nb); if (err) return err; - /* Receive OACK. */ - grub_netbuff_clear (nb); - grub_netbuff_reserve (nb,2048); - - do + /* Receive OACK packet. */ + for ( i = 0; i < 3; i++) { - err = grub_net_recv_udp_packet (&addr, nb, - TFTP_CLIENT_PORT, TFTP_SERVER_PORT); - if (err) - return err; + grub_net_pool_cards (100); + if (grub_errno) + return grub_errno; + if (file->device->net->socket->status != 0) + break; + /* Retry. */ + //err = grub_net_send_udp_packet (file->device->net->socket, &nb); + // if (err) + // return err; } - while (nb->tail == nb->data); - file->size = 0; + if (file->device->net->socket->status == 0) + return grub_error (GRUB_ERR_TIMEOUT,"Time out opening tftp."); + file->size = data->file_size; - for (ptr = nb->data; ptr < nb->tail; ) - grub_printf ("%02x ", *ptr); - - for (ptr = nb->data; ptr < nb->tail; ) - { - if (grub_memcmp (ptr, "tsize\0=", sizeof ("tsize\0=") - 1) == 0) - { - file->size = grub_strtoul (ptr + sizeof ("tsize\0=") - 1, 0, 0); - grub_errno = GRUB_ERR_NONE; - } - while (ptr < nb->tail && *ptr) - ptr++; - ptr++; - } return GRUB_ERR_NONE; } -static grub_ssize_t -tftp_receive (struct grub_file *file, char *buf, grub_size_t len) +static grub_err_t +tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) { struct tftphdr *tftph; - // char *token,*value,*temp; + char nbdata[128]; + tftp_data_t data = sock->data; grub_err_t err; - grub_net_network_level_address_t addr; - struct grub_net_buff nb; + char *ptr; + struct grub_net_buff nb_ack; - err = grub_net_resolve_address (file->device->net->name - + sizeof ("tftp,") - 1, &addr); - if (err) - return err; + nb_ack.head = nbdata; + nb_ack.end = nbdata + sizeof (nbdata); - grub_net_recv_udp_packet (&addr, &nb, - TFTP_CLIENT_PORT, TFTP_SERVER_PORT); - - tftph = (struct tftphdr *) nb.data; + + tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) { + case TFTP_OACK: + for (ptr = nb->data; ptr < nb->tail; ) + { + if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) + data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, 0, 0); + while (ptr < nb->tail && *ptr) + ptr++; + ptr++; + } + sock->status = 1; + data->block = 0; + grub_netbuff_clear(nb); + break; case TFTP_DATA: - grub_netbuff_pull (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); - // if (tftph->u.data.block == block + 1) - //{ - // block = tftph->u.data.block; - grub_memcpy (buf, nb.data, len); - //} - //else - //grub_netbuff_clear(&nb); - break; + grub_netbuff_pull (nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); + + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + { + data->block++; + if (nb->tail - nb->data < 1024) + sock->status = 2; + } + else + grub_netbuff_clear(nb); + + break; case TFTP_ERROR: - grub_netbuff_clear (&nb); + grub_netbuff_clear (nb); return grub_error (GRUB_ERR_IO, (char *)tftph->u.err.errmsg); + break; } + grub_netbuff_clear (&nb_ack); + grub_netbuff_reserve (&nb_ack,128); + grub_netbuff_push (&nb_ack,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); - nb.data = nb.tail = nb.end; - - grub_netbuff_push (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); - - tftph = (struct tftphdr *) nb.data; + tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - // tftph->u.ack.block = block; + tftph->u.ack.block = data->block; - return grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT); + err = grub_net_send_udp_packet (sock, &nb_ack); + return err; } static grub_err_t @@ -155,7 +156,7 @@ tftp_close (struct grub_file *file __attribute__ ((unused))) return 0; } -static struct grub_fs grub_tftp_protocol = +static struct grub_net_app_protocol grub_tftp_protocol = { .name = "tftp", .open = tftp_open, diff --git a/include/grub/net.h b/include/grub/net.h index 20bf3c0e6..37b258f36 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -23,19 +23,10 @@ #include #include #include +#include #include #include -typedef struct grub_fs *grub_net_app_level_t; - -typedef struct grub_net -{ - char *name; - grub_net_app_level_t protocol; -} *grub_net_t; - -extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); - typedef enum grub_link_level_protocol_id { GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET @@ -75,6 +66,37 @@ struct grub_net_card_driver grub_size_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); }; +extern struct grub_net_card_driver *grub_net_card_drivers; + +static inline void +grub_net_card_driver_register (struct grub_net_card_driver *driver) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +static inline void +grub_net_card_driver_unregister (struct grub_net_card_driver *driver) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_card_drivers), + GRUB_AS_LIST (driver)); +} + +#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next) + +typedef struct grub_net_packet +{ + struct grub_net_packet *next; + struct grub_net_packet *prev; + struct grub_net_packets *up; + struct grub_net_buff *nb; +} grub_net_packet_t; + +typedef struct grub_net_packets +{ + grub_net_packet_t *first; + grub_net_packet_t *last; +} grub_net_packets_t; struct grub_net_card { @@ -118,20 +140,6 @@ typedef struct grub_net_network_level_netaddress }; } grub_net_network_level_netaddress_t; -typedef struct grub_net_packet -{ - struct grub_net_packet *next; - struct grub_net_packet *prev; - struct grub_net_packets *up; - struct grub_net_buff *nb; -} grub_net_packet_t; - -typedef struct grub_net_packets -{ - struct grub_net_packet *first; - struct grub_net_packet *last; -} grub_net_packets_t; - #define FOR_PACKETS(cont,var) for (var = (cont).first; var; var = var->next) static inline grub_err_t @@ -172,6 +180,66 @@ grub_net_remove_packet (grub_net_packet_t *pkt) pkt->up->last = pkt->prev; } +typedef struct grub_net_app_protocol *grub_net_app_level_t; + +typedef struct grub_net_socket *grub_net_socket_t; + +struct grub_net_app_protocol +{ + struct grub_net_app_protocol *next; + char *name; + grub_err_t (*dir) (grub_device_t device, const char *path, + int (*hook) (const char *filename, + const struct grub_dirhook_info *info)); + grub_err_t (*open) (struct grub_file *file, const char *filename); + grub_err_t (*read) (grub_net_socket_t sock, struct grub_net_buff *nb); + grub_err_t (*close) (struct grub_file *file); + grub_err_t (*label) (grub_device_t device, char **label); +}; + +struct grub_net_socket +{ + struct grub_net_socket *next; + int status; + int in_port; + int out_port; + grub_net_app_level_t app; + grub_net_network_level_address_t out_nla; + struct grub_net_network_level_interface *inf; + grub_net_packets_t *packs; + void *data; +}; + +extern struct grub_net_socket *grub_net_sockets; + +static inline void +grub_net_socket_register (grub_net_socket_t socket) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets), + GRUB_AS_LIST (socket)); +} + +static inline void +grub_net_socket_unregister (grub_net_socket_t socket) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets), + GRUB_AS_LIST (socket)); +} + +#define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next) + +typedef struct grub_net +{ + char *name; + grub_net_app_level_t protocol; + grub_net_socket_t socket; +} *grub_net_t; + +extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); +extern grub_ssize_t (*EXPORT_VAR (grub_file_net_read)) (grub_file_t file, void *buf, grub_size_t len); +extern grub_err_t (*EXPORT_VAR (grub_file_net_open)) (struct grub_file *file, const char *name); +extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); + struct grub_net_network_level_interface { struct grub_net_network_level_interface *next; @@ -182,7 +250,6 @@ struct grub_net_network_level_interface grub_net_interface_flags_t flags; struct grub_net_bootp_ack *dhcp_ack; grub_size_t dhcp_acklen; - grub_net_packets_t nl_pending; void *data; }; @@ -354,7 +421,7 @@ grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *in grub_net_packet_handler_t handler); grub_err_t -grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf); +grub_net_recv_ip_packets (struct grub_net_buff *nb); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, @@ -363,4 +430,10 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, #define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var) +void +grub_net_pool_cards (unsigned time); + +void +hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); + #endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 691fda307..c60ea333f 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -27,8 +27,7 @@ struct arphdr { grub_uint16_t op; } __attribute__ ((packed)); -extern grub_err_t grub_net_arp_receive(struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb); +extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb); extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *addr, diff --git a/include/grub/net/device.h b/include/grub/net/device.h index 9f1b9bf1d..e69de29bb 100644 --- a/include/grub/net/device.h +++ b/include/grub/net/device.h @@ -1,7 +0,0 @@ -struct grub_net_card -{ - struct grub_net_card *next; - char *name; - struct grub_net_card_driver *driver; - void *data; -}; diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 7a0235be6..7ff7a4562 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -52,8 +52,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_net_link_level_address_t target_addr, grub_uint16_t ethertype); grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb, - grub_uint16_t ethertype); +grub_net_recv_ethernet_packet (struct grub_net_buff *nb); #endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 6f748bbf3..cb8481a7d 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -26,7 +26,7 @@ struct ip6hdr grub_uint8_t daddr[16]; } __attribute__ ((packed)); -#define IP_UDP 17 /* UDP protocol */ +#define IP_UDP 0x11 /* UDP protocol */ #define IP_BROADCAST 0xFFFFFFFF grub_uint16_t ipchksum(void *ipv, int len); diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h index 1f1c48616..c67380817 100644 --- a/include/grub/net/tftp.h +++ b/include/grub/net/tftp.h @@ -14,7 +14,6 @@ /* IP port for the TFTP server */ #define TFTP_SERVER_PORT 69 -#define TFTP_CLIENT_PORT 26300 /* We define these based on what's in arpa/tftp.h. We just like our @@ -40,10 +39,17 @@ #define TFTP_EBADID 5 /* unknown transfer ID */ #define TFTP_EEXISTS 6 /* file already exists */ #define TFTP_ENOUSER 7 /* no such user */ -#define TFTP_DEFAULT_FILENAME "kernel" /* * own here because this is cleaner, and maps to the same data layout. * */ + +typedef struct tftp_data + { + int file_size; + int block; + } *tftp_data_t; + + struct tftphdr { grub_uint16_t opcode; union { @@ -65,6 +71,4 @@ struct tftphdr { } u; } __attribute__ ((packed)) ; -void tftp_ini(void); -void tftp_fini(void); #endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index f1992467d..86311ccf1 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -12,20 +12,12 @@ struct udphdr } __attribute__ ((packed)); grub_err_t -grub_net_send_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *nb, grub_uint16_t srcport, - grub_uint16_t destport); - +grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); grub_err_t -grub_net_recv_udp_packets (struct grub_net_network_level_interface *inf); +grub_net_recv_udp_packet (struct grub_net_buff *nb); -grub_err_t -grub_net_recv_udp_packet (const grub_net_network_level_address_t *target, - struct grub_net_buff *buf, - grub_uint16_t srcport, grub_uint16_t destport); #define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var) - #endif From 6ac14e6cef8b3dc675fc09239b2101dcc4393a18 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Apr 2011 09:34:58 +0200 Subject: [PATCH 099/673] Fix EFI compilation --- grub-core/disk/efi/efidisk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 20fea956f..1bf764f10 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -537,11 +537,11 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", m, (unsigned long long) m->last_block, m->block_size); disk->total_sectors = m->last_block; - if (m->blocksize & (m->blocksize - 1) || !m->blocksize) + if (m->block_size & (m->block_size - 1) || !m->block_size) return grub_error (GRUB_ERR_IO, "invalid sector size %d", - m->blocksize); + m->block_size); for (disk->log_sector_size = 0; - (1 << disk->log_sector_size) < m->blocksize; + (1U << disk->log_sector_size) < m->block_size; disk->log_sector_size++); disk->data = d; From b0bfc5937d6232c01dbb44f7ad3135eb5aa07ff8 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 10:31:32 +0100 Subject: [PATCH 100/673] fix header comment --- util/grub-mount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index 7f0ad0d0f..c1c7ecad8 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -1,4 +1,4 @@ -/* grub-fstest.c - debug tool for filesystem driver */ +/* grub-mount.c - FUSE driver for filesystems that GRUB understands */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc. From 9aa6fcc17e7b7d6e1712a0cc400c39b44a6e6a72 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 10:38:41 +0100 Subject: [PATCH 101/673] fix duplicate --enable-grub-mkfont option; this should be --enable-grub-fuse instead --- configure.ac | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index b71aea910..12ac0e917 100644 --- a/configure.ac +++ b/configure.ac @@ -856,11 +856,11 @@ AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) -AC_ARG_ENABLE([grub-mkfont], - [AS_HELP_STRING([--enable-grub-mkfont], - [build and install the `grub-mkfont' utility (default=guessed)])]) -if test x"$enable_grub_mkfont" = xno ; then - grub_mkfont_excuse="explicitly disabled" +AC_ARG_ENABLE([grub-fuse], + [AS_HELP_STRING([--enable-grub-fuse], + [build and install the `grub-fuse' utility (default=guessed)])]) +if test x"$enable_grub_fuse" = xno ; then + grub_fuse_excuse="explicitly disabled" fi if test x"$grub_fuse_excuse" = x ; then From 897e62079e0bab32f089a44b791116493d34ef45 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 10:43:12 +0100 Subject: [PATCH 102/673] rename grub-fuse to grub-mount throughout configuration --- Makefile.util.def | 2 +- configure.ac | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 3009ff76a..cd37d0d65 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -224,7 +224,7 @@ program = { ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)' '-lfuse'; - condition = COND_GRUB_FUSE; + condition = COND_GRUB_MOUNT; }; program = { diff --git a/configure.ac b/configure.ac index 12ac0e917..d1eaa0c84 100644 --- a/configure.ac +++ b/configure.ac @@ -856,36 +856,36 @@ AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) -AC_ARG_ENABLE([grub-fuse], - [AS_HELP_STRING([--enable-grub-fuse], - [build and install the `grub-fuse' utility (default=guessed)])]) -if test x"$enable_grub_fuse" = xno ; then - grub_fuse_excuse="explicitly disabled" +AC_ARG_ENABLE([grub-mount], + [AS_HELP_STRING([--enable-grub-mount], + [build and install the `grub-mount' utility (default=guessed)])]) +if test x"$enable_grub_mount" = xno ; then + grub_mount_excuse="explicitly disabled" fi -if test x"$grub_fuse_excuse" = x ; then +if test x"$grub_mount_excuse" = x ; then AC_CHECK_LIB([fuse], [fuse_main_real], [], - [grub_fuse_excuse="need FUSE library"]) + [grub_mount_excuse="need FUSE library"]) fi -if test x"$grub_fuse_excuse" = x ; then +if test x"$grub_mount_excuse" = x ; then # Check for fuse headers. SAVED_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" AC_CHECK_HEADERS([fuse/fuse.h], [], - [grub_fuse_excuse=["need FUSE headers"]]) + [grub_mount_excuse=["need FUSE headers"]]) CPPFLAGS="$SAVED_CPPFLAGS" fi -if test x"$enable_grub_fuse" = xyes && test x"$grub_fuse_excuse" != x ; then +if test x"$enable_grub_mount" = xyes && test x"$grub_mount_excuse" != x ; then AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled]) fi -if test x"$grub_fuse_excuse" = x ; then -enable_grub_fuse=yes +if test x"$grub_mount_excuse" = x ; then +enable_grub_mount=yes else -enable_grub_fuse=no +enable_grub_mount=no fi -AC_SUBST([enable_grub_fuse]) +AC_SUBST([enable_grub_mount]) AC_ARG_ENABLE([device-mapper], [AS_HELP_STRING([--enable-device-mapper], @@ -983,7 +983,7 @@ AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) -AM_CONDITIONAL([COND_GRUB_FUSE], [test x$enable_grub_fuse = xyes]) +AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) @@ -1059,10 +1059,10 @@ echo grub-mkfont: Yes else echo grub-mkfont: No "($grub_mkfont_excuse)" fi -if [ x"$grub_fuse_excuse" = x ]; then +if [ x"$grub_mount_excuse" = x ]; then echo grub-mount: Yes else -echo grub-mount: No "($grub_fuse_excuse)" +echo grub-mount: No "($grub_mount_excuse)" fi echo "*******************************************************" ] From f387685926dc0dedfa8eace8a76955c845e25a84 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 8 Apr 2011 11:45:10 +0100 Subject: [PATCH 103/673] remove trailing full stop, for consistency with other pages --- docs/man/grub-mount.h2m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man/grub-mount.h2m b/docs/man/grub-mount.h2m index 73e7246a3..8d168982d 100644 --- a/docs/man/grub-mount.h2m +++ b/docs/man/grub-mount.h2m @@ -1,2 +1,2 @@ [NAME] -grub-mount \- export GRUB filesystem with FUSE. +grub-mount \- export GRUB filesystem with FUSE From 5b3633002b9fb95c830a4c339c64a25fa43013ea Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 10 Apr 2011 21:41:55 +0100 Subject: [PATCH 104/673] Make grub-mount exit non-zero if opening the device or filesystem fails. Translate GRUB error codes into OS error codes for FUSE. --- util/grub-mount.c | 132 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 91 insertions(+), 41 deletions(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index c1c7ecad8..efada771a 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -44,6 +44,8 @@ #include "argp.h" static char *root = NULL; +grub_device_t dev = NULL; +grub_fs_t fs = NULL; static char **images = NULL; static char *debug_str = NULL; static char **fuse_args = NULL; @@ -62,13 +64,61 @@ execute_command (char *name, int n, char **args) return (cmd->func) (cmd, n, args); } +/* Translate GRUB error numbers into OS error numbers. Print any unexpected + errors. */ +static int +translate_error (void) +{ + int ret; + + switch (grub_errno) + { + case GRUB_ERR_NONE: + ret = 0; + break; + + case GRUB_ERR_OUT_OF_MEMORY: + grub_print_error (); + ret = -ENOMEM; + break; + + case GRUB_ERR_BAD_FILE_TYPE: + /* This could also be EISDIR. Take a guess. */ + ret = -ENOTDIR; + break; + + case GRUB_ERR_FILE_NOT_FOUND: + ret = -ENOENT; + break; + + case GRUB_ERR_FILE_READ_ERROR: + case GRUB_ERR_READ_ERROR: + case GRUB_ERR_IO: + grub_print_error (); + ret = -EIO; + break; + + case GRUB_ERR_SYMLINK_LOOP: + ret = -ELOOP; + break; + + default: + grub_print_error (); + ret = -EINVAL; + break; + } + + /* Any previous errors were handled. */ + grub_errno = GRUB_ERR_NONE; + + return ret; +} + static int fuse_getattr (const char *path, struct stat *st) { char *filename, *pathname, *path2; const char *pathname_t; - grub_fs_t fs; - grub_device_t dev; struct grub_dirhook_info file_info; int file_exists = 0; @@ -104,16 +154,6 @@ fuse_getattr (const char *path, struct stat *st) } file_exists = 0; - dev = grub_device_open (0); - if (! dev) - return -1; - - fs = grub_fs_probe (dev); - if (! fs) - { - grub_device_close (dev); - return -1; - } pathname_t = grub_strchr (path, ')'); if (! pathname_t) @@ -143,10 +183,12 @@ fuse_getattr (const char *path, struct stat *st) /* It's the whole device. */ (fs->dir) (dev, path2, find_file); - grub_device_close (dev); grub_free (path2); if (!file_exists) - return -1; + { + grub_errno = GRUB_ERR_NONE; + return -ENOENT; + } st->st_dev = 0; st->st_ino = 0; st->st_mode = file_info.dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); @@ -158,10 +200,7 @@ fuse_getattr (const char *path, struct stat *st) grub_file_t file; file = grub_file_open (path); if (! file) - { - grub_print_error (); - return -1; - } + return translate_error (); st->st_size = file->size; grub_file_close (file); } @@ -171,6 +210,7 @@ fuse_getattr (const char *path, struct stat *st) st->st_blocks = (st->st_size + 511) >> 9; st->st_atime = st->st_mtime = st->st_ctime = file_info.mtimeset ? file_info.mtime : 0; + grub_errno = GRUB_ERR_NONE; return 0; } @@ -190,13 +230,11 @@ fuse_open (const char *path, struct fuse_file_info *fi __attribute__ ((unused))) grub_file_t file; file = grub_file_open (path); if (! file) - { - grub_print_error (); - return -1; - } + return translate_error (); files[first_fd++] = file; fi->fh = first_fd; files[first_fd++] = file; + grub_errno = GRUB_ERR_NONE; return 0; } @@ -205,13 +243,21 @@ fuse_read (const char *path, char *buf, size_t sz, off_t off, struct fuse_file_info *fi) { grub_file_t file = files[fi->fh]; + grub_ssize_t size; if (off > file->size) - return -1; + return -EINVAL; file->offset = off; - return grub_file_read (file, buf, sz); + size = grub_file_read (file, buf, sz); + if (size < 0) + return translate_error (); + else + { + grub_errno = GRUB_ERR_NONE; + return size; + } } static int @@ -219,6 +265,7 @@ fuse_release (const char *path, struct fuse_file_info *fi) { grub_file_close (files[fi->fh]); files[fi->fh] = NULL; + grub_errno = GRUB_ERR_NONE; return 0; } @@ -227,8 +274,6 @@ fuse_readdir (const char *path, void *buf, fuse_fill_dir_t fill, off_t off, struct fuse_file_info *fi) { char *pathname; - grub_fs_t fs; - grub_device_t dev; auto int call_fill (const char *filename, const struct grub_dirhook_info *info); @@ -238,19 +283,6 @@ fuse_readdir (const char *path, void *buf, return 0; } - dev = grub_device_open (0); - if (! dev) - { - return 1; - } - - fs = grub_fs_probe (dev); - if (! fs) - { - grub_device_close (dev); - return 1; - } - pathname = xstrdup (path); /* Remove trailing '/'. */ @@ -259,8 +291,8 @@ fuse_readdir (const char *path, void *buf, pathname[grub_strlen (pathname) - 1] = 0; (fs->dir) (dev, pathname, call_fill); - grub_device_close (dev); free (pathname); + grub_errno = GRUB_ERR_NONE; return 0; } @@ -273,7 +305,7 @@ struct fuse_operations grub_opers = { .read = fuse_read }; -static void +static grub_err_t fuse_init (void) { int i; @@ -310,6 +342,17 @@ fuse_init (void) grub_mdraid1x_init (); grub_lvm_init (); + dev = grub_device_open (0); + if (! dev) + return grub_errno; + + fs = grub_fs_probe (dev); + if (! fs) + { + grub_device_close (dev); + return grub_errno; + } + fuse_main (fuse_argc, fuse_args, &grub_opers, NULL); for (i = 0; i < num_disks; i++) @@ -328,6 +371,8 @@ fuse_init (void) grub_free (loop_name); } + + return GRUB_ERR_NONE; } static struct argp_option options[] = { @@ -447,6 +492,11 @@ main (int argc, char *argv[]) /* Do it. */ fuse_init (); + if (grub_errno) + { + grub_print_error (); + return 1; + } /* Free resources. */ grub_fini_all (); From 4ac93e6c4f8137a32a9591caf9cf7e2af234c12b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 10 Apr 2011 22:12:23 +0100 Subject: [PATCH 105/673] add grub-mount to .bzrignore --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 0cbb3f17f..d4d5987ec 100644 --- a/.bzrignore +++ b/.bzrignore @@ -44,6 +44,7 @@ grub-kbdcomp grub-macho2img grub-menulst2cfg grub-mk* +grub-mount grub-pbkdf2 grub-pe2elf grub-probe From 48fe18dcf2d2003846046a808d984a4db0a336ba Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 18:13:00 +0200 Subject: [PATCH 106/673] exfat reader --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/fs/exfat.c | 2 + grub-core/fs/fat.c | 369 ++++++++++++++++++++++++++++++++++-- 4 files changed, 359 insertions(+), 18 deletions(-) create mode 100644 grub-core/fs/exfat.c diff --git a/Makefile.util.def b/Makefile.util.def index 303baea3f..a1d00a683 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -53,6 +53,7 @@ library = { common = grub-core/fs/cpio.c; common = grub-core/fs/ext2.c; common = grub-core/fs/fat.c; + common = grub-core/fs/exfat.c; common = grub-core/fs/fshelp.c; common = grub-core/fs/hfs.c; common = grub-core/fs/hfsplus.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7c26b37e9..3ec41ac7f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -923,6 +923,11 @@ module = { common = fs/fat.c; }; +module = { + name = exfat; + common = fs/exfat.c; +}; + module = { name = fshelp; common = fs/fshelp.c; diff --git a/grub-core/fs/exfat.c b/grub-core/fs/exfat.c new file mode 100644 index 000000000..fe149ddd3 --- /dev/null +++ b/grub-core/fs/exfat.c @@ -0,0 +1,2 @@ +#define MODE_EXFAT 1 +#include "fat.c" diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 89050943c..5f7a58571 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -32,23 +32,54 @@ #define GRUB_FAT_ATTR_READ_ONLY 0x01 #define GRUB_FAT_ATTR_HIDDEN 0x02 #define GRUB_FAT_ATTR_SYSTEM 0x04 +#ifndef MODE_EXFAT #define GRUB_FAT_ATTR_VOLUME_ID 0x08 +#endif #define GRUB_FAT_ATTR_DIRECTORY 0x10 #define GRUB_FAT_ATTR_ARCHIVE 0x20 #define GRUB_FAT_MAXFILE 256 +#ifndef MODE_EXFAT #define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \ | GRUB_FAT_ATTR_HIDDEN \ | GRUB_FAT_ATTR_SYSTEM \ | GRUB_FAT_ATTR_VOLUME_ID) -#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \ - | GRUB_FAT_ATTR_HIDDEN \ - | GRUB_FAT_ATTR_SYSTEM \ - | GRUB_FAT_ATTR_DIRECTORY \ - | GRUB_FAT_ATTR_ARCHIVE \ - | GRUB_FAT_ATTR_VOLUME_ID) +#endif +static const grub_uint8_t GRUB_FAT_ATTR_VALID = (GRUB_FAT_ATTR_READ_ONLY + | GRUB_FAT_ATTR_HIDDEN + | GRUB_FAT_ATTR_SYSTEM + | GRUB_FAT_ATTR_DIRECTORY + | GRUB_FAT_ATTR_ARCHIVE +#ifndef MODE_EXFAT + | GRUB_FAT_ATTR_VOLUME_ID +#endif + ); +#ifdef MODE_EXFAT +struct grub_fat_bpb +{ + grub_uint8_t jmp_boot[3]; + grub_uint8_t oem_name[8]; + grub_uint8_t mbz[53]; + grub_uint64_t num_hidden_sectors; + grub_uint64_t num_total_sectors; + grub_uint32_t num_reserved_sectors; + grub_uint32_t sectors_per_fat; + grub_uint32_t cluster_offset; + grub_uint32_t cluster_count; + grub_uint32_t root_cluster; + grub_uint32_t num_serial; + grub_uint16_t fs_revision; + grub_uint16_t volume_flags; + grub_uint8_t bytes_per_sector_shift; + grub_uint8_t sectors_per_cluster_shift; + grub_uint8_t num_fats; + grub_uint8_t num_ph_drive; + grub_uint8_t reserved[8]; +} __attribute__ ((packed)); + +#else struct grub_fat_bpb { grub_uint8_t jmp_boot[3]; @@ -94,7 +125,64 @@ struct grub_fat_bpb } __attribute__ ((packed)) fat32; } __attribute__ ((packed)) version_specific; } __attribute__ ((packed)); +#endif +#ifdef MODE_EXFAT +struct grub_fat_dir_entry +{ + grub_uint8_t entry_type; + union + { + grub_uint8_t placeholder[31]; + struct { + grub_uint8_t secondary_count; + grub_uint16_t checksum; + grub_uint16_t attr; + grub_uint16_t reserved1; + grub_uint32_t c_time; + grub_uint32_t m_time; + grub_uint32_t a_time; + grub_uint8_t c_time_tenth; + grub_uint8_t m_time_tenth; + grub_uint8_t a_time_tenth; + grub_uint8_t reserved2[9]; + } __attribute__ ((packed)) file; + struct { + grub_uint8_t flags; + grub_uint8_t reserved1; + grub_uint8_t name_length; + grub_uint16_t name_hash; + grub_uint16_t reserved2; + grub_uint64_t valid_size; + grub_uint32_t reserved3; + grub_uint32_t first_cluster; + grub_uint64_t file_size; + } __attribute__ ((packed)) stream_extension; + struct { + grub_uint8_t flags; + grub_uint16_t str[15]; + } __attribute__ ((packed)) file_name; + struct { + grub_uint8_t character_count; + grub_uint16_t str[11]; + grub_uint8_t reserved[8]; + } __attribute__ ((packed)) volume_label; + } __attribute__ ((packed)) type_specific; +} __attribute__ ((packed)); + +struct grub_fat_dir_node +{ + grub_uint32_t attr; + grub_uint32_t first_cluster; + grub_uint64_t file_size; + grub_uint64_t valid_size; + int have_stream; + int is_label; +}; + +typedef struct grub_fat_dir_node grub_fat_dir_node_t; + +#else struct grub_fat_dir_entry { grub_uint8_t name[11]; @@ -123,6 +211,10 @@ struct grub_fat_long_name_entry grub_uint16_t name3[2]; } __attribute__ ((packed)); +typedef struct grub_fat_dir_entry grub_fat_dir_node_t; + +#endif + struct grub_fat_data { int logical_sector_bits; @@ -133,8 +225,10 @@ struct grub_fat_data int fat_size; grub_uint32_t root_cluster; +#ifndef MODE_EXFAT grub_uint32_t root_sector; grub_uint32_t num_root_sectors; +#endif int cluster_bits; grub_uint32_t cluster_eof_mark; @@ -152,6 +246,7 @@ struct grub_fat_data static grub_dl_t my_mod; +#ifndef MODE_EXFAT static int fat_log2 (unsigned x) { @@ -168,6 +263,7 @@ fat_log2 (unsigned x) return i; } +#endif static struct grub_fat_data * grub_fat_mount (grub_disk_t disk) @@ -187,20 +283,37 @@ grub_fat_mount (grub_disk_t disk) if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb)) goto fail; +#ifdef MODE_EXFAT + if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ", + sizeof (bpb.oem_name)) != 0) + goto fail; +#else if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5) && grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5) && grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5)) goto fail; +#endif + + grub_dprintf ("exfat", "alive\n"); /* Get the sizes of logical sectors and clusters. */ +#ifdef MODE_EXFAT + data->logical_sector_bits = bpb.bytes_per_sector_shift; +#else data->logical_sector_bits = fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector)); - if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS) +#endif + if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS + || data->logical_sector_bits >= 16) goto fail; data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS; +#ifdef MODE_EXFAT + data->cluster_bits = bpb.sectors_per_cluster_shift; +#else data->cluster_bits = fat_log2 (bpb.sectors_per_cluster); - if (data->cluster_bits < 0) +#endif + if (data->cluster_bits < 0 || data->cluster_bits > 25) goto fail; data->cluster_bits += data->logical_sector_bits; @@ -210,18 +323,28 @@ grub_fat_mount (grub_disk_t disk) if (data->fat_sector == 0) goto fail; +#ifdef MODE_EXFAT + data->sectors_per_fat = (grub_le_to_cpu32 (bpb.sectors_per_fat) + << data->logical_sector_bits); +#else data->sectors_per_fat = ((bpb.sectors_per_fat_16 ? grub_le_to_cpu16 (bpb.sectors_per_fat_16) : grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32)) << data->logical_sector_bits); +#endif if (data->sectors_per_fat == 0) goto fail; /* Get the number of sectors in this volume. */ +#ifdef MODE_EXFAT + data->num_sectors = ((grub_le_to_cpu64 (bpb.num_total_sectors)) + << data->logical_sector_bits); +#else data->num_sectors = ((bpb.num_total_sectors_16 ? grub_le_to_cpu16 (bpb.num_total_sectors_16) : grub_le_to_cpu32 (bpb.num_total_sectors_32)) << data->logical_sector_bits); +#endif if (data->num_sectors == 0) goto fail; @@ -229,6 +352,9 @@ grub_fat_mount (grub_disk_t disk) if (bpb.num_fats == 0) goto fail; + grub_dprintf ("exfat", "alive\n"); + +#ifndef MODE_EXFAT data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat; data->num_root_sectors = ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries) @@ -236,15 +362,36 @@ grub_fat_mount (grub_disk_t disk) + grub_le_to_cpu16 (bpb.bytes_per_sector) - 1) >> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS)) << (data->logical_sector_bits)); +#endif +#ifdef MODE_EXFAT + data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset) + << data->logical_sector_bits); + data->num_clusters = (grub_le_to_cpu32 (bpb.cluster_count) + << data->logical_sector_bits); +#else data->cluster_sector = data->root_sector + data->num_root_sectors; data->num_clusters = (((data->num_sectors - data->cluster_sector) >> (data->cluster_bits + data->logical_sector_bits)) + 2); +#endif if (data->num_clusters <= 2) goto fail; +#ifdef MODE_EXFAT + { + /* exFAT. */ + grub_uint16_t flags = grub_le_to_cpu16 (bpb.volume_flags); + + data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster); + data->fat_size = 32; + data->cluster_eof_mark = 0xffffffff; + + if ((flags & 0x1) && bpb.num_fats > 1) + data->fat_sector += data->sectors_per_fat; + } +#else if (! bpb.sectors_per_fat_16) { /* FAT32. */ @@ -286,6 +433,7 @@ grub_fat_mount (grub_disk_t disk) data->cluster_eof_mark = 0xfff8; } } +#endif /* More sanity checks. */ if (data->num_sectors <= data->fat_sector) @@ -317,17 +465,23 @@ grub_fat_mount (grub_disk_t disk) } /* Serial number. */ +#ifdef MODE_EXFAT + data->uuid = grub_le_to_cpu32 (bpb.num_serial); +#else if (bpb.sectors_per_fat_16) data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial); else data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial); +#endif +#ifndef MODE_EXFAT /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media descriptor, even if it is a so-called superfloppy (e.g. an USB key). The check may be too strict for this kind of stupid BIOSes, as they overwrite the media descriptor. */ if ((first_fat | 0x8) != (magic | bpb.media | 0x8)) goto fail; +#endif /* Start from the root directory. */ data->file_cluster = data->root_cluster; @@ -354,6 +508,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, grub_ssize_t ret = 0; unsigned long sector; +#ifndef MODE_EXFAT /* This is a special case. FAT12 and FAT16 doesn't have the root directory in clusters. */ if (data->file_cluster == ~0U) @@ -367,6 +522,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, return size; } +#endif /* Calculate the logical cluster number and offset. */ logical_cluster_bits = (data->cluster_bits @@ -465,13 +621,115 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, return ret; } +#ifdef MODE_EXFAT +static grub_err_t +grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, + int (*hook) (const char *filename, + grub_fat_dir_node_t *node)) +{ + struct grub_fat_dir_entry dir; + grub_ssize_t offset = -sizeof(dir); + grub_uint16_t *unibuf; + char *filename; + + unibuf = grub_malloc (15 * 256 * 2); + filename = grub_malloc (15 * 256 * 4 + 1); + + while (1) + { + offset += sizeof (dir); + + if (grub_fat_read_data (disk, data, 0, + offset, sizeof (dir), (char *) &dir) + != sizeof (dir)) + break; + + if (dir.entry_type == 0) + break; + if (!(dir.entry_type & 0x80)) + continue; + + if (dir.entry_type == 0x85) + { + unsigned i, nsec, slots = 0; + grub_fat_dir_node_t node; + + nsec = dir.type_specific.file.secondary_count; + + node.attr = grub_cpu_to_le32 (dir.type_specific.file.attr); + node.have_stream = 0; + for (i = 0; i < nsec; i++) + { + struct grub_fat_dir_entry sec; + offset += sizeof (sec); + if (grub_fat_read_data (disk, data, 0, + offset, sizeof (sec), (char *) &sec) + != sizeof (sec)) + break; + if (!(sec.entry_type & 0x80)) + continue; + if (!(sec.entry_type & 0x40)) + break; + switch (sec.entry_type) + { + case 0xc0: + node.first_cluster = grub_cpu_to_le32 (sec.type_specific.stream_extension.first_cluster); + node.valid_size + = grub_cpu_to_le32 (sec.type_specific.stream_extension.valid_size); + node.file_size + = grub_cpu_to_le32 (sec.type_specific.stream_extension.file_size); + node.have_stream = 1; + break; + case 0xc1: + grub_memcpy (unibuf + slots * 15, + sec.type_specific.file_name.str, 30); + slots++; + break; + default: + grub_printf ("unknown secondary type 0x%02x\n", sec.entry_type); + } + } + + if (i != nsec) + { + offset -= sizeof (dir); + continue; + } + + *grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf, + slots * 15) = '\0'; + + if (hook (filename, &node)) + break; + continue; + } + /* Allocation bitmap. */ + if (dir.entry_type == 0x81) + continue; + /* Upcase table. */ + if (dir.entry_type == 0x82) + continue; + /* Volume label. */ + if (dir.entry_type == 0x83) + continue; + grub_printf ("unknown primary type 0x%02x\n", dir.entry_type); + } + grub_free (filename); + grub_free (unibuf); + + return grub_errno; +} + +#else + static grub_err_t grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, int (*hook) (const char *filename, struct grub_fat_dir_entry *dir)) { struct grub_fat_dir_entry dir; - char *filename, *filep = 0; + char *filename; + char *filep = 0; grub_uint16_t *unibuf; int slot = -1, slots = -1; int checksum = -1; @@ -498,10 +756,11 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, offset += sizeof (dir); /* Read a directory entry. */ - if ((grub_fat_read_data (disk, data, 0, + if (grub_fat_read_data (disk, data, 0, offset, sizeof (dir), (char *) &dir) - != sizeof (dir) || dir.name[0] == 0)) + != sizeof (dir) || dir.name[0] == 0) break; + /* Handle long name entries. */ if (dir.attr == GRUB_FAT_ATTR_LONG_NAME) { @@ -586,7 +845,6 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, filep++; } *filep = '\0'; - if (hook (filename, &dir)) break; } @@ -596,7 +854,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, return grub_errno; } - +#endif /* Find the underlying directory or file in PATH and return the next path. If there is no next path or an error occurs, return NULL. @@ -611,8 +869,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, int call_hook; int found = 0; - auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir); - int iter_hook (const char *filename, struct grub_fat_dir_entry *dir) + auto int iter_hook (const char *filename, grub_fat_dir_node_t *dir); + int iter_hook (const char *filename, grub_fat_dir_node_t *dir) { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); @@ -620,8 +878,13 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY); info.case_insensitive = 1; +#ifdef MODE_EXFAT + if (!dir->have_stream) + return 0; +#else if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID) return 0; +#endif if (*dirname == '\0' && call_hook) return hook (filename, &info); @@ -629,9 +892,14 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, { found = 1; data->attr = dir->attr; +#ifdef MODE_EXFAT + data->file_size = dir->file_size; + data->file_cluster = dir->first_cluster; +#else data->file_size = grub_le_to_cpu32 (dir->file_size); data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16) | grub_le_to_cpu16 (dir->first_cluster_low)); +#endif data->cur_cluster_num = ~0U; if (call_hook) @@ -781,14 +1049,61 @@ grub_fat_close (grub_file_t file) return grub_errno; } +#ifdef MODE_EXFAT +static grub_err_t +grub_fat_label (grub_device_t device, char **label) +{ + struct grub_fat_dir_entry dir; + grub_ssize_t offset = -sizeof(dir); + struct grub_fat_data *data; + grub_disk_t disk = device->disk; + + data = grub_fat_mount (disk); + if (! data) + return grub_errno; + + while (1) + { + offset += sizeof (dir); + + if (grub_fat_read_data (disk, data, 0, + offset, sizeof (dir), (char *) &dir) + != sizeof (dir)) + break; + + if (dir.entry_type == 0) + break; + if (!(dir.entry_type & 0x80)) + continue; + + /* Volume label. */ + if (dir.entry_type == 0x83) + { + grub_size_t chc; + *label = grub_malloc (11 * 4 + 1); + if (!*label) + return grub_errno; + chc = dir.type_specific.volume_label.character_count; + if (chc > ARRAY_SIZE (dir.type_specific.volume_label.str)) + chc = ARRAY_SIZE (dir.type_specific.volume_label.str); + *grub_utf16_to_utf8 ((grub_uint8_t *) *label, + dir.type_specific.volume_label.str, chc) = '\0'; + } + } + + return grub_errno; +} + +#else + static grub_err_t grub_fat_label (grub_device_t device, char **label) { struct grub_fat_data *data; grub_disk_t disk = device->disk; - auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir); - int iter_hook (const char *filename, struct grub_fat_dir_entry *dir) + auto int iter_hook (const char *filename, grub_fat_dir_node_t *dir); + int iter_hook (const char *filename, grub_fat_dir_node_t *dir) { if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID) { @@ -823,6 +1138,8 @@ grub_fat_label (grub_device_t device, char **label) return grub_errno; } +#endif + static grub_err_t grub_fat_uuid (grub_device_t device, char **uuid) { @@ -850,7 +1167,11 @@ grub_fat_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_fat_fs = { +#ifdef MODE_EXFAT + .name = "exfat", +#else .name = "fat", +#endif .dir = grub_fat_dir, .open = grub_fat_open, .read = grub_fat_read, @@ -858,18 +1179,30 @@ static struct grub_fs grub_fat_fs = .label = grub_fat_label, .uuid = grub_fat_uuid, #ifdef GRUB_UTIL +#ifdef MODE_EXFAT + /* ExFAT BPB is 30 larger than FAT32 one. */ + .reserved_first_sector = 0, +#else .reserved_first_sector = 1, +#endif #endif .next = 0 }; +#ifdef MODE_EXFAT +GRUB_MOD_INIT(exfat) +#else GRUB_MOD_INIT(fat) +#endif { grub_fs_register (&grub_fat_fs); my_mod = mod; } - +#ifdef MODE_EXFAT +GRUB_MOD_FINI(exfat) +#else GRUB_MOD_FINI(fat) +#endif { grub_fs_unregister (&grub_fat_fs); } From b6929f5ef598a6d76129fc1915a87bdcf7c62fb8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 11 Apr 2011 20:38:08 +0200 Subject: [PATCH 107/673] Transform exfat printfs into dprintfs --- grub-core/fs/fat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 5f7a58571..49bb3a599 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -686,7 +686,8 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, slots++; break; default: - grub_printf ("unknown secondary type 0x%02x\n", sec.entry_type); + grub_dprintf ("exfat", "unknown secondary type 0x%02x\n", + sec.entry_type); } } @@ -712,7 +713,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, /* Volume label. */ if (dir.entry_type == 0x83) continue; - grub_printf ("unknown primary type 0x%02x\n", dir.entry_type); + grub_dprintf ("exfat", "unknown primary type 0x%02x\n", dir.entry_type); } grub_free (filename); grub_free (unibuf); From 2a861f38a7f0b17ada0057b139f9ad6f63aad24f Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 14 Apr 2011 20:27:27 +0100 Subject: [PATCH 108/673] Tell FUSE to run single-threaded, since GRUB code is not thread-safe. Fixes Ubuntu bug #756297. --- util/grub-mount.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index efada771a..434772eec 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -450,9 +450,12 @@ main (int argc, char *argv[]) grub_util_init_nls (); - fuse_args = xrealloc (fuse_args, (fuse_argc + 1) * sizeof (fuse_args[0])); + fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0])); fuse_args[fuse_argc] = xstrdup (argv[0]); fuse_argc++; + /* Run single-threaded. */ + fuse_args[fuse_argc] = xstrdup ("-s"); + fuse_argc++; argp_parse (&argp, argc, argv, 0, 0, 0); From bd671cc4fe27784df6bacb57d83f691a84e3f5f0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 15 Apr 2011 18:15:06 +0200 Subject: [PATCH 109/673] Use Block IO on EFI --- grub-core/disk/efi/efidisk.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 1bf764f10..35602513e 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -33,12 +33,10 @@ struct grub_efidisk_data grub_efi_device_path_t *device_path; grub_efi_device_path_t *last_device_path; grub_efi_block_io_t *block_io; - grub_efi_disk_io_t *disk_io; struct grub_efidisk_data *next; }; -/* GUIDs. */ -static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID; +/* GUID. */ static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID; static struct grub_efidisk_data *fd_devices; @@ -143,7 +141,7 @@ make_devices (void) struct grub_efidisk_data *devices = 0; /* Find handles which support the disk io interface. */ - handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid, + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid, 0, &num_handles); if (! handles) return 0; @@ -155,7 +153,6 @@ make_devices (void) grub_efi_device_path_t *ldp; struct grub_efidisk_data *d; grub_efi_block_io_t *bio; - grub_efi_disk_io_t *dio; dp = grub_efi_get_device_path (*handle); if (! dp) @@ -168,9 +165,7 @@ make_devices (void) bio = grub_efi_open_protocol (*handle, &block_io_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); - dio = grub_efi_open_protocol (*handle, &disk_io_guid, - GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (! bio || ! dio) + if (! bio) /* This should not happen... Why? */ continue; @@ -186,7 +181,6 @@ make_devices (void) d->device_path = dp; d->last_device_path = ldp; d->block_io = bio; - d->disk_io = dio; d->next = devices; devices = d; } @@ -563,22 +557,20 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, { /* For now, use the disk io interface rather than the block io's. */ struct grub_efidisk_data *d; - grub_efi_disk_io_t *dio; grub_efi_block_io_t *bio; grub_efi_status_t status; d = disk->data; - dio = d->disk_io; bio = d->block_io; grub_dprintf ("efidisk", "reading 0x%lx sectors at the sector 0x%llx from %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (dio->read, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << disk->log_sector_size, - (grub_efi_uintn_t) size << disk->log_sector_size, - buf); + status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id, + (grub_efi_uint64_t) sector, + (grub_efi_uintn_t) size << disk->log_sector_size, + buf); if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error"); @@ -591,20 +583,18 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, { /* For now, use the disk io interface rather than the block io's. */ struct grub_efidisk_data *d; - grub_efi_disk_io_t *dio; grub_efi_block_io_t *bio; grub_efi_status_t status; d = disk->data; - dio = d->disk_io; bio = d->block_io; grub_dprintf ("efidisk", "writing 0x%lx sectors at the sector 0x%llx to %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (dio->write, dio, bio->media->media_id, - (grub_efi_uint64_t) sector << disk->log_sector_size, + status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id, + (grub_efi_uint64_t) sector, (grub_efi_uintn_t) size << disk->log_sector_size, (void *) buf); if (status != GRUB_EFI_SUCCESS) From d8a2bcf564728cc38b138fed18cd89b097493e75 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 15 Apr 2011 21:42:29 +0200 Subject: [PATCH 110/673] contiguous read --- grub-core/kern/disk.c | 296 +++++++++++++++++++++++++----------------- 1 file changed, 178 insertions(+), 118 deletions(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index af56527ad..5439a02f6 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -398,13 +398,93 @@ transform_sector (grub_disk_t disk, grub_disk_addr_t sector) return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); } +/* Small read (less than cache size and not pass across cache unit boundaries). + sector is already adjusted and is divisible by cache unit size. + */ +static grub_err_t +grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, void *buf) +{ + char *data; + char *tmp_buf; + + /* Fetch the cache. */ + data = grub_disk_cache_fetch (disk->dev->id, disk->id, sector); + if (data) + { + /* Just copy it! */ + grub_memcpy (buf, data + offset, size); + grub_disk_cache_unlock (disk->dev->id, disk->id, sector); + return GRUB_ERR_NONE; + } + + /* Allocate a temporary buffer. */ + tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS); + if (! tmp_buf) + return grub_errno; + + /* Otherwise read data from the disk actually. */ + if (disk->total_sectors == GRUB_DISK_SIZE_UNKNOWN + || sector + GRUB_DISK_CACHE_SIZE + < (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) + { + grub_err_t err; + err = (disk->dev->read) (disk, transform_sector (disk, sector), + 1 << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), tmp_buf); + if (!err) + { + /* Copy it and store it in the disk cache. */ + grub_memcpy (buf, tmp_buf + offset, size); + grub_disk_cache_store (disk->dev->id, disk->id, + sector, tmp_buf); + grub_free (tmp_buf); + return GRUB_ERR_NONE; + } + } + + grub_errno = GRUB_ERR_NONE; + + { + /* Uggh... Failed. Instead, just read necessary data. */ + unsigned num; + grub_disk_addr_t aligned_sector; + + sector += (offset >> GRUB_DISK_SECTOR_BITS); + offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1); + aligned_sector = (sector & ~((1 << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + - 1)); + offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); + num = ((size + offset + (1 << (disk->log_sector_size)) + - 1) >> (disk->log_sector_size)); + + tmp_buf = grub_malloc (num << disk->log_sector_size); + if (!tmp_buf) + return grub_errno; + + if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector), + num, tmp_buf)) + { + grub_error_push (); + grub_dprintf ("disk", "%s read failed\n", disk->name); + grub_error_pop (); + return grub_errno; + } + grub_memcpy (buf, tmp_buf + offset, size); + return GRUB_ERR_NONE; + } +} + /* Read data from the disk. */ grub_err_t grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, void *buf) { - char *tmp_buf; - unsigned real_offset; + grub_off_t real_offset; + grub_disk_addr_t real_sector; + grub_size_t real_size; /* First of all, check if the region is within the disk. */ if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) @@ -416,138 +496,118 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, return grub_errno; } + real_sector = sector; real_offset = offset; + real_size = size; - /* Allocate a temporary buffer. */ - tmp_buf = grub_malloc (GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS); - if (! tmp_buf) - return grub_errno; - - /* Until SIZE is zero... */ - while (size) + /* First read until first cache boundary. */ + if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1))) { - char *data; grub_disk_addr_t start_sector; - grub_size_t len; grub_size_t pos; + grub_err_t err; + grub_size_t len; - /* For reading bulk data. */ start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1); pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS; len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS) - - pos - real_offset); + - pos - offset); if (len > size) len = size; - - /* Fetch the cache. */ - data = grub_disk_cache_fetch (disk->dev->id, disk->id, start_sector); - if (data) - { - /* Just copy it! */ - grub_memcpy (buf, data + pos + real_offset, len); - grub_disk_cache_unlock (disk->dev->id, disk->id, start_sector); - } - else - { - /* Otherwise read data from the disk actually. */ - if ((disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN - && start_sector + GRUB_DISK_CACHE_SIZE - > (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) - || (disk->dev->read) (disk, transform_sector (disk, start_sector), - 1 << (GRUB_DISK_CACHE_BITS - + GRUB_DISK_SECTOR_BITS - - disk->log_sector_size), tmp_buf) - != GRUB_ERR_NONE) - { - /* Uggh... Failed. Instead, just read necessary data. */ - unsigned num; - char *p; - grub_disk_addr_t aligned_sector; - - grub_errno = GRUB_ERR_NONE; - - aligned_sector = (sector & ~((1 << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - - 1)); - real_offset += ((sector - aligned_sector) - << GRUB_DISK_SECTOR_BITS); - num = ((size + real_offset + (1 << (disk->log_sector_size)) - - 1) >> (disk->log_sector_size)); - - p = grub_realloc (tmp_buf, num << disk->log_sector_size); - if (!p) - goto finish; - - tmp_buf = p; - - if ((disk->dev->read) (disk, transform_sector (disk, - aligned_sector), - num, tmp_buf)) - { - grub_error_push (); - grub_dprintf ("disk", "%s read failed\n", disk->name); - grub_error_pop (); - goto finish; - } - - grub_memcpy (buf, tmp_buf + real_offset, size); - - /* Call the read hook, if any. */ - if (disk->read_hook) - while (size) - { - grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size; - (disk->read_hook) (sector, real_offset, - to_read); - if (grub_errno != GRUB_ERR_NONE) - goto finish; - - sector++; - size -= to_read - real_offset; - real_offset = 0; - } - - /* This must be the end. */ - goto finish; - } - - /* Copy it and store it in the disk cache. */ - grub_memcpy (buf, tmp_buf + pos + real_offset, len); - grub_disk_cache_store (disk->dev->id, disk->id, - start_sector, tmp_buf); - } - - /* Call the read hook, if any. */ - if (disk->read_hook) - { - grub_disk_addr_t s = sector; - grub_size_t l = len; - - while (l) - { - (disk->read_hook) (s, real_offset, - ((l > GRUB_DISK_SECTOR_SIZE) - ? GRUB_DISK_SECTOR_SIZE - : l)); - - if (l < GRUB_DISK_SECTOR_SIZE - real_offset) - break; - - s++; - l -= GRUB_DISK_SECTOR_SIZE - real_offset; - real_offset = 0; - } - } - - sector = start_sector + GRUB_DISK_CACHE_SIZE; + err = grub_disk_read_small (disk, start_sector, + offset + pos, len, buf); + if (err) + return err; buf = (char *) buf + len; size -= len; - real_offset = 0; + offset += len; + sector += (offset >> GRUB_DISK_SECTOR_BITS); + offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1); } - finish: + /* Until SIZE is zero... */ + while (size >= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS)) + { + char *data = NULL; + grub_disk_addr_t agglomerate; + grub_err_t err; - grub_free (tmp_buf); + /* agglomerate read until we find a first cached entry. */ + for (agglomerate = 0; agglomerate + < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)); + agglomerate++) + { + data = grub_disk_cache_fetch (disk->dev->id, disk->id, + sector + (agglomerate + << GRUB_DISK_CACHE_BITS)); + if (data) + break; + } + + if (agglomerate) + { + grub_disk_addr_t i; + + err = (disk->dev->read) (disk, transform_sector (disk, sector), + agglomerate << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), + buf); + if (err) + return err; + + for (i = 0; i < agglomerate; i ++) + grub_disk_cache_store (disk->dev->id, disk->id, + sector + (i << GRUB_DISK_CACHE_BITS), + (char *) buf + + (i << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS))); + + sector += agglomerate << GRUB_DISK_CACHE_BITS; + size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); + buf = (char *) buf + + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); + } + + if (data) + { + grub_memcpy (buf, data, GRUB_DISK_CACHE_SIZE); + sector += GRUB_DISK_CACHE_SIZE; + buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); + size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); + grub_disk_cache_unlock (disk->dev->id, disk->id, + sector + (agglomerate + << GRUB_DISK_CACHE_BITS)); + } + } + + /* And now read the last part. */ + if (size) + { + grub_err_t err; + err = grub_disk_read_small (disk, sector, 0, size, buf); + if (err) + return err; + } + + /* Call the read hook, if any. */ + if (disk->read_hook) + { + grub_disk_addr_t s = real_sector; + grub_size_t l = real_size; + grub_off_t o = real_offset; + + while (l) + { + (disk->read_hook) (s, o, + ((l > GRUB_DISK_SECTOR_SIZE) + ? GRUB_DISK_SECTOR_SIZE + : l)); + s++; + l -= GRUB_DISK_SECTOR_SIZE - o; + o = 0; + } + } return grub_errno; } From 7217f315d375c678d4f00a4601923769b9b5a6ad Mon Sep 17 00:00:00 2001 From: Michael Gorven Date: Thu, 21 Apr 2011 11:14:29 +0200 Subject: [PATCH 111/673] LUKS support based on work of Michael Gorven with some code from Clemens Fruhwirth and heavily cleaned up by me (phcoder) Also-By: Clemens Fruhwirth Also-By: Vladimir Serbinenko --- grub-core/Makefile.core.def | 6 + grub-core/disk/AFSplitter.c | 104 ++++++ grub-core/disk/luks.c | 700 ++++++++++++++++++++++++++++++++++++ 3 files changed, 810 insertions(+) create mode 100644 grub-core/disk/AFSplitter.c create mode 100644 grub-core/disk/luks.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index f4d38149d..b8c996ba7 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -767,6 +767,12 @@ module = { common = disk/loopback.c; }; +module = { + name = luks; + common = disk/luks.c; + common = disk/AFSplitter.c; +}; + module = { name = lvm; common = disk/lvm.c; diff --git a/grub-core/disk/AFSplitter.c b/grub-core/disk/AFSplitter.c new file mode 100644 index 000000000..6c3dc488e --- /dev/null +++ b/grub-core/disk/AFSplitter.c @@ -0,0 +1,104 @@ +/* + * AFsplitter - Anti forensic information splitter + * Copyright 2004, Clemens Fruhwirth + * + * AFsplitter diffuses information over a large stripe of data, + * therefor supporting secure data destruction. + * + * This program is grub_free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the grub_free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the grub_free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, + grub_uint8_t * dst, grub_size_t blocksize, + grub_size_t blocknumbers); +static void diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src, + grub_uint8_t * dst, grub_size_t size); +gcry_err_code_t AF_split (const gcry_md_spec_t * hash, grub_uint8_t * src, + grub_uint8_t * dst, grub_size_t blocksize, + grub_size_t blocknumbers); + + +static void +diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src, + grub_uint8_t * dst, grub_size_t size) +{ + grub_size_t i; + grub_uint32_t IV; /* host byte order independend hash IV */ + + grub_size_t fullblocks = size / hash->mdlen; + int padding = size % hash->mdlen; + grub_uint8_t final[hash->mdlen]; + grub_uint8_t temp[sizeof (IV) + hash->mdlen]; + + /* hash block the whole data set with different IVs to produce + * more than just a single data block + */ + for (i = 0; i < fullblocks; i++) + { + IV = grub_cpu_to_be32 (i); + grub_memcpy (temp, &IV, sizeof (IV)); + grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, hash->mdlen); + grub_crypto_hash (hash, dst + hash->mdlen * i, temp, + sizeof (IV) + hash->mdlen); + } + + if (padding) + { + IV = grub_cpu_to_be32 (i); + grub_memcpy (temp, &IV, sizeof (IV)); + grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, padding); + grub_crypto_hash (hash, final, temp, sizeof (IV) + padding); + grub_memcpy (dst + hash->mdlen * i, final, padding); + } +} + +/** + * Merges the splitted master key stored on disk into the original key + */ +gcry_err_code_t +AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst, + grub_size_t blocksize, grub_size_t blocknumbers) +{ + grub_size_t i; + grub_uint8_t *bufblock; + + bufblock = grub_zalloc (blocksize); + if (bufblock == NULL) + return GPG_ERR_OUT_OF_MEMORY; + + grub_memset (bufblock, 0, blocksize); + for (i = 0; i < blocknumbers - 1; i++) + { + grub_crypto_xor (bufblock, src + (blocksize * i), bufblock, blocksize); + diffuse (hash, bufblock, bufblock, blocksize); + } + grub_crypto_xor (dst, src + (i * blocksize), bufblock, blocksize); + + grub_free (bufblock); + return GPG_ERR_NO_ERROR; +} diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c new file mode 100644 index 000000000..47d10d63c --- /dev/null +++ b/grub-core/disk/luks.c @@ -0,0 +1,700 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007,2010,2011 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define MAX_PASSPHRASE 256 + +#define LUKS_KEY_ENABLED 0x00AC71F3 +#define LUKS_STRIPES 4000 + +/* On disk LUKS header */ +struct grub_luks_phdr +{ + grub_uint8_t magic[6]; +#define LUKS_MAGIC "LUKS\xBA\xBE" + grub_uint16_t version; + char cipherName[32]; + char cipherMode[32]; + char hashSpec[32]; + grub_uint32_t payloadOffset; + grub_uint32_t keyBytes; + grub_uint8_t mkDigest[20]; + grub_uint8_t mkDigestSalt[32]; + grub_uint32_t mkDigestIterations; + grub_uint8_t uuid[40]; + struct + { + grub_uint32_t active; + grub_uint32_t passwordIterations; + grub_uint8_t passwordSalt[32]; + grub_uint32_t keyMaterialOffset; + grub_uint32_t stripes; + } keyblock[8]; +} __attribute__ ((packed)); + +typedef struct grub_luks_phdr *grub_luks_phdr_t; + +typedef enum +{ + GRUB_LUKS_MODE_ECB, + GRUB_LUKS_MODE_CBC_PLAIN, + GRUB_LUKS_MODE_CBC_ESSIV +} +luks_mode_t; + +struct grub_luks +{ + char *devname, *source; + grub_uint32_t offset; + grub_disk_t source_disk; + int ref; + grub_crypto_cipher_handle_t cipher; + grub_crypto_cipher_handle_t essiv_cipher; + luks_mode_t mode; + int id; + struct grub_luks *next; +}; +typedef struct grub_luks *grub_luks_t; + +static grub_luks_t luks_list = NULL; +static grub_uint8_t n = 0; + +gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, + grub_uint8_t * dst, grub_size_t blocksize, + grub_size_t blocknumbers); + +static const struct grub_arg_option options[] = + { + {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static gcry_err_code_t +luks_decrypt (grub_crypto_cipher_handle_t cipher, luks_mode_t mode, + grub_uint8_t * data, grub_size_t len, + grub_size_t sector, grub_crypto_cipher_handle_t essiv_cipher) +{ + grub_size_t i; + gcry_err_code_t err; + + switch (mode) + { + case GRUB_LUKS_MODE_ECB: + return grub_crypto_ecb_decrypt (cipher, data, data, len); + + case GRUB_LUKS_MODE_CBC_PLAIN: + for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) + { + grub_uint32_t iv[(cipher->cipher->blocksize + + sizeof (grub_uint32_t) - 1) + / sizeof (grub_uint32_t)]; + grub_memset (iv, 0, cipher->cipher->blocksize); + iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + err = grub_crypto_cbc_decrypt (cipher, data + i, data + i, + GRUB_DISK_SECTOR_SIZE, iv); + if (err) + return err; + sector++; + } + return GPG_ERR_NO_ERROR; + + case GRUB_LUKS_MODE_CBC_ESSIV: + for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) + { + grub_uint32_t iv[(cipher->cipher->blocksize + + sizeof (grub_uint32_t) - 1) + / sizeof (grub_uint32_t)]; + grub_memset (iv, 0, cipher->cipher->blocksize); + iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + err = + grub_crypto_ecb_encrypt (essiv_cipher, iv, iv, + cipher->cipher->blocksize); + if (err) + return err; + err = grub_crypto_cbc_decrypt (cipher, data + i, data + i, + GRUB_DISK_SECTOR_SIZE, iv); + if (err) + return err; + sector++; + } + return GPG_ERR_NO_ERROR; + + default: + return GPG_ERR_NOT_IMPLEMENTED; + } +} + +static int check_uuid, have_it; +static char *uuid; + +static grub_err_t +grub_luks_scan_device_real (const char *name) +{ + grub_disk_t source; + grub_err_t err; + grub_luks_t newdev; + struct grub_luks_phdr header; + grub_crypto_cipher_handle_t cipher = NULL, essiv_cipher = NULL; + const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; + grub_size_t keysize; + /* GCC thinks we may use this variable uninitialised. Silence the warning. */ + grub_size_t essiv_keysize = 0; + grub_uint8_t *hashed_key = NULL; + luks_mode_t mode; + grub_uint8_t *split_key = NULL; + unsigned i; + grub_size_t length; + const struct gcry_cipher_spec *ciph; + char passphrase[MAX_PASSPHRASE] = ""; + grub_uint8_t candidate_digest[sizeof (header.mkDigest)]; + + /* Try to open disk. */ + source = grub_disk_open (name); + if (!source) + return grub_errno; + + /* Read the LUKS header. */ + err = grub_disk_read (source, 0, 0, sizeof (header), &header); + if (err) + { + grub_disk_close (source); + return err; + } + + /* Look for LUKS magic sequence. */ + if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic)) + || grub_be_to_cpu16 (header.version) != 1) + { + grub_disk_close (source); + return GRUB_ERR_NONE; + } + + if (check_uuid && grub_memcmp (header.uuid, uuid, + sizeof (header.uuid)) != 0) + return 0; + + newdev = grub_zalloc (sizeof (struct grub_luks)); + if (!newdev) + { + grub_disk_close (source); + return grub_errno; + } + + newdev->id = n; + newdev->devname = grub_xasprintf ("luks%d", n); + newdev->source = grub_strdup (name); + n++; + + /* Make sure that strings are null terminated. */ + header.cipherName[sizeof (header.cipherName) - 1] = 0; + header.cipherMode[sizeof (header.cipherMode) - 1] = 0; + header.hashSpec[sizeof (header.hashSpec) - 1] = 0; + + ciph = grub_crypto_lookup_cipher_by_name (header.cipherName); + if (!ciph) + { + grub_disk_close (source); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", + header.cipherName); + } + + /* Configure the cipher used for the bulk data. */ + cipher = grub_crypto_cipher_open (ciph); + if (!cipher) + { + grub_disk_close (source); + grub_free (newdev); + return grub_errno; + } + + keysize = grub_be_to_cpu32 (header.keyBytes); + if (keysize > 1024) + { + grub_disk_close (source); + grub_free (newdev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", + keysize); + } + + /* Configure the cipher mode. */ + if (grub_strncmp (header.cipherMode, "ecb", 3) == 0) + mode = GRUB_LUKS_MODE_ECB; + else if (grub_strncmp (header.cipherMode, "cbc-plain", 9) == 0 + || grub_strncmp (header.cipherMode, "plain", 5) == 0) + mode = GRUB_LUKS_MODE_CBC_PLAIN; + else if (grub_strncmp (header.cipherMode, "cbc-essiv", 9) == 0) + { + mode = GRUB_LUKS_MODE_CBC_ESSIV; + char *hash_str = header.cipherMode + 10; + + /* Configure the hash and cipher used for ESSIV. */ + essiv_hash = grub_crypto_lookup_md_by_name (hash_str); + if (!essiv_hash) + { + grub_crypto_cipher_close (cipher); + grub_disk_close (source); + grub_free (newdev); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Couldn't load %s hash", hash_str); + } + essiv_cipher = grub_crypto_cipher_open (ciph); + if (!cipher) + { + grub_crypto_cipher_close (cipher); + grub_disk_close (source); + grub_free (newdev); + return grub_errno; + } + + essiv_keysize = essiv_hash->mdlen; + hashed_key = grub_malloc (essiv_hash->mdlen); + if (!hashed_key) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_disk_close (source); + grub_free (newdev); + return grub_errno; + } + } + else + { + grub_crypto_cipher_close (cipher); + grub_disk_close (source); + grub_free (newdev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", + header.cipherMode); + } + + /* Configure the hash used for the AF splitter and HMAC. */ + hash = grub_crypto_lookup_md_by_name (header.hashSpec); + if (!hash) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_disk_close (source); + grub_free (newdev); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", + header.hashSpec); + } + + grub_printf ("Attempting to decrypt master key...\n"); + + grub_uint8_t candidate_key[keysize]; + grub_uint8_t digest[keysize]; + + split_key = grub_malloc (keysize * LUKS_STRIPES); + if (!split_key) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_disk_close (source); + grub_free (newdev); + return grub_errno; + } + + /* Get the passphrase from the user. */ + grub_printf ("Enter passphrase: "); + if (!grub_password_get (passphrase, MAX_PASSPHRASE)) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_disk_close (source); + grub_free (newdev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); + } + + /* Try to recover master key from each active keyslot. */ + for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) + { + gcry_err_code_t gcry_err; + + /* Check if keyslot is enabled. */ + if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) + continue; + + grub_dprintf ("luks", "Trying keyslot %d\n", i); + + /* Calculate the PBKDF2 of the user supplied passphrase. */ + gcry_err = grub_crypto_pbkdf2 (hash, (grub_uint8_t *) passphrase, + grub_strlen (passphrase), + header.keyblock[i].passwordSalt, + sizeof (header. + keyblock[i].passwordSalt), + grub_be_to_cpu32 (header.keyblock[i]. + passwordIterations), + digest, keysize); + + if (gcry_err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_disk_close (source); + grub_free (newdev); + return grub_crypto_gcry_error (gcry_err); + } + + grub_dprintf ("luks", "PBKDF2 done\n"); + + /* Set the PBKDF2 output as the cipher key. */ + gcry_err = grub_crypto_cipher_set_key (cipher, digest, keysize); + if (gcry_err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_disk_close (source); + grub_free (newdev); + return grub_crypto_gcry_error (gcry_err); + } + + /* Configure ESSIV if necessary. */ + if (mode == GRUB_LUKS_MODE_CBC_ESSIV) + { + grub_crypto_hash (essiv_hash, hashed_key, digest, keysize); + grub_crypto_cipher_set_key (essiv_cipher, hashed_key, + essiv_keysize); + } + + length = + grub_be_to_cpu32 (header.keyBytes) * + grub_be_to_cpu32 (header.keyblock[i].stripes); + + /* Read and decrypt the key material from the disk. */ + err = grub_disk_read (source, + grub_be_to_cpu32 (header.keyblock + [i].keyMaterialOffset), 0, + length, split_key); + if (err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_disk_close (source); + grub_free (newdev); + return err; + } + + gcry_err = luks_decrypt (cipher, mode, split_key, + length, 0, essiv_cipher); + if (gcry_err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_disk_close (source); + grub_free (newdev); + return grub_crypto_gcry_error (gcry_err); + } + + /* Merge the decrypted key material to get the candidate master key. */ + gcry_err = AF_merge (hash, split_key, candidate_key, keysize, + grub_be_to_cpu32 (header.keyblock[i].stripes)); + if (gcry_err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_disk_close (source); + grub_free (newdev); + return grub_crypto_gcry_error (gcry_err); + } + + grub_dprintf ("luks", "candidate key recovered\n"); + + /* Calculate the PBKDF2 of the candidate master key. */ + gcry_err = grub_crypto_pbkdf2 (hash, candidate_key, + grub_be_to_cpu32 (header.keyBytes), + header.mkDigestSalt, + sizeof (header.mkDigestSalt), + grub_be_to_cpu32 + (header.mkDigestIterations), + candidate_digest, + sizeof (candidate_digest)); + if (gcry_err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_disk_close (source); + grub_free (newdev); + return grub_crypto_gcry_error (gcry_err); + } + + /* Compare the calculated PBKDF2 to the digest stored + in the header to see if it's correct. */ + if (grub_memcmp (candidate_digest, header.mkDigest, + sizeof (header.mkDigest)) != 0) + continue; + + grub_disk_close (source); + + grub_printf ("Slot %d opened\n", i); + + /* Set the master key. */ + gcry_err = grub_crypto_cipher_set_key (cipher, candidate_key, keysize); + if (gcry_err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_free (newdev); + return grub_crypto_gcry_error (gcry_err); + } + + newdev->cipher = cipher; + + /* Configure ESSIV if necessary. */ + if (mode == GRUB_LUKS_MODE_CBC_ESSIV) + { + grub_crypto_hash (essiv_hash, hashed_key, candidate_key, keysize); + gcry_err = + grub_crypto_cipher_set_key (essiv_cipher, hashed_key, + essiv_keysize); + if (gcry_err) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); + grub_free (hashed_key); + grub_free (split_key); + grub_free (newdev); + return grub_crypto_gcry_error (gcry_err); + } + newdev->essiv_cipher = essiv_cipher; + } + else + { + newdev->essiv_cipher = NULL; + } + + newdev->offset = grub_be_to_cpu32 (header.payloadOffset); + newdev->source_disk = NULL; + newdev->mode = mode; + + grub_free (split_key); + grub_free (hashed_key); + newdev->next = luks_list; + luks_list = newdev; + + have_it = 1; + + return GRUB_ERR_NONE; + } + + return GRUB_ACCESS_DENIED; +} + +static int +grub_luks_scan_device (const char *name) +{ + grub_err_t err; + err = grub_luks_scan_device_real (name); + if (err) + grub_print_error (); + return have_it && check_uuid ? 0 : 1; +} + +static int +grub_luks_iterate (int (*hook) (const char *name)) +{ + grub_luks_t i; + + for (i = luks_list; i != NULL; i = i->next) + if (hook (i->devname)) + return 1; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_luks_open (const char *name, grub_disk_t disk) +{ + grub_luks_t dev; + + /* Search for requested device in the list of LUKS devices. */ + for (dev = luks_list; dev != NULL; dev = dev->next) + if (grub_strcmp (dev->devname, name) == 0) + break; + + if (!dev) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + + if (!dev->source_disk) + { + grub_dprintf ("luks", "Opening device %s\n", name); + /* Try to open the source disk and populate the requested disk. */ + dev->source_disk = grub_disk_open (dev->source); + if (!dev->source_disk) + return grub_errno; + } + + disk->data = dev; + disk->total_sectors = grub_disk_get_size (dev->source_disk) - dev->offset; + disk->id = dev->id; + dev->ref++; + return GRUB_ERR_NONE; +} + +static void +grub_luks_close (grub_disk_t disk) +{ + grub_luks_t dev = (grub_luks_t) disk->data; + grub_dprintf ("luks", "Closing disk\n"); + + dev->ref--; + + if (dev->ref == 0) + { + grub_disk_close (dev->source_disk); + dev->source_disk = NULL; + } +} + +static grub_err_t +grub_luks_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_luks_t dev = (grub_luks_t) disk->data; + grub_err_t err; + grub_dprintf ("luks", + "Reading %" PRIuGRUB_SIZE " sectors from sector 0x%" + PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT32_T "\n", + size, sector, dev->offset); + + err = grub_disk_read (dev->source_disk, sector + dev->offset, 0, + size << GRUB_DISK_SECTOR_BITS, buf); + if (err) + { + grub_dprintf ("luks", "grub_disk_read failed with error %d\n", err); + return err; + } + return grub_crypto_gcry_error (luks_decrypt (dev->cipher, + dev->mode, + (grub_uint8_t *) buf, + size << GRUB_DISK_SECTOR_BITS, + sector, dev->essiv_cipher)); +} + +static grub_err_t +grub_luks_write (grub_disk_t disk __attribute ((unused)), + grub_disk_addr_t sector __attribute ((unused)), + grub_size_t size __attribute ((unused)), + const char *buf __attribute ((unused))) +{ + return GRUB_ERR_NOT_IMPLEMENTED_YET; +} + +static void +luks_cleanup (void) +{ + grub_luks_t dev = luks_list; + grub_luks_t tmp; + + while (dev != NULL) + { + grub_free (dev->devname); + grub_free (dev->source); + grub_free (dev->cipher); + grub_free (dev->essiv_cipher); + tmp = dev->next; + grub_free (dev); + dev = tmp; + } +} + +static grub_err_t +grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); + + have_it = 0; + if (state[0].set) + { + check_uuid = 1; + uuid = args[0]; + grub_device_iterate (&grub_luks_scan_device); + uuid = NULL; + } + else + { + grub_err_t err; + check_uuid = 0; + uuid = NULL; + err = grub_luks_scan_device_real (args[0]); + return err; + } + if (!have_it) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); + return 0; +} + +static struct grub_disk_dev grub_luks_dev = { + .name = "luks", + .id = GRUB_DISK_DEVICE_LUKS_ID, + .iterate = grub_luks_iterate, + .open = grub_luks_open, + .close = grub_luks_close, + .read = grub_luks_read, + .write = grub_luks_write, + .next = 0 +}; + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT (luks) +{ + cmd = grub_register_extcmd ("luksmount", grub_cmd_luksmount, 0, + N_("SOURCE|-u UUID"), + N_("Mount a LUKS device."), options); + grub_disk_dev_register (&grub_luks_dev); +} + +GRUB_MOD_FINI (luks) +{ + grub_unregister_extcmd (cmd); + grub_disk_dev_unregister (&grub_luks_dev); + luks_cleanup (); +} From 5709ed126d9155ae06c284f9c8fceb11227cc73d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 21 Apr 2011 11:17:01 +0200 Subject: [PATCH 112/673] small cleanup --- grub-core/disk/AFSplitter.c | 19 ++----------------- grub-core/disk/luks.c | 2 -- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/grub-core/disk/AFSplitter.c b/grub-core/disk/AFSplitter.c index 6c3dc488e..ebcc35221 100644 --- a/grub-core/disk/AFSplitter.c +++ b/grub-core/disk/AFSplitter.c @@ -20,28 +20,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include +#include +#include gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst, grub_size_t blocksize, grub_size_t blocknumbers); -static void diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src, - grub_uint8_t * dst, grub_size_t size); -gcry_err_code_t AF_split (const gcry_md_spec_t * hash, grub_uint8_t * src, - grub_uint8_t * dst, grub_size_t blocksize, - grub_size_t blocknumbers); - static void diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src, diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 47d10d63c..78fcabb03 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -20,11 +20,9 @@ #include #include #include -#include #include #include #include -#include #include #include From a89c3dd3f7f587447b61cdfb4de587951217fca2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 21 Apr 2011 11:38:51 +0200 Subject: [PATCH 113/673] Don't mount the same LUKS volume twice --- grub-core/disk/luks.c | 171 ++++++++++++++++++------------------------ 1 file changed, 75 insertions(+), 96 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 78fcabb03..160d1102c 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -47,7 +47,7 @@ struct grub_luks_phdr grub_uint8_t mkDigest[20]; grub_uint8_t mkDigestSalt[32]; grub_uint32_t mkDigestIterations; - grub_uint8_t uuid[40]; + char uuid[40]; struct { grub_uint32_t active; @@ -65,8 +65,7 @@ typedef enum GRUB_LUKS_MODE_ECB, GRUB_LUKS_MODE_CBC_PLAIN, GRUB_LUKS_MODE_CBC_ESSIV -} -luks_mode_t; +} luks_mode_t; struct grub_luks { @@ -77,7 +76,9 @@ struct grub_luks grub_crypto_cipher_handle_t cipher; grub_crypto_cipher_handle_t essiv_cipher; luks_mode_t mode; - int id; + unsigned long id, source_id; + enum grub_disk_dev_id source_dev_id; + char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid)]; struct grub_luks *next; }; typedef struct grub_luks *grub_luks_t; @@ -154,11 +155,9 @@ static int check_uuid, have_it; static char *uuid; static grub_err_t -grub_luks_scan_device_real (const char *name) +grub_luks_scan_device_real (const char *name, grub_disk_t source) { - grub_disk_t source; grub_err_t err; - grub_luks_t newdev; struct grub_luks_phdr header; grub_crypto_cipher_handle_t cipher = NULL, essiv_cipher = NULL; const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; @@ -174,73 +173,38 @@ grub_luks_scan_device_real (const char *name) char passphrase[MAX_PASSPHRASE] = ""; grub_uint8_t candidate_digest[sizeof (header.mkDigest)]; - /* Try to open disk. */ - source = grub_disk_open (name); - if (!source) - return grub_errno; - /* Read the LUKS header. */ err = grub_disk_read (source, 0, 0, sizeof (header), &header); if (err) - { - grub_disk_close (source); - return err; - } + return err; /* Look for LUKS magic sequence. */ if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic)) || grub_be_to_cpu16 (header.version) != 1) - { - grub_disk_close (source); - return GRUB_ERR_NONE; - } - - if (check_uuid && grub_memcmp (header.uuid, uuid, - sizeof (header.uuid)) != 0) - return 0; - - newdev = grub_zalloc (sizeof (struct grub_luks)); - if (!newdev) - { - grub_disk_close (source); - return grub_errno; - } - - newdev->id = n; - newdev->devname = grub_xasprintf ("luks%d", n); - newdev->source = grub_strdup (name); - n++; + return GRUB_ERR_NONE; /* Make sure that strings are null terminated. */ header.cipherName[sizeof (header.cipherName) - 1] = 0; header.cipherMode[sizeof (header.cipherMode) - 1] = 0; header.hashSpec[sizeof (header.hashSpec) - 1] = 0; + header.uuid[sizeof (header.uuid) - 1] = 0; + + if (check_uuid && grub_strcmp (header.uuid, uuid) != 0) + return 0; ciph = grub_crypto_lookup_cipher_by_name (header.cipherName); if (!ciph) - { - grub_disk_close (source); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", - header.cipherName); - } + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", + header.cipherName); /* Configure the cipher used for the bulk data. */ cipher = grub_crypto_cipher_open (ciph); if (!cipher) - { - grub_disk_close (source); - grub_free (newdev); - return grub_errno; - } + return grub_errno; keysize = grub_be_to_cpu32 (header.keyBytes); if (keysize > 1024) - { - grub_disk_close (source); - grub_free (newdev); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", - keysize); - } + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", keysize); /* Configure the cipher mode. */ if (grub_strncmp (header.cipherMode, "ecb", 3) == 0) @@ -258,8 +222,6 @@ grub_luks_scan_device_real (const char *name) if (!essiv_hash) { grub_crypto_cipher_close (cipher); - grub_disk_close (source); - grub_free (newdev); return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", hash_str); } @@ -267,8 +229,6 @@ grub_luks_scan_device_real (const char *name) if (!cipher) { grub_crypto_cipher_close (cipher); - grub_disk_close (source); - grub_free (newdev); return grub_errno; } @@ -278,16 +238,12 @@ grub_luks_scan_device_real (const char *name) { grub_crypto_cipher_close (cipher); grub_crypto_cipher_close (essiv_cipher); - grub_disk_close (source); - grub_free (newdev); return grub_errno; } } else { grub_crypto_cipher_close (cipher); - grub_disk_close (source); - grub_free (newdev); return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", header.cipherMode); } @@ -299,8 +255,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (cipher); grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); - grub_disk_close (source); - grub_free (newdev); return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", header.hashSpec); } @@ -316,8 +270,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (cipher); grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); - grub_disk_close (source); - grub_free (newdev); return grub_errno; } @@ -329,8 +281,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_disk_close (source); - grub_free (newdev); return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); } @@ -361,8 +311,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_disk_close (source); - grub_free (newdev); return grub_crypto_gcry_error (gcry_err); } @@ -376,8 +324,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_disk_close (source); - grub_free (newdev); return grub_crypto_gcry_error (gcry_err); } @@ -404,8 +350,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_disk_close (source); - grub_free (newdev); return err; } @@ -417,8 +361,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_disk_close (source); - grub_free (newdev); return grub_crypto_gcry_error (gcry_err); } @@ -431,8 +373,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_disk_close (source); - grub_free (newdev); return grub_crypto_gcry_error (gcry_err); } @@ -453,8 +393,6 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_disk_close (source); - grub_free (newdev); return grub_crypto_gcry_error (gcry_err); } @@ -464,8 +402,6 @@ grub_luks_scan_device_real (const char *name) sizeof (header.mkDigest)) != 0) continue; - grub_disk_close (source); - grub_printf ("Slot %d opened\n", i); /* Set the master key. */ @@ -476,12 +412,9 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_free (newdev); return grub_crypto_gcry_error (gcry_err); } - newdev->cipher = cipher; - /* Configure ESSIV if necessary. */ if (mode == GRUB_LUKS_MODE_CBC_ESSIV) { @@ -495,24 +428,33 @@ grub_luks_scan_device_real (const char *name) grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); - grub_free (newdev); return grub_crypto_gcry_error (gcry_err); } - newdev->essiv_cipher = essiv_cipher; - } - else - { - newdev->essiv_cipher = NULL; } - newdev->offset = grub_be_to_cpu32 (header.payloadOffset); - newdev->source_disk = NULL; - newdev->mode = mode; + { + grub_luks_t newdev; + newdev = grub_zalloc (sizeof (struct grub_luks)); + if (!newdev) + return grub_errno; + newdev->id = n; + newdev->devname = grub_xasprintf ("luks%d", n); + newdev->source = grub_strdup (name); + newdev->source_id = source->id; + newdev->source_dev_id = source->dev->id; + newdev->cipher = cipher; + newdev->offset = grub_be_to_cpu32 (header.payloadOffset); + newdev->source_disk = NULL; + newdev->mode = mode; + newdev->essiv_cipher = essiv_cipher; + grub_memcpy (newdev->uuid, header.uuid, sizeof (newdev->uuid)); + newdev->next = luks_list; + luks_list = newdev; + n++; + } grub_free (split_key); grub_free (hashed_key); - newdev->next = luks_list; - luks_list = newdev; have_it = 1; @@ -526,7 +468,17 @@ static int grub_luks_scan_device (const char *name) { grub_err_t err; - err = grub_luks_scan_device_real (name); + grub_disk_t source; + + /* Try to open disk. */ + source = grub_disk_open (name); + if (!source) + return grub_errno; + + err = grub_luks_scan_device_real (name, source); + + grub_disk_close (source); + if (err) grub_print_error (); return have_it && check_uuid ? 0 : 1; @@ -651,6 +603,15 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) have_it = 0; if (state[0].set) { + grub_luks_t dev; + + for (dev = luks_list; dev != NULL; dev = dev->next) + if (grub_strcmp (dev->uuid, args[0]) == 0) + { + grub_dprintf ("luks", "already mounted as %s\n", dev->devname); + return GRUB_ERR_NONE; + } + check_uuid = 1; uuid = args[0]; grub_device_iterate (&grub_luks_scan_device); @@ -659,9 +620,27 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) else { grub_err_t err; + grub_disk_t disk; + grub_luks_t dev; + check_uuid = 0; uuid = NULL; - err = grub_luks_scan_device_real (args[0]); + disk = grub_disk_open (args[0]); + if (!disk) + return grub_errno; + + for (dev = luks_list; dev != NULL; dev = dev->next) + if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id) + { + grub_dprintf ("luks", "already mounted as %s\n", dev->devname); + grub_disk_close (disk); + return GRUB_ERR_NONE; + } + + err = grub_luks_scan_device_real (args[0], disk); + + grub_disk_close (disk); + return err; } if (!have_it) From 79cde98f5d1c77697e8e3713987136cbf35a13c8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 21 Apr 2011 11:58:06 +0200 Subject: [PATCH 114/673] Support luksuuid specification --- grub-core/disk/luks.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 160d1102c..3ab6b844d 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -69,7 +69,7 @@ typedef enum struct grub_luks { - char *devname, *source; + char *source; grub_uint32_t offset; grub_disk_t source_disk; int ref; @@ -438,7 +438,6 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) if (!newdev) return grub_errno; newdev->id = n; - newdev->devname = grub_xasprintf ("luks%d", n); newdev->source = grub_strdup (name); newdev->source_id = source->id; newdev->source_dev_id = source->dev->id; @@ -490,8 +489,12 @@ grub_luks_iterate (int (*hook) (const char *name)) grub_luks_t i; for (i = luks_list; i != NULL; i = i->next) - if (hook (i->devname)) - return 1; + { + char buf[30]; + grub_snprintf (buf, sizeof (buf), "luks%lu", i->id); + if (hook (buf)) + return 1; + } return GRUB_ERR_NONE; } @@ -501,11 +504,25 @@ grub_luks_open (const char *name, grub_disk_t disk) { grub_luks_t dev; - /* Search for requested device in the list of LUKS devices. */ - for (dev = luks_list; dev != NULL; dev = dev->next) - if (grub_strcmp (dev->devname, name) == 0) - break; + if (grub_memcmp (name, "luks", sizeof ("luks") - 1) != 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + if (grub_memcmp (name, "luksuuid/", sizeof ("luksuuid/") - 1) == 0) + { + for (dev = luks_list; dev != NULL; dev = dev->next) + if (grub_strcmp (name + sizeof ("luksuuid/") - 1, dev->uuid) == 0) + break; + } + else + { + unsigned long id = grub_strtoul (name + sizeof ("luks") - 1, 0, 0); + if (grub_errno) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + /* Search for requested device in the list of LUKS devices. */ + for (dev = luks_list; dev != NULL; dev = dev->next) + if (dev->id == id) + break; + } if (!dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); @@ -582,7 +599,6 @@ luks_cleanup (void) while (dev != NULL) { - grub_free (dev->devname); grub_free (dev->source); grub_free (dev->cipher); grub_free (dev->essiv_cipher); @@ -608,7 +624,7 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) for (dev = luks_list; dev != NULL; dev = dev->next) if (grub_strcmp (dev->uuid, args[0]) == 0) { - grub_dprintf ("luks", "already mounted as %s\n", dev->devname); + grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); return GRUB_ERR_NONE; } @@ -632,7 +648,7 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) for (dev = luks_list; dev != NULL; dev = dev->next) if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id) { - grub_dprintf ("luks", "already mounted as %s\n", dev->devname); + grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); grub_disk_close (disk); return GRUB_ERR_NONE; } From 64516e9df6de88b84e53e7b84a25bff2130c00ae Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 21 Apr 2011 12:39:14 +0200 Subject: [PATCH 115/673] Fix couple of UUID problems --- grub-core/disk/luks.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 3ab6b844d..bc53e0a2b 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -78,7 +78,7 @@ struct grub_luks luks_mode_t mode; unsigned long id, source_id; enum grub_disk_dev_id source_dev_id; - char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid)]; + char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; struct grub_luks *next; }; typedef struct grub_luks *grub_luks_t; @@ -152,7 +152,7 @@ luks_decrypt (grub_crypto_cipher_handle_t cipher, luks_mode_t mode, } static int check_uuid, have_it; -static char *uuid; +static char *search_uuid; static grub_err_t grub_luks_scan_device_real (const char *name, grub_disk_t source) @@ -172,6 +172,8 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) const struct gcry_cipher_spec *ciph; char passphrase[MAX_PASSPHRASE] = ""; grub_uint8_t candidate_digest[sizeof (header.mkDigest)]; + char uuid[sizeof (header.uuid) + 1]; + char *iptr, *optr; /* Read the LUKS header. */ err = grub_disk_read (source, 0, 0, sizeof (header), &header); @@ -189,8 +191,20 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) header.hashSpec[sizeof (header.hashSpec) - 1] = 0; header.uuid[sizeof (header.uuid) - 1] = 0; - if (check_uuid && grub_strcmp (header.uuid, uuid) != 0) - return 0; + optr = uuid; + for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)]; + iptr++) + { + if (*iptr != '-') + *optr++ = *iptr; + } + *optr = 0; + + if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0) + { + grub_dprintf ("luks", "%s != %s", uuid, search_uuid); + return 0; + } ciph = grub_crypto_lookup_cipher_by_name (header.cipherName); if (!ciph) @@ -274,7 +288,7 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) } /* Get the passphrase from the user. */ - grub_printf ("Enter passphrase: "); + grub_printf ("Enter passphrase for %s (%s): ", name, uuid); if (!grub_password_get (passphrase, MAX_PASSPHRASE)) { grub_crypto_cipher_close (cipher); @@ -446,7 +460,7 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) newdev->source_disk = NULL; newdev->mode = mode; newdev->essiv_cipher = essiv_cipher; - grub_memcpy (newdev->uuid, header.uuid, sizeof (newdev->uuid)); + grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); newdev->next = luks_list; luks_list = newdev; n++; @@ -510,7 +524,7 @@ grub_luks_open (const char *name, grub_disk_t disk) if (grub_memcmp (name, "luksuuid/", sizeof ("luksuuid/") - 1) == 0) { for (dev = luks_list; dev != NULL; dev = dev->next) - if (grub_strcmp (name + sizeof ("luksuuid/") - 1, dev->uuid) == 0) + if (grub_strcasecmp (name + sizeof ("luksuuid/") - 1, dev->uuid) == 0) break; } else @@ -622,16 +636,20 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) grub_luks_t dev; for (dev = luks_list; dev != NULL; dev = dev->next) - if (grub_strcmp (dev->uuid, args[0]) == 0) + if (grub_strcasecmp (dev->uuid, args[0]) == 0) { grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); return GRUB_ERR_NONE; } check_uuid = 1; - uuid = args[0]; + search_uuid = args[0]; grub_device_iterate (&grub_luks_scan_device); - uuid = NULL; + search_uuid = NULL; + + if (!have_it) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); + return GRUB_ERR_NONE; } else { @@ -640,7 +658,7 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) grub_luks_t dev; check_uuid = 0; - uuid = NULL; + search_uuid = NULL; disk = grub_disk_open (args[0]); if (!disk) return grub_errno; @@ -659,9 +677,6 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) return err; } - if (!have_it) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); - return 0; } static struct grub_disk_dev grub_luks_dev = { From a10e7a5a8918bea6e2632055129fa9b516fe965a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 21 Apr 2011 12:39:31 +0200 Subject: [PATCH 116/673] Support grub-probe -t drive --- grub-core/kern/emu/getroot.c | 75 +++++++++++++++++++++++++++--------- include/grub/emu/getroot.h | 1 + 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index f47203cfc..40cbc4998 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -640,11 +640,11 @@ grub_guess_root_device (const char *dir) return os_dev; } -static int -grub_util_is_lvm (const char *os_dev) +static char * +get_dm_uuid (const char *os_dev) { if ((strncmp ("/dev/mapper/", os_dev, 12) != 0)) - return 0; + return NULL; #ifdef HAVE_DEVICE_MAPPER { @@ -652,17 +652,18 @@ grub_util_is_lvm (const char *os_dev) uint32_t maj, min; struct dm_tree_node *node = NULL; const char *node_uuid; + char *ret; struct stat st; if (stat (os_dev, &st) < 0) - return 0; + return NULL; tree = dm_tree_create (); if (! tree) { grub_printf ("Failed to create tree\n"); grub_dprintf ("hostdisk", "dm_tree_create failed\n"); - return 0; + return NULL; } maj = major (st.st_rdev); @@ -672,7 +673,7 @@ grub_util_is_lvm (const char *os_dev) { grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); dm_tree_free (tree); - return 0; + return NULL; } node = dm_tree_find_node (tree, maj, min); @@ -680,39 +681,64 @@ grub_util_is_lvm (const char *os_dev) { grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); dm_tree_free (tree); - return 0; + return NULL; } node_uuid = dm_tree_node_get_uuid (node); if (! node_uuid) { grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev); dm_tree_free (tree); - return 0; - } - if (strncmp (node_uuid, "LVM-", 4) != 0) - { - dm_tree_free (tree); - return 0; + return NULL; } + + ret = grub_strdup (node_uuid); dm_tree_free (tree); - return 1; + return ret; } #else - return 1; + return NULL; #endif /* HAVE_DEVICE_MAPPER */ } +static enum grub_dev_abstraction_types +grub_util_get_dm_abstraction (const char *os_dev) +{ + char *uuid; + uuid = get_dm_uuid (os_dev); + + if (uuid == NULL) + return GRUB_DEV_ABSTRACTION_NONE; + + if (strncmp (uuid, "LVM-", 4) == 0) + { + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_LVM; + } + if (strncmp (uuid, "CRYPT-LUKS1-", 4) == 0) + { + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_LUKS; + } + + grub_free (uuid); + return GRUB_DEV_ABSTRACTION_NONE; +} + int grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) { #ifdef __linux__ + enum grub_dev_abstraction_types ret; + /* User explicitly claims that this drive is visible by BIOS. */ if (grub_util_biosdisk_is_present (os_dev)) return GRUB_DEV_ABSTRACTION_NONE; - /* Check for LVM. */ - if (grub_util_is_lvm (os_dev)) - return GRUB_DEV_ABSTRACTION_LVM; + /* Check for LVM and LUKS. */ + ret = grub_util_get_dm_abstraction (os_dev); + + if (ret != GRUB_DEV_ABSTRACTION_NONE) + return ret; /* Check for RAID. */ if (!strncmp (os_dev, "/dev/md", 7) && ! grub_util_device_is_mapped (os_dev)) @@ -830,6 +856,19 @@ grub_util_get_grub_dev (const char *os_dev) break; + case GRUB_DEV_ABSTRACTION_LUKS: + { + char *uuid, *dash; + uuid = get_dm_uuid (os_dev); + dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-'); + if (dash) + *dash = 0; + grub_dev = grub_xasprintf ("luksuuid/%s", + uuid + sizeof ("CRYPT-LUKS1-") - 1); + grub_free (uuid); + } + break; + case GRUB_DEV_ABSTRACTION_RAID: if (os_dev[7] == '_' && os_dev[8] == 'd') diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index 581ea8056..14df583b3 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -25,6 +25,7 @@ enum grub_dev_abstraction_types { GRUB_DEV_ABSTRACTION_NONE, GRUB_DEV_ABSTRACTION_LVM, GRUB_DEV_ABSTRACTION_RAID, + GRUB_DEV_ABSTRACTION_LUKS, }; char *grub_find_device (const char *dir, dev_t dev); From 24b905a11c90e47cb271397bd507e0496fe130e7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 00:09:07 +0200 Subject: [PATCH 117/673] Lazy LVM and RAID assembly --- grub-core/disk/ata.c | 9 +- grub-core/disk/host.c | 9 +- grub-core/disk/i386/pc/biosdisk.c | 56 ++++++---- grub-core/disk/loopback.c | 8 +- grub-core/disk/lvm.c | 139 ++++++++++++++++++++--- grub-core/disk/memdisk.c | 9 +- grub-core/disk/raid.c | 178 ++++++++++++++++++++++-------- grub-core/disk/scsi.c | 9 +- grub-core/fs/i386/pc/pxe.c | 9 +- grub-core/kern/disk.c | 31 ++++-- grub-core/kern/emu/hostdisk.c | 6 +- include/grub/disk.h | 15 ++- include/grub/raid.h | 1 + 13 files changed, 365 insertions(+), 114 deletions(-) diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 7f261560d..3a43a8cae 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -666,10 +666,14 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, static int -grub_ata_iterate (int (*hook) (const char *name)) +grub_ata_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { struct grub_ata_device *dev; + if (pull != GRUB_DISK_PULL_NONE) + return 0; + for (dev = grub_ata_devices; dev; dev = dev->next) { char devname[10]; @@ -696,7 +700,8 @@ grub_ata_iterate (int (*hook) (const char *name)) } static grub_err_t -grub_ata_open (const char *name, grub_disk_t disk) +grub_ata_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { struct grub_ata_device *dev; grub_err_t err; diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index c51966293..5376cc6ce 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -27,15 +27,20 @@ int grub_disk_host_i_want_a_reference; static int -grub_host_iterate (int (*hook) (const char *name)) +grub_host_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { + if (pull != GRUB_DISK_PULL_NONE) + return 0; + if (hook ("host")) return 1; return 0; } static grub_err_t -grub_host_open (const char *name, grub_disk_t disk) +grub_host_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { if (grub_strcmp (name, "host")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a host disk"); diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 1d47dc727..e75ab184b 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -284,42 +284,52 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) } static int -grub_biosdisk_iterate (int (*hook) (const char *name)) +grub_biosdisk_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull __attribute__ ((unused))) { - int drive; int num_floppies; + int drive; /* For hard disks, attempt to read the MBR. */ - for (drive = 0x80; drive < 0x90; drive++) + switch (pull) { - if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1, - GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0) + case GRUB_DISK_PULL_NONE: + for (drive = 0x80; drive < 0x90; drive++) { - grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive); - break; + if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1, + GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0) + { + grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive); + break; + } + + if (grub_biosdisk_call_hook (hook, drive)) + return 1; + } + return 0; + + case GRUB_DISK_PULL_REMOVABLE: + if (cd_drive) + { + if (grub_biosdisk_call_hook (hook, cd_drive)) + return 1; } - if (grub_biosdisk_call_hook (hook, drive)) - return 1; + /* For floppy disks, we can get the number safely. */ + num_floppies = grub_biosdisk_get_num_floppies (); + for (drive = 0; drive < num_floppies; drive++) + if (grub_biosdisk_call_hook (hook, drive)) + return 1; + return 0; + default: + return 0; } - - if (cd_drive) - { - if (grub_biosdisk_call_hook (hook, cd_drive)) - return 1; - } - - /* For floppy disks, we can get the number safely. */ - num_floppies = grub_biosdisk_get_num_floppies (); - for (drive = 0; drive < num_floppies; drive++) - if (grub_biosdisk_call_hook (hook, drive)) - return 1; - return 0; } static grub_err_t -grub_biosdisk_open (const char *name, grub_disk_t disk) +grub_biosdisk_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { grub_uint64_t total_sectors = 0; int drive; diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index d50f353b1..21345af57 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -133,9 +133,12 @@ fail: static int -grub_loopback_iterate (int (*hook) (const char *name)) +grub_loopback_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { struct grub_loopback *d; + if (pull != GRUB_DISK_PULL_NONE) + return 0; for (d = loopback_list; d; d = d->next) { if (hook (d->devname)) @@ -145,7 +148,8 @@ grub_loopback_iterate (int (*hook) (const char *name)) } static grub_err_t -grub_loopback_open (const char *name, grub_disk_t disk) +grub_loopback_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { struct grub_loopback *dev; diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 206e3e220..72f493540 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -32,7 +32,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); static struct grub_lvm_vg *vg_list; static int lv_count; +static int scan_depth = 0; +static int is_lv_readable (struct grub_lvm_lv *lv); + +static int +grub_lvm_scan_device (const char *name); /* Go the string STR and return the number after STR. *P will point at the number. In case STR is not found, *P will be NULL and the @@ -96,16 +101,39 @@ grub_lvm_check_flag (char *p, char *str, char *flag) } static int -grub_lvm_iterate (int (*hook) (const char *name)) +grub_lvm_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { struct grub_lvm_vg *vg; + unsigned old_count = 0; + if (pull == GRUB_DISK_PULL_RESCAN && scan_depth) + return 0; + + if (pull == GRUB_DISK_PULL_RESCAN) + { + old_count = lv_count; + if (!scan_depth) + { + scan_depth++; + grub_device_iterate (&grub_lvm_scan_device); + scan_depth--; + } + } + if (pull != GRUB_DISK_PULL_RESCAN && pull != GRUB_DISK_PULL_NONE) + return GRUB_ERR_NONE; for (vg = vg_list; vg; vg = vg->next) { struct grub_lvm_lv *lv; if (vg->lvs) for (lv = vg->lvs; lv; lv = lv->next) - if (lv->visible && hook (lv->name)) - return 1; + if (lv->visible && lv->number >= old_count) + { + char lvname[sizeof ("lvm/") + grub_strlen (lv->name)]; + grub_memcpy (lvname, "lvm/", sizeof ("lvm/") - 1); + grub_strcpy (lvname + sizeof ("lvm/") - 1, lv->name); + if (hook (lvname)) + return 1; + } } return 0; @@ -135,8 +163,8 @@ grub_lvm_memberlist (grub_disk_t disk) } #endif -static grub_err_t -grub_lvm_open (const char *name, grub_disk_t disk) +static struct grub_lvm_lv * +find_lv (const char *name) { struct grub_lvm_vg *vg; struct grub_lvm_lv *lv = NULL; @@ -144,11 +172,43 @@ grub_lvm_open (const char *name, grub_disk_t disk) { if (vg->lvs) for (lv = vg->lvs; lv; lv = lv->next) - if (! grub_strcmp (lv->name, name)) - break; + if (! grub_strcmp (lv->name, name) && is_lv_readable (lv)) + return lv; + } + return NULL; +} - if (lv) - break; +static const char *scan_for = NULL; + +static grub_err_t +grub_lvm_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull) +{ + struct grub_lvm_lv *lv = NULL; + int explicit = 0; + + if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0) + { + name += sizeof ("lvm/") - 1; + explicit = 1; + } + + lv = find_lv (name); + + if (! lv && !scan_depth && + pull == (explicit ? GRUB_DISK_PULL_RESCAN : GRUB_DISK_PULL_RESCAN_UNTYPED)) + { + scan_for = name; + scan_depth++; + grub_device_iterate (&grub_lvm_scan_device); + scan_depth--; + scan_for = NULL; + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + lv = find_lv (name); } if (! lv) @@ -285,6 +345,49 @@ read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, return grub_error (GRUB_ERR_IO, "unknown LVM segment"); } +static grub_err_t +is_node_readable (const struct grub_lvm_node *node) +{ + /* Check whether we actually know the physical volume we want to + read from. */ + if (node->pv) + return !!(node->pv->disk); + if (node->lv) + return is_lv_readable (node->lv); + return 0; +} + +static int +is_lv_readable (struct grub_lvm_lv *lv) +{ + unsigned int i, j; + + if (!lv) + return 0; + + /* Find the right segment. */ + for (i = 0; i < lv->segment_count; i++) + switch (lv->segments[i].type) + { + case GRUB_LVM_STRIPED: + for (j = 0; j < lv->segments[i].node_count; j++) + if (!is_node_readable (lv->segments[i].nodes + j)) + return 0; + break; + case GRUB_LVM_MIRROR: + for (j = 0; j < lv->segments[i].node_count; j++) + if (is_node_readable (lv->segments[i].nodes + j)) + break; + if (j == lv->segments[i].node_count) + return 0; + default: + return 0; + } + + return 1; +} + + static grub_err_t grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) @@ -332,6 +435,15 @@ grub_lvm_scan_device (const char *name) return 0; } + for (vg = vg_list; vg; vg = vg->next) + for (pv = vg->pvs; pv; pv = pv->next) + if (pv->disk && pv->disk->id == disk->id + && pv->disk->dev->id == disk->dev->id) + { + grub_disk_close (disk); + return 0; + } + /* Search for label. */ for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++) { @@ -857,6 +969,8 @@ grub_lvm_scan_device (const char *name) if (grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_errno = GRUB_ERR_NONE; grub_print_error (); + if (scan_for && find_lv (scan_for)) + return 1; return 0; } @@ -878,13 +992,6 @@ static struct grub_disk_dev grub_lvm_dev = GRUB_MOD_INIT(lvm) { - grub_device_iterate (&grub_lvm_scan_device); - if (grub_errno) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - } - grub_disk_dev_register (&grub_lvm_dev); } diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 114ac0d9e..775234055 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -30,13 +30,18 @@ static char *memdisk_addr; static grub_off_t memdisk_size = 0; static int -grub_memdisk_iterate (int (*hook) (const char *name)) +grub_memdisk_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { + if (pull != GRUB_DISK_PULL_NONE) + return 0; + return hook ("memdisk"); } static grub_err_t -grub_memdisk_open (const char *name, grub_disk_t disk) +grub_memdisk_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { if (grub_strcmp (name, "memdisk")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk"); diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 946e6d2c2..78453ac88 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -33,6 +33,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); static struct grub_raid_array *array_list; grub_raid5_recover_func_t grub_raid5_recover_func; grub_raid6_recover_func_t grub_raid6_recover_func; +static grub_raid_t grub_raid_list; +static int inscnt = 0; + +static struct grub_raid_array * +find_array (const char *name); static char @@ -78,14 +83,98 @@ grub_is_array_readable (struct grub_raid_array *array) return 0; } +static grub_err_t +insert_array (grub_disk_t disk, struct grub_raid_array *new_array, + grub_disk_addr_t start_sector, const char *scanner_name, + grub_raid_t raid __attribute__ ((unused))); + +static int scan_depth = 0; + +static void +scan_devices (const char *arname) +{ + grub_raid_t raid; + + auto int hook (const char *name); + int hook (const char *name) + { + grub_disk_t disk; + struct grub_raid_array array; + struct grub_raid_array *arr; + grub_disk_addr_t start_sector; + + grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n", + raid->name, name); +#ifdef GRUB_UTIL + grub_util_info ("Scanning for %s RAID devices on disk %s", + raid->name, name); +#endif + + disk = grub_disk_open (name); + if (!disk) + return 0; + + for (arr = array_list; arr != NULL; arr = arr->next) + { + struct grub_raid_member *m; + for (m = arr->members; m < arr->members + arr->nr_devs; m++) + if (m->device && m->device->id == disk->id + && m->device->dev->id == m->device->dev->id) + { + grub_disk_close (disk); + return 0; + } + } + + if ((disk->total_sectors != GRUB_ULONG_MAX) && + (! raid->detect (disk, &array, &start_sector)) && + (! insert_array (disk, &array, start_sector, raid->name, + raid))) + return 0; + + /* This error usually means it's not raid, no need to display + it. */ + if (grub_errno != GRUB_ERR_OUT_OF_RANGE) + grub_print_error (); + + grub_errno = GRUB_ERR_NONE; + + grub_disk_close (disk); + + if (arname && find_array (arname)) + return 1; + + return 0; + } + + if (scan_depth) + return; + + scan_depth++; + for (raid = grub_raid_list; raid; raid = raid->next) + grub_device_iterate (&hook); + scan_depth--; +} + static int -grub_raid_iterate (int (*hook) (const char *name)) +grub_raid_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { struct grub_raid_array *array; + int islcnt = 0; + + if (pull == GRUB_DISK_PULL_RESCAN) + { + islcnt = inscnt; + scan_devices (NULL); + } + + if (pull != GRUB_DISK_PULL_NONE && pull != GRUB_DISK_PULL_RESCAN) + return 0; for (array = array_list; array != NULL; array = array->next) { - if (grub_is_array_readable (array)) + if (grub_is_array_readable (array) && array->became_readable_at >= islcnt) if (hook (array->name)) return 1; } @@ -134,11 +223,10 @@ ascii2hex (char c) return 0; } -static grub_err_t -grub_raid_open (const char *name, grub_disk_t disk) +static struct grub_raid_array * +find_array (const char *name) { struct grub_raid_array *array; - unsigned n; if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0) { @@ -155,7 +243,7 @@ grub_raid_open (const char *name, grub_disk_t disk) if (uuid_len == (unsigned) array->uuid_len && grub_memcmp (uuidbin, array->uuid, uuid_len) == 0) if (grub_is_array_readable (array)) - break; + return array; } } else @@ -163,8 +251,33 @@ grub_raid_open (const char *name, grub_disk_t disk) { if (!grub_strcmp (array->name, name)) if (grub_is_array_readable (array)) - break; + return array; } + return NULL; +} + +static grub_err_t +grub_raid_open (const char *name, grub_disk_t disk, grub_disk_pull_t pull) +{ + struct grub_raid_array *array; + unsigned n; + + if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", + name); + + array = find_array (name); + + if (! array && pull == GRUB_DISK_PULL_RESCAN) + { + scan_devices (name); + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + array = find_array (name); + } if (!array) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", @@ -690,15 +803,19 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, } /* Add the device to the array. */ - array->members[new_array->index].device = disk; - array->members[new_array->index].start_sector = start_sector; - array->nr_devs++; + { + int was_readable = grub_is_array_readable (array); + + array->members[new_array->index].device = disk; + array->members[new_array->index].start_sector = start_sector; + array->nr_devs++; + if (!was_readable && grub_is_array_readable (array)) + array->became_readable_at = inscnt++; + } return 0; } -static grub_raid_t grub_raid_list; - static void free_array (void) { @@ -729,45 +846,8 @@ free_array (void) void grub_raid_register (grub_raid_t raid) { - auto int hook (const char *name); - int hook (const char *name) - { - grub_disk_t disk; - struct grub_raid_array array; - grub_disk_addr_t start_sector; - - grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n", - grub_raid_list->name, name); -#ifdef GRUB_UTIL - grub_util_info ("Scanning for %s RAID devices on disk %s", - grub_raid_list->name, name); -#endif - - disk = grub_disk_open (name); - if (!disk) - return 0; - - if ((disk->total_sectors != GRUB_ULONG_MAX) && - (! grub_raid_list->detect (disk, &array, &start_sector)) && - (! insert_array (disk, &array, start_sector, grub_raid_list->name, - grub_raid_list))) - return 0; - - /* This error usually means it's not raid, no need to display - it. */ - if (grub_errno != GRUB_ERR_OUT_OF_RANGE) - grub_print_error (); - - grub_errno = GRUB_ERR_NONE; - - grub_disk_close (disk); - - return 0; - } - raid->next = grub_raid_list; grub_raid_list = raid; - grub_device_iterate (&hook); } void diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 25f0e3aea..e85036860 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -316,7 +316,8 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector, static int -grub_scsi_iterate (int (*hook) (const char *name)) +grub_scsi_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { grub_scsi_dev_t p; @@ -356,6 +357,9 @@ grub_scsi_iterate (int (*hook) (const char *name)) return 0; } + if (pull != GRUB_DISK_PULL_NONE) + return 0; + for (p = grub_scsi_dev_list; p; p = p->next) if (p->iterate && (p->iterate) (scsi_iterate)) return 1; @@ -364,7 +368,8 @@ grub_scsi_iterate (int (*hook) (const char *name)) } static grub_err_t -grub_scsi_open (const char *name, grub_disk_t disk) +grub_scsi_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { grub_scsi_dev_t p; grub_scsi_t scsi; diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index d6dc2c22d..929f44587 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -104,8 +104,12 @@ grub_pxe_scan (void) } static int -grub_pxe_iterate (int (*hook) (const char *name)) +grub_pxe_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { + if (pull != GRUB_DISK_PULL_NONE) + return 0; + if (hook ("pxe")) return 1; return 0; @@ -139,7 +143,8 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) } static grub_err_t -grub_pxe_open (const char *name, grub_disk_t disk) +grub_pxe_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { struct grub_pxe_disk_data *data; diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 807ee4277..9c2c70b80 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -207,10 +207,16 @@ int grub_disk_dev_iterate (int (*hook) (const char *name)) { grub_disk_dev_t p; + grub_disk_pull_t pull; - for (p = grub_disk_dev_list; p; p = p->next) - if (p->iterate && (p->iterate) (hook)) - return 1; + for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) + { + if (pull == GRUB_DISK_PULL_RESCAN_UNTYPED) + continue; + for (p = grub_disk_dev_list; p; p = p->next) + if (p->iterate && (p->iterate) (hook, pull)) + return 1; + } return 0; } @@ -241,6 +247,7 @@ grub_disk_open (const char *name) grub_disk_dev_t dev; char *raw = (char *) name; grub_uint64_t current_time; + grub_disk_pull_t pull; grub_dprintf ("disk", "Opening `%s'...\n", name); @@ -266,15 +273,19 @@ grub_disk_open (const char *name) if (! disk->name) goto fail; - - for (dev = grub_disk_dev_list; dev; dev = dev->next) + for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) { - if ((dev->open) (raw, disk) == GRUB_ERR_NONE) + for (dev = grub_disk_dev_list; dev; dev = dev->next) + { + if ((dev->open) (raw, disk, pull) == GRUB_ERR_NONE) + break; + else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + grub_errno = GRUB_ERR_NONE; + else + goto fail; + } + if (dev) break; - else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) - grub_errno = GRUB_ERR_NONE; - else - goto fail; } if (! dev) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 63bca37ee..3ee6174d0 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -212,7 +212,8 @@ find_free_slot (void) } static int -grub_util_biosdisk_iterate (int (*hook) (const char *name)) +grub_util_biosdisk_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) { unsigned i; @@ -224,7 +225,8 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name)) } static grub_err_t -grub_util_biosdisk_open (const char *name, grub_disk_t disk) +grub_util_biosdisk_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) { int drive; struct stat st; diff --git a/include/grub/disk.h b/include/grub/disk.h index 66db1149a..2678ad5eb 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -50,6 +50,15 @@ struct grub_disk; struct grub_disk_memberlist; #endif +typedef enum + { + GRUB_DISK_PULL_NONE, + GRUB_DISK_PULL_REMOVABLE, + GRUB_DISK_PULL_RESCAN, + GRUB_DISK_PULL_RESCAN_UNTYPED, + GRUB_DISK_PULL_MAX + } grub_disk_pull_t; + /* Disk device. */ struct grub_disk_dev { @@ -60,10 +69,12 @@ struct grub_disk_dev enum grub_disk_dev_id id; /* Call HOOK with each device name, until HOOK returns non-zero. */ - int (*iterate) (int (*hook) (const char *name)); + int (*iterate) (int (*hook) (const char *name), + grub_disk_pull_t pull); /* Open the device named NAME, and set up DISK. */ - grub_err_t (*open) (const char *name, struct grub_disk *disk); + grub_err_t (*open) (const char *name, struct grub_disk *disk, + grub_disk_pull_t pull); /* Close the disk DISK. */ void (*close) (struct grub_disk *disk); diff --git a/include/grub/raid.h b/include/grub/raid.h index d5853639d..1eb43721a 100644 --- a/include/grub/raid.h +++ b/include/grub/raid.h @@ -42,6 +42,7 @@ struct grub_raid_array int number; /* The device number, taken from md_minor so we are consistent with the device name in Linux. */ + int became_readable_at; int level; /* RAID levels, only 0, 1 or 5 at the moment. */ int layout; /* Layout for RAID 5/6. */ unsigned int total_devs; /* Total number of devices in the array. */ From 5dad99b7304b4b2bb0daaa0c379420b4dd1955d5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 01:10:24 +0200 Subject: [PATCH 118/673] more linux-like name for LVM volumes --- grub-core/disk/lvm.c | 42 +++++++++++++++++++++++++++--------- grub-core/kern/emu/getroot.c | 10 +++------ include/grub/lvm.h | 2 ++ 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 72f493540..c430f596d 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -172,7 +172,9 @@ find_lv (const char *name) { if (vg->lvs) for (lv = vg->lvs; lv; lv = lv->next) - if (! grub_strcmp (lv->name, name) && is_lv_readable (lv)) + if ((grub_strcmp (lv->fullname, name) == 0 + || grub_strcmp (lv->compatname, name) == 0) + && is_lv_readable (lv)) return lv; } return NULL; @@ -188,10 +190,7 @@ grub_lvm_open (const char *name, grub_disk_t disk, int explicit = 0; if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0) - { - name += sizeof ("lvm/") - 1; - explicit = 1; - } + explicit = 1; lv = find_lv (name); @@ -685,11 +684,34 @@ grub_lvm_scan_device (const char *name) q++; s = q - p; - lv->name = grub_malloc (vgname_len + 1 + s + 1); - grub_memcpy (lv->name, vgname, vgname_len); - lv->name[vgname_len] = '-'; - grub_memcpy (lv->name + vgname_len + 1, p, s); - lv->name[vgname_len + 1 + s] = '\0'; + lv->name = grub_strndup (p, s); + lv->compatname = grub_malloc (vgname_len + 1 + s + 1); + grub_memcpy (lv->compatname, vgname, vgname_len); + lv->compatname[vgname_len] = '-'; + grub_memcpy (lv->compatname + vgname_len + 1, p, s); + lv->compatname[vgname_len + 1 + s] = '\0'; + + { + const char *iptr; + char *optr; + lv->fullname = grub_malloc (sizeof("lvm/") + 2 * vgname_len + + 1 + 2 * s + 1); + optr = lv->fullname; + for (iptr = vgname; iptr < vgname + vgname_len; iptr++) + { + *optr++ = *iptr; + if (*iptr == '-') + *optr++ = '-'; + } + *optr++ = '-'; + for (iptr = p; iptr < p + s; iptr++) + { + *optr++ = *iptr; + if (*iptr == '-') + *optr++ = '-'; + } + *optr++ = 0; + } lv->size = 0; diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index f836a6625..c780fd94d 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -783,14 +783,10 @@ grub_util_get_grub_dev (const char *os_dev) grub_size_t offset = sizeof ("/dev/mapper/") - 1; len = strlen (os_dev) - offset + 1; - grub_dev = xmalloc (len); + grub_dev = xmalloc (len + sizeof ("lvm/")); - for (i = 0; i < len; i++, offset++) - { - grub_dev[i] = os_dev[offset]; - if (os_dev[offset] == '-' && os_dev[offset + 1] == '-') - offset++; - } + grub_memcpy (grub_dev, "lvm/", sizeof ("lvm/") - 1); + grub_memcpy (grub_dev + sizeof ("lvm/") - 1, os_dev + offset, len); } break; diff --git a/include/grub/lvm.h b/include/grub/lvm.h index b962dfd6c..b5352c75c 100644 --- a/include/grub/lvm.h +++ b/include/grub/lvm.h @@ -44,6 +44,8 @@ struct grub_lvm_pv { struct grub_lvm_lv { char *name; + char *fullname; + char *compatname; unsigned int number; unsigned int segment_count; grub_uint64_t size; From 65b4742cd70d15d41483582b454f21144b9ba60e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 02:46:36 +0200 Subject: [PATCH 119/673] Add lost lvm/ prefix. Autoadd lvm subdevices. --- grub-core/disk/lvm.c | 20 ++++++ grub-core/kern/emu/getroot.c | 120 ++++++++++++++++++++++++++--------- include/grub/emu/hostdisk.h | 1 + 3 files changed, 111 insertions(+), 30 deletions(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index c430f596d..d104be750 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -26,6 +26,7 @@ #ifdef GRUB_UTIL #include +#include #endif GRUB_MOD_LICENSE ("GPLv3+"); @@ -197,6 +198,16 @@ grub_lvm_open (const char *name, grub_disk_t disk, if (! lv && !scan_depth && pull == (explicit ? GRUB_DISK_PULL_RESCAN : GRUB_DISK_PULL_RESCAN_UNTYPED)) { +#ifdef GRUB_UTIL + if (explicit) + { + char buf[grub_strlen (name) + sizeof ("/dev/mapper/")]; + grub_memcpy (buf, "/dev/mapper/", sizeof ("/dev/mapper/")); + grub_strcpy (buf + sizeof ("/dev/mapper/") - 1, + name + sizeof ("lvm/") - 1); + grub_util_pull_device (buf); + } +#endif scan_for = name; scan_depth++; grub_device_iterate (&grub_lvm_scan_device); @@ -685,7 +696,11 @@ grub_lvm_scan_device (const char *name) s = q - p; lv->name = grub_strndup (p, s); + if (!lv->name) + goto lvs_fail; lv->compatname = grub_malloc (vgname_len + 1 + s + 1); + if (!lv->compatname) + goto lvs_fail; grub_memcpy (lv->compatname, vgname, vgname_len); lv->compatname[vgname_len] = '-'; grub_memcpy (lv->compatname + vgname_len + 1, p, s); @@ -696,7 +711,12 @@ grub_lvm_scan_device (const char *name) char *optr; lv->fullname = grub_malloc (sizeof("lvm/") + 2 * vgname_len + 1 + 2 * s + 1); + if (!lv->fullname) + goto lvs_fail; + optr = lv->fullname; + grub_memcpy (optr, "lvm/", sizeof ("lvm/") - 1); + optr += sizeof ("lvm/") - 1; for (iptr = vgname; iptr < vgname + vgname_len; iptr++) { *optr++ = *iptr; diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index dd277d705..474bb42bc 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -640,6 +640,56 @@ grub_guess_root_device (const char *dir) return os_dev; } +#ifdef HAVE_DEVICE_MAPPER + +static int +grub_util_open_dm (const char *os_dev, struct dm_tree **tree, + struct dm_tree_node **node) +{ + uint32_t maj, min; + struct stat st; + + *node = NULL; + *tree = NULL; + + if ((strncmp ("/dev/mapper/", os_dev, 12) != 0)) + return 0; + + if (stat (os_dev, &st) < 0) + return 0; + + *tree = dm_tree_create (); + if (! *tree) + { + grub_printf ("Failed to create tree\n"); + grub_dprintf ("hostdisk", "dm_tree_create failed\n"); + return 0; + } + + maj = major (st.st_rdev); + min = minor (st.st_rdev); + + if (! dm_tree_add_dev (*tree, maj, min)) + { + grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); + dm_tree_free (*tree); + *tree = NULL; + return 0; + } + + *node = dm_tree_find_node (*tree, maj, min); + if (! *node) + { + grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); + dm_tree_free (*tree); + *tree = NULL; + return 0; + } + return 1; +} + +#endif + static int grub_util_is_lvm (const char *os_dev) { @@ -648,40 +698,13 @@ grub_util_is_lvm (const char *os_dev) #ifdef HAVE_DEVICE_MAPPER { - struct dm_tree *tree; - uint32_t maj, min; - struct dm_tree_node *node = NULL; const char *node_uuid; - struct stat st; + struct dm_tree *tree; + struct dm_tree_node *node; - if (stat (os_dev, &st) < 0) + if (!grub_util_open_dm (os_dev, &tree, &node)) return 0; - tree = dm_tree_create (); - if (! tree) - { - grub_printf ("Failed to create tree\n"); - grub_dprintf ("hostdisk", "dm_tree_create failed\n"); - return 0; - } - - maj = major (st.st_rdev); - min = minor (st.st_rdev); - - if (! dm_tree_add_dev (tree, maj, min)) - { - grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); - dm_tree_free (tree); - return 0; - } - - node = dm_tree_find_node (tree, maj, min); - if (! node) - { - grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); - dm_tree_free (tree); - return 0; - } node_uuid = dm_tree_node_get_uuid (node); if (! node_uuid) { @@ -804,6 +827,43 @@ out: } #endif /* __linux__ */ +void +grub_util_pull_device (const char *os_dev) +{ + switch (grub_util_get_dev_abstraction (os_dev)) + { + case GRUB_DEV_ABSTRACTION_LVM: +#ifdef HAVE_DEVICE_MAPPER + { + struct dm_tree *tree; + struct dm_tree_node *node; + struct dm_tree_node *child; + void *handle = NULL; + + if (!grub_util_open_dm (os_dev, &tree, &node)) + return; + + while ((child = dm_tree_next_child (&handle, node, 0))) + { + const struct dm_info *dm = dm_tree_node_get_info (child); + char *subdev; + if (!dm) + continue; + subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor)); + if (subdev) + grub_util_pull_device (subdev); + } + dm_tree_free (tree); + return; + } +#endif + + default: /* GRUB_DEV_ABSTRACTION_NONE */ + grub_util_biosdisk_get_grub_dev (os_dev); + return; + } +} + char * grub_util_get_grub_dev (const char *os_dev) { diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 842dff496..803c0f755 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -29,5 +29,6 @@ const char *grub_util_biosdisk_get_osdev (grub_disk_t disk); int grub_util_biosdisk_is_present (const char *name); int grub_util_biosdisk_is_floppy (grub_disk_t disk); grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk); +void grub_util_pull_device (const char *osname); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ From 4defebbec8eeae0909c6912d757e2a2f510dae78 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 13:55:30 +0200 Subject: [PATCH 120/673] automatic raid members addition --- Makefile.util.def | 2 +- grub-core/Makefile.core.def | 1 + grub-core/disk/lvm.c | 10 ---------- grub-core/kern/emu/getroot.c | 15 ++++++++++++++- {util => grub-core/kern/emu}/raid.c | 12 +++++++++--- include/grub/emu/getroot.h | 3 +++ include/grub/util/raid.h | 27 --------------------------- util/grub-setup.c | 5 ++--- 8 files changed, 30 insertions(+), 45 deletions(-) rename {util => grub-core/kern/emu}/raid.c (84%) delete mode 100644 include/grub/util/raid.h diff --git a/Makefile.util.def b/Makefile.util.def index 058572f06..40c67c233 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -10,6 +10,7 @@ library = { common = grub-core/kern/device.c; common = grub-core/kern/disk.c; common = grub-core/kern/emu/getroot.c; + common = grub-core/kern/emu/raid.c; common = grub-core/kern/emu/hostdisk.c; common = grub-core/kern/emu/misc.c; common = grub-core/kern/emu/mm.c; @@ -265,7 +266,6 @@ program = { installdir = sbin; mansection = 8; common = util/grub-setup.c; - common = util/raid.c; common = util/lvm.c; common = grub-core/lib/reed_solomon.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index f4d38149d..4146e3841 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -165,6 +165,7 @@ kernel = { emu = kern/emu/cache.S; emu = kern/emu/console.c; emu = kern/emu/getroot.c; + emu = kern/emu/raid.c; emu = kern/emu/hostdisk.c; emu = kern/emu/hostfs.c; emu = kern/emu/main.c; diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index d104be750..b86cd8023 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -198,16 +198,6 @@ grub_lvm_open (const char *name, grub_disk_t disk, if (! lv && !scan_depth && pull == (explicit ? GRUB_DISK_PULL_RESCAN : GRUB_DISK_PULL_RESCAN_UNTYPED)) { -#ifdef GRUB_UTIL - if (explicit) - { - char buf[grub_strlen (name) + sizeof ("/dev/mapper/")]; - grub_memcpy (buf, "/dev/mapper/", sizeof ("/dev/mapper/")); - grub_strcpy (buf + sizeof ("/dev/mapper/") - 1, - name + sizeof ("lvm/") - 1); - grub_util_pull_device (buf); - } -#endif scan_for = name; scan_depth++; grub_device_iterate (&grub_lvm_scan_device); diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index 474bb42bc..d9c1c9e08 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -854,9 +854,20 @@ grub_util_pull_device (const char *os_dev) grub_util_pull_device (subdev); } dm_tree_free (tree); - return; } #endif + return; + case GRUB_DEV_ABSTRACTION_RAID: +#ifdef __linux__ + { + char **devicelist = grub_util_raid_getmembers (os_dev, 0); + int i; + for (i = 0; devicelist[i];i++) + grub_util_pull_device (devicelist[i]); + free (devicelist); + } +#endif + return; default: /* GRUB_DEV_ABSTRACTION_NONE */ grub_util_biosdisk_get_grub_dev (os_dev); @@ -869,6 +880,8 @@ grub_util_get_grub_dev (const char *os_dev) { char *grub_dev = NULL; + grub_util_pull_device (os_dev); + switch (grub_util_get_dev_abstraction (os_dev)) { case GRUB_DEV_ABSTRACTION_LVM: diff --git a/util/raid.c b/grub-core/kern/emu/raid.c similarity index 84% rename from util/raid.c rename to grub-core/kern/emu/raid.c index a6aa5f95e..1371117da 100644 --- a/util/raid.c +++ b/grub-core/kern/emu/raid.c @@ -21,7 +21,6 @@ #ifdef __linux__ #include #include -#include #include #include @@ -36,7 +35,7 @@ #include char ** -grub_util_raid_getmembers (const char *name) +grub_util_raid_getmembers (const char *name, int bootable) { int fd, ret, i, j; char **devicelist; @@ -53,7 +52,14 @@ grub_util_raid_getmembers (const char *name) if (ret != 0) grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno)); - if (version.major != 0 || version.minor != 90) + if ((version.major != 0 || version.minor != 90) + && (version.major != 1 || version.minor != 0) + && (version.major != 1 || version.minor != 1) + && (version.major != 1 || version.minor != 2)) + grub_util_error ("unsupported RAID version: %d.%d", + version.major, version.minor); + + if (bootable && (version.major != 0 || version.minor != 90)) grub_util_error ("unsupported RAID version: %d.%d", version.major, version.minor); diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index 581ea8056..702903ee6 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -34,5 +34,8 @@ char *grub_util_get_grub_dev (const char *os_dev); char *grub_make_system_path_relative_to_its_root (const char *path); const char *grub_util_check_block_device (const char *blk_dev); const char *grub_util_check_char_device (const char *blk_dev); +#ifdef __linux__ +char **grub_util_raid_getmembers (const char *name, int bootable); +#endif #endif /* ! GRUB_UTIL_GETROOT_HEADER */ diff --git a/include/grub/util/raid.h b/include/grub/util/raid.h deleted file mode 100644 index 4da5eaaa8..000000000 --- a/include/grub/util/raid.h +++ /dev/null @@ -1,27 +0,0 @@ -/* raid.h - RAID support for GRUB utils. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007 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 . - */ - -#ifndef GRUB_RAID_UTIL_HEADER -#define GRUB_RAID_UTIL_HEADER 1 - -#ifdef __linux__ -char** grub_util_raid_getmembers (const char *name); -#endif - -#endif /* ! GRUB_RAID_UTIL_HEADER */ diff --git a/util/grub-setup.c b/util/grub-setup.c index 7d47fa654..8482e11c9 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #ifdef GRUB_MACHINE_IEEE1275 #include @@ -972,12 +971,12 @@ main (int argc, char *argv[]) int i; if (arguments.device[0] == '/') - devicelist = grub_util_raid_getmembers (arguments.device); + devicelist = grub_util_raid_getmembers (arguments.device, 1); else { char *devname; devname = xasprintf ("/dev/%s", dest_dev); - devicelist = grub_util_raid_getmembers (dest_dev); + devicelist = grub_util_raid_getmembers (dest_dev, 1); free (devname); } From 716aa45e40c96ddbe01403faa42355b22a4d4b96 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 14:58:12 +0200 Subject: [PATCH 121/673] Fix LVM listing --- grub-core/disk/lvm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index b86cd8023..ec1780e32 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -129,10 +129,7 @@ grub_lvm_iterate (int (*hook) (const char *name), for (lv = vg->lvs; lv; lv = lv->next) if (lv->visible && lv->number >= old_count) { - char lvname[sizeof ("lvm/") + grub_strlen (lv->name)]; - grub_memcpy (lvname, "lvm/", sizeof ("lvm/") - 1); - grub_strcpy (lvname + sizeof ("lvm/") - 1, lv->name); - if (hook (lvname)) + if (hook (lv->fullname)) return 1; } } From f3470f4eb51026e410c687f10065a1fc797ba384 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 16:32:27 +0200 Subject: [PATCH 122/673] restructure prior to adding cheatmounts --- grub-core/disk/luks.c | 302 +++++++++++++++++++++++------------------- 1 file changed, 166 insertions(+), 136 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 12a37b98b..4d907b4c6 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -75,6 +75,7 @@ struct grub_luks int ref; grub_crypto_cipher_handle_t cipher; grub_crypto_cipher_handle_t essiv_cipher; + const gcry_md_spec_t *essiv_hash, *hash; luks_mode_t mode; unsigned long id, source_id; enum grub_disk_dev_id source_dev_id; @@ -154,45 +155,28 @@ luks_decrypt (grub_crypto_cipher_handle_t cipher, luks_mode_t mode, static int check_uuid, have_it; static char *search_uuid; -static grub_err_t -grub_luks_scan_device_real (const char *name, grub_disk_t source) +static grub_luks_t +configure_ciphers (const struct grub_luks_phdr *header) { - grub_err_t err; - struct grub_luks_phdr header; + grub_luks_t newdev; + const char *iptr; + char *optr; + char uuid[sizeof (header->uuid) + 1]; + char ciphername[sizeof (header->cipherName) + 1]; + char ciphermode[sizeof (header->cipherMode) + 1]; + char hashspec[sizeof (header->hashSpec) + 1]; grub_crypto_cipher_handle_t cipher = NULL, essiv_cipher = NULL; const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; - grub_size_t keysize; - /* GCC thinks we may use this variable uninitialised. Silence the warning. */ - grub_size_t essiv_keysize = 0; - grub_uint8_t *hashed_key = NULL; - luks_mode_t mode; - grub_uint8_t *split_key = NULL; - unsigned i; - grub_size_t length; const struct gcry_cipher_spec *ciph; - char passphrase[MAX_PASSPHRASE] = ""; - grub_uint8_t candidate_digest[sizeof (header.mkDigest)]; - char uuid[sizeof (header.uuid) + 1]; - char *iptr, *optr; - - /* Read the LUKS header. */ - err = grub_disk_read (source, 0, 0, sizeof (header), &header); - if (err) - return err; - + luks_mode_t mode; + /* Look for LUKS magic sequence. */ - if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic)) - || grub_be_to_cpu16 (header.version) != 1) - return GRUB_ERR_NONE; - - /* Make sure that strings are null terminated. */ - header.cipherName[sizeof (header.cipherName) - 1] = 0; - header.cipherMode[sizeof (header.cipherMode) - 1] = 0; - header.hashSpec[sizeof (header.hashSpec) - 1] = 0; - header.uuid[sizeof (header.uuid) - 1] = 0; + if (grub_memcmp (header->magic, LUKS_MAGIC, sizeof (header->magic)) + || grub_be_to_cpu16 (header->version) != 1) + return NULL; optr = uuid; - for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)]; + for (iptr = header->uuid; iptr < &header->uuid[ARRAY_SIZE (header->uuid)]; iptr++) { if (*iptr != '-') @@ -203,126 +187,163 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0) { grub_dprintf ("luks", "%s != %s", uuid, search_uuid); - return 0; + return NULL; } - ciph = grub_crypto_lookup_cipher_by_name (header.cipherName); + /* Make sure that strings are null terminated. */ + grub_memcpy (ciphername, header->cipherName, sizeof (header->cipherName)); + ciphername[sizeof (header->cipherName)] = 0; + grub_memcpy (ciphermode, header->cipherMode, sizeof (header->cipherMode)); + ciphermode[sizeof (header->cipherMode)] = 0; + grub_memcpy (hashspec, header->hashSpec, sizeof (header->hashSpec)); + hashspec[sizeof (header->hashSpec)] = 0; + + ciph = grub_crypto_lookup_cipher_by_name (ciphername); if (!ciph) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", - header.cipherName); + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", + ciphername); + return NULL; + } /* Configure the cipher used for the bulk data. */ cipher = grub_crypto_cipher_open (ciph); if (!cipher) - return grub_errno; + return NULL; - keysize = grub_be_to_cpu32 (header.keyBytes); - if (keysize > 1024) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", keysize); + if (grub_be_to_cpu32 (header->keyBytes) > 1024) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", + grub_be_to_cpu32 (header->keyBytes)); + return NULL; + } /* Configure the cipher mode. */ - if (grub_strncmp (header.cipherMode, "ecb", 3) == 0) + if (grub_strncmp (ciphermode, "ecb", 3) == 0) mode = GRUB_LUKS_MODE_ECB; - else if (grub_strncmp (header.cipherMode, "cbc-plain", 9) == 0 - || grub_strncmp (header.cipherMode, "plain", 5) == 0) + else if (grub_strncmp (ciphermode, "cbc-plain", 9) == 0 + || grub_strncmp (ciphermode, "plain", 5) == 0) mode = GRUB_LUKS_MODE_CBC_PLAIN; - else if (grub_strncmp (header.cipherMode, "cbc-essiv", 9) == 0) + else if (grub_strncmp (ciphermode, "cbc-essiv", 9) == 0) { mode = GRUB_LUKS_MODE_CBC_ESSIV; - char *hash_str = header.cipherMode + 10; + char *hash_str = ciphermode + 10; /* Configure the hash and cipher used for ESSIV. */ essiv_hash = grub_crypto_lookup_md_by_name (hash_str); if (!essiv_hash) { grub_crypto_cipher_close (cipher); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "Couldn't load %s hash", hash_str); + grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Couldn't load %s hash", hash_str); + return NULL; } essiv_cipher = grub_crypto_cipher_open (ciph); if (!cipher) { grub_crypto_cipher_close (cipher); - return grub_errno; - } - - essiv_keysize = essiv_hash->mdlen; - hashed_key = grub_malloc (essiv_hash->mdlen); - if (!hashed_key) - { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); - return grub_errno; + return NULL; } } else { grub_crypto_cipher_close (cipher); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", - header.cipherMode); + grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", + ciphermode); + return NULL; } /* Configure the hash used for the AF splitter and HMAC. */ - hash = grub_crypto_lookup_md_by_name (header.hashSpec); + hash = grub_crypto_lookup_md_by_name (hashspec); if (!hash) { grub_crypto_cipher_close (cipher); grub_crypto_cipher_close (essiv_cipher); - grub_free (hashed_key); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", - header.hashSpec); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", + hashspec); + return NULL; + } + + newdev = grub_zalloc (sizeof (struct grub_luks)); + if (!newdev) + return NULL; + newdev->cipher = cipher; + newdev->offset = grub_be_to_cpu32 (header->payloadOffset); + newdev->source_disk = NULL; + newdev->mode = mode; + newdev->essiv_cipher = essiv_cipher; + newdev->essiv_hash = essiv_hash; + newdev->hash = hash; + newdev->id = n++; + grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); + return newdev; +} + +static grub_err_t +luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, + const char *name, grub_disk_t source) +{ + grub_size_t keysize = grub_be_to_cpu32 (header->keyBytes); + grub_uint8_t candidate_key[keysize]; + grub_uint8_t digest[keysize]; + grub_uint8_t *hashed_key = NULL; + grub_uint8_t *split_key = NULL; + char passphrase[MAX_PASSPHRASE] = ""; + grub_uint8_t candidate_digest[sizeof (header->mkDigest)]; + unsigned i; + grub_size_t essiv_keysize = 0; + grub_size_t length; + grub_err_t err; + + if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) + essiv_keysize = dev->essiv_hash->mdlen; + hashed_key = grub_malloc (dev->essiv_hash->mdlen); + if (!hashed_key) + { + return grub_errno; } grub_printf ("Attempting to decrypt master key...\n"); - grub_uint8_t candidate_key[keysize]; - grub_uint8_t digest[keysize]; - split_key = grub_malloc (keysize * LUKS_STRIPES); if (!split_key) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); return grub_errno; } /* Get the passphrase from the user. */ - grub_printf ("Enter passphrase for %s (%s): ", name, uuid); + grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid); if (!grub_password_get (passphrase, MAX_PASSPHRASE)) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); } /* Try to recover master key from each active keyslot. */ - for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) + for (i = 0; i < ARRAY_SIZE (header->keyblock); i++) { gcry_err_code_t gcry_err; /* Check if keyslot is enabled. */ - if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) + if (grub_be_to_cpu32 (header->keyblock[i].active) != LUKS_KEY_ENABLED) continue; grub_dprintf ("luks", "Trying keyslot %d\n", i); /* Calculate the PBKDF2 of the user supplied passphrase. */ - gcry_err = grub_crypto_pbkdf2 (hash, (grub_uint8_t *) passphrase, + gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, grub_strlen (passphrase), - header.keyblock[i].passwordSalt, - sizeof (header. + header->keyblock[i].passwordSalt, + sizeof (header-> keyblock[i].passwordSalt), - grub_be_to_cpu32 (header.keyblock[i]. + grub_be_to_cpu32 (header->keyblock[i]. passwordIterations), digest, keysize); if (gcry_err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); @@ -331,60 +352,52 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) grub_dprintf ("luks", "PBKDF2 done\n"); /* Set the PBKDF2 output as the cipher key. */ - gcry_err = grub_crypto_cipher_set_key (cipher, digest, keysize); + gcry_err = grub_crypto_cipher_set_key (dev->cipher, digest, keysize); if (gcry_err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } /* Configure ESSIV if necessary. */ - if (mode == GRUB_LUKS_MODE_CBC_ESSIV) + if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) { - grub_crypto_hash (essiv_hash, hashed_key, digest, keysize); - grub_crypto_cipher_set_key (essiv_cipher, hashed_key, + grub_crypto_hash (dev->essiv_hash, hashed_key, digest, keysize); + grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key, essiv_keysize); } length = - grub_be_to_cpu32 (header.keyBytes) * - grub_be_to_cpu32 (header.keyblock[i].stripes); + grub_be_to_cpu32 (header->keyBytes) * + grub_be_to_cpu32 (header->keyblock[i].stripes); /* Read and decrypt the key material from the disk. */ err = grub_disk_read (source, - grub_be_to_cpu32 (header.keyblock + grub_be_to_cpu32 (header->keyblock [i].keyMaterialOffset), 0, length, split_key); if (err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return err; } - gcry_err = luks_decrypt (cipher, mode, split_key, - length, 0, essiv_cipher); + gcry_err = luks_decrypt (dev->cipher, dev->mode, split_key, + length, 0, dev->essiv_cipher); if (gcry_err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } /* Merge the decrypted key material to get the candidate master key. */ - gcry_err = AF_merge (hash, split_key, candidate_key, keysize, - grub_be_to_cpu32 (header.keyblock[i].stripes)); + gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize, + grub_be_to_cpu32 (header->keyblock[i].stripes)); if (gcry_err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); @@ -393,18 +406,16 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) grub_dprintf ("luks", "candidate key recovered\n"); /* Calculate the PBKDF2 of the candidate master key. */ - gcry_err = grub_crypto_pbkdf2 (hash, candidate_key, - grub_be_to_cpu32 (header.keyBytes), - header.mkDigestSalt, - sizeof (header.mkDigestSalt), + gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key, + grub_be_to_cpu32 (header->keyBytes), + header->mkDigestSalt, + sizeof (header->mkDigestSalt), grub_be_to_cpu32 - (header.mkDigestIterations), + (header->mkDigestIterations), candidate_digest, sizeof (candidate_digest)); if (gcry_err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); @@ -412,71 +423,90 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) /* Compare the calculated PBKDF2 to the digest stored in the header to see if it's correct. */ - if (grub_memcmp (candidate_digest, header.mkDigest, - sizeof (header.mkDigest)) != 0) + if (grub_memcmp (candidate_digest, header->mkDigest, + sizeof (header->mkDigest)) != 0) continue; grub_printf ("Slot %d opened\n", i); /* Set the master key. */ - gcry_err = grub_crypto_cipher_set_key (cipher, candidate_key, keysize); + gcry_err = grub_crypto_cipher_set_key (dev->cipher, + candidate_key, keysize); if (gcry_err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } /* Configure ESSIV if necessary. */ - if (mode == GRUB_LUKS_MODE_CBC_ESSIV) + if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) { - grub_crypto_hash (essiv_hash, hashed_key, candidate_key, keysize); + grub_crypto_hash (dev->essiv_hash, hashed_key, + candidate_key, keysize); gcry_err = - grub_crypto_cipher_set_key (essiv_cipher, hashed_key, + grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key, essiv_keysize); if (gcry_err) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } } - { - grub_luks_t newdev; - newdev = grub_zalloc (sizeof (struct grub_luks)); - if (!newdev) - return grub_errno; - newdev->id = n; - newdev->source = grub_strdup (name); - newdev->source_id = source->id; - newdev->source_dev_id = source->dev->id; - newdev->cipher = cipher; - newdev->offset = grub_be_to_cpu32 (header.payloadOffset); - newdev->source_disk = NULL; - newdev->mode = mode; - newdev->essiv_cipher = essiv_cipher; - grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); - newdev->next = luks_list; - luks_list = newdev; - n++; - } grub_free (split_key); grub_free (hashed_key); - have_it = 1; - return GRUB_ERR_NONE; } return GRUB_ACCESS_DENIED; } +static void +luks_close (grub_luks_t luks) +{ + grub_crypto_cipher_close (luks->cipher); + grub_crypto_cipher_close (luks->essiv_cipher); + grub_free (luks); +} + +static grub_err_t +grub_luks_scan_device_real (const char *name, grub_disk_t source) +{ + grub_err_t err; + struct grub_luks_phdr header; + grub_luks_t newdev; + + /* Read the LUKS header. */ + err = grub_disk_read (source, 0, 0, sizeof (header), &header); + if (err) + return err; + + newdev = configure_ciphers (&header); + if (!newdev) + return grub_errno; + + err = luks_recover_key (newdev, &header, name, source); + if (err) + { + luks_close (newdev); + return err; + } + + newdev->source = grub_strdup (name); + newdev->source_id = source->id; + newdev->source_dev_id = source->dev->id; + newdev->next = luks_list; + luks_list = newdev; + + have_it = 1; + + return GRUB_ERR_NONE; +} + static int grub_luks_scan_device (const char *name) { From dcd73ec05ef7a98f403860fcf7c9d80ef3c6440b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 19:04:21 +0200 Subject: [PATCH 123/673] add gcry to utils --- .bzrignore | 1 + Makefile.util.def | 18 ++++++++++-------- autogen.sh | 2 +- include/grub/crypto.h | 6 ++++++ util/grub-probe.c | 2 ++ util/import_gcry.py | 36 ++++++++++++++++++++++++++++++++++++ 6 files changed, 56 insertions(+), 9 deletions(-) diff --git a/.bzrignore b/.bzrignore index 55cbdaeeb..204fc182f 100644 --- a/.bzrignore +++ b/.bzrignore @@ -135,3 +135,4 @@ widthspec.bin widthspec.h docs/stamp-1 docs/version-dev.texi +Makefile.utilgcry.def diff --git a/Makefile.util.def b/Makefile.util.def index 40c67c233..693a7d127 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -21,12 +21,16 @@ library = { common = grub-core/kern/list.c; common = grub-core/kern/misc.c; common = grub-core/kern/partition.c; + common = grub-core/lib/crypto.c; + common = grub-core/disk/luks.c; + common = grub-core/disk/AFSplitter.c; + common = grub-core/lib/pbkdf2.c; + common = grub-core/commands/extcmd.c; + common = grub-core/lib/arg.c; }; library = { name = libgrubmods.a; - cflags = '$(CFLAGS_GCRY)'; - cppflags = '$(CPPFLAGS_GCRY)'; common_nodist = grub_script.tab.c; common_nodist = grub_script.yy.c; @@ -35,7 +39,6 @@ library = { common_nodist = grub_script.tab.h; common = grub-core/commands/blocklist.c; - common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/loopback.c; @@ -75,15 +78,10 @@ library = { common = grub-core/fs/zfs/zfs_lzjb.c; common = grub-core/fs/zfs/zfs_sha256.c; common = grub-core/fs/zfs/zfs_fletcher.c; - common = grub-core/lib/arg.c; - common = grub-core/lib/crypto.c; common = grub-core/lib/envblk.c; common = grub-core/lib/hexdump.c; - common = grub-core/lib/libgcrypt-grub/cipher/sha512.c; - common = grub-core/lib/libgcrypt-grub/cipher/crc.c; common = grub-core/lib/LzFind.c; common = grub-core/lib/LzmaEnc.c; - common = grub-core/lib/pbkdf2.c; common = grub-core/lib/crc.c; common = grub-core/normal/datetime.c; common = grub-core/normal/misc.c; @@ -123,6 +121,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBLZMA)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; @@ -173,6 +172,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; cflags = '$(CFLAGS_GCRY)'; @@ -211,6 +211,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -257,6 +258,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; diff --git a/autogen.sh b/autogen.sh index d14707aad..db719cd1d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -26,7 +26,7 @@ if [ "x${GRUB_CONTRIB}" != x ]; then [ "${GRUB_CONTRIB}" = grub-core/contrib ] || ln -s ../contrib grub-core/contrib fi -UTIL_DEFS=Makefile.util.def +UTIL_DEFS='Makefile.util.def Makefile.utilgcry.def' CORE_DEFS='grub-core/Makefile.core.def grub-core/Makefile.gcry.def' for extra in contrib/*/Makefile.util.def; do diff --git a/include/grub/crypto.h b/include/grub/crypto.h index ebe78e7a1..a8ca2106d 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -274,4 +274,10 @@ grub_password_get (char buf[], unsigned buf_size); extern void (*grub_crypto_autoload_hook) (const char *name); +#ifdef GRUB_UTIL +void grub_gcry_init_all (void); +void grub_gcry_fini_all (void); +#endif + + #endif diff --git a/util/grub-probe.c b/util/grub-probe.c index 0d5dac902..6c6220b8b 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -393,6 +393,7 @@ main (int argc, char *argv[]) /* Initialize all modules. */ grub_init_all (); + grub_gcry_init_all (); grub_lvm_fini (); grub_mdraid09_fini (); @@ -410,6 +411,7 @@ main (int argc, char *argv[]) probe (argument, NULL); /* Free resources. */ + grub_gcry_fini_all (); grub_fini_all (); grub_util_biosdisk_fini (); diff --git a/util/import_gcry.py b/util/import_gcry.py index b2a0a5451..3a110f028 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -42,7 +42,15 @@ except: cipher_files = os.listdir (cipher_dir_in) conf = open (os.path.join ("grub-core", "Makefile.gcry.def"), "w") conf.write ("AutoGen definitions Makefile.tpl;\n\n") +confutil = open ("Makefile.utilgcry.def", "w") +confutil.write ("AutoGen definitions Makefile.tpl;\n\n") +confutil.write ("library = {\n"); +confutil.write (" name = libgrubgcry.a;\n"); +confutil.write (" cflags = '$(CFLAGS_GCRY)';\n"); +confutil.write (" cppflags = '$(CPPFLAGS_GCRY)';\n"); +confutil.write ("\n"); chlog = "" +modules = [] # Strictly speaking CRC32/CRC24 work on bytes so this value should be 1 # But libgcrypt uses 64. Let's keep the value for compatibility. Since @@ -249,6 +257,7 @@ for cipher_file in cipher_files: % (cipher_file, cipher_file.replace ("-glue.c", ".c")) else: modfiles = "lib/libgcrypt-grub/cipher/%s" % cipher_file + modules.append (modname) chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname if nch: chlognew = "%s\n %s" % (chlognew, chmsg) @@ -283,6 +292,7 @@ for cipher_file in cipher_files: conf.write (" name = %s;\n" % modname) for src in modfiles.split(): conf.write (" common = %s;\n" % src) + confutil.write (" common = grub-core/%s;\n" % src) conf.write (" cflags = '$(CFLAGS_GCRY)';\n"); conf.write (" cppflags = '$(CPPFLAGS_GCRY)';\n"); conf.write ("};\n\n") @@ -329,6 +339,32 @@ fw.close () infile = os.path.join (cipher_dir_in, "ChangeLog") outfile = os.path.join (cipher_dir_out, "ChangeLog") +conf.close (); + +initfile = open (os.path.join (cipher_dir_out, "init.c"), "w") +for module in modules: + initfile.write ("extern void grub_%s_init (void);\n" % module) + initfile.write ("extern void grub_%s_fini (void);\n" % module) +initfile.write ("\n") +initfile.write ("void\n") +initfile.write ("grub_gcry_init_all (void)\n") +initfile.write ("{\n") +for module in modules: + initfile.write (" grub_%s_init ();\n" % module) +initfile.write ("}\n") +initfile.write ("\n") +initfile.write ("void\n") +initfile.write ("grub_gcry_fini_all (void)\n") +initfile.write ("{\n") +for module in modules: + initfile.write (" grub_%s_fini ();\n" % module) +initfile.write ("}\n") +initfile.close () + +confutil.write (" common = grub-core/lib/libgcrypt-grub/cipher/init.c;\n") +confutil.write ("};\n"); +confutil.close (); + f=open (infile, "r") fw=open (outfile, "w") From 24089d19e2dde4e72d8c783a3f1a607f5a8e7729 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 19:20:46 +0200 Subject: [PATCH 124/673] Add cheatmounting --- grub-core/disk/luks.c | 99 +++++++++++++++++++++++++++++++++-- grub-core/kern/emu/getroot.c | 26 +++++++-- grub-core/kern/emu/hostdisk.c | 75 ++++++++++++++------------ include/grub/emu/hostdisk.h | 6 +++ 4 files changed, 166 insertions(+), 40 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 4d907b4c6..99dd3a8e6 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -25,6 +25,15 @@ #include #include #include +#ifdef GRUB_UTIL +#include +#include +#include +#include +#include +#include +#include +#endif GRUB_MOD_LICENSE ("GPLv3+"); @@ -80,6 +89,10 @@ struct grub_luks unsigned long id, source_id; enum grub_disk_dev_id source_dev_id; char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; +#ifdef GRUB_UTIL + char *cheat; + int cheat_fd; +#endif struct grub_luks *next; }; typedef struct grub_luks *grub_luks_t; @@ -497,6 +510,12 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) } newdev->source = grub_strdup (name); + if (!newdev->source) + { + grub_free (newdev); + return grub_errno; + } + newdev->source_id = source->id; newdev->source_dev_id = source->dev->id; newdev->next = luks_list; @@ -507,6 +526,48 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) return GRUB_ERR_NONE; } +#ifdef GRUB_UTIL +grub_err_t +grub_luks_cheat_mount (const char *sourcedev, const char *cheat) +{ + grub_err_t err; + struct grub_luks_phdr header; + grub_luks_t newdev; + grub_disk_t source; + + /* Try to open disk. */ + source = grub_disk_open (sourcedev); + if (!source) + return grub_errno; + + /* Read the LUKS header. */ + err = grub_disk_read (source, 0, 0, sizeof (header), &header); + if (err) + return err; + + newdev = configure_ciphers (&header); + grub_disk_close (source); + if (!newdev) + return grub_errno; + + newdev->cheat = grub_strdup (cheat); + newdev->source = grub_strdup (sourcedev); + if (!newdev->source || !newdev->cheat) + { + grub_free (newdev->source); + grub_free (newdev->cheat); + grub_free (newdev); + return grub_errno; + } + newdev->cheat_fd = -1; + newdev->source_id = source->id; + newdev->source_dev_id = source->dev->id; + newdev->next = luks_list; + luks_list = newdev; + return GRUB_ERR_NONE; +} +#endif + static int grub_luks_scan_device (const char *name) { @@ -575,6 +636,17 @@ grub_luks_open (const char *name, grub_disk_t disk, if (!dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); +#ifdef GRUB_UTIL + if (dev->cheat) + { + if (dev->cheat_fd == -1) + dev->cheat_fd = open (dev->cheat, O_RDONLY); + if (dev->cheat_fd == -1) + return grub_error (GRUB_ERR_IO, "couldn't open %s: %s", + dev->cheat, strerror (errno)); + } +#endif + if (!dev->source_disk) { grub_dprintf ("luks", "Opening device %s\n", name); @@ -599,11 +671,17 @@ grub_luks_close (grub_disk_t disk) dev->ref--; - if (dev->ref == 0) + if (dev->ref != 0) + return; +#ifdef GRUB_UTIL + if (dev->cheat) { - grub_disk_close (dev->source_disk); - dev->source_disk = NULL; + close (dev->cheat_fd); + dev->cheat_fd = -1; } +#endif + grub_disk_close (dev->source_disk); + dev->source_disk = NULL; } static grub_err_t @@ -612,6 +690,21 @@ grub_luks_read (grub_disk_t disk, grub_disk_addr_t sector, { grub_luks_t dev = (grub_luks_t) disk->data; grub_err_t err; + +#ifdef GRUB_UTIL + if (dev->cheat) + { + err = grub_util_fd_sector_seek (dev->cheat_fd, dev->cheat, sector); + if (err) + return err; + if (grub_util_fd_read (dev->cheat_fd, buf, size << GRUB_DISK_SECTOR_BITS) + != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", + dev->cheat); + return GRUB_ERR_NONE; + } +#endif + grub_dprintf ("luks", "Reading %" PRIuGRUB_SIZE " sectors from sector 0x%" PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT32_T "\n", diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index 6cc745833..c3a971689 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -865,7 +865,9 @@ out: void grub_util_pull_device (const char *os_dev) { - switch (grub_util_get_dev_abstraction (os_dev)) + int ab; + ab = grub_util_get_dev_abstraction (os_dev); + switch (ab) { case GRUB_DEV_ABSTRACTION_LVM: case GRUB_DEV_ABSTRACTION_LUKS: @@ -875,6 +877,7 @@ grub_util_pull_device (const char *os_dev) struct dm_tree_node *node; struct dm_tree_node *child; void *handle = NULL; + char *lastsubdev = NULL; if (!grub_util_open_dm (os_dev, &tree, &node)) return; @@ -887,9 +890,26 @@ grub_util_pull_device (const char *os_dev) continue; subdev = grub_find_device ("/dev", makedev (dm->major, dm->minor)); if (subdev) - grub_util_pull_device (subdev); + { + lastsubdev = subdev; + grub_util_pull_device (subdev); + } } - dm_tree_free (tree); + if (ab == GRUB_DEV_ABSTRACTION_LUKS && lastsubdev) + { + char *grdev = grub_util_get_grub_dev (lastsubdev); + dm_tree_free (tree); + if (grdev) + { + grub_err_t err; + err = grub_luks_cheat_mount (grdev, os_dev); + if (err) + grub_util_error ("Can't mount LUKS: %s", grub_errmsg); + } + grub_free (grdev); + } + else + dm_tree_free (tree); } #endif return; diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 9b65d417e..110d3e291 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -631,6 +631,37 @@ linux_find_partition (char *dev, unsigned long sector) } #endif /* __linux__ */ +#if defined(__linux__) && (!defined(__GLIBC__) || \ + ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) + /* Maybe libc doesn't have large file support. */ +grub_err_t +grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector) +{ + loff_t offset, result; + static int _llseek (uint filedes, ulong hi, ulong lo, + loff_t *res, uint wh); + _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, + loff_t *, res, uint, wh); + + offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS; + if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) + { + return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name); + } + return GRUB_ERR_NONE; +} +#else +grub_err_t +grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector) +{ + off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS; + + if (lseek (fd, offset, SEEK_SET) != offset) + return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name); + return 0; +} +#endif + static int open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) { @@ -781,44 +812,19 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) configure_device_driver (fd); #endif /* defined(__NetBSD__) */ -#if defined(__linux__) && (!defined(__GLIBC__) || \ - ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) - /* Maybe libc doesn't have large file support. */ - { - loff_t offset, result; - static int _llseek (uint filedes, ulong hi, ulong lo, - loff_t *res, uint wh); - _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, - loff_t *, res, uint, wh); - - offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS; - if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device); - close (fd); - return -1; - } - } -#else - { - off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS; - - if (lseek (fd, offset, SEEK_SET) != offset) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device); - close (fd); - return -1; - } - } -#endif + if (grub_util_fd_sector_seek (fd, map[disk->id].device, sector)) + { + close (fd); + return -1; + } return fd; } /* Read LEN bytes from FD in BUF. Return less than or equal to zero if an error occurs, otherwise return LEN. */ -static ssize_t -nread (int fd, char *buf, size_t len) +ssize_t +grub_util_fd_read (int fd, char *buf, size_t len) { ssize_t size = len; @@ -901,7 +907,8 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, sectors that are read together with the MBR in one read. It should only remap the MBR, so we split the read in two parts. -jochen */ - if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) + if (grub_util_fd_read (fd, buf, GRUB_DISK_SECTOR_SIZE) + != GRUB_DISK_SECTOR_SIZE) { grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device); return grub_errno; @@ -912,7 +919,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, } #endif /* __linux__ */ - if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS) + if (grub_util_fd_read (fd, buf, size << GRUB_DISK_SECTOR_BITS) != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device); diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 803c0f755..c7a794d68 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -21,6 +21,7 @@ #define GRUB_BIOSDISK_MACHINE_UTIL_HEADER 1 #include +#include void grub_util_biosdisk_init (const char *dev_map); void grub_util_biosdisk_fini (void); @@ -30,5 +31,10 @@ int grub_util_biosdisk_is_present (const char *name); int grub_util_biosdisk_is_floppy (grub_disk_t disk); grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk); void grub_util_pull_device (const char *osname); +grub_err_t +grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector); +ssize_t grub_util_fd_read (int fd, char *buf, size_t len); +grub_err_t +grub_luks_cheat_mount (const char *sourcedev, const char *cheat); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ From 4169260830d30fca23af54441bfd3ea749b7c006 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 19:44:41 +0200 Subject: [PATCH 125/673] grub-fstest luks support --- grub-core/disk/luks.c | 28 ++++++++++++++++++++++++---- util/grub-fstest.c | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 99dd3a8e6..eb9dd050e 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -107,6 +107,7 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, static const struct grub_arg_option options[] = { {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, + {"all", 'a', 0, N_("Mount all."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -491,7 +492,11 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) { grub_err_t err; struct grub_luks_phdr header; - grub_luks_t newdev; + grub_luks_t newdev, dev; + + for (dev = luks_list; dev != NULL; dev = dev->next) + if (dev->source_id == source->id && dev->source_dev_id == source->dev->id) + return GRUB_ERR_NONE; /* Read the LUKS header. */ err = grub_disk_read (source, 0, 0, sizeof (header), &header); @@ -532,7 +537,7 @@ grub_luks_cheat_mount (const char *sourcedev, const char *cheat) { grub_err_t err; struct grub_luks_phdr header; - grub_luks_t newdev; + grub_luks_t newdev, dev; grub_disk_t source; /* Try to open disk. */ @@ -540,6 +545,13 @@ grub_luks_cheat_mount (const char *sourcedev, const char *cheat) if (!source) return grub_errno; + for (dev = luks_list; dev != NULL; dev = dev->next) + if (dev->source_id == source->id && dev->source_dev_id == source->dev->id) + { + grub_disk_close (source); + return GRUB_ERR_NONE; + } + /* Read the LUKS header. */ err = grub_disk_read (source, 0, 0, sizeof (header), &header); if (err) @@ -755,7 +767,7 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; - if (argc < 1) + if (argc < 1 && !state[1].set) return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); have_it = 0; @@ -779,6 +791,14 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); return GRUB_ERR_NONE; } + else if (state[1].set) + { + check_uuid = 0; + search_uuid = NULL; + grub_device_iterate (&grub_luks_scan_device); + search_uuid = NULL; + return GRUB_ERR_NONE; + } else { grub_err_t err; @@ -823,7 +843,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (luks) { cmd = grub_register_extcmd ("luksmount", grub_cmd_luksmount, 0, - N_("SOURCE|-u UUID"), + N_("SOURCE|-u UUID|-a"), N_("Mount a LUKS device."), options); grub_disk_dev_register (&grub_luks_dev); } diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 293bdf74a..2adb2331d 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -275,6 +275,7 @@ static char **images = NULL; static int cmd = 0; static char *debug_str = NULL; static char **args = NULL; +static int mount_crypt = 0; static void fstest (int n, char **args) @@ -304,6 +305,13 @@ fstest (int n, char **args) grub_free (host_file); } + { + char *argv[2] = { "-a", NULL}; + if (mount_crypt) + if (execute_command ("luksmount", 1, argv)) + grub_util_error (_("luksmount command fails: %s"), grub_errmsg); + } + grub_lvm_fini (); grub_mdraid09_fini (); grub_mdraid1x_fini (); @@ -366,6 +374,7 @@ static struct argp_option options[] = { {"length", 'n', "N", 0, N_("Handle N bytes in output file."), 2}, {"diskcount", 'c', "N", 0, N_("N input files."), 2}, {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, + {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, {0, 0, 0, 0, 0, 0} }; @@ -389,6 +398,10 @@ argp_parser (int key, char *arg, struct argp_state *state) root = arg; return 0; + case 'C': + mount_crypt = 1; + return 0; + case 's': skip = grub_strtoul (arg, &p, 0); if (*p == 's') @@ -523,6 +536,7 @@ main (int argc, char *argv[]) /* Initialize all modules. */ grub_init_all (); + grub_gcry_init_all (); if (debug_str) grub_env_set ("debug", debug_str); @@ -551,6 +565,7 @@ main (int argc, char *argv[]) fstest (args_count - 1 - num_disks, args); /* Free resources. */ + grub_gcry_fini_all (); grub_fini_all (); return 0; From 84a411c0c3b17ba1a67ef30a94134bb8c8a9266a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 19:51:06 +0200 Subject: [PATCH 126/673] small argument revamp --- grub-core/disk/luks.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index eb9dd050e..8bf07903c 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -112,27 +112,26 @@ static const struct grub_arg_option options[] = }; static gcry_err_code_t -luks_decrypt (grub_crypto_cipher_handle_t cipher, luks_mode_t mode, - grub_uint8_t * data, grub_size_t len, - grub_size_t sector, grub_crypto_cipher_handle_t essiv_cipher) +luks_decrypt (const struct grub_luks *dev, + grub_uint8_t * data, grub_size_t len, grub_size_t sector) { grub_size_t i; gcry_err_code_t err; - switch (mode) + switch (dev->mode) { case GRUB_LUKS_MODE_ECB: - return grub_crypto_ecb_decrypt (cipher, data, data, len); + return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); case GRUB_LUKS_MODE_CBC_PLAIN: for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) { - grub_uint32_t iv[(cipher->cipher->blocksize + grub_uint32_t iv[(dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) / sizeof (grub_uint32_t)]; - grub_memset (iv, 0, cipher->cipher->blocksize); + grub_memset (iv, 0, dev->cipher->cipher->blocksize); iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); - err = grub_crypto_cbc_decrypt (cipher, data + i, data + i, + err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, GRUB_DISK_SECTOR_SIZE, iv); if (err) return err; @@ -143,17 +142,17 @@ luks_decrypt (grub_crypto_cipher_handle_t cipher, luks_mode_t mode, case GRUB_LUKS_MODE_CBC_ESSIV: for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) { - grub_uint32_t iv[(cipher->cipher->blocksize + grub_uint32_t iv[(dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) / sizeof (grub_uint32_t)]; - grub_memset (iv, 0, cipher->cipher->blocksize); + grub_memset (iv, 0, dev->cipher->cipher->blocksize); iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); err = - grub_crypto_ecb_encrypt (essiv_cipher, iv, iv, - cipher->cipher->blocksize); + grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv, + dev->cipher->cipher->blocksize); if (err) return err; - err = grub_crypto_cbc_decrypt (cipher, data + i, data + i, + err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, GRUB_DISK_SECTOR_SIZE, iv); if (err) return err; @@ -398,8 +397,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, return err; } - gcry_err = luks_decrypt (dev->cipher, dev->mode, split_key, - length, 0, dev->essiv_cipher); + gcry_err = luks_decrypt (dev, split_key, length, 0); if (gcry_err) { grub_free (hashed_key); @@ -729,11 +727,9 @@ grub_luks_read (grub_disk_t disk, grub_disk_addr_t sector, grub_dprintf ("luks", "grub_disk_read failed with error %d\n", err); return err; } - return grub_crypto_gcry_error (luks_decrypt (dev->cipher, - dev->mode, - (grub_uint8_t *) buf, + return grub_crypto_gcry_error (luks_decrypt (dev, (grub_uint8_t *) buf, size << GRUB_DISK_SECTOR_BITS, - sector, dev->essiv_cipher)); + sector)); } static grub_err_t From 2cb55e6f7356d82f826e65577373167a46b73f8d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 21:46:00 +0200 Subject: [PATCH 127/673] make grub_password_get work in userland --- grub-core/lib/crypto.c | 44 ++++++++++++++++++++- util/grub-mkpasswd-pbkdf2.c | 76 ++++++------------------------------- 2 files changed, 53 insertions(+), 67 deletions(-) diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index ad1bfc4d3..2f172ebf8 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -23,6 +23,13 @@ #include #include +#ifdef GRUB_UTIL +#include +#include +#include +#include +#endif + GRUB_MOD_LICENSE ("GPLv3+"); struct grub_crypto_hmac_handle @@ -414,10 +421,43 @@ grub_crypto_memcmp (const void *a, const void *b, grub_size_t n) return !!counter; } -#ifndef GRUB_MKPASSWD int grub_password_get (char buf[], unsigned buf_size) { +#ifdef GRUB_UTIL + FILE *in; + struct termios s, t; + int tty_changed = 0; + char *ptr; + + /* Disable echoing. Based on glibc. */ + in = fopen ("/dev/tty", "w+c"); + if (in == NULL) + in = stdin; + + if (tcgetattr (fileno (in), &t) == 0) + { + /* Save the old one. */ + s = t; + /* Tricky, tricky. */ + t.c_lflag &= ~(ECHO|ISIG); + tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0); + } + else + tty_changed = 0; + fgets (buf, buf_size, stdin); + ptr = buf + strlen (buf) - 1; + while (buf <= ptr && (*ptr == '\n' || *ptr == '\r')) + *ptr-- = 0; + /* Restore the original setting. */ + if (tty_changed) + (void) tcsetattr (fileno (in), TCSAFLUSH, &s); + + grub_xputs ("\n"); + grub_refresh (); + + return 1; +#else unsigned cur_len = 0; int key; @@ -452,5 +492,5 @@ grub_password_get (char buf[], unsigned buf_size) grub_refresh (); return (key != '\e'); -} #endif +} diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index fe1887f8f..032a8b586 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include #include "progname.h" @@ -85,14 +85,12 @@ int main (int argc, char *argv[]) { unsigned int count = 10000, buflen = 64, saltlen = 64; - char *pass1, *pass2; char *bufhex, *salthex; gcry_err_code_t gcry_err; grub_uint8_t *buf, *salt; ssize_t nr; - FILE *in, *out; - struct termios s, t; - int tty_changed; + char pass1[GRUB_AUTH_MAX_PASSLEN]; + char pass2[GRUB_AUTH_MAX_PASSLEN]; set_program_name (argv[0]); @@ -160,86 +158,37 @@ main (int argc, char *argv[]) free (buf); grub_util_error ("out of memory"); } - - /* Disable echoing. Based on glibc. */ - in = fopen ("/dev/tty", "w+c"); - if (in == NULL) - { - in = stdin; - out = stderr; - } - else - out = in; - - if (tcgetattr (fileno (in), &t) == 0) - { - /* Save the old one. */ - s = t; - /* Tricky, tricky. */ - t.c_lflag &= ~(ECHO|ISIG); - tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0); - } - else - tty_changed = 0; printf ("Enter password: "); - pass1 = NULL; - { - grub_size_t n; - nr = getline (&pass1, &n, stdin); - } - if (nr < 0 || !pass1) + if (!grub_password_get (pass1, GRUB_AUTH_MAX_PASSLEN)) { free (buf); free (bufhex); free (salthex); free (salt); - /* Restore the original setting. */ - if (tty_changed) - (void) tcsetattr (fileno (in), TCSAFLUSH, &s); grub_util_error ("failure to read password"); } - if (nr >= 1 && pass1[nr-1] == '\n') - pass1[nr-1] = 0; - printf ("\nReenter password: "); - pass2 = NULL; - { - grub_size_t n; - nr = getline (&pass2, &n, stdin); - } - /* Restore the original setting. */ - if (tty_changed) - (void) tcsetattr (fileno (in), TCSAFLUSH, &s); - printf ("\n"); - - if (nr < 0 || !pass2) + if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN)) { - memset (pass1, 0, strlen (pass1)); - free (pass1); free (buf); free (bufhex); free (salthex); free (salt); grub_util_error ("failure to read password"); } - if (nr >= 1 && pass2[nr-1] == '\n') - pass2[nr-1] = 0; if (strcmp (pass1, pass2) != 0) { - memset (pass1, 0, strlen (pass1)); - memset (pass2, 0, strlen (pass2)); - free (pass1); - free (pass2); + memset (pass1, 0, sizeof (pass1)); + memset (pass2, 0, sizeof (pass2)); free (buf); free (bufhex); free (salthex); free (salt); grub_util_error ("passwords don't match"); } - memset (pass2, 0, strlen (pass2)); - free (pass2); + memset (pass2, 0, sizeof (pass2)); #if ! defined (__linux__) && ! defined (__FreeBSD__) printf ("WARNING: your random generator isn't known to be secure\n"); @@ -251,8 +200,7 @@ main (int argc, char *argv[]) f = fopen ("/dev/random", "rb"); if (!f) { - memset (pass1, 0, strlen (pass1)); - free (pass1); + memset (pass1, 0, sizeof (pass1)); free (buf); free (bufhex); free (salthex); @@ -264,8 +212,7 @@ main (int argc, char *argv[]) if (rd != saltlen) { fclose (f); - memset (pass1, 0, strlen (pass1)); - free (pass1); + memset (pass1, 0, sizeof (pass1)); free (buf); free (bufhex); free (salthex); @@ -280,8 +227,7 @@ main (int argc, char *argv[]) (grub_uint8_t *) pass1, strlen (pass1), salt, saltlen, count, buf, buflen); - memset (pass1, 0, strlen (pass1)); - free (pass1); + memset (pass1, 0, sizeof (pass1)); if (gcry_err) { From fe32915a5ebc39f21524547c6a7ec6d123534828 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 21:48:32 +0200 Subject: [PATCH 128/673] XTS support --- grub-core/disk/luks.c | 192 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 157 insertions(+), 35 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 8bf07903c..0098c9d49 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -73,7 +73,8 @@ typedef enum { GRUB_LUKS_MODE_ECB, GRUB_LUKS_MODE_CBC_PLAIN, - GRUB_LUKS_MODE_CBC_ESSIV + GRUB_LUKS_MODE_CBC_ESSIV, + GRUB_LUKS_MODE_XTS } luks_mode_t; struct grub_luks @@ -83,7 +84,7 @@ struct grub_luks grub_disk_t source_disk; int ref; grub_crypto_cipher_handle_t cipher; - grub_crypto_cipher_handle_t essiv_cipher; + grub_crypto_cipher_handle_t secondary_cipher; const gcry_md_spec_t *essiv_hash, *hash; luks_mode_t mode; unsigned long id, source_id; @@ -111,6 +112,33 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; +static inline void +make_iv (grub_uint32_t *iv, grub_size_t sz, grub_disk_addr_t sector) +{ + grub_memset (iv, 0, sz * sizeof (iv[0])); + iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); +} + +/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ +#define POLYNOM 0x87 + +static void +gf_mul_x (grub_uint8_t *g) +{ + int over = 0, over2 = 0; + int j; + + for (j = 0; j < 16; j++) + { + over2 = !!(g[j] & 0x80); + g[j] <<= 1; + g[j] |= over; + over = over2; + } + if (over) + g[0] ^= POLYNOM; +} + static gcry_err_code_t luks_decrypt (const struct grub_luks *dev, grub_uint8_t * data, grub_size_t len, grub_size_t sector) @@ -126,11 +154,11 @@ luks_decrypt (const struct grub_luks *dev, case GRUB_LUKS_MODE_CBC_PLAIN: for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) { - grub_uint32_t iv[(dev->cipher->cipher->blocksize + grub_size_t sz = ((dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) - / sizeof (grub_uint32_t)]; - grub_memset (iv, 0, dev->cipher->cipher->blocksize); - iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + / sizeof (grub_uint32_t)); + grub_uint32_t iv[sz]; + make_iv (iv, sz, sector); err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, GRUB_DISK_SECTOR_SIZE, iv); if (err) @@ -142,14 +170,14 @@ luks_decrypt (const struct grub_luks *dev, case GRUB_LUKS_MODE_CBC_ESSIV: for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) { - grub_uint32_t iv[(dev->cipher->cipher->blocksize + grub_size_t sz = ((dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) - / sizeof (grub_uint32_t)]; - grub_memset (iv, 0, dev->cipher->cipher->blocksize); - iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); - err = - grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv, - dev->cipher->cipher->blocksize); + / sizeof (grub_uint32_t)); + grub_uint32_t iv[sz]; + make_iv (iv, sz, sector); + + err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, + dev->cipher->cipher->blocksize); if (err) return err; err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, @@ -160,6 +188,39 @@ luks_decrypt (const struct grub_luks *dev, } return GPG_ERR_NO_ERROR; + case GRUB_LUKS_MODE_XTS: + for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) + { + grub_size_t sz = ((dev->cipher->cipher->blocksize + + sizeof (grub_uint32_t) - 1) + / sizeof (grub_uint32_t)); + grub_uint32_t iv[sz]; + int j; + make_iv (iv, sz, sector); + + err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, + dev->cipher->cipher->blocksize); + if (err) + return err; + + for (j = 0; j < GRUB_DISK_SECTOR_SIZE; + j += dev->cipher->cipher->blocksize) + { + grub_crypto_xor (data + i + j, data + i + j, iv, + dev->cipher->cipher->blocksize); + err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, + data + i + j, + dev->cipher->cipher->blocksize); + if (err) + return err; + grub_crypto_xor (data + i + j, data + i + j, iv, + dev->cipher->cipher->blocksize); + gf_mul_x ((grub_uint8_t *) iv); + } + sector++; + } + return GPG_ERR_NO_ERROR; + default: return GPG_ERR_NOT_IMPLEMENTED; } @@ -178,7 +239,7 @@ configure_ciphers (const struct grub_luks_phdr *header) char ciphername[sizeof (header->cipherName) + 1]; char ciphermode[sizeof (header->cipherMode) + 1]; char hashspec[sizeof (header->hashSpec) + 1]; - grub_crypto_cipher_handle_t cipher = NULL, essiv_cipher = NULL; + grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; const struct gcry_cipher_spec *ciph; luks_mode_t mode; @@ -232,12 +293,13 @@ configure_ciphers (const struct grub_luks_phdr *header) } /* Configure the cipher mode. */ - if (grub_strncmp (ciphermode, "ecb", 3) == 0) + if (grub_strcmp (ciphermode, "ecb") == 0) mode = GRUB_LUKS_MODE_ECB; - else if (grub_strncmp (ciphermode, "cbc-plain", 9) == 0 - || grub_strncmp (ciphermode, "plain", 5) == 0) + else if (grub_strcmp (ciphermode, "cbc-plain") == 0 + || grub_strcmp (ciphermode, "plain") == 0) mode = GRUB_LUKS_MODE_CBC_PLAIN; - else if (grub_strncmp (ciphermode, "cbc-essiv", 9) == 0) + else if (grub_memcmp (ciphermode, "cbc-essiv:", sizeof ("cbc-essiv:") - 1) + == 0) { mode = GRUB_LUKS_MODE_CBC_ESSIV; char *hash_str = ciphermode + 10; @@ -251,13 +313,35 @@ configure_ciphers (const struct grub_luks_phdr *header) "Couldn't load %s hash", hash_str); return NULL; } - essiv_cipher = grub_crypto_cipher_open (ciph); - if (!cipher) + secondary_cipher = grub_crypto_cipher_open (ciph); + if (!secondary_cipher) { grub_crypto_cipher_close (cipher); return NULL; } } + else if (grub_strcmp (ciphermode, "xts-plain") == 0) + { + mode = GRUB_LUKS_MODE_XTS; + secondary_cipher = grub_crypto_cipher_open (ciph); + if (!secondary_cipher) + { + grub_crypto_cipher_close (cipher); + return NULL; + } + if (cipher->cipher->blocksize != 16) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", + cipher->cipher->blocksize); + return NULL; + } + if (secondary_cipher->cipher->blocksize != 16) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", + secondary_cipher->cipher->blocksize); + return NULL; + } + } else { grub_crypto_cipher_close (cipher); @@ -271,7 +355,7 @@ configure_ciphers (const struct grub_luks_phdr *header) if (!hash) { grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); + grub_crypto_cipher_close (secondary_cipher); grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", hashspec); return NULL; @@ -284,7 +368,7 @@ configure_ciphers (const struct grub_luks_phdr *header) newdev->offset = grub_be_to_cpu32 (header->payloadOffset); newdev->source_disk = NULL; newdev->mode = mode; - newdev->essiv_cipher = essiv_cipher; + newdev->secondary_cipher = secondary_cipher; newdev->essiv_hash = essiv_hash; newdev->hash = hash; newdev->id = n++; @@ -309,11 +393,11 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_err_t err; if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) - essiv_keysize = dev->essiv_hash->mdlen; - hashed_key = grub_malloc (dev->essiv_hash->mdlen); - if (!hashed_key) { - return grub_errno; + essiv_keysize = dev->essiv_hash->mdlen; + hashed_key = grub_malloc (dev->essiv_hash->mdlen); + if (!hashed_key) + return grub_errno; } grub_printf ("Attempting to decrypt master key...\n"); @@ -365,7 +449,9 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_dprintf ("luks", "PBKDF2 done\n"); /* Set the PBKDF2 output as the cipher key. */ - gcry_err = grub_crypto_cipher_set_key (dev->cipher, digest, keysize); + gcry_err = grub_crypto_cipher_set_key (dev->cipher, digest, + (dev->mode == GRUB_LUKS_MODE_XTS) + ? (keysize / 2) : keysize); if (gcry_err) { grub_free (hashed_key); @@ -377,8 +463,28 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) { grub_crypto_hash (dev->essiv_hash, hashed_key, digest, keysize); - grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key, - essiv_keysize); + gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, + hashed_key, + essiv_keysize); + if (gcry_err) + { + grub_free (hashed_key); + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } + } + + if (dev->mode == GRUB_LUKS_MODE_XTS) + { + gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, + digest + (keysize / 2), + keysize / 2); + if (gcry_err) + { + grub_free (hashed_key); + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } } length = @@ -437,13 +543,17 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, in the header to see if it's correct. */ if (grub_memcmp (candidate_digest, header->mkDigest, sizeof (header->mkDigest)) != 0) - continue; + { + grub_dprintf ("luks", "bad digest\n"); + continue; + } grub_printf ("Slot %d opened\n", i); /* Set the master key. */ - gcry_err = grub_crypto_cipher_set_key (dev->cipher, - candidate_key, keysize); + gcry_err = grub_crypto_cipher_set_key (dev->cipher, candidate_key, + (dev->mode == GRUB_LUKS_MODE_XTS) + ? (keysize / 2) : keysize); if (gcry_err) { grub_free (hashed_key); @@ -457,7 +567,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_crypto_hash (dev->essiv_hash, hashed_key, candidate_key, keysize); gcry_err = - grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key, + grub_crypto_cipher_set_key (dev->secondary_cipher, hashed_key, essiv_keysize); if (gcry_err) { @@ -467,6 +577,18 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, } } + if (dev->mode == GRUB_LUKS_MODE_XTS) + { + gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, + candidate_key + (keysize / 2), + keysize / 2); + if (gcry_err) + { + grub_free (hashed_key); + grub_free (split_key); + return grub_crypto_gcry_error (gcry_err); + } + } grub_free (split_key); grub_free (hashed_key); @@ -481,7 +603,7 @@ static void luks_close (grub_luks_t luks) { grub_crypto_cipher_close (luks->cipher); - grub_crypto_cipher_close (luks->essiv_cipher); + grub_crypto_cipher_close (luks->secondary_cipher); grub_free (luks); } @@ -751,7 +873,7 @@ luks_cleanup (void) { grub_free (dev->source); grub_free (dev->cipher); - grub_free (dev->essiv_cipher); + grub_free (dev->secondary_cipher); tmp = dev->next; grub_free (dev); dev = tmp; From 50ad7d9cae1c31bbcd2ec776083f5ca59f01c06a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 23:39:36 +0200 Subject: [PATCH 129/673] luks grub-probe support --- grub-core/disk/luks.c | 35 ++++++++++ include/grub/crypto.h | 6 ++ include/grub/emu/hostdisk.h | 1 + util/grub-probe.c | 136 +++++++++++++++--------------------- util/import_gcry.py | 22 ++++-- 5 files changed, 116 insertions(+), 84 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 0098c9d49..ce1f1bfc6 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -863,6 +863,38 @@ grub_luks_write (grub_disk_t disk __attribute ((unused)), return GRUB_ERR_NOT_IMPLEMENTED_YET; } +#ifdef GRUB_UTIL +static grub_disk_memberlist_t +grub_luks_memberlist (grub_disk_t disk) +{ + grub_luks_t dev = (grub_luks_t) disk->data; + grub_disk_memberlist_t list = NULL; + + list = grub_malloc (sizeof (*list)); + if (list) + { + list->disk = dev->source_disk; + list->next = NULL; + } + + return list; +} + +void +grub_util_luks_print_ciphers (grub_disk_t disk) +{ + grub_luks_t dev = (grub_luks_t) disk->data; + if (dev->cipher) + grub_printf ("%s ", dev->cipher->cipher->modname); + if (dev->secondary_cipher) + grub_printf ("%s ", dev->secondary_cipher->cipher->modname); + if (dev->hash) + grub_printf ("%s ", dev->hash->modname); + if (dev->essiv_hash) + grub_printf ("%s ", dev->essiv_hash->modname); +} +#endif + static void luks_cleanup (void) { @@ -953,6 +985,9 @@ static struct grub_disk_dev grub_luks_dev = { .close = grub_luks_close, .read = grub_luks_read, .write = grub_luks_write, +#ifdef GRUB_UTIL + .memberlist = grub_luks_memberlist, +#endif .next = 0 }; diff --git a/include/grub/crypto.h b/include/grub/crypto.h index a8ca2106d..62ed2015c 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -126,6 +126,9 @@ typedef struct gcry_cipher_spec gcry_cipher_decrypt_t decrypt; gcry_cipher_stencrypt_t stencrypt; gcry_cipher_stdecrypt_t stdecrypt; +#ifdef GRUB_UTIL + const char *modname; +#endif struct gcry_cipher_spec *next; } gcry_cipher_spec_t; @@ -161,6 +164,9 @@ typedef struct gcry_md_spec grub_size_t contextsize; /* allocate this amount of context */ /* Block size, needed for HMAC. */ grub_size_t blocksize; +#ifdef GRUB_UTIL + const char *modname; +#endif struct gcry_md_spec *next; } gcry_md_spec_t; diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index c7a794d68..2be24cc3f 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -36,5 +36,6 @@ grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector); ssize_t grub_util_fd_read (int fd, char *buf, size_t len); grub_err_t grub_luks_cheat_mount (const char *sourcedev, const char *cheat); +void grub_util_luks_print_ciphers (grub_disk_t disk); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/util/grub-probe.c b/util/grub-probe.c index 6c6220b8b..68d9b06f1 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -63,15 +64,28 @@ static void probe_partmap (grub_disk_t disk) { grub_partition_t part; + grub_disk_memberlist_t list = NULL, tmp; if (disk->partition == NULL) { grub_util_info ("no partition map found for %s", disk->name); - return; } for (part = disk->partition; part; part = part->parent) - printf ("%s\n", part->partmap->name); + printf ("%s ", part->partmap->name); + + /* In case of LVM/RAID, check the member devices as well. */ + if (disk->dev->memberlist) + { + list = disk->dev->memberlist (disk); + } + while (list) + { + probe_partmap (list->disk); + tmp = list->next; + free (list); + list = tmp; + } } static int @@ -88,6 +102,45 @@ probe_raid_level (grub_disk_t disk) return ((struct grub_raid_array *) disk->data)->level; } +static void +probe_abstraction (grub_disk_t disk) +{ + grub_disk_memberlist_t list = NULL, tmp; + int raid_level; + + if (disk->dev->memberlist) + list = disk->dev->memberlist (disk); + while (list) + { + probe_abstraction (list->disk); + + tmp = list->next; + free (list); + list = tmp; + } + + if (disk->dev->id == GRUB_DISK_DEVICE_LVM_ID) + printf ("lvm "); + + if (disk->dev->id == GRUB_DISK_DEVICE_LUKS_ID) + { + printf ("luks "); + grub_util_luks_print_ciphers (disk); + } + + raid_level = probe_raid_level (disk); + if (raid_level >= 0) + { + printf ("raid "); + if (disk->dev->raidname) + printf ("%s ", disk->dev->raidname (disk)); + } + if (raid_level == 5) + printf ("raid5rec "); + if (raid_level == 6) + printf ("raid6rec "); +} + static void probe (const char *path, char *device_name) { @@ -136,91 +189,16 @@ probe (const char *path, char *device_name) if (print == PRINT_ABSTRACTION) { - grub_disk_memberlist_t list = NULL, tmp; - const int is_lvm = (dev->disk->dev->id == GRUB_DISK_DEVICE_LVM_ID); - int is_raid = 0; - int is_raid5 = 0; - int is_raid6 = 0; - int raid_level; - grub_disk_t raid_disk; - - raid_level = probe_raid_level (dev->disk); - if (raid_level >= 0) - { - is_raid = 1; - is_raid5 |= (raid_level == 5); - is_raid6 |= (raid_level == 6); - raid_disk = dev->disk; - } - - if ((is_lvm) && (dev->disk->dev->memberlist)) - list = dev->disk->dev->memberlist (dev->disk); - while (list) - { - raid_level = probe_raid_level (list->disk); - if (raid_level >= 0) - { - is_raid = 1; - is_raid5 |= (raid_level == 5); - is_raid6 |= (raid_level == 6); - raid_disk = list->disk; - } - - tmp = list->next; - free (list); - list = tmp; - } - - if (is_raid) - { - printf ("raid "); - if (is_raid5) - printf ("raid5rec "); - if (is_raid6) - printf ("raid6rec "); - if (raid_disk->dev->raidname) - printf ("%s ", raid_disk->dev->raidname (raid_disk)); - } - - if (is_lvm) - printf ("lvm "); - + probe_abstraction (dev->disk); printf ("\n"); - goto end; } if (print == PRINT_PARTMAP) { - grub_disk_memberlist_t list = NULL, tmp; - /* Check if dev->disk itself is contained in a partmap. */ probe_partmap (dev->disk); - - /* In case of LVM/RAID, check the member devices as well. */ - if (dev->disk->dev->memberlist) - list = dev->disk->dev->memberlist (dev->disk); - while (list) - { - probe_partmap (list->disk); - /* LVM on RAID */ - if (list->disk->dev->memberlist) - { - grub_disk_memberlist_t sub_list; - - sub_list = list->disk->dev->memberlist (list->disk); - while (sub_list) - { - probe_partmap (sub_list->disk); - tmp = sub_list->next; - free (sub_list); - sub_list = tmp; - } - } - tmp = list->next; - free (list); - list = tmp; - } + printf ("\n"); goto end; } diff --git a/util/import_gcry.py b/util/import_gcry.py index 3a110f028..0ebfd1f56 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -111,6 +111,7 @@ for cipher_file in cipher_files: skip = False skip2 = False ismd = False + iscipher = False iscryptostart = False iscomma = False isglue = False @@ -140,15 +141,22 @@ for cipher_file in cipher_files: sg = s.groups()[0] cryptolist.write (("%s: %s\n") % (sg, modname)) iscryptostart = False - if ismd: + if ismd or iscipher: if not re.search (" *};", line) is None: - if not mdblocksizes.has_key (mdname): - print ("ERROR: Unknown digest blocksize: %s\n" % mdname) - exit (1) if not iscomma: fw.write (" ,\n") - fw.write (" .blocksize = %s\n" % mdblocksizes [mdname]) + fw.write ("#ifdef GRUB_UTIL\n"); + fw.write (" .modname = \"%s\",\n" % modname); + fw.write ("#endif\n"); + if ismd: + if not mdblocksizes.has_key (mdname): + print ("ERROR: Unknown digest blocksize: %s\n" + % mdname) + exit (1) + fw.write (" .blocksize = %s\n" + % mdblocksizes [mdname]) ismd = False + iscipher = False iscomma = not re.search (",$", line) is None # Used only for selftests. m = re.match ("(static byte|static unsigned char) (weak_keys_chksum)\[[0-9]*\] =", line) @@ -189,14 +197,18 @@ for cipher_file in cipher_files: continue m = re.match ("gcry_cipher_spec_t", line) if isc and not m is None: + assert (not iscryptostart) + assert (not iscipher) assert (not iscryptostart) ciphername = line [len ("gcry_cipher_spec_t"):].strip () ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group () ciphernames.append (ciphername) + iscipher = True iscryptostart = True m = re.match ("gcry_md_spec_t", line) if isc and not m is None: assert (not ismd) + assert (not iscipher) assert (not iscryptostart) mdname = line [len ("gcry_md_spec_t"):].strip () mdname = re.match("[a-zA-Z0-9_]*",mdname).group () From 9d647e4e181b0f88b5107b3f00e4f7d3bb9a1686 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 22 Apr 2011 23:51:16 +0200 Subject: [PATCH 130/673] New -t luks_uuid --- grub-core/disk/luks.c | 7 +++++++ include/grub/emu/hostdisk.h | 1 + util/grub-probe.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index ce1f1bfc6..997e2eb30 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -893,6 +893,13 @@ grub_util_luks_print_ciphers (grub_disk_t disk) if (dev->essiv_hash) grub_printf ("%s ", dev->essiv_hash->modname); } + +void +grub_util_luks_print_uuid (grub_disk_t disk) +{ + grub_luks_t dev = (grub_luks_t) disk->data; + grub_printf ("%s ", dev->uuid); +} #endif static void diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 2be24cc3f..7541308e6 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -37,5 +37,6 @@ ssize_t grub_util_fd_read (int fd, char *buf, size_t len); grub_err_t grub_luks_cheat_mount (const char *sourcedev, const char *cheat); void grub_util_luks_print_ciphers (grub_disk_t disk); +void grub_util_luks_print_uuid (grub_disk_t disk); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/util/grub-probe.c b/util/grub-probe.c index 68d9b06f1..21fc21b02 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -55,6 +55,7 @@ enum { PRINT_DEVICE, PRINT_PARTMAP, PRINT_ABSTRACTION, + PRINT_LUKS_UUID }; int print = PRINT_FS; @@ -88,6 +89,27 @@ probe_partmap (grub_disk_t disk) } } +static void +probe_luks_uuid (grub_disk_t disk) +{ + grub_disk_memberlist_t list = NULL, tmp; + + /* In case of LVM/RAID, check the member devices as well. */ + if (disk->dev->memberlist) + { + list = disk->dev->memberlist (disk); + } + while (list) + { + probe_luks_uuid (list->disk); + tmp = list->next; + free (list); + list = tmp; + } + if (disk->dev->id == GRUB_DISK_DEVICE_LUKS_ID) + grub_util_luks_print_uuid (disk); +} + static int probe_raid_level (grub_disk_t disk) { @@ -194,6 +216,13 @@ probe (const char *path, char *device_name) goto end; } + if (print == PRINT_LUKS_UUID) + { + probe_luks_uuid (dev->disk); + printf ("\n"); + goto end; + } + if (print == PRINT_PARTMAP) { /* Check if dev->disk itself is contained in a partmap. */ @@ -267,8 +296,8 @@ Probe device information for a given path (or device, if the -d option is given) \n\ -d, --device given argument is a system device, not a path\n\ -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction)\n\ - print filesystem module, GRUB drive, system device, partition map module or abstraction module [default=fs]\n\ + -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|luks_uuid)\n\ + print filesystem module, GRUB drive, system device, partition map module, abstraction module or LUKS UUID [default=fs]\n\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ @@ -326,6 +355,8 @@ main (int argc, char *argv[]) print = PRINT_PARTMAP; else if (!strcmp (optarg, "abstraction")) print = PRINT_ABSTRACTION; + else if (!strcmp (optarg, "luks_uuid")) + print = PRINT_LUKS_UUID; else usage (1); break; From 8306591ff30a94c5f9dfcaa4ee02a06a8c0021a5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 00:13:56 +0200 Subject: [PATCH 131/673] support LUKS in shell libraries --- util/grub-install.in | 8 ++++++++ util/grub-mkconfig.in | 1 + util/grub-mkconfig_lib.in | 20 +++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/util/grub-install.in b/util/grub-install.in index ff8bea87c..3b3383ab4 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -456,6 +456,8 @@ for dir in "${localedir}"/*; do fi done +is_path_readable_by_grub "${grubdir}" || (echo "${grubdir}" not readable 1>&2 ; exit 1) + # Write device to a variable so we don't have to traverse /dev every time. grub_device="`"$grub_probe" --device-map="${device_map}" --target=device "${grubdir}"`" || exit 1 @@ -536,6 +538,12 @@ if [ "x${devabstraction_module}" = "x" ] ; then exit 1 fi + if [ x$GRUB_LUKS_ENABLE = xy ]; then + for uuid in "`"${grub_probe}" --device "${device}" --target=luks_uuid`"; do + echo "luksmount -u $uuid" + done + fi + echo "search.fs_uuid ${uuid} root " >> "${grubdir}/load.cfg" echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg" config_opt="-c ${grubdir}/load.cfg " diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index afc66f886..41e68bc1b 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -254,6 +254,7 @@ export GRUB_DEFAULT \ GRUB_DISABLE_OS_PROBER \ GRUB_INIT_TUNE \ GRUB_SAVEDEFAULT \ + GRUB_ENABLE_LUKS \ GRUB_BADRAM if test "x${grub_cfg}" != "x"; then diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 2c5fd8c6f..1664b6bbe 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -63,10 +63,22 @@ is_path_readable_by_grub () # ... or if we can't figure out the abstraction module, for example if # memberlist fails on an LVM volume group. - if ${grub_probe} -t abstraction $path > /dev/null 2>&1 ; then : ; else + if abstractions="`"${grub_probe}" -t abstraction "$path"`" 2>&1 ; then + : + else return 1 fi + if [ x$GRUB_LUKS_ENABLE = xy ]; then + return 0 + fi + + for abstraction in $abstractions; do + if [ "x$abstraction" = xluks ]; then + return 1 + fi + done + return 0 } @@ -126,6 +138,12 @@ prepare_grub_to_access_device () echo "insmod ${module}" done + if [ x$GRUB_LUKS_ENABLE = xy ]; then + for uuid in "`"${grub_probe}" --device "${device}" --target=luks_uuid`"; do + echo "luksmount -u $uuid" + done + fi + # If there's a filesystem UUID that GRUB is capable of identifying, use it; # otherwise set root as per value in device.map. echo "set root='`"${grub_probe}" --device "${device}" --target=drive`'" From 4879d87871dceba99558c7911cc15b9ddee4b4bf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 02:01:39 +0200 Subject: [PATCH 132/673] fix bug caused by import_gcry modifications --- util/import_gcry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/import_gcry.py b/util/import_gcry.py index 0ebfd1f56..727492f10 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -153,8 +153,8 @@ for cipher_file in cipher_files: print ("ERROR: Unknown digest blocksize: %s\n" % mdname) exit (1) - fw.write (" .blocksize = %s\n" - % mdblocksizes [mdname]) + fw.write (" .blocksize = %s\n" + % mdblocksizes [mdname]) ismd = False iscipher = False iscomma = not re.search (",$", line) is None From 95172af9fa30d41b6f37e32ee9e0e79a2e10930d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 02:04:40 +0200 Subject: [PATCH 133/673] Better IV modes support --- grub-core/disk/luks.c | 266 ++++++++++++++++++++++++------------------ 1 file changed, 151 insertions(+), 115 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 997e2eb30..8f8b8dbe4 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -70,12 +70,20 @@ struct grub_luks_phdr typedef struct grub_luks_phdr *grub_luks_phdr_t; typedef enum -{ - GRUB_LUKS_MODE_ECB, - GRUB_LUKS_MODE_CBC_PLAIN, - GRUB_LUKS_MODE_CBC_ESSIV, - GRUB_LUKS_MODE_XTS -} luks_mode_t; + { + GRUB_LUKS_MODE_ECB, + GRUB_LUKS_MODE_CBC, + GRUB_LUKS_MODE_XTS + } luks_mode_t; + +typedef enum + { + GRUB_LUKS_MODE_IV_NULL, + GRUB_LUKS_MODE_IV_PLAIN, + GRUB_LUKS_MODE_IV_PLAIN64, + GRUB_LUKS_MODE_IV_ESSIV, + GRUB_LUKS_MODE_IV_BENBI, + } luks_mode_iv_t; struct grub_luks { @@ -85,8 +93,10 @@ struct grub_luks int ref; grub_crypto_cipher_handle_t cipher; grub_crypto_cipher_handle_t secondary_cipher; + grub_crypto_cipher_handle_t essiv_cipher; const gcry_md_spec_t *essiv_hash, *hash; luks_mode_t mode; + luks_mode_iv_t mode_iv; unsigned long id, source_id; enum grub_disk_dev_id source_dev_id; char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; @@ -112,13 +122,6 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static inline void -make_iv (grub_uint32_t *iv, grub_size_t sz, grub_disk_addr_t sector) -{ - grub_memset (iv, 0, sz * sizeof (iv[0])); - iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); -} - /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ #define POLYNOM 0x87 @@ -141,89 +144,83 @@ gf_mul_x (grub_uint8_t *g) static gcry_err_code_t luks_decrypt (const struct grub_luks *dev, - grub_uint8_t * data, grub_size_t len, grub_size_t sector) + grub_uint8_t * data, grub_size_t len, grub_disk_addr_t sector) { grub_size_t i; gcry_err_code_t err; - switch (dev->mode) + /* The only mode without IV. */ + if (dev->mode == GRUB_LUKS_MODE_ECB) + return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); + + for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) { - case GRUB_LUKS_MODE_ECB: - return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); + grub_size_t sz = ((dev->cipher->cipher->blocksize + + sizeof (grub_uint32_t) - 1) + / sizeof (grub_uint32_t)); + grub_uint32_t iv[sz]; - case GRUB_LUKS_MODE_CBC_PLAIN: - for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) + grub_memset (iv, 0, sz * sizeof (iv[0])); + switch (dev->mode_iv) { - grub_size_t sz = ((dev->cipher->cipher->blocksize - + sizeof (grub_uint32_t) - 1) - / sizeof (grub_uint32_t)); - grub_uint32_t iv[sz]; - make_iv (iv, sz, sector); + case GRUB_LUKS_MODE_IV_NULL: + break; + case GRUB_LUKS_MODE_IV_PLAIN64: + iv[1] = grub_cpu_to_le32 (sector >> 32); + case GRUB_LUKS_MODE_IV_PLAIN: + iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + break; + case GRUB_LUKS_MODE_IV_BENBI: + iv[sz - 2] = grub_cpu_to_be32 (sector >> 32); + iv[sz - 1] = grub_cpu_to_be32 (sector & 0xFFFFFFFF); + break; + case GRUB_LUKS_MODE_IV_ESSIV: + iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv, + dev->cipher->cipher->blocksize); + if (err) + return err; + } + + switch (dev->mode) + { + case GRUB_LUKS_MODE_CBC: err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, GRUB_DISK_SECTOR_SIZE, iv); if (err) return err; - sector++; + break; + + case GRUB_LUKS_MODE_XTS: + { + int j; + err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, + dev->cipher->cipher->blocksize); + if (err) + return err; + + for (j = 0; j < GRUB_DISK_SECTOR_SIZE; + j += dev->cipher->cipher->blocksize) + { + grub_crypto_xor (data + i + j, data + i + j, iv, + dev->cipher->cipher->blocksize); + err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, + data + i + j, + dev->cipher->cipher->blocksize); + if (err) + return err; + grub_crypto_xor (data + i + j, data + i + j, iv, + dev->cipher->cipher->blocksize); + gf_mul_x ((grub_uint8_t *) iv); + } + } + break; + default: + return GPG_ERR_NOT_IMPLEMENTED; } - return GPG_ERR_NO_ERROR; - - case GRUB_LUKS_MODE_CBC_ESSIV: - for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) - { - grub_size_t sz = ((dev->cipher->cipher->blocksize - + sizeof (grub_uint32_t) - 1) - / sizeof (grub_uint32_t)); - grub_uint32_t iv[sz]; - make_iv (iv, sz, sector); - - err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, - dev->cipher->cipher->blocksize); - if (err) - return err; - err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, - GRUB_DISK_SECTOR_SIZE, iv); - if (err) - return err; - sector++; - } - return GPG_ERR_NO_ERROR; - - case GRUB_LUKS_MODE_XTS: - for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) - { - grub_size_t sz = ((dev->cipher->cipher->blocksize - + sizeof (grub_uint32_t) - 1) - / sizeof (grub_uint32_t)); - grub_uint32_t iv[sz]; - int j; - make_iv (iv, sz, sector); - - err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, - dev->cipher->cipher->blocksize); - if (err) - return err; - - for (j = 0; j < GRUB_DISK_SECTOR_SIZE; - j += dev->cipher->cipher->blocksize) - { - grub_crypto_xor (data + i + j, data + i + j, iv, - dev->cipher->cipher->blocksize); - err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, - data + i + j, - dev->cipher->cipher->blocksize); - if (err) - return err; - grub_crypto_xor (data + i + j, data + i + j, iv, - dev->cipher->cipher->blocksize); - gf_mul_x ((grub_uint8_t *) iv); - } - sector++; - } - return GPG_ERR_NO_ERROR; - - default: - return GPG_ERR_NOT_IMPLEMENTED; + sector++; } + return GPG_ERR_NO_ERROR; } static int check_uuid, have_it; @@ -238,11 +235,14 @@ configure_ciphers (const struct grub_luks_phdr *header) char uuid[sizeof (header->uuid) + 1]; char ciphername[sizeof (header->cipherName) + 1]; char ciphermode[sizeof (header->cipherMode) + 1]; + char *cipheriv = NULL; char hashspec[sizeof (header->hashSpec) + 1]; grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; + grub_crypto_cipher_handle_t essiv_cipher = NULL; const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; const struct gcry_cipher_spec *ciph; luks_mode_t mode; + luks_mode_iv_t mode_iv; /* Look for LUKS magic sequence. */ if (grub_memcmp (header->magic, LUKS_MAGIC, sizeof (header->magic)) @@ -294,35 +294,26 @@ configure_ciphers (const struct grub_luks_phdr *header) /* Configure the cipher mode. */ if (grub_strcmp (ciphermode, "ecb") == 0) - mode = GRUB_LUKS_MODE_ECB; - else if (grub_strcmp (ciphermode, "cbc-plain") == 0 - || grub_strcmp (ciphermode, "plain") == 0) - mode = GRUB_LUKS_MODE_CBC_PLAIN; - else if (grub_memcmp (ciphermode, "cbc-essiv:", sizeof ("cbc-essiv:") - 1) - == 0) { - mode = GRUB_LUKS_MODE_CBC_ESSIV; - char *hash_str = ciphermode + 10; - - /* Configure the hash and cipher used for ESSIV. */ - essiv_hash = grub_crypto_lookup_md_by_name (hash_str); - if (!essiv_hash) - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_FILE_NOT_FOUND, - "Couldn't load %s hash", hash_str); - return NULL; - } - secondary_cipher = grub_crypto_cipher_open (ciph); - if (!secondary_cipher) - { - grub_crypto_cipher_close (cipher); - return NULL; - } + mode = GRUB_LUKS_MODE_ECB; + mode_iv = GRUB_LUKS_MODE_IV_PLAIN; + cipheriv = NULL; } - else if (grub_strcmp (ciphermode, "xts-plain") == 0) + else if (grub_strcmp (ciphermode, "plain") == 0) + { + mode = GRUB_LUKS_MODE_CBC; + mode_iv = GRUB_LUKS_MODE_IV_PLAIN; + cipheriv = NULL; + } + else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0) + { + mode = GRUB_LUKS_MODE_CBC; + cipheriv = ciphermode + sizeof ("cbc-") - 1; + } + else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0) { mode = GRUB_LUKS_MODE_XTS; + cipheriv = ciphermode + sizeof ("xts-") - 1; secondary_cipher = grub_crypto_cipher_open (ciph); if (!secondary_cipher) { @@ -350,11 +341,51 @@ configure_ciphers (const struct grub_luks_phdr *header) return NULL; } + if (cipheriv == NULL); + else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0) + mode_iv = GRUB_LUKS_MODE_IV_PLAIN; + else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0) + mode_iv = GRUB_LUKS_MODE_IV_PLAIN64; + else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0) + mode_iv = GRUB_LUKS_MODE_IV_BENBI; + else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0) + mode_iv = GRUB_LUKS_MODE_IV_NULL; + else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0) + { + char *hash_str = cipheriv + 6; + + mode_iv = GRUB_LUKS_MODE_IV_ESSIV; + + /* Configure the hash and cipher used for ESSIV. */ + essiv_hash = grub_crypto_lookup_md_by_name (hash_str); + if (!essiv_hash) + { + grub_crypto_cipher_close (cipher); + grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Couldn't load %s hash", hash_str); + return NULL; + } + essiv_cipher = grub_crypto_cipher_open (ciph); + if (!essiv_cipher) + { + grub_crypto_cipher_close (cipher); + return NULL; + } + } + else + { + grub_crypto_cipher_close (cipher); + grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s", + cipheriv); + return NULL; + } + /* Configure the hash used for the AF splitter and HMAC. */ hash = grub_crypto_lookup_md_by_name (hashspec); if (!hash) { grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (essiv_cipher); grub_crypto_cipher_close (secondary_cipher); grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", hashspec); @@ -368,7 +399,9 @@ configure_ciphers (const struct grub_luks_phdr *header) newdev->offset = grub_be_to_cpu32 (header->payloadOffset); newdev->source_disk = NULL; newdev->mode = mode; + newdev->mode_iv = mode_iv; newdev->secondary_cipher = secondary_cipher; + newdev->essiv_cipher = essiv_cipher; newdev->essiv_hash = essiv_hash; newdev->hash = hash; newdev->id = n++; @@ -392,7 +425,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_size_t length; grub_err_t err; - if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) + if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) { essiv_keysize = dev->essiv_hash->mdlen; hashed_key = grub_malloc (dev->essiv_hash->mdlen); @@ -433,8 +466,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, grub_strlen (passphrase), header->keyblock[i].passwordSalt, - sizeof (header-> - keyblock[i].passwordSalt), + sizeof (header->keyblock[i].passwordSalt), grub_be_to_cpu32 (header->keyblock[i]. passwordIterations), digest, keysize); @@ -460,10 +492,10 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, } /* Configure ESSIV if necessary. */ - if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) + if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) { grub_crypto_hash (dev->essiv_hash, hashed_key, digest, keysize); - gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, + gcry_err = grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key, essiv_keysize); if (gcry_err) @@ -562,12 +594,12 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, } /* Configure ESSIV if necessary. */ - if (dev->mode == GRUB_LUKS_MODE_CBC_ESSIV) + if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) { grub_crypto_hash (dev->essiv_hash, hashed_key, candidate_key, keysize); gcry_err = - grub_crypto_cipher_set_key (dev->secondary_cipher, hashed_key, + grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key, essiv_keysize); if (gcry_err) { @@ -604,6 +636,7 @@ luks_close (grub_luks_t luks) { grub_crypto_cipher_close (luks->cipher); grub_crypto_cipher_close (luks->secondary_cipher); + grub_crypto_cipher_close (luks->essiv_cipher); grub_free (luks); } @@ -888,6 +921,8 @@ grub_util_luks_print_ciphers (grub_disk_t disk) grub_printf ("%s ", dev->cipher->cipher->modname); if (dev->secondary_cipher) grub_printf ("%s ", dev->secondary_cipher->cipher->modname); + if (dev->essiv_cipher) + grub_printf ("%s ", dev->essiv_cipher->cipher->modname); if (dev->hash) grub_printf ("%s ", dev->hash->modname); if (dev->essiv_hash) @@ -913,6 +948,7 @@ luks_cleanup (void) grub_free (dev->source); grub_free (dev->cipher); grub_free (dev->secondary_cipher); + grub_free (dev->essiv_cipher); tmp = dev->next; grub_free (dev); dev = tmp; From ed38c849f4bc6b193431360dd21424c013b594fd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 02:27:45 +0200 Subject: [PATCH 134/673] pcbc support --- grub-core/disk/luks.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 8f8b8dbe4..ac3b81e99 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -73,6 +73,7 @@ typedef enum { GRUB_LUKS_MODE_ECB, GRUB_LUKS_MODE_CBC, + GRUB_LUKS_MODE_PCBC, GRUB_LUKS_MODE_XTS } luks_mode_t; @@ -142,6 +143,29 @@ gf_mul_x (grub_uint8_t *g) g[0] ^= POLYNOM; } +static gcry_err_code_t +grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, + void *out, void *in, grub_size_t size, + void *iv) +{ + grub_uint8_t *inptr, *outptr, *end; + grub_uint8_t ivt[cipher->cipher->blocksize]; + if (!cipher->cipher->decrypt) + return GPG_ERR_NOT_SUPPORTED; + if (size % cipher->cipher->blocksize != 0) + return GPG_ERR_INV_ARG; + end = (grub_uint8_t *) in + size; + for (inptr = in, outptr = out; inptr < end; + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + { + grub_memcpy (ivt, inptr, cipher->cipher->blocksize); + cipher->cipher->decrypt (cipher->ctx, outptr, inptr); + grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); + grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); + } + return GPG_ERR_NO_ERROR; +} + static gcry_err_code_t luks_decrypt (const struct grub_luks *dev, grub_uint8_t * data, grub_size_t len, grub_disk_addr_t sector) @@ -191,6 +215,12 @@ luks_decrypt (const struct grub_luks *dev, return err; break; + case GRUB_LUKS_MODE_PCBC: + err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, + GRUB_DISK_SECTOR_SIZE, iv); + if (err) + return err; + break; case GRUB_LUKS_MODE_XTS: { int j; @@ -310,6 +340,11 @@ configure_ciphers (const struct grub_luks_phdr *header) mode = GRUB_LUKS_MODE_CBC; cipheriv = ciphermode + sizeof ("cbc-") - 1; } + else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0) + { + mode = GRUB_LUKS_MODE_PCBC; + cipheriv = ciphermode + sizeof ("pcbc-") - 1; + } else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0) { mode = GRUB_LUKS_MODE_XTS; From 4b35060f6fd84a6fc5fb19974098d66e16a44964 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 03:18:07 +0200 Subject: [PATCH 135/673] Fix benbi --- grub-core/disk/luks.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index ac3b81e99..8af087eea 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -98,6 +98,7 @@ struct grub_luks const gcry_md_spec_t *essiv_hash, *hash; luks_mode_t mode; luks_mode_iv_t mode_iv; + int benbi_log; unsigned long id, source_id; enum grub_disk_dev_id source_dev_id; char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; @@ -195,8 +196,11 @@ luks_decrypt (const struct grub_luks *dev, iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); break; case GRUB_LUKS_MODE_IV_BENBI: - iv[sz - 2] = grub_cpu_to_be32 (sector >> 32); - iv[sz - 1] = grub_cpu_to_be32 (sector & 0xFFFFFFFF); + { + grub_uint64_t num = (sector << dev->benbi_log) + 1; + iv[sz - 2] = grub_cpu_to_be32 (num >> 32); + iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF); + } break; case GRUB_LUKS_MODE_IV_ESSIV: iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); @@ -273,7 +277,8 @@ configure_ciphers (const struct grub_luks_phdr *header) const struct gcry_cipher_spec *ciph; luks_mode_t mode; luks_mode_iv_t mode_iv; - + int benbi_log = 0; + /* Look for LUKS magic sequence. */ if (grub_memcmp (header->magic, LUKS_MAGIC, sizeof (header->magic)) || grub_be_to_cpu16 (header->version) != 1) @@ -382,7 +387,16 @@ configure_ciphers (const struct grub_luks_phdr *header) else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0) mode_iv = GRUB_LUKS_MODE_IV_PLAIN64; else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0) + { + if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1) + || cipher->cipher->blocksize == 0) + grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d", + cipher->cipher->blocksize); + for (benbi_log = 0; + (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE; + benbi_log++); mode_iv = GRUB_LUKS_MODE_IV_BENBI; + } else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0) mode_iv = GRUB_LUKS_MODE_IV_NULL; else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0) @@ -433,6 +447,7 @@ configure_ciphers (const struct grub_luks_phdr *header) newdev->cipher = cipher; newdev->offset = grub_be_to_cpu32 (header->payloadOffset); newdev->source_disk = NULL; + newdev->benbi_log = benbi_log; newdev->mode = mode; newdev->mode_iv = mode_iv; newdev->secondary_cipher = secondary_cipher; From 2f179c3236573a4aca5816aac4b3bb5ed16f8268 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 04:51:53 +0200 Subject: [PATCH 136/673] LRW support --- grub-core/disk/luks.c | 120 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 15 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 8af087eea..775a10f20 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -74,7 +74,8 @@ typedef enum GRUB_LUKS_MODE_ECB, GRUB_LUKS_MODE_CBC, GRUB_LUKS_MODE_PCBC, - GRUB_LUKS_MODE_XTS + GRUB_LUKS_MODE_XTS, + GRUB_LUKS_MODE_LRW } luks_mode_t; typedef enum @@ -86,6 +87,10 @@ typedef enum GRUB_LUKS_MODE_IV_BENBI, } luks_mode_iv_t; +/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ +#define GF_POLYNOM 0x87 +#define GF_SIZE 128 + struct grub_luks { char *source; @@ -102,6 +107,7 @@ struct grub_luks unsigned long id, source_id; enum grub_disk_dev_id source_dev_id; char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; + grub_uint8_t lrw_key[GF_SIZE / 8]; #ifdef GRUB_UTIL char *cheat; int cheat_fd; @@ -124,16 +130,13 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ -#define POLYNOM 0x87 - static void gf_mul_x (grub_uint8_t *g) { int over = 0, over2 = 0; int j; - for (j = 0; j < 16; j++) + for (j = 0; j < GF_SIZE / 8; j++) { over2 = !!(g[j] & 0x80); g[j] <<= 1; @@ -141,7 +144,40 @@ gf_mul_x (grub_uint8_t *g) over = over2; } if (over) - g[0] ^= POLYNOM; + g[0] ^= GF_POLYNOM; +} + + +static void +gf_mul_x_be (grub_uint8_t *g) +{ + int over = 0, over2 = 0; + int j; + + for (j = GF_SIZE / 8 - 1; j >= 0; j--) + { + over2 = !!(g[j] & 0x80); + g[j] <<= 1; + g[j] |= over; + over = over2; + } + if (over) + g[GF_SIZE / 8 - 1] ^= GF_POLYNOM; +} + +static void +gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b) +{ + int i; + grub_uint8_t t[GF_SIZE / 8]; + grub_memset (o, 0, GF_SIZE / 8); + grub_memcpy (t, b, GF_SIZE / 8); + for (i = 0; i < GF_SIZE; i++) + { + if (((a[GF_SIZE / 8 - i / 8 - 1] >> (i % 8))) & 1) + grub_crypto_xor (o, o, t, GF_SIZE / 8); + gf_mul_x_be (t); + } } static gcry_err_code_t @@ -249,6 +285,34 @@ luks_decrypt (const struct grub_luks *dev, } } break; + case GRUB_LUKS_MODE_LRW: + { + int j, k; + for (j = 0; + j < GRUB_DISK_SECTOR_SIZE; + j += dev->cipher->cipher->blocksize) + { + grub_uint8_t x[sz * sizeof (grub_uint32_t)]; + + gf_mul_be (x, dev->lrw_key, (grub_uint8_t *) iv); + grub_crypto_xor (data + i + j, data + i + j, x, + dev->cipher->cipher->blocksize); + err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, + data + i + j, + dev->cipher->cipher->blocksize); + if (err) + return err; + grub_crypto_xor (data + i + j, data + i + j, x, + dev->cipher->cipher->blocksize); + for (k = sz - 1; k >= 0; k++) + { + iv[k] = grub_cpu_to_be32 (grub_be_to_cpu32 (iv[k]) + 1); + if (iv[k] != 0) + break; + } + } + } + break; default: return GPG_ERR_NOT_IMPLEMENTED; } @@ -360,19 +424,33 @@ configure_ciphers (const struct grub_luks_phdr *header) grub_crypto_cipher_close (cipher); return NULL; } - if (cipher->cipher->blocksize != 16) + if (cipher->cipher->blocksize != GF_SIZE / 8) { + grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", cipher->cipher->blocksize); return NULL; } - if (secondary_cipher->cipher->blocksize != 16) + if (secondary_cipher->cipher->blocksize != GF_SIZE / 8) { + grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", secondary_cipher->cipher->blocksize); return NULL; } } + else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0) + { + mode = GRUB_LUKS_MODE_LRW; + cipheriv = ciphermode + sizeof ("lrw-") - 1; + if (cipher->cipher->blocksize != GF_SIZE / 8) + { + grub_crypto_cipher_close (cipher); + grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d", + cipher->cipher->blocksize); + return NULL; + } + } else { grub_crypto_cipher_close (cipher); @@ -505,6 +583,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, for (i = 0; i < ARRAY_SIZE (header->keyblock); i++) { gcry_err_code_t gcry_err; + int real_keysize; /* Check if keyslot is enabled. */ if (grub_be_to_cpu32 (header->keyblock[i].active) != LUKS_KEY_ENABLED) @@ -530,10 +609,14 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_dprintf ("luks", "PBKDF2 done\n"); + real_keysize = keysize; + if (dev->mode == GRUB_LUKS_MODE_XTS) + real_keysize /= 2; + if (dev->mode == GRUB_LUKS_MODE_LRW) + real_keysize -= dev->cipher->cipher->blocksize; + /* Set the PBKDF2 output as the cipher key. */ - gcry_err = grub_crypto_cipher_set_key (dev->cipher, digest, - (dev->mode == GRUB_LUKS_MODE_XTS) - ? (keysize / 2) : keysize); + gcry_err = grub_crypto_cipher_set_key (dev->cipher, digest, real_keysize); if (gcry_err) { grub_free (hashed_key); @@ -559,7 +642,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, if (dev->mode == GRUB_LUKS_MODE_XTS) { gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, - digest + (keysize / 2), + digest + real_keysize, keysize / 2); if (gcry_err) { @@ -569,6 +652,10 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, } } + if (dev->mode == GRUB_LUKS_MODE_LRW) + grub_memcpy (dev->lrw_key, digest + real_keysize, + dev->cipher->cipher->blocksize); + length = grub_be_to_cpu32 (header->keyBytes) * grub_be_to_cpu32 (header->keyblock[i].stripes); @@ -634,8 +721,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, /* Set the master key. */ gcry_err = grub_crypto_cipher_set_key (dev->cipher, candidate_key, - (dev->mode == GRUB_LUKS_MODE_XTS) - ? (keysize / 2) : keysize); + real_keysize); if (gcry_err) { grub_free (hashed_key); @@ -662,7 +748,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, if (dev->mode == GRUB_LUKS_MODE_XTS) { gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, - candidate_key + (keysize / 2), + candidate_key + real_keysize, keysize / 2); if (gcry_err) { @@ -672,6 +758,10 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, } } + if (dev->mode == GRUB_LUKS_MODE_LRW) + grub_memcpy (dev->lrw_key, candidate_key + real_keysize, + dev->cipher->cipher->blocksize); + grub_free (split_key); grub_free (hashed_key); From 6fd80b9ac45df8a5b417f1a215e8cd428ebe8b82 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 12:40:43 +0200 Subject: [PATCH 137/673] factor luks_set_key out --- grub-core/disk/luks.c | 151 ++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 102 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 775a10f20..b1c738f2a 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -537,6 +537,50 @@ configure_ciphers (const struct grub_luks_phdr *header) return newdev; } +static gcry_err_code_t +luks_setkey (grub_luks_t dev, grub_uint8_t *key, grub_size_t keysize) +{ + gcry_err_code_t err; + int real_keysize; + + real_keysize = keysize; + if (dev->mode == GRUB_LUKS_MODE_XTS) + real_keysize /= 2; + if (dev->mode == GRUB_LUKS_MODE_LRW) + real_keysize -= dev->cipher->cipher->blocksize; + + /* Set the PBKDF2 output as the cipher key. */ + err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize); + if (err) + return err; + + /* Configure ESSIV if necessary. */ + if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) + { + grub_size_t essiv_keysize = dev->essiv_hash->mdlen; + grub_uint8_t hashed_key[essiv_keysize]; + + grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize); + err = grub_crypto_cipher_set_key (dev->essiv_cipher, + hashed_key, essiv_keysize); + if (err) + return err; + } + if (dev->mode == GRUB_LUKS_MODE_XTS) + { + err = grub_crypto_cipher_set_key (dev->secondary_cipher, + key + real_keysize, + keysize / 2); + if (err) + return err; + } + + if (dev->mode == GRUB_LUKS_MODE_LRW) + grub_memcpy (dev->lrw_key, key + real_keysize, + dev->cipher->cipher->blocksize); + return GPG_ERR_NO_ERROR; +} + static grub_err_t luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, const char *name, grub_disk_t source) @@ -544,37 +588,23 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_size_t keysize = grub_be_to_cpu32 (header->keyBytes); grub_uint8_t candidate_key[keysize]; grub_uint8_t digest[keysize]; - grub_uint8_t *hashed_key = NULL; grub_uint8_t *split_key = NULL; char passphrase[MAX_PASSPHRASE] = ""; grub_uint8_t candidate_digest[sizeof (header->mkDigest)]; unsigned i; - grub_size_t essiv_keysize = 0; grub_size_t length; grub_err_t err; - if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) - { - essiv_keysize = dev->essiv_hash->mdlen; - hashed_key = grub_malloc (dev->essiv_hash->mdlen); - if (!hashed_key) - return grub_errno; - } - grub_printf ("Attempting to decrypt master key...\n"); split_key = grub_malloc (keysize * LUKS_STRIPES); if (!split_key) - { - grub_free (hashed_key); - return grub_errno; - } + return grub_errno; /* Get the passphrase from the user. */ grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid); if (!grub_password_get (passphrase, MAX_PASSPHRASE)) { - grub_free (hashed_key); grub_free (split_key); return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); } @@ -583,7 +613,6 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, for (i = 0; i < ARRAY_SIZE (header->keyblock); i++) { gcry_err_code_t gcry_err; - int real_keysize; /* Check if keyslot is enabled. */ if (grub_be_to_cpu32 (header->keyblock[i].active) != LUKS_KEY_ENABLED) @@ -602,63 +631,21 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, if (gcry_err) { - grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } grub_dprintf ("luks", "PBKDF2 done\n"); - real_keysize = keysize; - if (dev->mode == GRUB_LUKS_MODE_XTS) - real_keysize /= 2; - if (dev->mode == GRUB_LUKS_MODE_LRW) - real_keysize -= dev->cipher->cipher->blocksize; - - /* Set the PBKDF2 output as the cipher key. */ - gcry_err = grub_crypto_cipher_set_key (dev->cipher, digest, real_keysize); + gcry_err = luks_setkey (dev, digest, keysize); if (gcry_err) { - grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } - /* Configure ESSIV if necessary. */ - if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) - { - grub_crypto_hash (dev->essiv_hash, hashed_key, digest, keysize); - gcry_err = grub_crypto_cipher_set_key (dev->essiv_cipher, - hashed_key, - essiv_keysize); - if (gcry_err) - { - grub_free (hashed_key); - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } - } - - if (dev->mode == GRUB_LUKS_MODE_XTS) - { - gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, - digest + real_keysize, - keysize / 2); - if (gcry_err) - { - grub_free (hashed_key); - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } - } - - if (dev->mode == GRUB_LUKS_MODE_LRW) - grub_memcpy (dev->lrw_key, digest + real_keysize, - dev->cipher->cipher->blocksize); - - length = - grub_be_to_cpu32 (header->keyBytes) * - grub_be_to_cpu32 (header->keyblock[i].stripes); + length = (grub_be_to_cpu32 (header->keyBytes) + * grub_be_to_cpu32 (header->keyblock[i].stripes)); /* Read and decrypt the key material from the disk. */ err = grub_disk_read (source, @@ -667,7 +654,6 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, length, split_key); if (err) { - grub_free (hashed_key); grub_free (split_key); return err; } @@ -675,7 +661,6 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, gcry_err = luks_decrypt (dev, split_key, length, 0); if (gcry_err) { - grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } @@ -685,7 +670,6 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_be_to_cpu32 (header->keyblock[i].stripes)); if (gcry_err) { - grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } @@ -703,7 +687,6 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, sizeof (candidate_digest)); if (gcry_err) { - grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } @@ -720,50 +703,14 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_printf ("Slot %d opened\n", i); /* Set the master key. */ - gcry_err = grub_crypto_cipher_set_key (dev->cipher, candidate_key, - real_keysize); + gcry_err = luks_setkey (dev, candidate_key, keysize); if (gcry_err) { - grub_free (hashed_key); grub_free (split_key); return grub_crypto_gcry_error (gcry_err); } - /* Configure ESSIV if necessary. */ - if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) - { - grub_crypto_hash (dev->essiv_hash, hashed_key, - candidate_key, keysize); - gcry_err = - grub_crypto_cipher_set_key (dev->essiv_cipher, hashed_key, - essiv_keysize); - if (gcry_err) - { - grub_free (hashed_key); - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } - } - - if (dev->mode == GRUB_LUKS_MODE_XTS) - { - gcry_err = grub_crypto_cipher_set_key (dev->secondary_cipher, - candidate_key + real_keysize, - keysize / 2); - if (gcry_err) - { - grub_free (hashed_key); - grub_free (split_key); - return grub_crypto_gcry_error (gcry_err); - } - } - - if (dev->mode == GRUB_LUKS_MODE_LRW) - grub_memcpy (dev->lrw_key, candidate_key + real_keysize, - dev->cipher->cipher->blocksize); - grub_free (split_key); - grub_free (hashed_key); return GRUB_ERR_NONE; } From 6f33a8eebc99d6b3cb22f17a94779f6171aca17b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 16:41:43 +0200 Subject: [PATCH 138/673] optimize LRW --- grub-core/disk/luks.c | 114 +++++++++++++++++++++++++++++++++--------- 1 file changed, 89 insertions(+), 25 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index b1c738f2a..542ad4c9c 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -108,6 +108,7 @@ struct grub_luks enum grub_disk_dev_id source_dev_id; char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; grub_uint8_t lrw_key[GF_SIZE / 8]; + grub_uint8_t *lrw_precalc; #ifdef GRUB_UTIL char *cheat; int cheat_fd; @@ -203,6 +204,68 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, return GPG_ERR_NO_ERROR; } +#define GF_BYTES (GF_SIZE / 8) +#define GF_PER_SECTOR (GRUB_DISK_SECTOR_SIZE / GF_BYTES) + +struct lrw_sector +{ + grub_uint8_t low[GF_BYTES]; + grub_uint8_t high[GF_BYTES]; + grub_uint8_t low_byte, low_byte_c; +}; + +static void +generate_lrw_sector (struct lrw_sector *sec, + const struct grub_luks *dev, + const grub_uint8_t *iv) +{ + grub_uint8_t idx[GF_BYTES]; + grub_uint16_t c; + int j; + grub_memcpy (idx, iv, GF_BYTES); + sec->low_byte = (idx[GF_BYTES - 1] & (GF_PER_SECTOR - 1)); + sec->low_byte_c = (((GF_PER_SECTOR - 1) & ~sec->low_byte) + 1); + idx[GF_BYTES - 1] &= ~(GF_PER_SECTOR - 1); + gf_mul_be (sec->low, dev->lrw_key, idx); + if (!sec->low_byte) + return; + + c = idx[GF_BYTES - 1] + GF_PER_SECTOR; + if (c & 0x100) + { + for (j = GF_BYTES - 2; j >= 0; j--) + { + idx[j]++; + if (idx[j] != 0) + break; + } + } + idx[GF_BYTES - 1] = c; + gf_mul_be (sec->high, dev->lrw_key, idx); +} + +static void __attribute__ ((unused)) +lrw_xor (const struct lrw_sector *sec, + const struct grub_luks *dev, + grub_uint8_t *b) +{ + int i; + + for (i = 0; i < sec->low_byte_c * GF_BYTES; i += GF_BYTES) + grub_crypto_xor (b + i, b + i, sec->low, GF_BYTES); + grub_crypto_xor (b, b, dev->lrw_precalc + GF_BYTES * sec->low_byte, + sec->low_byte_c * GF_BYTES); + if (!sec->low_byte) + return; + + for (i = sec->low_byte_c * GF_BYTES; + i < GRUB_DISK_SECTOR_SIZE; i += GF_BYTES) + grub_crypto_xor (b + i, b + i, sec->high, GF_BYTES); + grub_crypto_xor (b + sec->low_byte_c * GF_BYTES, + b + sec->low_byte_c * GF_BYTES, + dev->lrw_precalc, sec->low_byte * GF_BYTES); +} + static gcry_err_code_t luks_decrypt (const struct grub_luks *dev, grub_uint8_t * data, grub_size_t len, grub_disk_addr_t sector) @@ -287,30 +350,16 @@ luks_decrypt (const struct grub_luks *dev, break; case GRUB_LUKS_MODE_LRW: { - int j, k; - for (j = 0; - j < GRUB_DISK_SECTOR_SIZE; - j += dev->cipher->cipher->blocksize) - { - grub_uint8_t x[sz * sizeof (grub_uint32_t)]; + struct lrw_sector sec; - gf_mul_be (x, dev->lrw_key, (grub_uint8_t *) iv); - grub_crypto_xor (data + i + j, data + i + j, x, - dev->cipher->cipher->blocksize); - err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, - data + i + j, - dev->cipher->cipher->blocksize); - if (err) - return err; - grub_crypto_xor (data + i + j, data + i + j, x, - dev->cipher->cipher->blocksize); - for (k = sz - 1; k >= 0; k++) - { - iv[k] = grub_cpu_to_be32 (grub_be_to_cpu32 (iv[k]) + 1); - if (iv[k] != 0) - break; - } - } + generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv); + lrw_xor (&sec, dev, data + i); + + err = grub_crypto_ecb_decrypt (dev->cipher, data + i, + data + i, GRUB_DISK_SECTOR_SIZE); + if (err) + return err; + lrw_xor (&sec, dev, data + i); } break; default: @@ -576,8 +625,23 @@ luks_setkey (grub_luks_t dev, grub_uint8_t *key, grub_size_t keysize) } if (dev->mode == GRUB_LUKS_MODE_LRW) - grub_memcpy (dev->lrw_key, key + real_keysize, - dev->cipher->cipher->blocksize); + { + int i; + grub_uint8_t idx[GF_SIZE / 8]; + + grub_free (dev->lrw_precalc); + grub_memcpy (dev->lrw_key, key + real_keysize, + dev->cipher->cipher->blocksize); + dev->lrw_precalc = grub_malloc (GRUB_DISK_SECTOR_SIZE); + if (!dev->lrw_precalc) + return GPG_ERR_OUT_OF_MEMORY; + grub_memset (idx, 0, GF_SIZE / 8); + for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i += GF_SIZE / 8) + { + idx[15] = i / (GF_SIZE / 8); + gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key); + } + } return GPG_ERR_NO_ERROR; } From b896ae82db4584b29ebbfabac99c02a6abd070d7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 16:43:55 +0200 Subject: [PATCH 139/673] small readability improvement --- grub-core/disk/luks.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 542ad4c9c..4a35ef011 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -90,6 +90,8 @@ typedef enum /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ #define GF_POLYNOM 0x87 #define GF_SIZE 128 +#define GF_BYTES (GF_SIZE / 8) +#define GF_PER_SECTOR (GRUB_DISK_SECTOR_SIZE / GF_BYTES) struct grub_luks { @@ -107,7 +109,7 @@ struct grub_luks unsigned long id, source_id; enum grub_disk_dev_id source_dev_id; char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; - grub_uint8_t lrw_key[GF_SIZE / 8]; + grub_uint8_t lrw_key[GF_BYTES]; grub_uint8_t *lrw_precalc; #ifdef GRUB_UTIL char *cheat; @@ -137,7 +139,7 @@ gf_mul_x (grub_uint8_t *g) int over = 0, over2 = 0; int j; - for (j = 0; j < GF_SIZE / 8; j++) + for (j = 0; j < GF_BYTES; j++) { over2 = !!(g[j] & 0x80); g[j] <<= 1; @@ -155,7 +157,7 @@ gf_mul_x_be (grub_uint8_t *g) int over = 0, over2 = 0; int j; - for (j = GF_SIZE / 8 - 1; j >= 0; j--) + for (j = GF_BYTES - 1; j >= 0; j--) { over2 = !!(g[j] & 0x80); g[j] <<= 1; @@ -163,20 +165,20 @@ gf_mul_x_be (grub_uint8_t *g) over = over2; } if (over) - g[GF_SIZE / 8 - 1] ^= GF_POLYNOM; + g[GF_BYTES - 1] ^= GF_POLYNOM; } static void gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b) { int i; - grub_uint8_t t[GF_SIZE / 8]; - grub_memset (o, 0, GF_SIZE / 8); - grub_memcpy (t, b, GF_SIZE / 8); + grub_uint8_t t[GF_BYTES]; + grub_memset (o, 0, GF_BYTES); + grub_memcpy (t, b, GF_BYTES); for (i = 0; i < GF_SIZE; i++) { - if (((a[GF_SIZE / 8 - i / 8 - 1] >> (i % 8))) & 1) - grub_crypto_xor (o, o, t, GF_SIZE / 8); + if (((a[GF_BYTES - i / 8 - 1] >> (i % 8))) & 1) + grub_crypto_xor (o, o, t, GF_BYTES); gf_mul_x_be (t); } } @@ -204,9 +206,6 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, return GPG_ERR_NO_ERROR; } -#define GF_BYTES (GF_SIZE / 8) -#define GF_PER_SECTOR (GRUB_DISK_SECTOR_SIZE / GF_BYTES) - struct lrw_sector { grub_uint8_t low[GF_BYTES]; @@ -473,14 +472,14 @@ configure_ciphers (const struct grub_luks_phdr *header) grub_crypto_cipher_close (cipher); return NULL; } - if (cipher->cipher->blocksize != GF_SIZE / 8) + if (cipher->cipher->blocksize != GF_BYTES) { grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", cipher->cipher->blocksize); return NULL; } - if (secondary_cipher->cipher->blocksize != GF_SIZE / 8) + if (secondary_cipher->cipher->blocksize != GF_BYTES) { grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", @@ -492,7 +491,7 @@ configure_ciphers (const struct grub_luks_phdr *header) { mode = GRUB_LUKS_MODE_LRW; cipheriv = ciphermode + sizeof ("lrw-") - 1; - if (cipher->cipher->blocksize != GF_SIZE / 8) + if (cipher->cipher->blocksize != GF_BYTES) { grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d", @@ -627,7 +626,7 @@ luks_setkey (grub_luks_t dev, grub_uint8_t *key, grub_size_t keysize) if (dev->mode == GRUB_LUKS_MODE_LRW) { int i; - grub_uint8_t idx[GF_SIZE / 8]; + grub_uint8_t idx[GF_BYTES]; grub_free (dev->lrw_precalc); grub_memcpy (dev->lrw_key, key + real_keysize, @@ -635,10 +634,10 @@ luks_setkey (grub_luks_t dev, grub_uint8_t *key, grub_size_t keysize) dev->lrw_precalc = grub_malloc (GRUB_DISK_SECTOR_SIZE); if (!dev->lrw_precalc) return GPG_ERR_OUT_OF_MEMORY; - grub_memset (idx, 0, GF_SIZE / 8); - for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i += GF_SIZE / 8) + grub_memset (idx, 0, GF_BYTES); + for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i += GF_BYTES) { - idx[15] = i / (GF_SIZE / 8); + idx[15] = i / GF_BYTES; gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key); } } From fcf3bfb6ffcd03e2b134f6b1c09571351793d50b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 16:45:00 +0200 Subject: [PATCH 140/673] small readability improvement --- grub-core/disk/luks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 4a35ef011..a9590cab5 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -637,7 +637,7 @@ luks_setkey (grub_luks_t dev, grub_uint8_t *key, grub_size_t keysize) grub_memset (idx, 0, GF_BYTES); for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i += GF_BYTES) { - idx[15] = i / GF_BYTES; + idx[GF_BYTES - 1] = i / GF_BYTES; gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key); } } From 8585e54becc32be8cb8e45b85fd14f5235a5c2dd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Apr 2011 18:00:42 +0200 Subject: [PATCH 141/673] factor cryptodisk part out --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/disk/luks.c | 713 ++++------------------------------- grub-core/kern/emu/getroot.c | 2 +- include/grub/disk.h | 2 +- include/grub/emu/hostdisk.h | 1 - util/grub-probe.c | 11 +- 7 files changed, 80 insertions(+), 655 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 693a7d127..ffa7a794f 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -23,6 +23,7 @@ library = { common = grub-core/kern/partition.c; common = grub-core/lib/crypto.c; common = grub-core/disk/luks.c; + common = grub-core/disk/cryptodisk.c; common = grub-core/disk/AFSplitter.c; common = grub-core/lib/pbkdf2.c; common = grub-core/commands/extcmd.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8dc810200..c55fff13a 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -768,6 +768,11 @@ module = { common = disk/loopback.c; }; +module = { + name = cryptodisk; + common = disk/cryptodisk.c; +}; + module = { name = luks; common = disk/luks.c; diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index a9590cab5..361beb756 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -16,6 +16,7 @@ * along with GRUB. If not, see . */ +#include #include #include #include @@ -25,15 +26,6 @@ #include #include #include -#ifdef GRUB_UTIL -#include -#include -#include -#include -#include -#include -#include -#endif GRUB_MOD_LICENSE ("GPLv3+"); @@ -69,59 +61,6 @@ struct grub_luks_phdr typedef struct grub_luks_phdr *grub_luks_phdr_t; -typedef enum - { - GRUB_LUKS_MODE_ECB, - GRUB_LUKS_MODE_CBC, - GRUB_LUKS_MODE_PCBC, - GRUB_LUKS_MODE_XTS, - GRUB_LUKS_MODE_LRW - } luks_mode_t; - -typedef enum - { - GRUB_LUKS_MODE_IV_NULL, - GRUB_LUKS_MODE_IV_PLAIN, - GRUB_LUKS_MODE_IV_PLAIN64, - GRUB_LUKS_MODE_IV_ESSIV, - GRUB_LUKS_MODE_IV_BENBI, - } luks_mode_iv_t; - -/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ -#define GF_POLYNOM 0x87 -#define GF_SIZE 128 -#define GF_BYTES (GF_SIZE / 8) -#define GF_PER_SECTOR (GRUB_DISK_SECTOR_SIZE / GF_BYTES) - -struct grub_luks -{ - char *source; - grub_uint32_t offset; - grub_disk_t source_disk; - int ref; - grub_crypto_cipher_handle_t cipher; - grub_crypto_cipher_handle_t secondary_cipher; - grub_crypto_cipher_handle_t essiv_cipher; - const gcry_md_spec_t *essiv_hash, *hash; - luks_mode_t mode; - luks_mode_iv_t mode_iv; - int benbi_log; - unsigned long id, source_id; - enum grub_disk_dev_id source_dev_id; - char uuid[sizeof (((struct grub_luks_phdr *) 0)->uuid) + 1]; - grub_uint8_t lrw_key[GF_BYTES]; - grub_uint8_t *lrw_precalc; -#ifdef GRUB_UTIL - char *cheat; - int cheat_fd; -#endif - struct grub_luks *next; -}; -typedef struct grub_luks *grub_luks_t; - -static grub_luks_t luks_list = NULL; -static grub_uint8_t n = 0; - gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst, grub_size_t blocksize, grub_size_t blocknumbers); @@ -133,249 +72,13 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static void -gf_mul_x (grub_uint8_t *g) -{ - int over = 0, over2 = 0; - int j; - - for (j = 0; j < GF_BYTES; j++) - { - over2 = !!(g[j] & 0x80); - g[j] <<= 1; - g[j] |= over; - over = over2; - } - if (over) - g[0] ^= GF_POLYNOM; -} - - -static void -gf_mul_x_be (grub_uint8_t *g) -{ - int over = 0, over2 = 0; - int j; - - for (j = GF_BYTES - 1; j >= 0; j--) - { - over2 = !!(g[j] & 0x80); - g[j] <<= 1; - g[j] |= over; - over = over2; - } - if (over) - g[GF_BYTES - 1] ^= GF_POLYNOM; -} - -static void -gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b) -{ - int i; - grub_uint8_t t[GF_BYTES]; - grub_memset (o, 0, GF_BYTES); - grub_memcpy (t, b, GF_BYTES); - for (i = 0; i < GF_SIZE; i++) - { - if (((a[GF_BYTES - i / 8 - 1] >> (i % 8))) & 1) - grub_crypto_xor (o, o, t, GF_BYTES); - gf_mul_x_be (t); - } -} - -static gcry_err_code_t -grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size, - void *iv) -{ - grub_uint8_t *inptr, *outptr, *end; - grub_uint8_t ivt[cipher->cipher->blocksize]; - if (!cipher->cipher->decrypt) - return GPG_ERR_NOT_SUPPORTED; - if (size % cipher->cipher->blocksize != 0) - return GPG_ERR_INV_ARG; - end = (grub_uint8_t *) in + size; - for (inptr = in, outptr = out; inptr < end; - inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) - { - grub_memcpy (ivt, inptr, cipher->cipher->blocksize); - cipher->cipher->decrypt (cipher->ctx, outptr, inptr); - grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); - grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); - } - return GPG_ERR_NO_ERROR; -} - -struct lrw_sector -{ - grub_uint8_t low[GF_BYTES]; - grub_uint8_t high[GF_BYTES]; - grub_uint8_t low_byte, low_byte_c; -}; - -static void -generate_lrw_sector (struct lrw_sector *sec, - const struct grub_luks *dev, - const grub_uint8_t *iv) -{ - grub_uint8_t idx[GF_BYTES]; - grub_uint16_t c; - int j; - grub_memcpy (idx, iv, GF_BYTES); - sec->low_byte = (idx[GF_BYTES - 1] & (GF_PER_SECTOR - 1)); - sec->low_byte_c = (((GF_PER_SECTOR - 1) & ~sec->low_byte) + 1); - idx[GF_BYTES - 1] &= ~(GF_PER_SECTOR - 1); - gf_mul_be (sec->low, dev->lrw_key, idx); - if (!sec->low_byte) - return; - - c = idx[GF_BYTES - 1] + GF_PER_SECTOR; - if (c & 0x100) - { - for (j = GF_BYTES - 2; j >= 0; j--) - { - idx[j]++; - if (idx[j] != 0) - break; - } - } - idx[GF_BYTES - 1] = c; - gf_mul_be (sec->high, dev->lrw_key, idx); -} - -static void __attribute__ ((unused)) -lrw_xor (const struct lrw_sector *sec, - const struct grub_luks *dev, - grub_uint8_t *b) -{ - int i; - - for (i = 0; i < sec->low_byte_c * GF_BYTES; i += GF_BYTES) - grub_crypto_xor (b + i, b + i, sec->low, GF_BYTES); - grub_crypto_xor (b, b, dev->lrw_precalc + GF_BYTES * sec->low_byte, - sec->low_byte_c * GF_BYTES); - if (!sec->low_byte) - return; - - for (i = sec->low_byte_c * GF_BYTES; - i < GRUB_DISK_SECTOR_SIZE; i += GF_BYTES) - grub_crypto_xor (b + i, b + i, sec->high, GF_BYTES); - grub_crypto_xor (b + sec->low_byte_c * GF_BYTES, - b + sec->low_byte_c * GF_BYTES, - dev->lrw_precalc, sec->low_byte * GF_BYTES); -} - -static gcry_err_code_t -luks_decrypt (const struct grub_luks *dev, - grub_uint8_t * data, grub_size_t len, grub_disk_addr_t sector) -{ - grub_size_t i; - gcry_err_code_t err; - - /* The only mode without IV. */ - if (dev->mode == GRUB_LUKS_MODE_ECB) - return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); - - for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) - { - grub_size_t sz = ((dev->cipher->cipher->blocksize - + sizeof (grub_uint32_t) - 1) - / sizeof (grub_uint32_t)); - grub_uint32_t iv[sz]; - - grub_memset (iv, 0, sz * sizeof (iv[0])); - switch (dev->mode_iv) - { - case GRUB_LUKS_MODE_IV_NULL: - break; - case GRUB_LUKS_MODE_IV_PLAIN64: - iv[1] = grub_cpu_to_le32 (sector >> 32); - case GRUB_LUKS_MODE_IV_PLAIN: - iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); - break; - case GRUB_LUKS_MODE_IV_BENBI: - { - grub_uint64_t num = (sector << dev->benbi_log) + 1; - iv[sz - 2] = grub_cpu_to_be32 (num >> 32); - iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF); - } - break; - case GRUB_LUKS_MODE_IV_ESSIV: - iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); - err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv, - dev->cipher->cipher->blocksize); - if (err) - return err; - } - - switch (dev->mode) - { - case GRUB_LUKS_MODE_CBC: - err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, - GRUB_DISK_SECTOR_SIZE, iv); - if (err) - return err; - break; - - case GRUB_LUKS_MODE_PCBC: - err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, - GRUB_DISK_SECTOR_SIZE, iv); - if (err) - return err; - break; - case GRUB_LUKS_MODE_XTS: - { - int j; - err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, - dev->cipher->cipher->blocksize); - if (err) - return err; - - for (j = 0; j < GRUB_DISK_SECTOR_SIZE; - j += dev->cipher->cipher->blocksize) - { - grub_crypto_xor (data + i + j, data + i + j, iv, - dev->cipher->cipher->blocksize); - err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, - data + i + j, - dev->cipher->cipher->blocksize); - if (err) - return err; - grub_crypto_xor (data + i + j, data + i + j, iv, - dev->cipher->cipher->blocksize); - gf_mul_x ((grub_uint8_t *) iv); - } - } - break; - case GRUB_LUKS_MODE_LRW: - { - struct lrw_sector sec; - - generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv); - lrw_xor (&sec, dev, data + i); - - err = grub_crypto_ecb_decrypt (dev->cipher, data + i, - data + i, GRUB_DISK_SECTOR_SIZE); - if (err) - return err; - lrw_xor (&sec, dev, data + i); - } - break; - default: - return GPG_ERR_NOT_IMPLEMENTED; - } - sector++; - } - return GPG_ERR_NO_ERROR; -} - static int check_uuid, have_it; static char *search_uuid; -static grub_luks_t +static grub_cryptodisk_t configure_ciphers (const struct grub_luks_phdr *header) { - grub_luks_t newdev; + grub_cryptodisk_t newdev; const char *iptr; char *optr; char uuid[sizeof (header->uuid) + 1]; @@ -387,8 +90,8 @@ configure_ciphers (const struct grub_luks_phdr *header) grub_crypto_cipher_handle_t essiv_cipher = NULL; const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; const struct gcry_cipher_spec *ciph; - luks_mode_t mode; - luks_mode_iv_t mode_iv; + grub_cryptodisk_mode_t mode; + grub_cryptodisk_mode_iv_t mode_iv; int benbi_log = 0; /* Look for LUKS magic sequence. */ @@ -442,29 +145,29 @@ configure_ciphers (const struct grub_luks_phdr *header) /* Configure the cipher mode. */ if (grub_strcmp (ciphermode, "ecb") == 0) { - mode = GRUB_LUKS_MODE_ECB; - mode_iv = GRUB_LUKS_MODE_IV_PLAIN; + mode = GRUB_CRYPTODISK_MODE_ECB; + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; cipheriv = NULL; } else if (grub_strcmp (ciphermode, "plain") == 0) { - mode = GRUB_LUKS_MODE_CBC; - mode_iv = GRUB_LUKS_MODE_IV_PLAIN; + mode = GRUB_CRYPTODISK_MODE_CBC; + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; cipheriv = NULL; } else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0) { - mode = GRUB_LUKS_MODE_CBC; + mode = GRUB_CRYPTODISK_MODE_CBC; cipheriv = ciphermode + sizeof ("cbc-") - 1; } else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0) { - mode = GRUB_LUKS_MODE_PCBC; + mode = GRUB_CRYPTODISK_MODE_PCBC; cipheriv = ciphermode + sizeof ("pcbc-") - 1; } else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0) { - mode = GRUB_LUKS_MODE_XTS; + mode = GRUB_CRYPTODISK_MODE_XTS; cipheriv = ciphermode + sizeof ("xts-") - 1; secondary_cipher = grub_crypto_cipher_open (ciph); if (!secondary_cipher) @@ -472,14 +175,14 @@ configure_ciphers (const struct grub_luks_phdr *header) grub_crypto_cipher_close (cipher); return NULL; } - if (cipher->cipher->blocksize != GF_BYTES) + if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) { grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", cipher->cipher->blocksize); return NULL; } - if (secondary_cipher->cipher->blocksize != GF_BYTES) + if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) { grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", @@ -489,9 +192,9 @@ configure_ciphers (const struct grub_luks_phdr *header) } else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0) { - mode = GRUB_LUKS_MODE_LRW; + mode = GRUB_CRYPTODISK_MODE_LRW; cipheriv = ciphermode + sizeof ("lrw-") - 1; - if (cipher->cipher->blocksize != GF_BYTES) + if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) { grub_crypto_cipher_close (cipher); grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d", @@ -509,9 +212,9 @@ configure_ciphers (const struct grub_luks_phdr *header) if (cipheriv == NULL); else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0) - mode_iv = GRUB_LUKS_MODE_IV_PLAIN; + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0) - mode_iv = GRUB_LUKS_MODE_IV_PLAIN64; + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64; else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0) { if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1) @@ -521,15 +224,15 @@ configure_ciphers (const struct grub_luks_phdr *header) for (benbi_log = 0; (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE; benbi_log++); - mode_iv = GRUB_LUKS_MODE_IV_BENBI; + mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI; } else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0) - mode_iv = GRUB_LUKS_MODE_IV_NULL; + mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL; else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0) { char *hash_str = cipheriv + 6; - mode_iv = GRUB_LUKS_MODE_IV_ESSIV; + mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV; /* Configure the hash and cipher used for ESSIV. */ essiv_hash = grub_crypto_lookup_md_by_name (hash_str); @@ -567,7 +270,7 @@ configure_ciphers (const struct grub_luks_phdr *header) return NULL; } - newdev = grub_zalloc (sizeof (struct grub_luks)); + newdev = grub_zalloc (sizeof (struct grub_cryptodisk)); if (!newdev) return NULL; newdev->cipher = cipher; @@ -580,72 +283,12 @@ configure_ciphers (const struct grub_luks_phdr *header) newdev->essiv_cipher = essiv_cipher; newdev->essiv_hash = essiv_hash; newdev->hash = hash; - newdev->id = n++; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); return newdev; } -static gcry_err_code_t -luks_setkey (grub_luks_t dev, grub_uint8_t *key, grub_size_t keysize) -{ - gcry_err_code_t err; - int real_keysize; - - real_keysize = keysize; - if (dev->mode == GRUB_LUKS_MODE_XTS) - real_keysize /= 2; - if (dev->mode == GRUB_LUKS_MODE_LRW) - real_keysize -= dev->cipher->cipher->blocksize; - - /* Set the PBKDF2 output as the cipher key. */ - err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize); - if (err) - return err; - - /* Configure ESSIV if necessary. */ - if (dev->mode_iv == GRUB_LUKS_MODE_IV_ESSIV) - { - grub_size_t essiv_keysize = dev->essiv_hash->mdlen; - grub_uint8_t hashed_key[essiv_keysize]; - - grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize); - err = grub_crypto_cipher_set_key (dev->essiv_cipher, - hashed_key, essiv_keysize); - if (err) - return err; - } - if (dev->mode == GRUB_LUKS_MODE_XTS) - { - err = grub_crypto_cipher_set_key (dev->secondary_cipher, - key + real_keysize, - keysize / 2); - if (err) - return err; - } - - if (dev->mode == GRUB_LUKS_MODE_LRW) - { - int i; - grub_uint8_t idx[GF_BYTES]; - - grub_free (dev->lrw_precalc); - grub_memcpy (dev->lrw_key, key + real_keysize, - dev->cipher->cipher->blocksize); - dev->lrw_precalc = grub_malloc (GRUB_DISK_SECTOR_SIZE); - if (!dev->lrw_precalc) - return GPG_ERR_OUT_OF_MEMORY; - grub_memset (idx, 0, GF_BYTES); - for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i += GF_BYTES) - { - idx[GF_BYTES - 1] = i / GF_BYTES; - gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key); - } - } - return GPG_ERR_NO_ERROR; -} - static grub_err_t -luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, +luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, const char *name, grub_disk_t source) { grub_size_t keysize = grub_be_to_cpu32 (header->keyBytes); @@ -700,7 +343,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_dprintf ("luks", "PBKDF2 done\n"); - gcry_err = luks_setkey (dev, digest, keysize); + gcry_err = grub_cryptodisk_setkey (dev, digest, keysize); if (gcry_err) { grub_free (split_key); @@ -721,7 +364,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, return err; } - gcry_err = luks_decrypt (dev, split_key, length, 0); + gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0); if (gcry_err) { grub_free (split_key); @@ -766,7 +409,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, grub_printf ("Slot %d opened\n", i); /* Set the master key. */ - gcry_err = luks_setkey (dev, candidate_key, keysize); + gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); if (gcry_err) { grub_free (split_key); @@ -782,7 +425,7 @@ luks_recover_key (grub_luks_t dev, const struct grub_luks_phdr *header, } static void -luks_close (grub_luks_t luks) +luks_close (grub_cryptodisk_t luks) { grub_crypto_cipher_close (luks->cipher); grub_crypto_cipher_close (luks->secondary_cipher); @@ -795,11 +438,12 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) { grub_err_t err; struct grub_luks_phdr header; - grub_luks_t newdev, dev; + grub_cryptodisk_t newdev, dev; - for (dev = luks_list; dev != NULL; dev = dev->next) - if (dev->source_id == source->id && dev->source_dev_id == source->dev->id) - return GRUB_ERR_NONE; + dev = grub_cryptodisk_get_by_source_disk (source); + + if (dev) + return GRUB_ERR_NONE; /* Read the LUKS header. */ err = grub_disk_read (source, 0, 0, sizeof (header), &header); @@ -817,17 +461,7 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) return err; } - newdev->source = grub_strdup (name); - if (!newdev->source) - { - grub_free (newdev); - return grub_errno; - } - - newdev->source_id = source->id; - newdev->source_dev_id = source->dev->id; - newdev->next = luks_list; - luks_list = newdev; + grub_cryptodisk_insert (newdev, name, source); have_it = 1; @@ -840,7 +474,7 @@ grub_luks_cheat_mount (const char *sourcedev, const char *cheat) { grub_err_t err; struct grub_luks_phdr header; - grub_luks_t newdev, dev; + grub_cryptodisk_t newdev, dev; grub_disk_t source; /* Try to open disk. */ @@ -848,12 +482,13 @@ grub_luks_cheat_mount (const char *sourcedev, const char *cheat) if (!source) return grub_errno; - for (dev = luks_list; dev != NULL; dev = dev->next) - if (dev->source_id == source->id && dev->source_dev_id == source->dev->id) - { - grub_disk_close (source); - return GRUB_ERR_NONE; - } + dev = grub_cryptodisk_get_by_source_disk (source); + + if (dev) + { + grub_disk_close (source); + return GRUB_ERR_NONE; + } /* Read the LUKS header. */ err = grub_disk_read (source, 0, 0, sizeof (header), &header); @@ -861,25 +496,18 @@ grub_luks_cheat_mount (const char *sourcedev, const char *cheat) return err; newdev = configure_ciphers (&header); - grub_disk_close (source); if (!newdev) - return grub_errno; - - newdev->cheat = grub_strdup (cheat); - newdev->source = grub_strdup (sourcedev); - if (!newdev->source || !newdev->cheat) { - grub_free (newdev->source); - grub_free (newdev->cheat); - grub_free (newdev); + grub_disk_close (source); return grub_errno; } - newdev->cheat_fd = -1; - newdev->source_id = source->id; - newdev->source_dev_id = source->dev->id; - newdev->next = luks_list; - luks_list = newdev; - return GRUB_ERR_NONE; + + err = grub_cryptodisk_cheat_insert (newdev, sourcedev, source, cheat); + grub_disk_close (source); + if (err) + grub_free (newdev); + + return err; } #endif @@ -903,208 +531,16 @@ grub_luks_scan_device (const char *name) return have_it && check_uuid ? 0 : 1; } -static int -grub_luks_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) -{ - grub_luks_t i; - - if (pull != GRUB_DISK_PULL_NONE) - return 0; - - for (i = luks_list; i != NULL; i = i->next) - { - char buf[30]; - grub_snprintf (buf, sizeof (buf), "luks%lu", i->id); - if (hook (buf)) - return 1; - } - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_luks_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) -{ - grub_luks_t dev; - - if (grub_memcmp (name, "luks", sizeof ("luks") - 1) != 0) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); - - if (grub_memcmp (name, "luksuuid/", sizeof ("luksuuid/") - 1) == 0) - { - for (dev = luks_list; dev != NULL; dev = dev->next) - if (grub_strcasecmp (name + sizeof ("luksuuid/") - 1, dev->uuid) == 0) - break; - } - else - { - unsigned long id = grub_strtoul (name + sizeof ("luks") - 1, 0, 0); - if (grub_errno) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); - /* Search for requested device in the list of LUKS devices. */ - for (dev = luks_list; dev != NULL; dev = dev->next) - if (dev->id == id) - break; - } - if (!dev) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); - #ifdef GRUB_UTIL - if (dev->cheat) - { - if (dev->cheat_fd == -1) - dev->cheat_fd = open (dev->cheat, O_RDONLY); - if (dev->cheat_fd == -1) - return grub_error (GRUB_ERR_IO, "couldn't open %s: %s", - dev->cheat, strerror (errno)); - } -#endif - - if (!dev->source_disk) - { - grub_dprintf ("luks", "Opening device %s\n", name); - /* Try to open the source disk and populate the requested disk. */ - dev->source_disk = grub_disk_open (dev->source); - if (!dev->source_disk) - return grub_errno; - } - - disk->data = dev; - disk->total_sectors = grub_disk_get_size (dev->source_disk) - dev->offset; - disk->id = dev->id; - dev->ref++; - return GRUB_ERR_NONE; -} - -static void -grub_luks_close (grub_disk_t disk) -{ - grub_luks_t dev = (grub_luks_t) disk->data; - grub_dprintf ("luks", "Closing disk\n"); - - dev->ref--; - - if (dev->ref != 0) - return; -#ifdef GRUB_UTIL - if (dev->cheat) - { - close (dev->cheat_fd); - dev->cheat_fd = -1; - } -#endif - grub_disk_close (dev->source_disk); - dev->source_disk = NULL; -} - -static grub_err_t -grub_luks_read (grub_disk_t disk, grub_disk_addr_t sector, - grub_size_t size, char *buf) -{ - grub_luks_t dev = (grub_luks_t) disk->data; - grub_err_t err; - -#ifdef GRUB_UTIL - if (dev->cheat) - { - err = grub_util_fd_sector_seek (dev->cheat_fd, dev->cheat, sector); - if (err) - return err; - if (grub_util_fd_read (dev->cheat_fd, buf, size << GRUB_DISK_SECTOR_BITS) - != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) - return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", - dev->cheat); - return GRUB_ERR_NONE; - } -#endif - - grub_dprintf ("luks", - "Reading %" PRIuGRUB_SIZE " sectors from sector 0x%" - PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT32_T "\n", - size, sector, dev->offset); - - err = grub_disk_read (dev->source_disk, sector + dev->offset, 0, - size << GRUB_DISK_SECTOR_BITS, buf); - if (err) - { - grub_dprintf ("luks", "grub_disk_read failed with error %d\n", err); - return err; - } - return grub_crypto_gcry_error (luks_decrypt (dev, (grub_uint8_t *) buf, - size << GRUB_DISK_SECTOR_BITS, - sector)); -} - -static grub_err_t -grub_luks_write (grub_disk_t disk __attribute ((unused)), - grub_disk_addr_t sector __attribute ((unused)), - grub_size_t size __attribute ((unused)), - const char *buf __attribute ((unused))) -{ - return GRUB_ERR_NOT_IMPLEMENTED_YET; -} - -#ifdef GRUB_UTIL -static grub_disk_memberlist_t -grub_luks_memberlist (grub_disk_t disk) -{ - grub_luks_t dev = (grub_luks_t) disk->data; - grub_disk_memberlist_t list = NULL; - - list = grub_malloc (sizeof (*list)); - if (list) - { - list->disk = dev->source_disk; - list->next = NULL; - } - - return list; -} - -void -grub_util_luks_print_ciphers (grub_disk_t disk) -{ - grub_luks_t dev = (grub_luks_t) disk->data; - if (dev->cipher) - grub_printf ("%s ", dev->cipher->cipher->modname); - if (dev->secondary_cipher) - grub_printf ("%s ", dev->secondary_cipher->cipher->modname); - if (dev->essiv_cipher) - grub_printf ("%s ", dev->essiv_cipher->cipher->modname); - if (dev->hash) - grub_printf ("%s ", dev->hash->modname); - if (dev->essiv_hash) - grub_printf ("%s ", dev->essiv_hash->modname); -} void grub_util_luks_print_uuid (grub_disk_t disk) { - grub_luks_t dev = (grub_luks_t) disk->data; + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; grub_printf ("%s ", dev->uuid); } #endif -static void -luks_cleanup (void) -{ - grub_luks_t dev = luks_list; - grub_luks_t tmp; - - while (dev != NULL) - { - grub_free (dev->source); - grub_free (dev->cipher); - grub_free (dev->secondary_cipher); - grub_free (dev->essiv_cipher); - tmp = dev->next; - grub_free (dev); - dev = tmp; - } -} - static grub_err_t grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) { @@ -1116,14 +552,14 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) have_it = 0; if (state[0].set) { - grub_luks_t dev; + grub_cryptodisk_t dev; - for (dev = luks_list; dev != NULL; dev = dev->next) - if (grub_strcasecmp (dev->uuid, args[0]) == 0) - { - grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); - return GRUB_ERR_NONE; - } + dev = grub_cryptodisk_get_by_uuid (args[0]); + if (dev) + { + grub_dprintf ("luks", "already mounted as crypto%lu\n", dev->id); + return GRUB_ERR_NONE; + } check_uuid = 1; search_uuid = args[0]; @@ -1146,7 +582,7 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) { grub_err_t err; grub_disk_t disk; - grub_luks_t dev; + grub_cryptodisk_t dev; check_uuid = 0; search_uuid = NULL; @@ -1154,13 +590,13 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) if (!disk) return grub_errno; - for (dev = luks_list; dev != NULL; dev = dev->next) - if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id) - { - grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); - grub_disk_close (disk); - return GRUB_ERR_NONE; - } + dev = grub_cryptodisk_get_by_source_disk (disk); + if (dev) + { + grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); + grub_disk_close (disk); + return GRUB_ERR_NONE; + } err = grub_luks_scan_device_real (args[0], disk); @@ -1170,33 +606,18 @@ grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) } } -static struct grub_disk_dev grub_luks_dev = { - .name = "luks", - .id = GRUB_DISK_DEVICE_LUKS_ID, - .iterate = grub_luks_iterate, - .open = grub_luks_open, - .close = grub_luks_close, - .read = grub_luks_read, - .write = grub_luks_write, -#ifdef GRUB_UTIL - .memberlist = grub_luks_memberlist, -#endif - .next = 0 -}; - static grub_extcmd_t cmd; GRUB_MOD_INIT (luks) { + COMPILE_TIME_ASSERT (sizeof (((struct grub_luks_phdr *) 0)->uuid) + < GRUB_CRYPTODISK_MAX_UUID_LENGTH); cmd = grub_register_extcmd ("luksmount", grub_cmd_luksmount, 0, N_("SOURCE|-u UUID|-a"), N_("Mount a LUKS device."), options); - grub_disk_dev_register (&grub_luks_dev); } GRUB_MOD_FINI (luks) { grub_unregister_extcmd (cmd); - grub_disk_dev_unregister (&grub_luks_dev); - luks_cleanup (); } diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index c3a971689..642d77cf0 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -962,7 +962,7 @@ grub_util_get_grub_dev (const char *os_dev) dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-'); if (dash) *dash = 0; - grub_dev = grub_xasprintf ("luksuuid/%s", + grub_dev = grub_xasprintf ("cryptouuid/%s", uuid + sizeof ("CRYPT-LUKS1-") - 1); grub_free (uuid); } diff --git a/include/grub/disk.h b/include/grub/disk.h index 2678ad5eb..52f3e61b0 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -42,7 +42,7 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_FILE_ID, - GRUB_DISK_DEVICE_LUKS_ID + GRUB_DISK_DEVICE_CRYPTODISK_ID }; struct grub_disk; diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 7541308e6..c1350a370 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -36,7 +36,6 @@ grub_util_fd_sector_seek (int fd, const char *name, grub_disk_addr_t sector); ssize_t grub_util_fd_read (int fd, char *buf, size_t len); grub_err_t grub_luks_cheat_mount (const char *sourcedev, const char *cheat); -void grub_util_luks_print_ciphers (grub_disk_t disk); void grub_util_luks_print_uuid (grub_disk_t disk); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/util/grub-probe.c b/util/grub-probe.c index 21fc21b02..f5d93ac4e 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -106,7 +107,8 @@ probe_luks_uuid (grub_disk_t disk) free (list); list = tmp; } - if (disk->dev->id == GRUB_DISK_DEVICE_LUKS_ID) + /* FIXME: support non-LUKS. */ + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) grub_util_luks_print_uuid (disk); } @@ -144,11 +146,8 @@ probe_abstraction (grub_disk_t disk) if (disk->dev->id == GRUB_DISK_DEVICE_LVM_ID) printf ("lvm "); - if (disk->dev->id == GRUB_DISK_DEVICE_LUKS_ID) - { - printf ("luks "); - grub_util_luks_print_ciphers (disk); - } + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) + grub_util_cryptodisk_print_abstraction (disk); raid_level = probe_raid_level (disk); if (raid_level >= 0) From 1a1f408f206f2e29b40b172b0e9857f0137d91a6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 00:00:29 +0200 Subject: [PATCH 142/673] geli support --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/disk/cryptodisk.c | 643 ++++++++++++++++++++++++++++++++++++ grub-core/disk/geli.c | 515 +++++++++++++++++++++++++++++ grub-core/disk/luks.c | 4 + grub-core/lib/crypto.c | 10 +- include/grub/crypto.h | 4 +- include/grub/cryptodisk.h | 99 ++++++ util/grub-fstest.c | 8 +- 9 files changed, 1281 insertions(+), 8 deletions(-) create mode 100644 grub-core/disk/cryptodisk.c create mode 100644 grub-core/disk/geli.c create mode 100644 include/grub/cryptodisk.h diff --git a/Makefile.util.def b/Makefile.util.def index ffa7a794f..fe9e8c036 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -23,6 +23,7 @@ library = { common = grub-core/kern/partition.c; common = grub-core/lib/crypto.c; common = grub-core/disk/luks.c; + common = grub-core/disk/geli.c; common = grub-core/disk/cryptodisk.c; common = grub-core/disk/AFSplitter.c; common = grub-core/lib/pbkdf2.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index c55fff13a..52add9f1b 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -779,6 +779,11 @@ module = { common = disk/AFSplitter.c; }; +module = { + name = geli; + common = disk/geli.c; +}; + module = { name = lvm; common = disk/lvm.c; diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c new file mode 100644 index 000000000..7f3b60bf5 --- /dev/null +++ b/grub-core/disk/cryptodisk.c @@ -0,0 +1,643 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007,2010,2011 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 . + */ + +#include +#include +#include +#include + +#ifdef GRUB_UTIL +#include +#include +#include +#include +#include +#include +#include +#endif + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ +#define GF_POLYNOM 0x87 +#define GF_PER_SECTOR (GRUB_DISK_SECTOR_SIZE / GRUB_CRYPTODISK_GF_BYTES) + +static grub_cryptodisk_t cryptodisk_list = NULL; +static grub_uint8_t n = 0; + +static void +gf_mul_x (grub_uint8_t *g) +{ + int over = 0, over2 = 0; + int j; + + for (j = 0; j < GRUB_CRYPTODISK_GF_BYTES; j++) + { + over2 = !!(g[j] & 0x80); + g[j] <<= 1; + g[j] |= over; + over = over2; + } + if (over) + g[0] ^= GF_POLYNOM; +} + + +static void +gf_mul_x_be (grub_uint8_t *g) +{ + int over = 0, over2 = 0; + int j; + + for (j = GRUB_CRYPTODISK_GF_BYTES - 1; j >= 0; j--) + { + over2 = !!(g[j] & 0x80); + g[j] <<= 1; + g[j] |= over; + over = over2; + } + if (over) + g[GRUB_CRYPTODISK_GF_BYTES - 1] ^= GF_POLYNOM; +} + +static void +gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b) +{ + int i; + grub_uint8_t t[GRUB_CRYPTODISK_GF_BYTES]; + grub_memset (o, 0, GRUB_CRYPTODISK_GF_BYTES); + grub_memcpy (t, b, GRUB_CRYPTODISK_GF_BYTES); + for (i = 0; i < GRUB_CRYPTODISK_GF_SIZE; i++) + { + if (((a[GRUB_CRYPTODISK_GF_BYTES - i / 8 - 1] >> (i % 8))) & 1) + grub_crypto_xor (o, o, t, GRUB_CRYPTODISK_GF_BYTES); + gf_mul_x_be (t); + } +} + +static gcry_err_code_t +grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, + void *out, void *in, grub_size_t size, + void *iv) +{ + grub_uint8_t *inptr, *outptr, *end; + grub_uint8_t ivt[cipher->cipher->blocksize]; + if (!cipher->cipher->decrypt) + return GPG_ERR_NOT_SUPPORTED; + if (size % cipher->cipher->blocksize != 0) + return GPG_ERR_INV_ARG; + end = (grub_uint8_t *) in + size; + for (inptr = in, outptr = out; inptr < end; + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + { + grub_memcpy (ivt, inptr, cipher->cipher->blocksize); + cipher->cipher->decrypt (cipher->ctx, outptr, inptr); + grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); + grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); + } + return GPG_ERR_NO_ERROR; +} + +struct lrw_sector +{ + grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES]; + grub_uint8_t high[GRUB_CRYPTODISK_GF_BYTES]; + grub_uint8_t low_byte, low_byte_c; +}; + +static void +generate_lrw_sector (struct lrw_sector *sec, + const struct grub_cryptodisk *dev, + const grub_uint8_t *iv) +{ + grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES]; + grub_uint16_t c; + int j; + grub_memcpy (idx, iv, GRUB_CRYPTODISK_GF_BYTES); + sec->low_byte = (idx[GRUB_CRYPTODISK_GF_BYTES - 1] & (GF_PER_SECTOR - 1)); + sec->low_byte_c = (((GF_PER_SECTOR - 1) & ~sec->low_byte) + 1); + idx[GRUB_CRYPTODISK_GF_BYTES - 1] &= ~(GF_PER_SECTOR - 1); + gf_mul_be (sec->low, dev->lrw_key, idx); + if (!sec->low_byte) + return; + + c = idx[GRUB_CRYPTODISK_GF_BYTES - 1] + GF_PER_SECTOR; + if (c & 0x100) + { + for (j = GRUB_CRYPTODISK_GF_BYTES - 2; j >= 0; j--) + { + idx[j]++; + if (idx[j] != 0) + break; + } + } + idx[GRUB_CRYPTODISK_GF_BYTES - 1] = c; + gf_mul_be (sec->high, dev->lrw_key, idx); +} + +static void __attribute__ ((unused)) +lrw_xor (const struct lrw_sector *sec, + const struct grub_cryptodisk *dev, + grub_uint8_t *b) +{ + int i; + + for (i = 0; i < sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES; i += GRUB_CRYPTODISK_GF_BYTES) + grub_crypto_xor (b + i, b + i, sec->low, GRUB_CRYPTODISK_GF_BYTES); + grub_crypto_xor (b, b, dev->lrw_precalc + GRUB_CRYPTODISK_GF_BYTES * sec->low_byte, + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES); + if (!sec->low_byte) + return; + + for (i = sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES; + i < GRUB_DISK_SECTOR_SIZE; i += GRUB_CRYPTODISK_GF_BYTES) + grub_crypto_xor (b + i, b + i, sec->high, GRUB_CRYPTODISK_GF_BYTES); + grub_crypto_xor (b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES, + b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES, + dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES); +} + +gcry_err_code_t +grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, + grub_uint8_t * data, grub_size_t len, + grub_disk_addr_t sector) +{ + grub_size_t i; + gcry_err_code_t err; + + /* The only mode without IV. */ + if (dev->mode == GRUB_CRYPTODISK_MODE_ECB) + return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); + + for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) + { + grub_size_t sz = ((dev->cipher->cipher->blocksize + + sizeof (grub_uint32_t) - 1) + / sizeof (grub_uint32_t)); + grub_uint32_t iv[sz]; + + grub_memset (iv, 0, sz * sizeof (iv[0])); + switch (dev->mode_iv) + { + case GRUB_CRYPTODISK_MODE_IV_NULL: + break; + case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH: + { + grub_uint64_t tmp; + grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8]; + tmp = grub_cpu_to_le64 (sector << GRUB_DISK_SECTOR_BITS); + dev->iv_hash->init (ctx); + dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len); + dev->iv_hash->write (ctx, &tmp, sizeof (tmp)); + dev->iv_hash->final (ctx); + + grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv)); + } + break; + case GRUB_CRYPTODISK_MODE_IV_PLAIN64: + iv[1] = grub_cpu_to_le32 (sector >> 32); + case GRUB_CRYPTODISK_MODE_IV_PLAIN: + iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + break; + case GRUB_CRYPTODISK_MODE_IV_BENBI: + { + grub_uint64_t num = (sector << dev->benbi_log) + 1; + iv[sz - 2] = grub_cpu_to_be32 (num >> 32); + iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF); + } + break; + case GRUB_CRYPTODISK_MODE_IV_ESSIV: + iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv, + dev->cipher->cipher->blocksize); + if (err) + return err; + } + + switch (dev->mode) + { + case GRUB_CRYPTODISK_MODE_CBC: + err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, + GRUB_DISK_SECTOR_SIZE, iv); + if (err) + return err; + break; + + case GRUB_CRYPTODISK_MODE_PCBC: + err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, + GRUB_DISK_SECTOR_SIZE, iv); + if (err) + return err; + break; + case GRUB_CRYPTODISK_MODE_XTS: + { + int j; + err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, + dev->cipher->cipher->blocksize); + if (err) + return err; + + for (j = 0; j < GRUB_DISK_SECTOR_SIZE; + j += dev->cipher->cipher->blocksize) + { + grub_crypto_xor (data + i + j, data + i + j, iv, + dev->cipher->cipher->blocksize); + err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, + data + i + j, + dev->cipher->cipher->blocksize); + if (err) + return err; + grub_crypto_xor (data + i + j, data + i + j, iv, + dev->cipher->cipher->blocksize); + gf_mul_x ((grub_uint8_t *) iv); + } + } + break; + case GRUB_CRYPTODISK_MODE_LRW: + { + struct lrw_sector sec; + + generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv); + lrw_xor (&sec, dev, data + i); + + err = grub_crypto_ecb_decrypt (dev->cipher, data + i, + data + i, GRUB_DISK_SECTOR_SIZE); + if (err) + return err; + lrw_xor (&sec, dev, data + i); + } + break; + default: + return GPG_ERR_NOT_IMPLEMENTED; + } + sector++; + } + return GPG_ERR_NO_ERROR; +} + +gcry_err_code_t +grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize) +{ + gcry_err_code_t err; + int real_keysize; + + real_keysize = keysize; + if (dev->mode == GRUB_CRYPTODISK_MODE_XTS) + real_keysize /= 2; + if (dev->mode == GRUB_CRYPTODISK_MODE_LRW) + real_keysize -= dev->cipher->cipher->blocksize; + + /* Set the PBKDF2 output as the cipher key. */ + err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize); + if (err) + return err; + + /* Configure ESSIV if necessary. */ + if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV) + { + grub_size_t essiv_keysize = dev->essiv_hash->mdlen; + grub_uint8_t hashed_key[essiv_keysize]; + + grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize); + err = grub_crypto_cipher_set_key (dev->essiv_cipher, + hashed_key, essiv_keysize); + if (err) + return err; + } + if (dev->mode == GRUB_CRYPTODISK_MODE_XTS) + { + err = grub_crypto_cipher_set_key (dev->secondary_cipher, + key + real_keysize, + keysize / 2); + if (err) + return err; + } + + if (dev->mode == GRUB_CRYPTODISK_MODE_LRW) + { + int i; + grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES]; + + grub_free (dev->lrw_precalc); + grub_memcpy (dev->lrw_key, key + real_keysize, + dev->cipher->cipher->blocksize); + dev->lrw_precalc = grub_malloc (GRUB_DISK_SECTOR_SIZE); + if (!dev->lrw_precalc) + return GPG_ERR_OUT_OF_MEMORY; + grub_memset (idx, 0, GRUB_CRYPTODISK_GF_BYTES); + for (i = 0; i < GRUB_DISK_SECTOR_SIZE; + i += GRUB_CRYPTODISK_GF_BYTES) + { + idx[GRUB_CRYPTODISK_GF_BYTES - 1] = i / GRUB_CRYPTODISK_GF_BYTES; + gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key); + } + } + return GPG_ERR_NO_ERROR; +} + +static int +grub_cryptodisk_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) +{ + grub_cryptodisk_t i; + + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + for (i = cryptodisk_list; i != NULL; i = i->next) + { + char buf[30]; + grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id); + if (hook (buf)) + return 1; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cryptodisk_open (const char *name, grub_disk_t disk, + grub_disk_pull_t pull __attribute__ ((unused))) +{ + grub_cryptodisk_t dev; + + if (grub_memcmp (name, "crypto", sizeof ("crypto") - 1) != 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + + if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0) + { + for (dev = cryptodisk_list; dev != NULL; dev = dev->next) + if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0) + break; + } + else + { + unsigned long id = grub_strtoul (name + sizeof ("crypto") - 1, 0, 0); + if (grub_errno) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + /* Search for requested device in the list of CRYPTODISK devices. */ + for (dev = cryptodisk_list; dev != NULL; dev = dev->next) + if (dev->id == id) + break; + } + if (!dev) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + +#ifdef GRUB_UTIL + if (dev->cheat) + { + if (dev->cheat_fd == -1) + dev->cheat_fd = open (dev->cheat, O_RDONLY); + if (dev->cheat_fd == -1) + return grub_error (GRUB_ERR_IO, "couldn't open %s: %s", + dev->cheat, strerror (errno)); + } +#endif + + if (!dev->source_disk) + { + grub_dprintf ("cryptodisk", "Opening device %s\n", name); + /* Try to open the source disk and populate the requested disk. */ + dev->source_disk = grub_disk_open (dev->source); + if (!dev->source_disk) + return grub_errno; + } + + disk->data = dev; + disk->total_sectors = dev->total_length; + disk->id = dev->id; + dev->ref++; + return GRUB_ERR_NONE; +} + +static void +grub_cryptodisk_close (grub_disk_t disk) +{ + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + grub_dprintf ("cryptodisk", "Closing disk\n"); + + dev->ref--; + + if (dev->ref != 0) + return; +#ifdef GRUB_UTIL + if (dev->cheat) + { + close (dev->cheat_fd); + dev->cheat_fd = -1; + } +#endif + grub_disk_close (dev->source_disk); + dev->source_disk = NULL; +} + +static grub_err_t +grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + grub_err_t err; + gcry_err_code_t gcry_err; + +#ifdef GRUB_UTIL + if (dev->cheat) + { + err = grub_util_fd_sector_seek (dev->cheat_fd, dev->cheat, sector); + if (err) + return err; + if (grub_util_fd_read (dev->cheat_fd, buf, size << GRUB_DISK_SECTOR_BITS) + != (ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", + dev->cheat); + return GRUB_ERR_NONE; + } +#endif + + grub_dprintf ("cryptodisk", + "Reading %" PRIuGRUB_SIZE " sectors from sector 0x%" + PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n", + size, sector, dev->offset); + + err = grub_disk_read (dev->source_disk, sector + dev->offset, 0, + size << GRUB_DISK_SECTOR_BITS, buf); + if (err) + { + grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err); + return err; + } + gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf, + size << GRUB_DISK_SECTOR_BITS, + sector); + return grub_crypto_gcry_error (gcry_err); +} + +static grub_err_t +grub_cryptodisk_write (grub_disk_t disk __attribute ((unused)), + grub_disk_addr_t sector __attribute ((unused)), + grub_size_t size __attribute ((unused)), + const char *buf __attribute ((unused))) +{ + return GRUB_ERR_NOT_IMPLEMENTED_YET; +} + +#ifdef GRUB_UTIL +static grub_disk_memberlist_t +grub_cryptodisk_memberlist (grub_disk_t disk) +{ + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + grub_disk_memberlist_t list = NULL; + + list = grub_malloc (sizeof (*list)); + if (list) + { + list->disk = dev->source_disk; + list->next = NULL; + } + + return list; +} +#endif + +static void +cryptodisk_cleanup (void) +{ + grub_cryptodisk_t dev = cryptodisk_list; + grub_cryptodisk_t tmp; + + while (dev != NULL) + { + grub_free (dev->source); + grub_free (dev->cipher); + grub_free (dev->secondary_cipher); + grub_free (dev->essiv_cipher); + tmp = dev->next; + grub_free (dev); + dev = tmp; + } +} + +grub_err_t +grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name, + grub_disk_t source) +{ + newdev->source = grub_strdup (name); + if (!newdev->source) + { + grub_free (newdev); + return grub_errno; + } + + newdev->id = n++; + newdev->source_id = source->id; + newdev->source_dev_id = source->dev->id; + newdev->next = cryptodisk_list; + cryptodisk_list = newdev; + + return GRUB_ERR_NONE; +} + +grub_cryptodisk_t +grub_cryptodisk_get_by_uuid (const char *uuid) +{ + grub_cryptodisk_t dev; + for (dev = cryptodisk_list; dev != NULL; dev = dev->next) + if (grub_strcasecmp (dev->uuid, uuid) == 0) + return dev; + return NULL; +} + +grub_cryptodisk_t +grub_cryptodisk_get_by_source_disk (grub_disk_t disk) +{ + grub_cryptodisk_t dev; + for (dev = cryptodisk_list; dev != NULL; dev = dev->next) + if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id) + return dev; + return NULL; +} + +#ifdef GRUB_UTIL +grub_err_t +grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, + grub_disk_t source, const char *cheat) +{ + newdev->cheat = grub_strdup (cheat); + newdev->source = grub_strdup (name); + if (!newdev->source || !newdev->cheat) + { + grub_free (newdev->source); + grub_free (newdev->cheat); + return grub_errno; + } + + newdev->cheat_fd = -1; + newdev->source_id = source->id; + newdev->source_dev_id = source->dev->id; + newdev->id = n++; + newdev->next = cryptodisk_list; + cryptodisk_list = newdev; + + return GRUB_ERR_NONE; +} + +void +grub_util_cryptodisk_print_abstraction (grub_disk_t disk) +{ + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + + grub_printf ("luks "); + + if (dev->cipher) + grub_printf ("%s ", dev->cipher->cipher->modname); + if (dev->secondary_cipher) + grub_printf ("%s ", dev->secondary_cipher->cipher->modname); + if (dev->essiv_cipher) + grub_printf ("%s ", dev->essiv_cipher->cipher->modname); + if (dev->hash) + grub_printf ("%s ", dev->hash->modname); + if (dev->essiv_hash) + grub_printf ("%s ", dev->essiv_hash->modname); + if (dev->iv_hash) + grub_printf ("%s ", dev->iv_hash->modname); +} +#endif + +static struct grub_disk_dev grub_cryptodisk_dev = { + .name = "cryptodisk", + .id = GRUB_DISK_DEVICE_CRYPTODISK_ID, + .iterate = grub_cryptodisk_iterate, + .open = grub_cryptodisk_open, + .close = grub_cryptodisk_close, + .read = grub_cryptodisk_read, + .write = grub_cryptodisk_write, +#ifdef GRUB_UTIL + .memberlist = grub_cryptodisk_memberlist, +#endif + .next = 0 +}; + +GRUB_MOD_INIT (cryptodisk) +{ + grub_disk_dev_register (&grub_cryptodisk_dev); +} + +GRUB_MOD_FINI (cryptodisk) +{ + grub_disk_dev_unregister (&grub_cryptodisk_dev); + cryptodisk_cleanup (); +} diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c new file mode 100644 index 000000000..6af1de766 --- /dev/null +++ b/grub-core/disk/geli.c @@ -0,0 +1,515 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007,2010,2011 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 . + */ + +/* This file is loosely based on FreeBSD geli implementation + (but no code was directly copied). FreeBSD geli is distributed under + following terms: */ +/*- + * Copyright (c) 2005-2006 Pawel Jakub Dawidek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_geli_key +{ + grub_uint8_t iv_key[64]; + grub_uint8_t cipher_key[64]; + grub_uint8_t hmac[64]; +} __attribute__ ((packed)); + +struct grub_geli_phdr +{ + grub_uint8_t magic[16]; +#define GELI_MAGIC "GEOM::ELI" + grub_uint32_t version; + grub_uint32_t unused1; + grub_uint16_t alg; + grub_uint16_t keylen; + grub_uint16_t unused3[7]; + grub_uint8_t keys_used; + grub_uint32_t niter; + grub_uint8_t salt[64]; + struct grub_geli_key keys[2]; +} __attribute__ ((packed)); + +const char *algorithms[] = { + [0x0b] = "aes", +}; + +#define MAX_PASSPHRASE 256 + +static const struct grub_arg_option options[] = + { + {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, + {"all", 'a', 0, N_("Mount all."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static int check_uuid, have_it; +static char *search_uuid; + +static grub_cryptodisk_t +configure_ciphers (const struct grub_geli_phdr *header) +{ + grub_cryptodisk_t newdev; + grub_crypto_cipher_handle_t cipher = NULL; + const struct gcry_cipher_spec *ciph; + const char *ciphername = NULL; + const gcry_md_spec_t *hash = NULL, *iv_hash = NULL; + + /* Look for GELI magic sequence. */ + if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) + || grub_le_to_cpu32 (header->version) != 3) + { + grub_dprintf ("geli", "wrong magic %02x\n", header->magic[0]); + return NULL; + } + +#if 0 + optr = uuid; + for (iptr = header->uuid; iptr < &header->uuid[ARRAY_SIZE (header->uuid)]; + iptr++) + { + if (*iptr != '-') + *optr++ = *iptr; + } + *optr = 0; + + if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0) + { + grub_dprintf ("luks", "%s != %s", uuid, search_uuid); + return NULL; + } +#endif + + if (grub_le_to_cpu16 (header->alg) >= ARRAY_SIZE (algorithms) + || algorithms[grub_le_to_cpu16 (header->alg)] == NULL) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher 0x%x unknown", + grub_le_to_cpu16 (header->alg)); + return NULL; + } + + ciphername = algorithms[grub_le_to_cpu16 (header->alg)]; + ciph = grub_crypto_lookup_cipher_by_name (ciphername); + if (!ciph) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", + ciphername); + return NULL; + } + + /* Configure the cipher used for the bulk data. */ + cipher = grub_crypto_cipher_open (ciph); + if (!cipher) + return NULL; + + if (grub_le_to_cpu16 (header->keylen) > 1024) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", + grub_le_to_cpu16 (header->keylen)); + return NULL; + } + + hash = grub_crypto_lookup_md_by_name ("sha512"); + if (!hash) + { + grub_crypto_cipher_close (cipher); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", + "sha512"); + return NULL; + } + + iv_hash = grub_crypto_lookup_md_by_name ("sha256"); + if (!hash) + { + grub_crypto_cipher_close (cipher); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", + "sha512"); + return NULL; + } + + newdev = grub_zalloc (sizeof (struct grub_cryptodisk)); + if (!newdev) + return NULL; + newdev->cipher = cipher; + newdev->offset = 0; + newdev->source_disk = NULL; + newdev->benbi_log = 0; + newdev->mode = GRUB_CRYPTODISK_MODE_CBC; + newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH; + newdev->secondary_cipher = NULL; + newdev->essiv_cipher = NULL; + newdev->essiv_hash = NULL; + newdev->hash = hash; + newdev->iv_hash = iv_hash; +#if 0 + grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); +#endif + return newdev; +} + +static grub_err_t +recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, + const char *name, grub_disk_t source __attribute__ ((unused))) +{ + grub_size_t keysize = grub_le_to_cpu16 (header->keylen) / 8; + grub_uint8_t digest[dev->hash->mdlen]; + grub_uint8_t geomkey[dev->hash->mdlen]; + grub_uint8_t verify_key[dev->hash->mdlen]; + grub_uint8_t pbkdf_key[64]; + grub_uint8_t zero[dev->cipher->cipher->blocksize]; + char passphrase[MAX_PASSPHRASE] = ""; + unsigned i; + gcry_err_code_t gcry_err; + + grub_memset (zero, 0, sizeof (zero)); + + grub_printf ("Attempting to decrypt master key...\n"); + + /* Get the passphrase from the user. */ + grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid); + if (!grub_password_get (passphrase, MAX_PASSPHRASE)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); + + /* Calculate the PBKDF2 of the user supplied passphrase. */ + gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, + grub_strlen (passphrase), + header->salt, + sizeof (header->salt), + grub_le_to_cpu32 (header->niter), + pbkdf_key, sizeof (pbkdf_key)); + + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + gcry_err = grub_crypto_hmac_buffer (dev->hash, NULL, 0, pbkdf_key, + sizeof (pbkdf_key), geomkey); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, + sizeof (geomkey), "\1", 1, digest); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, + sizeof (geomkey), "\0", 1, verify_key); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + grub_dprintf ("geli", "keylen = %" PRIuGRUB_SIZE "\n", keysize); + + /* Try to recover master key from each active keyslot. */ + for (i = 0; i < ARRAY_SIZE (header->keys); i++) + { + struct grub_geli_key candidate_key; + grub_uint8_t key_hmac[dev->hash->mdlen]; + + /* Check if keyslot is enabled. */ + if (! (header->keys_used & (1 << i))) + continue; + + grub_dprintf ("geli", "Trying keyslot %d\n", i); + + gcry_err = grub_crypto_cipher_set_key (dev->cipher, + digest, keysize); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + gcry_err = grub_crypto_cbc_decrypt (dev->cipher, &candidate_key, + &header->keys[i], + sizeof (candidate_key), + zero); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key, + sizeof (verify_key), + &candidate_key, + (sizeof (candidate_key) + - sizeof (candidate_key.hmac)), + key_hmac); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0) + continue; + grub_printf ("Slot %d opened\n", i); + + /* Set the master key. */ + gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key, + keysize); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + dev->iv_prefix_len = sizeof (candidate_key.iv_key); + grub_memcpy (dev->iv_prefix, candidate_key.iv_key, + sizeof (candidate_key.iv_key)); + + COMPILE_TIME_ASSERT (sizeof (dev->iv_prefix) >= sizeof (candidate_key.iv_key)); + + return GRUB_ERR_NONE; + } + + return GRUB_ACCESS_DENIED; +} + +static void +close (grub_cryptodisk_t luks) +{ + grub_crypto_cipher_close (luks->cipher); + grub_crypto_cipher_close (luks->secondary_cipher); + grub_crypto_cipher_close (luks->essiv_cipher); + grub_free (luks); +} + +static grub_err_t +grub_geli_scan_device_real (const char *name, grub_disk_t source) +{ + grub_err_t err; + struct grub_geli_phdr header; + grub_cryptodisk_t newdev, dev; + grub_disk_addr_t sector; + + grub_dprintf ("geli", "scanning %s\n", source->name); + dev = grub_cryptodisk_get_by_source_disk (source); + + if (dev) + return GRUB_ERR_NONE; + + sector = grub_disk_get_size (source); + if (sector == GRUB_DISK_SIZE_UNKNOWN) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli"); + + /* Read the LUKS header. */ + err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header); + if (err) + return err; + + newdev = configure_ciphers (&header); + if (!newdev) + return grub_errno; + + newdev->total_length = grub_disk_get_size (source) - 1; + + err = recover_key (newdev, &header, name, source); + if (err) + { + close (newdev); + return err; + } + + grub_cryptodisk_insert (newdev, name, source); + + have_it = 1; + + return GRUB_ERR_NONE; +} + +#ifdef GRUB_UTIL +grub_err_t +grub_geli_cheat_mount (const char *sourcedev, const char *cheat) +{ + grub_err_t err; + struct grub_geli_phdr header; + grub_cryptodisk_t newdev, dev; + grub_disk_t source; + grub_disk_addr_t sector; + + /* Try to open disk. */ + source = grub_disk_open (sourcedev); + if (!source) + return grub_errno; + + dev = grub_cryptodisk_get_by_source_disk (source); + + if (dev) + { + grub_disk_close (source); + return GRUB_ERR_NONE; + } + + sector = grub_disk_get_size (source); + if (sector == GRUB_DISK_SIZE_UNKNOWN) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli"); + + /* Read the LUKS header. */ + err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header); + if (err) + return err; + + newdev = configure_ciphers (&header); + if (!newdev) + { + grub_disk_close (source); + return grub_errno; + } + + newdev->total_length = grub_disk_get_size (source) - 1; + + err = grub_cryptodisk_cheat_insert (newdev, sourcedev, source, cheat); + grub_disk_close (source); + if (err) + grub_free (newdev); + + return err; +} +#endif + +static int +grub_geli_scan_device (const char *name) +{ + grub_err_t err; + grub_disk_t source; + + /* Try to open disk. */ + source = grub_disk_open (name); + if (!source) + return grub_errno; + + err = grub_geli_scan_device_real (name, source); + + grub_disk_close (source); + + if (err) + grub_print_error (); + return have_it && check_uuid ? 0 : 1; +} + +#ifdef GRUB_UTIL + +void +grub_util_geli_print_uuid (grub_disk_t disk) +{ + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + grub_printf ("%s ", dev->uuid); +} +#endif + +static grub_err_t +grub_cmd_gelimount (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + + if (argc < 1 && !state[1].set) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); + + have_it = 0; + if (state[0].set) + { + grub_cryptodisk_t dev; + + dev = grub_cryptodisk_get_by_uuid (args[0]); + if (dev) + { + grub_dprintf ("luks", "already mounted as crypto%lu\n", dev->id); + return GRUB_ERR_NONE; + } + + check_uuid = 1; + search_uuid = args[0]; + grub_device_iterate (&grub_geli_scan_device); + search_uuid = NULL; + + if (!have_it) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); + return GRUB_ERR_NONE; + } + else if (state[1].set) + { + check_uuid = 0; + search_uuid = NULL; + grub_device_iterate (&grub_geli_scan_device); + search_uuid = NULL; + return GRUB_ERR_NONE; + } + else + { + grub_err_t err; + grub_disk_t disk; + grub_cryptodisk_t dev; + + check_uuid = 0; + search_uuid = NULL; + disk = grub_disk_open (args[0]); + if (!disk) + return grub_errno; + + dev = grub_cryptodisk_get_by_source_disk (disk); + if (dev) + { + grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); + grub_disk_close (disk); + return GRUB_ERR_NONE; + } + + err = grub_geli_scan_device_real (args[0], disk); + + grub_disk_close (disk); + + return err; + } +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT (geli) +{ + cmd = grub_register_extcmd ("gelimount", grub_cmd_gelimount, 0, + N_("SOURCE|-u UUID|-a"), + N_("Mount a GELI device."), options); +} + +GRUB_MOD_FINI (geli) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 361beb756..0763da011 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -454,6 +454,8 @@ grub_luks_scan_device_real (const char *name, grub_disk_t source) if (!newdev) return grub_errno; + newdev->total_length = grub_disk_get_size (source) - newdev->offset; + err = luks_recover_key (newdev, &header, name, source); if (err) { @@ -502,6 +504,8 @@ grub_luks_cheat_mount (const char *sourcedev, const char *cheat) return grub_errno; } + newdev->total_length = grub_disk_get_size (source) - newdev->offset; + err = grub_cryptodisk_cheat_insert (newdev, sourcedev, source, cheat); grub_disk_close (source); if (err) diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index 2f172ebf8..e6f55062b 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -193,9 +193,10 @@ grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size) gcry_err_code_t grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size) + void *out, const void *in, grub_size_t size) { - grub_uint8_t *inptr, *outptr, *end; + const grub_uint8_t *inptr; + grub_uint8_t *outptr, *end; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; if (size % cipher->cipher->blocksize != 0) @@ -249,10 +250,11 @@ grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher, gcry_err_code_t grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size, + void *out, const void *in, grub_size_t size, void *iv) { - grub_uint8_t *inptr, *outptr, *end; + const grub_uint8_t *inptr; + grub_uint8_t *outptr, *end; grub_uint8_t ivt[cipher->cipher->blocksize]; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; diff --git a/include/grub/crypto.h b/include/grub/crypto.h index 62ed2015c..ab82da862 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -199,7 +199,7 @@ grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size); gcry_err_code_t grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size); + void *out, const void *in, grub_size_t size); gcry_err_code_t grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher, @@ -210,7 +210,7 @@ grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher, void *iv_in); gcry_err_code_t grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size, + void *out, const void *in, grub_size_t size, void *iv); void grub_cipher_register (gcry_cipher_spec_t *cipher); diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h new file mode 100644 index 000000000..284e599f2 --- /dev/null +++ b/include/grub/cryptodisk.h @@ -0,0 +1,99 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2005,2006,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 . + */ + +#ifndef GRUB_CRYPTODISK_HEADER +#define GRUB_CRYPTODISK_HEADER 1 + +#include +#include + +typedef enum + { + GRUB_CRYPTODISK_MODE_ECB, + GRUB_CRYPTODISK_MODE_CBC, + GRUB_CRYPTODISK_MODE_PCBC, + GRUB_CRYPTODISK_MODE_XTS, + GRUB_CRYPTODISK_MODE_LRW + } grub_cryptodisk_mode_t; + +typedef enum + { + GRUB_CRYPTODISK_MODE_IV_NULL, + GRUB_CRYPTODISK_MODE_IV_PLAIN, + GRUB_CRYPTODISK_MODE_IV_PLAIN64, + GRUB_CRYPTODISK_MODE_IV_ESSIV, + GRUB_CRYPTODISK_MODE_IV_BENBI, + GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH + } grub_cryptodisk_mode_iv_t; + +#define GRUB_CRYPTODISK_MAX_UUID_LENGTH 63 + +#define GRUB_CRYPTODISK_GF_SIZE 128 +#define GRUB_CRYPTODISK_GF_BYTES (GRUB_CRYPTODISK_GF_SIZE / 8) + +struct grub_cryptodisk +{ + char *source; + grub_disk_addr_t offset; + grub_disk_addr_t total_length; + grub_disk_t source_disk; + int ref; + grub_crypto_cipher_handle_t cipher; + grub_crypto_cipher_handle_t secondary_cipher; + grub_crypto_cipher_handle_t essiv_cipher; + const gcry_md_spec_t *essiv_hash, *hash, *iv_hash; + grub_cryptodisk_mode_t mode; + grub_cryptodisk_mode_iv_t mode_iv; + int benbi_log; + unsigned long id, source_id; + enum grub_disk_dev_id source_dev_id; + char uuid[GRUB_CRYPTODISK_MAX_UUID_LENGTH + 1]; + grub_uint8_t lrw_key[GRUB_CRYPTODISK_GF_BYTES]; + grub_uint8_t *lrw_precalc; + grub_uint8_t iv_prefix[64]; + grub_size_t iv_prefix_len; +#ifdef GRUB_UTIL + char *cheat; + int cheat_fd; +#endif + struct grub_cryptodisk *next; +}; +typedef struct grub_cryptodisk *grub_cryptodisk_t; + +gcry_err_code_t +grub_cryptodisk_setkey (grub_cryptodisk_t dev, + grub_uint8_t *key, grub_size_t keysize); +gcry_err_code_t +grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, + grub_uint8_t * data, grub_size_t len, + grub_disk_addr_t sector); +grub_err_t +grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name, + grub_disk_t source); +#ifdef GRUB_UTIL +grub_err_t +grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, + grub_disk_t source, const char *cheat); +void +grub_util_cryptodisk_print_abstraction (grub_disk_t disk); +#endif + +grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid); +grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk); + +#endif diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 2adb2331d..48a5be1ca 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -308,8 +308,12 @@ fstest (int n, char **args) { char *argv[2] = { "-a", NULL}; if (mount_crypt) - if (execute_command ("luksmount", 1, argv)) - grub_util_error (_("luksmount command fails: %s"), grub_errmsg); + { + if (execute_command ("luksmount", 1, argv)) + grub_util_error (_("luksmount command fails: %s"), grub_errmsg); + if (execute_command ("gelimount", 1, argv)) + grub_util_error (_("gelimount command fails: %s"), grub_errmsg); + } } grub_lvm_fini (); From b44cd9e710c0bf0c1d1dfceef5ba883a4eebe98f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 02:34:32 +0200 Subject: [PATCH 143/673] zero-fill hash context for safety --- grub-core/disk/cryptodisk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 7f3b60bf5..dc6ca486e 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -200,6 +200,9 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, { grub_uint64_t tmp; grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8]; + + grub_memset (ctx, 0, sizeof (ctx)); + tmp = grub_cpu_to_le64 (sector << GRUB_DISK_SECTOR_BITS); dev->iv_hash->init (ctx); dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len); From 7ede8f8b5b62f7244f3cc9e9e6927cac43df006b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 02:36:04 +0200 Subject: [PATCH 144/673] support niter == 0 --- grub-core/disk/geli.c | 46 ++++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 6af1de766..565498ece 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -205,7 +205,6 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, grub_uint8_t digest[dev->hash->mdlen]; grub_uint8_t geomkey[dev->hash->mdlen]; grub_uint8_t verify_key[dev->hash->mdlen]; - grub_uint8_t pbkdf_key[64]; grub_uint8_t zero[dev->cipher->cipher->blocksize]; char passphrase[MAX_PASSPHRASE] = ""; unsigned i; @@ -220,21 +219,40 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, if (!grub_password_get (passphrase, MAX_PASSPHRASE)) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); - /* Calculate the PBKDF2 of the user supplied passphrase. */ - gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, - grub_strlen (passphrase), - header->salt, - sizeof (header->salt), - grub_le_to_cpu32 (header->niter), - pbkdf_key, sizeof (pbkdf_key)); + /* Calculate the PBKDF2 of the user supplied passphrase. */ + if (grub_le_to_cpu32 (header->niter) != 0) + { + grub_uint8_t pbkdf_key[64]; + gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, + grub_strlen (passphrase), + header->salt, + sizeof (header->salt), + grub_le_to_cpu32 (header->niter), + pbkdf_key, sizeof (pbkdf_key)); - if (gcry_err) - return grub_crypto_gcry_error (gcry_err); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); - gcry_err = grub_crypto_hmac_buffer (dev->hash, NULL, 0, pbkdf_key, - sizeof (pbkdf_key), geomkey); - if (gcry_err) - return grub_crypto_gcry_error (gcry_err); + gcry_err = grub_crypto_hmac_buffer (dev->hash, NULL, 0, pbkdf_key, + sizeof (pbkdf_key), geomkey); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + } + else + { + struct grub_crypto_hmac_handle *hnd; + + hnd = grub_crypto_hmac_init (dev->hash, NULL, 0); + if (!hnd) + return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY); + + grub_crypto_hmac_write (hnd, header->salt, sizeof (header->salt)); + grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase)); + + gcry_err = grub_crypto_hmac_fini (hnd, geomkey); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + } gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, sizeof (geomkey), "\1", 1, digest); From 972d86df5f68efecb9952fa994aa851bae44aa28 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 02:36:50 +0200 Subject: [PATCH 145/673] accept version 2 geli --- grub-core/disk/geli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 565498ece..7d0c8621f 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -107,7 +107,8 @@ configure_ciphers (const struct grub_geli_phdr *header) /* Look for GELI magic sequence. */ if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) - || grub_le_to_cpu32 (header->version) != 3) + || grub_le_to_cpu32 (header->version) > 3 + || grub_le_to_cpu32 (header->version) < 2) { grub_dprintf ("geli", "wrong magic %02x\n", header->magic[0]); return NULL; From b6b4ea5fd1ee71062c05b89bd606d869ebc33517 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 02:37:23 +0200 Subject: [PATCH 146/673] Add IDs for more ciphers --- grub-core/disk/geli.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 7d0c8621f..843eb7d90 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -81,7 +81,14 @@ struct grub_geli_phdr } __attribute__ ((packed)); const char *algorithms[] = { + [0x01] = "des", + [0x02] = "3des", + [0x03] = "blowfish", + [0x04] = "cast5", + /* 0x05 is skipjack, but we don't have it. */ [0x0b] = "aes", + /* 0x10 is null. */ + [0x15] = "camellia128", }; #define MAX_PASSPHRASE 256 From 848c83e75c059b8463788ec1095b84158458c200 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 02:38:42 +0200 Subject: [PATCH 147/673] add few necessarry const qualifiers for pointers --- grub-core/lib/crypto.c | 3 ++- include/grub/crypto.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index e6f55062b..5098f0a66 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -345,7 +345,8 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md, } void -grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data, +grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, + const void *data, grub_size_t datalen) { hnd->md->write (hnd->ctx, data, datalen); diff --git a/include/grub/crypto.h b/include/grub/crypto.h index ab82da862..baccbcd06 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -235,7 +235,8 @@ struct grub_crypto_hmac_handle * grub_crypto_hmac_init (const struct gcry_md_spec *md, const void *key, grub_size_t keylen); void -grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data, +grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, + const void *data, grub_size_t datalen); gcry_err_code_t grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out); From b094f07c2364b616452639db9184d9411f376f38 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 02:39:21 +0200 Subject: [PATCH 148/673] Don't set was_readable for new array --- grub-core/disk/raid.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 78453ac88..27a57d7fc 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -637,6 +637,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, grub_raid_t raid __attribute__ ((unused))) { struct grub_raid_array *array = 0, *p; + int was_readable = 0; /* See whether the device is part of an array we have already seen a device from. */ @@ -647,6 +648,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, grub_free (new_array->uuid); array = p; + was_readable = grub_is_array_readable (array); + /* Do some checks before adding the device to the array. */ if (new_array->index >= array->allocated_devs) @@ -803,15 +806,11 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, } /* Add the device to the array. */ - { - int was_readable = grub_is_array_readable (array); - - array->members[new_array->index].device = disk; - array->members[new_array->index].start_sector = start_sector; - array->nr_devs++; - if (!was_readable && grub_is_array_readable (array)) - array->became_readable_at = inscnt++; - } + array->members[new_array->index].device = disk; + array->members[new_array->index].start_sector = start_sector; + array->nr_devs++; + if (!was_readable && grub_is_array_readable (array)) + array->became_readable_at = inscnt++; return 0; } From 0c512b092c885733eb31aa1a12c6e7289c5e5ea1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 14:52:00 +0200 Subject: [PATCH 149/673] Fix a cache retrieving bug --- grub-core/kern/disk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 5439a02f6..30bc604f0 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -571,7 +571,8 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, if (data) { - grub_memcpy (buf, data, GRUB_DISK_CACHE_SIZE); + grub_memcpy (buf, data, + GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); sector += GRUB_DISK_CACHE_SIZE; buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); From 3e90811d884cab7a333ad9a4458732409be9f88f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 14:59:38 +0200 Subject: [PATCH 150/673] support non-512B sectors for geli --- grub-core/disk/cryptodisk.c | 50 +++++++++++++++++++++---------------- grub-core/disk/geli.c | 15 ++++++++++- grub-core/disk/luks.c | 1 + include/grub/cryptodisk.h | 7 ++++-- 4 files changed, 49 insertions(+), 24 deletions(-) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 6dbd6bac6..4a716602e 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -35,7 +35,10 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ #define GF_POLYNOM 0x87 -#define GF_PER_SECTOR (GRUB_DISK_SECTOR_SIZE / GRUB_CRYPTODISK_GF_BYTES) +static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev) +{ + return 1U << (dev->log_sector_size - GRUB_CRYPTODISK_GF_LOG_BYTES); +} static grub_cryptodisk_t cryptodisk_list = NULL; static grub_uint8_t n = 0; @@ -44,7 +47,7 @@ static void gf_mul_x (grub_uint8_t *g) { int over = 0, over2 = 0; - int j; + unsigned j; for (j = 0; j < GRUB_CRYPTODISK_GF_BYTES; j++) { @@ -64,7 +67,7 @@ gf_mul_x_be (grub_uint8_t *g) int over = 0, over2 = 0; int j; - for (j = GRUB_CRYPTODISK_GF_BYTES - 1; j >= 0; j--) + for (j = (int) GRUB_CRYPTODISK_GF_BYTES - 1; j >= 0; j--) { over2 = !!(g[j] & 0x80); g[j] <<= 1; @@ -78,7 +81,7 @@ gf_mul_x_be (grub_uint8_t *g) static void gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b) { - int i; + unsigned i; grub_uint8_t t[GRUB_CRYPTODISK_GF_BYTES]; grub_memset (o, 0, GRUB_CRYPTODISK_GF_BYTES); grub_memcpy (t, b, GRUB_CRYPTODISK_GF_BYTES); @@ -129,14 +132,15 @@ generate_lrw_sector (struct lrw_sector *sec, grub_uint16_t c; int j; grub_memcpy (idx, iv, GRUB_CRYPTODISK_GF_BYTES); - sec->low_byte = (idx[GRUB_CRYPTODISK_GF_BYTES - 1] & (GF_PER_SECTOR - 1)); - sec->low_byte_c = (((GF_PER_SECTOR - 1) & ~sec->low_byte) + 1); - idx[GRUB_CRYPTODISK_GF_BYTES - 1] &= ~(GF_PER_SECTOR - 1); + sec->low_byte = (idx[GRUB_CRYPTODISK_GF_BYTES - 1] + & (GF_PER_SECTOR (dev) - 1)); + sec->low_byte_c = (((GF_PER_SECTOR (dev) - 1) & ~sec->low_byte) + 1); + idx[GRUB_CRYPTODISK_GF_BYTES - 1] &= ~(GF_PER_SECTOR (dev) - 1); gf_mul_be (sec->low, dev->lrw_key, idx); if (!sec->low_byte) return; - c = idx[GRUB_CRYPTODISK_GF_BYTES - 1] + GF_PER_SECTOR; + c = idx[GRUB_CRYPTODISK_GF_BYTES - 1] + GF_PER_SECTOR (dev); if (c & 0x100) { for (j = GRUB_CRYPTODISK_GF_BYTES - 2; j >= 0; j--) @@ -155,9 +159,10 @@ lrw_xor (const struct lrw_sector *sec, const struct grub_cryptodisk *dev, grub_uint8_t *b) { - int i; + unsigned i; - for (i = 0; i < sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES; i += GRUB_CRYPTODISK_GF_BYTES) + for (i = 0; i < sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES; + i += GRUB_CRYPTODISK_GF_BYTES) grub_crypto_xor (b + i, b + i, sec->low, GRUB_CRYPTODISK_GF_BYTES); grub_crypto_xor (b, b, dev->lrw_precalc + GRUB_CRYPTODISK_GF_BYTES * sec->low_byte, sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES); @@ -165,7 +170,7 @@ lrw_xor (const struct lrw_sector *sec, return; for (i = sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES; - i < GRUB_DISK_SECTOR_SIZE; i += GRUB_CRYPTODISK_GF_BYTES) + i < (1U << dev->log_sector_size); i += GRUB_CRYPTODISK_GF_BYTES) grub_crypto_xor (b + i, b + i, sec->high, GRUB_CRYPTODISK_GF_BYTES); grub_crypto_xor (b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES, b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES, @@ -184,7 +189,7 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, if (dev->mode == GRUB_CRYPTODISK_MODE_ECB) return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); - for (i = 0; i < len; i += GRUB_DISK_SECTOR_SIZE) + for (i = 0; i < len; i += (1U << dev->log_sector_size)) { grub_size_t sz = ((dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) @@ -203,7 +208,7 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, grub_memset (ctx, 0, sizeof (ctx)); - tmp = grub_cpu_to_le64 (sector << GRUB_DISK_SECTOR_BITS); + tmp = grub_cpu_to_le64 (sector << dev->log_sector_size); dev->iv_hash->init (ctx); dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp)); @@ -236,26 +241,26 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, { case GRUB_CRYPTODISK_MODE_CBC: err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, - GRUB_DISK_SECTOR_SIZE, iv); + (1U << dev->log_sector_size), iv); if (err) return err; break; case GRUB_CRYPTODISK_MODE_PCBC: err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, - GRUB_DISK_SECTOR_SIZE, iv); + (1U << dev->log_sector_size), iv); if (err) return err; break; case GRUB_CRYPTODISK_MODE_XTS: { - int j; + unsigned j; err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv, dev->cipher->cipher->blocksize); if (err) return err; - for (j = 0; j < GRUB_DISK_SECTOR_SIZE; + for (j = 0; j < (1U << dev->log_sector_size); j += dev->cipher->cipher->blocksize) { grub_crypto_xor (data + i + j, data + i + j, iv, @@ -279,7 +284,8 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, lrw_xor (&sec, dev, data + i); err = grub_crypto_ecb_decrypt (dev->cipher, data + i, - data + i, GRUB_DISK_SECTOR_SIZE); + data + i, + (1U << dev->log_sector_size)); if (err) return err; lrw_xor (&sec, dev, data + i); @@ -333,17 +339,17 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke if (dev->mode == GRUB_CRYPTODISK_MODE_LRW) { - int i; + unsigned i; grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES]; grub_free (dev->lrw_precalc); grub_memcpy (dev->lrw_key, key + real_keysize, dev->cipher->cipher->blocksize); - dev->lrw_precalc = grub_malloc (GRUB_DISK_SECTOR_SIZE); + dev->lrw_precalc = grub_malloc ((1U << dev->log_sector_size)); if (!dev->lrw_precalc) return GPG_ERR_OUT_OF_MEMORY; grub_memset (idx, 0, GRUB_CRYPTODISK_GF_BYTES); - for (i = 0; i < GRUB_DISK_SECTOR_SIZE; + for (i = 0; i < (1U << dev->log_sector_size); i += GRUB_CRYPTODISK_GF_BYTES) { idx[GRUB_CRYPTODISK_GF_BYTES - 1] = i / GRUB_CRYPTODISK_GF_BYTES; @@ -401,6 +407,8 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk, if (!dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); + disk->log_sector_size = dev->log_sector_size; + #ifdef GRUB_UTIL if (dev->cheat) { diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 843eb7d90..3c2cbb9ce 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -73,7 +73,8 @@ struct grub_geli_phdr grub_uint32_t unused1; grub_uint16_t alg; grub_uint16_t keylen; - grub_uint16_t unused3[7]; + grub_uint16_t unused3[5]; + grub_uint32_t sector_size; grub_uint8_t keys_used; grub_uint32_t niter; grub_uint8_t salt[64]; @@ -120,6 +121,14 @@ configure_ciphers (const struct grub_geli_phdr *header) grub_dprintf ("geli", "wrong magic %02x\n", header->magic[0]); return NULL; } + if ((grub_le_to_cpu32 (header->sector_size) + & (grub_le_to_cpu32 (header->sector_size) - 1)) + || grub_le_to_cpu32 (header->sector_size) == 0) + { + grub_dprintf ("geli", "incorrect sector size %d\n", + grub_le_to_cpu32 (header->sector_size)); + return NULL; + } #if 0 optr = uuid; @@ -199,6 +208,10 @@ configure_ciphers (const struct grub_geli_phdr *header) newdev->essiv_hash = NULL; newdev->hash = hash; newdev->iv_hash = iv_hash; + + for (newdev->log_sector_size = 0; + (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header->sector_size); + newdev->log_sector_size++); #if 0 grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); #endif diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 0763da011..7c39002b8 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -283,6 +283,7 @@ configure_ciphers (const struct grub_luks_phdr *header) newdev->essiv_cipher = essiv_cipher; newdev->essiv_hash = essiv_hash; newdev->hash = hash; + newdev->log_sector_size = 9; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); return newdev; } diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index 284e599f2..11181f42d 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -43,8 +43,10 @@ typedef enum #define GRUB_CRYPTODISK_MAX_UUID_LENGTH 63 -#define GRUB_CRYPTODISK_GF_SIZE 128 -#define GRUB_CRYPTODISK_GF_BYTES (GRUB_CRYPTODISK_GF_SIZE / 8) +#define GRUB_CRYPTODISK_GF_LOG_SIZE 7 +#define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE) +#define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3) +#define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES) struct grub_cryptodisk { @@ -71,6 +73,7 @@ struct grub_cryptodisk char *cheat; int cheat_fd; #endif + int log_sector_size; struct grub_cryptodisk *next; }; typedef struct grub_cryptodisk *grub_cryptodisk_t; From 88ac3146d6ad5d17788821fa4aa296271a2c0550 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 17:15:55 +0200 Subject: [PATCH 151/673] geli v5 (including rekeying support) --- grub-core/disk/cryptodisk.c | 20 ++++++++++++-- grub-core/disk/geli.c | 53 ++++++++++++++++++++++++++++++++----- grub-core/lib/crypto.c | 2 +- include/grub/crypto.h | 2 +- include/grub/cryptodisk.h | 13 ++++++++- 5 files changed, 79 insertions(+), 11 deletions(-) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 4a716602e..5ab607146 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -178,7 +178,7 @@ lrw_xor (const struct lrw_sector *sec, } gcry_err_code_t -grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, +grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, grub_uint8_t * data, grub_size_t len, grub_disk_addr_t sector) { @@ -186,7 +186,7 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, gcry_err_code_t err; /* The only mode without IV. */ - if (dev->mode == GRUB_CRYPTODISK_MODE_ECB) + if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey) return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); for (i = 0; i < len; i += (1U << dev->log_sector_size)) @@ -196,6 +196,18 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, / sizeof (grub_uint32_t)); grub_uint32_t iv[sz]; + if (dev->rekey) + { + grub_uint64_t zone = sector >> dev->rekey_shift; + if (zone != dev->last_rekey) + { + err = dev->rekey (dev, zone); + if (err) + return err; + dev->last_rekey = zone; + } + } + grub_memset (iv, 0, sz * sizeof (iv[0])); switch (dev->mode_iv) { @@ -291,6 +303,10 @@ grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, lrw_xor (&sec, dev, data + i); } break; + case GRUB_CRYPTODISK_MODE_ECB: + grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size)); + break; default: return GPG_ERR_NOT_IMPLEMENTED; } diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 3c2cbb9ce..b3fa10cc5 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -104,6 +104,28 @@ static const struct grub_arg_option options[] = static int check_uuid, have_it; static char *search_uuid; +static gcry_err_code_t +geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno) +{ + gcry_err_code_t gcry_err; + const struct { + char magic[4]; + grub_uint64_t zone; + } __attribute__ ((packed)) tohash + = { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) }; + grub_uint64_t key[(dev->hash->mdlen + 7) / 8]; + + grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n", + zoneno, dev->rekey_derived_size); + gcry_err = grub_crypto_hmac_buffer (dev->hash, dev->rekey_key, 64, + &tohash, sizeof (tohash), key); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + + return grub_cryptodisk_setkey (dev, (grub_uint8_t *) key, + dev->rekey_derived_size); +} + static grub_cryptodisk_t configure_ciphers (const struct grub_geli_phdr *header) { @@ -115,8 +137,8 @@ configure_ciphers (const struct grub_geli_phdr *header) /* Look for GELI magic sequence. */ if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) - || grub_le_to_cpu32 (header->version) > 3 - || grub_le_to_cpu32 (header->version) < 2) + || grub_le_to_cpu32 (header->version) > 5 + || grub_le_to_cpu32 (header->version) < 1) { grub_dprintf ("geli", "wrong magic %02x\n", header->magic[0]); return NULL; @@ -212,6 +234,12 @@ configure_ciphers (const struct grub_geli_phdr *header) for (newdev->log_sector_size = 0; (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header->sector_size); newdev->log_sector_size++); + + if (grub_le_to_cpu32 (header->version) >= 5) + { + newdev->rekey = geli_rekey; + newdev->rekey_shift = 20; + } #if 0 grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); #endif @@ -325,10 +353,23 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, grub_printf ("Slot %d opened\n", i); /* Set the master key. */ - gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key, - keysize); - if (gcry_err) - return grub_crypto_gcry_error (gcry_err); + if (!dev->rekey) + { + gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key, + keysize); + if (gcry_err) + return grub_crypto_gcry_error (gcry_err); + } + else + { + /* For a reason I don't know, the IV key is used in rekeying. */ + grub_memcpy (dev->rekey_key, candidate_key.iv_key, + sizeof (candidate_key.iv_key)); + dev->rekey_derived_size = keysize; + dev->last_rekey = -1; + COMPILE_TIME_ASSERT (sizeof (dev->rekey_key) + >= sizeof (candidate_key.iv_key)); + } dev->iv_prefix_len = sizeof (candidate_key.iv_key); grub_memcpy (dev->iv_prefix, candidate_key.iv_key, diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index 5098f0a66..8876cc326 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -388,7 +388,7 @@ grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out) gcry_err_code_t grub_crypto_hmac_buffer (const struct gcry_md_spec *md, const void *key, grub_size_t keylen, - void *data, grub_size_t datalen, void *out) + const void *data, grub_size_t datalen, void *out) { struct grub_crypto_hmac_handle *hnd; diff --git a/include/grub/crypto.h b/include/grub/crypto.h index baccbcd06..10368d99f 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -244,7 +244,7 @@ grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out); gcry_err_code_t grub_crypto_hmac_buffer (const struct gcry_md_spec *md, const void *key, grub_size_t keylen, - void *data, grub_size_t datalen, void *out); + const void *data, grub_size_t datalen, void *out); extern gcry_md_spec_t _gcry_digest_spec_md5; extern gcry_md_spec_t _gcry_digest_spec_sha1; diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index 11181f42d..2da3f76d2 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -48,6 +48,12 @@ typedef enum #define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3) #define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES) +struct grub_cryptodisk; + +typedef gcry_err_code_t +(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev, + grub_uint64_t zoneno); + struct grub_cryptodisk { char *source; @@ -74,6 +80,11 @@ struct grub_cryptodisk int cheat_fd; #endif int log_sector_size; + grub_cryptodisk_rekey_func_t rekey; + int rekey_shift; + grub_uint8_t rekey_key[64]; + grub_uint64_t last_rekey; + int rekey_derived_size; struct grub_cryptodisk *next; }; typedef struct grub_cryptodisk *grub_cryptodisk_t; @@ -82,7 +93,7 @@ gcry_err_code_t grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize); gcry_err_code_t -grub_cryptodisk_decrypt (const struct grub_cryptodisk *dev, +grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, grub_uint8_t * data, grub_size_t len, grub_disk_addr_t sector); grub_err_t From 574d268020510d7996c1e263f1fac79aefeaf854 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 17:18:18 +0200 Subject: [PATCH 152/673] Add few FIXME comments --- grub-core/disk/geli.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index b3fa10cc5..6ffc7c26e 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -81,14 +81,19 @@ struct grub_geli_phdr struct grub_geli_key keys[2]; } __attribute__ ((packed)); +/* FIXME: support big-endian pre-version-4 volumes. */ +/* FIXME: support for keyfiles. */ +/* FIXME: support for HMAC. */ +/* FIXME: support for UUID. */ +/* FIXME: support for mounting all boot volumes. */ const char *algorithms[] = { [0x01] = "des", [0x02] = "3des", [0x03] = "blowfish", [0x04] = "cast5", - /* 0x05 is skipjack, but we don't have it. */ + /* FIXME: 0x05 is skipjack, but we don't have it. */ [0x0b] = "aes", - /* 0x10 is null. */ + /* FIXME: 0x10 is null. */ [0x15] = "camellia128", }; From 171e2be183b086b1560630f02231ee15771176a7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 17:41:50 +0200 Subject: [PATCH 153/673] geli xts support --- grub-core/disk/cryptodisk.c | 5 +++++ grub-core/disk/geli.c | 34 ++++++++++++++++++++++++++++------ include/grub/cryptodisk.h | 1 + 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 5ab607146..bf0b1cde2 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -234,6 +234,11 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_IV_PLAIN: iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); break; + case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64: + iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size)); + iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size) + & 0xFFFFFFFF); + break; case GRUB_CRYPTODISK_MODE_IV_BENBI: { grub_uint64_t num = (sector << dev->benbi_log) + 1; diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 6ffc7c26e..334a06340 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -95,6 +95,7 @@ const char *algorithms[] = { [0x0b] = "aes", /* FIXME: 0x10 is null. */ [0x15] = "camellia128", + [0x16] = "aes" }; #define MAX_PASSPHRASE 256 @@ -135,7 +136,7 @@ static grub_cryptodisk_t configure_ciphers (const struct grub_geli_phdr *header) { grub_cryptodisk_t newdev; - grub_crypto_cipher_handle_t cipher = NULL; + grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; const struct gcry_cipher_spec *ciph; const char *ciphername = NULL; const gcry_md_spec_t *hash = NULL, *iv_hash = NULL; @@ -196,6 +197,13 @@ configure_ciphers (const struct grub_geli_phdr *header) if (!cipher) return NULL; + if (grub_le_to_cpu16 (header->alg) == 0x16) + { + secondary_cipher = grub_crypto_cipher_open (ciph); + if (!secondary_cipher) + return NULL; + } + if (grub_le_to_cpu16 (header->keylen) > 1024) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", @@ -225,12 +233,20 @@ configure_ciphers (const struct grub_geli_phdr *header) if (!newdev) return NULL; newdev->cipher = cipher; + newdev->secondary_cipher = secondary_cipher; newdev->offset = 0; newdev->source_disk = NULL; newdev->benbi_log = 0; - newdev->mode = GRUB_CRYPTODISK_MODE_CBC; - newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH; - newdev->secondary_cipher = NULL; + if (grub_le_to_cpu16 (header->alg) == 0x16) + { + newdev->mode = GRUB_CRYPTODISK_MODE_XTS; + newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64; + } + else + { + newdev->mode = GRUB_CRYPTODISK_MODE_CBC; + newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH; + } newdev->essiv_cipher = NULL; newdev->essiv_hash = NULL; newdev->hash = hash; @@ -360,17 +376,23 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, /* Set the master key. */ if (!dev->rekey) { + grub_size_t real_keysize = keysize; + if (grub_le_to_cpu16 (header->alg) == 0x16) + real_keysize *= 2; gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key, - keysize); + real_keysize); if (gcry_err) return grub_crypto_gcry_error (gcry_err); } else { + grub_size_t real_keysize = keysize; + if (grub_le_to_cpu16 (header->alg) == 0x16) + real_keysize *= 2; /* For a reason I don't know, the IV key is used in rekeying. */ grub_memcpy (dev->rekey_key, candidate_key.iv_key, sizeof (candidate_key.iv_key)); - dev->rekey_derived_size = keysize; + dev->rekey_derived_size = real_keysize; dev->last_rekey = -1; COMPILE_TIME_ASSERT (sizeof (dev->rekey_key) >= sizeof (candidate_key.iv_key)); diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index 2da3f76d2..1911c04be 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -38,6 +38,7 @@ typedef enum GRUB_CRYPTODISK_MODE_IV_PLAIN64, GRUB_CRYPTODISK_MODE_IV_ESSIV, GRUB_CRYPTODISK_MODE_IV_BENBI, + GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64, GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH } grub_cryptodisk_mode_iv_t; From 371a8f1183f2696b1a58e410d89ff131cfc830a7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 17:50:22 +0200 Subject: [PATCH 154/673] Fix a potential buffer overflow --- grub-core/disk/luks.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 7c39002b8..3f98dfc87 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -32,7 +32,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define MAX_PASSPHRASE 256 #define LUKS_KEY_ENABLED 0x00AC71F3 -#define LUKS_STRIPES 4000 /* On disk LUKS header */ struct grub_luks_phdr @@ -301,10 +300,16 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, unsigned i; grub_size_t length; grub_err_t err; + grub_size_t max_stripes = 1; grub_printf ("Attempting to decrypt master key...\n"); - split_key = grub_malloc (keysize * LUKS_STRIPES); + for (i = 0; i < ARRAY_SIZE (header->keyblock); i++) + if (grub_be_to_cpu32 (header->keyblock[i].active) == LUKS_KEY_ENABLED + && grub_be_to_cpu32 (header->keyblock[i].stripes) > max_stripes) + max_stripes = grub_be_to_cpu32 (header->keyblock[i].stripes); + + split_key = grub_malloc (keysize * max_stripes); if (!split_key) return grub_errno; @@ -351,8 +356,7 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, return grub_crypto_gcry_error (gcry_err); } - length = (grub_be_to_cpu32 (header->keyBytes) - * grub_be_to_cpu32 (header->keyblock[i].stripes)); + length = (keysize * grub_be_to_cpu32 (header->keyblock[i].stripes)); /* Read and decrypt the key material from the disk. */ err = grub_disk_read (source, From 7efb5c9eeaad83e8eb2fdcde0fd182828d157610 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 20:37:56 +0200 Subject: [PATCH 155/673] Use hardcoded reference to sha512 and sha256 in geli rather than runtime lookup since they are always used --- Makefile.util.def | 12 ++++++++++++ grub-core/disk/geli.c | 23 ++--------------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index fe9e8c036..51771b9fa 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -108,6 +108,7 @@ program = { common = util/bin2h.c; ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; mansection = 1; @@ -138,6 +139,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -150,6 +152,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -162,6 +165,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -195,6 +199,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL)'; condition = COND_GRUB_PE2ELF; @@ -228,6 +233,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(freetype_libs)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; @@ -248,6 +254,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -277,6 +284,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; @@ -292,6 +300,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)'; @@ -306,6 +315,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -616,6 +626,7 @@ program = { cflags = -Wno-format; ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -629,6 +640,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; + ldadd = libgrubgcry.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 334a06340..b86e363c7 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -139,7 +139,6 @@ configure_ciphers (const struct grub_geli_phdr *header) grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; const struct gcry_cipher_spec *ciph; const char *ciphername = NULL; - const gcry_md_spec_t *hash = NULL, *iv_hash = NULL; /* Look for GELI magic sequence. */ if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) @@ -211,24 +210,6 @@ configure_ciphers (const struct grub_geli_phdr *header) return NULL; } - hash = grub_crypto_lookup_md_by_name ("sha512"); - if (!hash) - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", - "sha512"); - return NULL; - } - - iv_hash = grub_crypto_lookup_md_by_name ("sha256"); - if (!hash) - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", - "sha512"); - return NULL; - } - newdev = grub_zalloc (sizeof (struct grub_cryptodisk)); if (!newdev) return NULL; @@ -249,8 +230,8 @@ configure_ciphers (const struct grub_geli_phdr *header) } newdev->essiv_cipher = NULL; newdev->essiv_hash = NULL; - newdev->hash = hash; - newdev->iv_hash = iv_hash; + newdev->hash = GRUB_MD_SHA512; + newdev->iv_hash = GRUB_MD_SHA256; for (newdev->log_sector_size = 0; (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header->sector_size); From 23432f6542506794cbcf1d3b75b1e9d3fe284ad4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 21:11:14 +0200 Subject: [PATCH 156/673] support UUID for geli --- grub-core/disk/geli.c | 41 +++++++++++++++++++++++++++++---------- grub-core/disk/luks.c | 1 + include/grub/cryptodisk.h | 2 +- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index b86e363c7..104200546 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -84,7 +84,6 @@ struct grub_geli_phdr /* FIXME: support big-endian pre-version-4 volumes. */ /* FIXME: support for keyfiles. */ /* FIXME: support for HMAC. */ -/* FIXME: support for UUID. */ /* FIXME: support for mounting all boot volumes. */ const char *algorithms[] = { [0x01] = "des", @@ -132,6 +131,18 @@ geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno) dev->rekey_derived_size); } +static inline int +ascii2hex (char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return 0; +} + static grub_cryptodisk_t configure_ciphers (const struct grub_geli_phdr *header) { @@ -139,6 +150,11 @@ configure_ciphers (const struct grub_geli_phdr *header) grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; const struct gcry_cipher_spec *ciph; const char *ciphername = NULL; + char uuid[GRUB_MD_SHA256->mdlen * 2 + 1]; + grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen]; + grub_uint8_t *iptr; + char *optr; + gcry_err_code_t gcry_err; /* Look for GELI magic sequence. */ if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) @@ -157,13 +173,19 @@ configure_ciphers (const struct grub_geli_phdr *header) return NULL; } -#if 0 - optr = uuid; - for (iptr = header->uuid; iptr < &header->uuid[ARRAY_SIZE (header->uuid)]; - iptr++) + gcry_err = grub_crypto_hmac_buffer (GRUB_MD_SHA256, + header->salt, sizeof (header->salt), + "uuid", sizeof ("uuid") - 1, uuidbin); + if (gcry_err) { - if (*iptr != '-') - *optr++ = *iptr; + grub_crypto_gcry_error (gcry_err); + return NULL; + } + optr = uuid; + for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++) + { + grub_snprintf (optr, 3, "%02x", *iptr); + optr += 2; } *optr = 0; @@ -172,7 +194,6 @@ configure_ciphers (const struct grub_geli_phdr *header) grub_dprintf ("luks", "%s != %s", uuid, search_uuid); return NULL; } -#endif if (grub_le_to_cpu16 (header->alg) >= ARRAY_SIZE (algorithms) || algorithms[grub_le_to_cpu16 (header->alg)] == NULL) @@ -242,9 +263,9 @@ configure_ciphers (const struct grub_geli_phdr *header) newdev->rekey = geli_rekey; newdev->rekey_shift = 20; } -#if 0 + grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); -#endif + COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1); return newdev; } diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 3f98dfc87..a94b3cc52 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -284,6 +284,7 @@ configure_ciphers (const struct grub_luks_phdr *header) newdev->hash = hash; newdev->log_sector_size = 9; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); + COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid)); return newdev; } diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index 1911c04be..169fb119d 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -42,7 +42,7 @@ typedef enum GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH } grub_cryptodisk_mode_iv_t; -#define GRUB_CRYPTODISK_MAX_UUID_LENGTH 63 +#define GRUB_CRYPTODISK_MAX_UUID_LENGTH 71 #define GRUB_CRYPTODISK_GF_LOG_SIZE 7 #define GRUB_CRYPTODISK_GF_SIZE (1U << GRUB_CRYPTODISK_GF_LOG_SIZE) From 8358d7f22154b26c94d440e5c76e6287dfdf1372 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 21:40:13 +0200 Subject: [PATCH 157/673] Skip one-time volumes and add option for skipping non-boot volumes --- grub-core/disk/geli.c | 36 +++++++++++++++++++++++++++++------- grub-core/disk/luks.c | 2 +- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 104200546..8731d3065 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -70,7 +70,7 @@ struct grub_geli_phdr grub_uint8_t magic[16]; #define GELI_MAGIC "GEOM::ELI" grub_uint32_t version; - grub_uint32_t unused1; + grub_uint32_t flags; grub_uint16_t alg; grub_uint16_t keylen; grub_uint16_t unused3[5]; @@ -81,6 +81,12 @@ struct grub_geli_phdr struct grub_geli_key keys[2]; } __attribute__ ((packed)); +enum + { + GRUB_GELI_FLAGS_ONETIME = 1, + GRUB_GELI_FLAGS_BOOT = 2, + }; + /* FIXME: support big-endian pre-version-4 volumes. */ /* FIXME: support for keyfiles. */ /* FIXME: support for HMAC. */ @@ -103,10 +109,11 @@ static const struct grub_arg_option options[] = { {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, {"all", 'a', 0, N_("Mount all."), 0, 0}, + {"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0}, {0, 0, 0, 0, 0, 0} }; -static int check_uuid, have_it; +static int check_uuid, check_boot, have_it; static char *search_uuid; static gcry_err_code_t @@ -171,7 +178,19 @@ configure_ciphers (const struct grub_geli_phdr *header) grub_dprintf ("geli", "incorrect sector size %d\n", grub_le_to_cpu32 (header->sector_size)); return NULL; - } + } + + if (grub_le_to_cpu32 (header->flags) & GRUB_GELI_FLAGS_ONETIME) + { + grub_dprintf ("geli", "skipping one-time volume\n"); + return NULL; + } + + if (check_boot && !(grub_le_to_cpu32 (header->flags) & GRUB_GELI_FLAGS_BOOT)) + { + grub_dprintf ("geli", "not a boot volume\n"); + return NULL; + } gcry_err = grub_crypto_hmac_buffer (GRUB_MD_SHA256, header->salt, sizeof (header->salt), @@ -191,7 +210,7 @@ configure_ciphers (const struct grub_geli_phdr *header) if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0) { - grub_dprintf ("luks", "%s != %s", uuid, search_uuid); + grub_dprintf ("geli", "%s != %s\n", uuid, search_uuid); return NULL; } @@ -549,7 +568,7 @@ grub_cmd_gelimount (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; - if (argc < 1 && !state[1].set) + if (argc < 1 && !state[1].set && !state[2].set) return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); have_it = 0; @@ -565,6 +584,7 @@ grub_cmd_gelimount (grub_extcmd_context_t ctxt, int argc, char **args) } check_uuid = 1; + check_boot = state[2].set; search_uuid = args[0]; grub_device_iterate (&grub_geli_scan_device); search_uuid = NULL; @@ -573,10 +593,11 @@ grub_cmd_gelimount (grub_extcmd_context_t ctxt, int argc, char **args) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); return GRUB_ERR_NONE; } - else if (state[1].set) + else if (state[1].set || (argc == 0 && state[2].set)) { check_uuid = 0; search_uuid = NULL; + check_boot = state[2].set; grub_device_iterate (&grub_geli_scan_device); search_uuid = NULL; return GRUB_ERR_NONE; @@ -589,6 +610,7 @@ grub_cmd_gelimount (grub_extcmd_context_t ctxt, int argc, char **args) check_uuid = 0; search_uuid = NULL; + check_boot = state[2].set; disk = grub_disk_open (args[0]); if (!disk) return grub_errno; @@ -614,7 +636,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (geli) { cmd = grub_register_extcmd ("gelimount", grub_cmd_gelimount, 0, - N_("SOURCE|-u UUID|-a"), + N_("SOURCE|-u UUID|-a|-b"), N_("Mount a GELI device."), options); } diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index a94b3cc52..aa23e2e35 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -109,7 +109,7 @@ configure_ciphers (const struct grub_luks_phdr *header) if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0) { - grub_dprintf ("luks", "%s != %s", uuid, search_uuid); + grub_dprintf ("luks", "%s != %s\n", uuid, search_uuid); return NULL; } From f718594e32da770ac412d1a02a2002c81d2302c2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 24 Apr 2011 21:41:49 +0200 Subject: [PATCH 158/673] update fixme --- grub-core/disk/geli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 8731d3065..1353be172 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -87,10 +87,10 @@ enum GRUB_GELI_FLAGS_BOOT = 2, }; +/* FIXME: support version 0. */ /* FIXME: support big-endian pre-version-4 volumes. */ /* FIXME: support for keyfiles. */ /* FIXME: support for HMAC. */ -/* FIXME: support for mounting all boot volumes. */ const char *algorithms[] = { [0x01] = "des", [0x02] = "3des", From d7bdab32b8e9e17c0111536b357189f72e6f330d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Apr 2011 14:46:47 +0200 Subject: [PATCH 159/673] fix linking trouble on FreeBSD --- Makefile.util.def | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 51771b9fa..3125b8b30 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -107,8 +107,8 @@ program = { name = grub-bin2h; common = util/bin2h.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; mansection = 1; @@ -123,8 +123,8 @@ program = { extra_dist = util/grub-mkimagexx.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBLZMA)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; @@ -138,8 +138,8 @@ program = { common = util/grub-mkrelpath.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -151,8 +151,8 @@ program = { common = util/grub-script-check.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -164,8 +164,8 @@ program = { common = util/grub-editenv.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -177,8 +177,8 @@ program = { common = util/grub-mkpasswd-pbkdf2.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; cflags = '$(CFLAGS_GCRY)'; @@ -198,8 +198,8 @@ program = { common = util/grub-pe2elf.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL)'; condition = COND_GRUB_PE2ELF; @@ -217,8 +217,8 @@ program = { cppflags = '$(CPPFLAGS_GCRY)'; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -232,8 +232,8 @@ program = { cflags = '$(freetype_cflags)'; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(freetype_libs)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; @@ -253,8 +253,8 @@ program = { sparc64_ieee1275 = util/ieee1275/devicemap.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -266,8 +266,8 @@ program = { common = util/grub-probe.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -299,8 +299,8 @@ program = { ieee1275 = util/ieee1275/ofpath.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)'; @@ -314,8 +314,8 @@ program = { common = util/grub-mklayout.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -625,8 +625,8 @@ program = { common = grub-core/tests/lib/test.c; cflags = -Wno-format; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -639,8 +639,8 @@ program = { common = grub-core/lib/i386/pc/vesa_modes_table.c; ldadd = libgrubmods.a; - ldadd = libgrubkern.a; ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; From 20a409405b6caf9f51bb391caaac24124c0de3f9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Apr 2011 14:52:07 +0200 Subject: [PATCH 160/673] Integrate geli into autoconfiguration system --- grub-core/disk/cryptodisk.c | 210 ++++++++++++++- grub-core/disk/geli.c | 464 +++++++++++++--------------------- grub-core/disk/luks.c | 329 ++++++------------------ grub-core/kern/emu/getroot.c | 217 +++++++++++++++- grub-core/kern/emu/hostdisk.c | 204 +++++++-------- include/grub/cryptodisk.h | 35 ++- include/grub/emu/getroot.h | 5 + include/grub/emu/hostdisk.h | 8 +- util/grub-fstest.c | 6 +- util/grub-install.in | 6 +- util/grub-mkconfig.in | 2 +- util/grub-mkconfig_lib.in | 10 +- util/grub-probe.c | 21 +- 13 files changed, 835 insertions(+), 682 deletions(-) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index bf0b1cde2..1a5e8164b 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #ifdef GRUB_UTIL #include @@ -33,6 +35,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); +grub_cryptodisk_dev_t grub_cryptodisk_list; + +static const struct grub_arg_option options[] = + { + {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, + {"all", 'a', 0, N_("Mount all."), 0, 0}, + {"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ #define GF_POLYNOM 0x87 static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev) @@ -480,7 +492,7 @@ grub_cryptodisk_close (grub_disk_t disk) static grub_err_t grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, - grub_size_t size, char *buf) + grub_size_t size, char *buf) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; grub_err_t err; @@ -635,7 +647,7 @@ grub_util_cryptodisk_print_abstraction (grub_disk_t disk) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - grub_printf ("luks "); + grub_printf ("cryptodisk %s ", dev->modname); if (dev->cipher) grub_printf ("%s ", dev->cipher->cipher->modname); @@ -650,8 +662,197 @@ grub_util_cryptodisk_print_abstraction (grub_disk_t disk) if (dev->iv_hash) grub_printf ("%s ", dev->iv_hash->modname); } + +void +grub_util_cryptodisk_print_uuid (grub_disk_t disk) +{ + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + grub_printf ("%s ", dev->uuid); +} + #endif +static int check_boot, have_it; +static char *search_uuid; + +static void +cryptodisk_close (grub_cryptodisk_t dev) +{ + grub_crypto_cipher_close (dev->cipher); + grub_crypto_cipher_close (dev->secondary_cipher); + grub_crypto_cipher_close (dev->essiv_cipher); + grub_free (dev); +} + +static grub_err_t +grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) +{ + grub_err_t err; + grub_cryptodisk_t dev; + grub_cryptodisk_dev_t cr; + + dev = grub_cryptodisk_get_by_source_disk (source); + + if (dev) + return GRUB_ERR_NONE; + + FOR_CRYPTODISK_DEVS (cr) + { + dev = cr->scan (source, search_uuid, check_boot); + if (grub_errno) + return grub_errno; + if (!dev) + continue; + + err = cr->recover_key (source, dev); + if (err) + { + cryptodisk_close (dev); + return err; + } + + grub_cryptodisk_insert (dev, name, source); + + have_it = 1; + + return GRUB_ERR_NONE; + } + return GRUB_ERR_NONE; +} + +#ifdef GRUB_UTIL +#include +grub_err_t +grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat) +{ + grub_err_t err; + grub_cryptodisk_t dev; + grub_cryptodisk_dev_t cr; + grub_disk_t source; + + /* Try to open disk. */ + source = grub_disk_open (sourcedev); + if (!source) + return grub_errno; + + dev = grub_cryptodisk_get_by_source_disk (source); + + if (dev) + { + grub_disk_close (source); + return GRUB_ERR_NONE; + } + + FOR_CRYPTODISK_DEVS (cr) + { + dev = cr->scan (source, search_uuid, check_boot); + if (grub_errno) + return grub_errno; + if (!dev) + continue; + + grub_util_info ("cheatmounted %s (%s) at %s", sourcedev, dev->modname, + cheat); + err = grub_cryptodisk_cheat_insert (dev, sourcedev, source, cheat); + grub_disk_close (source); + if (err) + grub_free (dev); + + return GRUB_ERR_NONE; + } + + grub_disk_close (source); + + return GRUB_ERR_NONE; +} +#endif + +static int +grub_cryptodisk_scan_device (const char *name) +{ + grub_err_t err; + grub_disk_t source; + + /* Try to open disk. */ + source = grub_disk_open (name); + if (!source) + return grub_errno; + + err = grub_cryptodisk_scan_device_real (name, source); + + grub_disk_close (source); + + if (err) + grub_print_error (); + return have_it && search_uuid ? 1 : 0; +} + +static grub_err_t +grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + + if (argc < 1 && !state[1].set && !state[2].set) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); + + have_it = 0; + if (state[0].set) + { + grub_cryptodisk_t dev; + + dev = grub_cryptodisk_get_by_uuid (args[0]); + if (dev) + { + grub_dprintf ("cryptodisk", + "already mounted as crypto%lu\n", dev->id); + return GRUB_ERR_NONE; + } + + check_boot = state[2].set; + search_uuid = args[0]; + grub_device_iterate (&grub_cryptodisk_scan_device); + search_uuid = NULL; + + if (!have_it) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found"); + return GRUB_ERR_NONE; + } + else if (state[1].set || (argc == 0 && state[2].set)) + { + search_uuid = NULL; + check_boot = state[2].set; + grub_device_iterate (&grub_cryptodisk_scan_device); + search_uuid = NULL; + return GRUB_ERR_NONE; + } + else + { + grub_err_t err; + grub_disk_t disk; + grub_cryptodisk_t dev; + + search_uuid = NULL; + check_boot = state[2].set; + disk = grub_disk_open (args[0]); + if (!disk) + return grub_errno; + + dev = grub_cryptodisk_get_by_source_disk (disk); + if (dev) + { + grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id); + grub_disk_close (disk); + return GRUB_ERR_NONE; + } + + err = grub_cryptodisk_scan_device_real (args[0], disk); + + grub_disk_close (disk); + + return err; + } +} + static struct grub_disk_dev grub_cryptodisk_dev = { .name = "cryptodisk", .id = GRUB_DISK_DEVICE_CRYPTODISK_ID, @@ -666,9 +867,14 @@ static struct grub_disk_dev grub_cryptodisk_dev = { .next = 0 }; +static grub_extcmd_t cmd; + GRUB_MOD_INIT (cryptodisk) { grub_disk_dev_register (&grub_cryptodisk_dev); + cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0, + N_("SOURCE|-u UUID|-a|-b"), + N_("Mount a crypto device."), options); } GRUB_MOD_FINI (cryptodisk) diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index 1353be172..d2ae5da56 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -53,7 +53,7 @@ #include #include #include -#include +#include #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -105,17 +105,6 @@ const char *algorithms[] = { #define MAX_PASSPHRASE 256 -static const struct grub_arg_option options[] = - { - {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, - {"all", 'a', 0, N_("Mount all."), 0, 0}, - {"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0}, - {0, 0, 0, 0, 0, 0} - }; - -static int check_uuid, check_boot, have_it; -static char *search_uuid; - static gcry_err_code_t geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno) { @@ -150,56 +139,21 @@ ascii2hex (char c) return 0; } -static grub_cryptodisk_t -configure_ciphers (const struct grub_geli_phdr *header) +static inline gcry_err_code_t +make_uuid (const struct grub_geli_phdr *header, + char *uuid) { - grub_cryptodisk_t newdev; - grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; - const struct gcry_cipher_spec *ciph; - const char *ciphername = NULL; - char uuid[GRUB_MD_SHA256->mdlen * 2 + 1]; grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen]; + gcry_err_code_t err; grub_uint8_t *iptr; char *optr; - gcry_err_code_t gcry_err; - /* Look for GELI magic sequence. */ - if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) - || grub_le_to_cpu32 (header->version) > 5 - || grub_le_to_cpu32 (header->version) < 1) - { - grub_dprintf ("geli", "wrong magic %02x\n", header->magic[0]); - return NULL; - } - if ((grub_le_to_cpu32 (header->sector_size) - & (grub_le_to_cpu32 (header->sector_size) - 1)) - || grub_le_to_cpu32 (header->sector_size) == 0) - { - grub_dprintf ("geli", "incorrect sector size %d\n", - grub_le_to_cpu32 (header->sector_size)); - return NULL; - } + err = grub_crypto_hmac_buffer (GRUB_MD_SHA256, + header->salt, sizeof (header->salt), + "uuid", sizeof ("uuid") - 1, uuidbin); + if (err) + return err; - if (grub_le_to_cpu32 (header->flags) & GRUB_GELI_FLAGS_ONETIME) - { - grub_dprintf ("geli", "skipping one-time volume\n"); - return NULL; - } - - if (check_boot && !(grub_le_to_cpu32 (header->flags) & GRUB_GELI_FLAGS_BOOT)) - { - grub_dprintf ("geli", "not a boot volume\n"); - return NULL; - } - - gcry_err = grub_crypto_hmac_buffer (GRUB_MD_SHA256, - header->salt, sizeof (header->salt), - "uuid", sizeof ("uuid") - 1, uuidbin); - if (gcry_err) - { - grub_crypto_gcry_error (gcry_err); - return NULL; - } optr = uuid; for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++) { @@ -207,22 +161,133 @@ configure_ciphers (const struct grub_geli_phdr *header) optr += 2; } *optr = 0; + return GPG_ERR_NO_ERROR; +} - if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0) +#ifdef GRUB_UTIL + +#include +#include +#include +#include +#include +#include +#include +#include + +char * +grub_util_get_geli_uuid (const char *dev) +{ + int fd = open (dev, O_RDONLY); + grub_uint64_t s; + unsigned log_secsize; + grub_uint8_t hdr[512]; + struct grub_geli_phdr *header; + char *uuid; + gcry_err_code_t err; + + if (fd < 0) + return NULL; + + s = grub_util_get_fd_sectors (fd, &log_secsize); + grub_util_fd_seek (fd, dev, (s << log_secsize) - 512); + + uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1); + if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0) + grub_util_error ("couldn't read ELI metadata"); + + COMPILE_TIME_ASSERT (sizeof (header) <= 512); + header = (void *) &hdr; + + /* Look for GELI magic sequence. */ + if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) + || grub_le_to_cpu32 (header->version) > 5 + || grub_le_to_cpu32 (header->version) < 1) + grub_util_error ("wrong ELI magic or version"); + + err = make_uuid ((void *) &hdr, uuid); + if (err) + return NULL; + + return uuid; +} +#endif + +static grub_cryptodisk_t +configure_ciphers (grub_disk_t disk, const char *check_uuid, + int boot_only) +{ + grub_cryptodisk_t newdev; + struct grub_geli_phdr header; + grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; + const struct gcry_cipher_spec *ciph; + const char *ciphername = NULL; + gcry_err_code_t gcry_err; + char uuid[GRUB_MD_SHA256->mdlen * 2 + 1]; + grub_disk_addr_t sector; + grub_err_t err; + + sector = grub_disk_get_size (disk); + if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) + return NULL; + + /* Read the GELI header. */ + err = grub_disk_read (disk, sector - 1, 0, sizeof (header), &header); + if (err) + return NULL; + + /* Look for GELI magic sequence. */ + if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC)) + || grub_le_to_cpu32 (header.version) > 5 + || grub_le_to_cpu32 (header.version) < 1) { - grub_dprintf ("geli", "%s != %s\n", uuid, search_uuid); + grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]); return NULL; } - if (grub_le_to_cpu16 (header->alg) >= ARRAY_SIZE (algorithms) - || algorithms[grub_le_to_cpu16 (header->alg)] == NULL) + if ((grub_le_to_cpu32 (header.sector_size) + & (grub_le_to_cpu32 (header.sector_size) - 1)) + || grub_le_to_cpu32 (header.sector_size) == 0) + { + grub_dprintf ("geli", "incorrect sector size %d\n", + grub_le_to_cpu32 (header.sector_size)); + return NULL; + } + + if (grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_ONETIME) + { + grub_dprintf ("geli", "skipping one-time volume\n"); + return NULL; + } + + if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT)) + { + grub_dprintf ("geli", "not a boot volume\n"); + return NULL; + } + + gcry_err = make_uuid (&header, uuid); + if (gcry_err) + { + grub_crypto_gcry_error (gcry_err); + return NULL; + } + + if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0) + { + grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid); + return NULL; + } + + if (grub_le_to_cpu16 (header.alg) >= ARRAY_SIZE (algorithms) + || algorithms[grub_le_to_cpu16 (header.alg)] == NULL) { grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher 0x%x unknown", - grub_le_to_cpu16 (header->alg)); + grub_le_to_cpu16 (header.alg)); return NULL; } - ciphername = algorithms[grub_le_to_cpu16 (header->alg)]; + ciphername = algorithms[grub_le_to_cpu16 (header.alg)]; ciph = grub_crypto_lookup_cipher_by_name (ciphername); if (!ciph) { @@ -236,17 +301,17 @@ configure_ciphers (const struct grub_geli_phdr *header) if (!cipher) return NULL; - if (grub_le_to_cpu16 (header->alg) == 0x16) + if (grub_le_to_cpu16 (header.alg) == 0x16) { secondary_cipher = grub_crypto_cipher_open (ciph); if (!secondary_cipher) return NULL; } - if (grub_le_to_cpu16 (header->keylen) > 1024) + if (grub_le_to_cpu16 (header.keylen) > 1024) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", - grub_le_to_cpu16 (header->keylen)); + grub_le_to_cpu16 (header.keylen)); return NULL; } @@ -258,7 +323,7 @@ configure_ciphers (const struct grub_geli_phdr *header) newdev->offset = 0; newdev->source_disk = NULL; newdev->benbi_log = 0; - if (grub_le_to_cpu16 (header->alg) == 0x16) + if (grub_le_to_cpu16 (header.alg) == 0x16) { newdev->mode = GRUB_CRYPTODISK_MODE_XTS; newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64; @@ -274,25 +339,29 @@ configure_ciphers (const struct grub_geli_phdr *header) newdev->iv_hash = GRUB_MD_SHA256; for (newdev->log_sector_size = 0; - (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header->sector_size); + (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header.sector_size); newdev->log_sector_size++); - if (grub_le_to_cpu32 (header->version) >= 5) + if (grub_le_to_cpu32 (header.version) >= 5) { newdev->rekey = geli_rekey; newdev->rekey_shift = 20; } +#ifdef GRUB_UTIL + newdev->modname = "geli"; +#endif + + newdev->total_length = grub_disk_get_size (disk) - 1; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1); return newdev; } static grub_err_t -recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, - const char *name, grub_disk_t source __attribute__ ((unused))) +recover_key (grub_disk_t source, grub_cryptodisk_t dev) { - grub_size_t keysize = grub_le_to_cpu16 (header->keylen) / 8; + grub_size_t keysize; grub_uint8_t digest[dev->hash->mdlen]; grub_uint8_t geomkey[dev->hash->mdlen]; grub_uint8_t verify_key[dev->hash->mdlen]; @@ -300,25 +369,45 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, char passphrase[MAX_PASSPHRASE] = ""; unsigned i; gcry_err_code_t gcry_err; + struct grub_geli_phdr header; + char *tmp; + grub_disk_addr_t sector; + grub_err_t err; + sector = grub_disk_get_size (source); + if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli"); + + /* Read the GELI header. */ + err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header); + if (err) + return err; + + keysize = grub_le_to_cpu16 (header.keylen) / 8; grub_memset (zero, 0, sizeof (zero)); grub_printf ("Attempting to decrypt master key...\n"); /* Get the passphrase from the user. */ - grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid); + tmp = NULL; + if (source->partition) + tmp = grub_partition_get_name (source->partition); + grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name, + source->partition ? "," : "", tmp ? : "", + dev->uuid); + grub_free (tmp); if (!grub_password_get (passphrase, MAX_PASSPHRASE)) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); /* Calculate the PBKDF2 of the user supplied passphrase. */ - if (grub_le_to_cpu32 (header->niter) != 0) + if (grub_le_to_cpu32 (header.niter) != 0) { grub_uint8_t pbkdf_key[64]; gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, grub_strlen (passphrase), - header->salt, - sizeof (header->salt), - grub_le_to_cpu32 (header->niter), + header.salt, + sizeof (header.salt), + grub_le_to_cpu32 (header.niter), pbkdf_key, sizeof (pbkdf_key)); if (gcry_err) @@ -337,7 +426,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, if (!hnd) return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY); - grub_crypto_hmac_write (hnd, header->salt, sizeof (header->salt)); + grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt)); grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase)); gcry_err = grub_crypto_hmac_fini (hnd, geomkey); @@ -358,13 +447,13 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, grub_dprintf ("geli", "keylen = %" PRIuGRUB_SIZE "\n", keysize); /* Try to recover master key from each active keyslot. */ - for (i = 0; i < ARRAY_SIZE (header->keys); i++) + for (i = 0; i < ARRAY_SIZE (header.keys); i++) { struct grub_geli_key candidate_key; grub_uint8_t key_hmac[dev->hash->mdlen]; /* Check if keyslot is enabled. */ - if (! (header->keys_used & (1 << i))) + if (! (header.keys_used & (1 << i))) continue; grub_dprintf ("geli", "Trying keyslot %d\n", i); @@ -375,7 +464,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, return grub_crypto_gcry_error (gcry_err); gcry_err = grub_crypto_cbc_decrypt (dev->cipher, &candidate_key, - &header->keys[i], + &header.keys[i], sizeof (candidate_key), zero); if (gcry_err) @@ -398,7 +487,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, if (!dev->rekey) { grub_size_t real_keysize = keysize; - if (grub_le_to_cpu16 (header->alg) == 0x16) + if (grub_le_to_cpu16 (header.alg) == 0x16) real_keysize *= 2; gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key, real_keysize); @@ -408,7 +497,7 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, else { grub_size_t real_keysize = keysize; - if (grub_le_to_cpu16 (header->alg) == 0x16) + if (grub_le_to_cpu16 (header.alg) == 0x16) real_keysize *= 2; /* For a reason I don't know, the IV key is used in rekeying. */ grub_memcpy (dev->rekey_key, candidate_key.iv_key, @@ -431,216 +520,17 @@ recover_key (grub_cryptodisk_t dev, const struct grub_geli_phdr *header, return GRUB_ACCESS_DENIED; } -static void -close (grub_cryptodisk_t luks) -{ - grub_crypto_cipher_close (luks->cipher); - grub_crypto_cipher_close (luks->secondary_cipher); - grub_crypto_cipher_close (luks->essiv_cipher); - grub_free (luks); -} - -static grub_err_t -grub_geli_scan_device_real (const char *name, grub_disk_t source) -{ - grub_err_t err; - struct grub_geli_phdr header; - grub_cryptodisk_t newdev, dev; - grub_disk_addr_t sector; - - grub_dprintf ("geli", "scanning %s\n", source->name); - dev = grub_cryptodisk_get_by_source_disk (source); - - if (dev) - return GRUB_ERR_NONE; - - sector = grub_disk_get_size (source); - if (sector == GRUB_DISK_SIZE_UNKNOWN) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli"); - - /* Read the LUKS header. */ - err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header); - if (err) - return err; - - newdev = configure_ciphers (&header); - if (!newdev) - return grub_errno; - - newdev->total_length = grub_disk_get_size (source) - 1; - - err = recover_key (newdev, &header, name, source); - if (err) - { - close (newdev); - return err; - } - - grub_cryptodisk_insert (newdev, name, source); - - have_it = 1; - - return GRUB_ERR_NONE; -} - -#ifdef GRUB_UTIL -grub_err_t -grub_geli_cheat_mount (const char *sourcedev, const char *cheat) -{ - grub_err_t err; - struct grub_geli_phdr header; - grub_cryptodisk_t newdev, dev; - grub_disk_t source; - grub_disk_addr_t sector; - - /* Try to open disk. */ - source = grub_disk_open (sourcedev); - if (!source) - return grub_errno; - - dev = grub_cryptodisk_get_by_source_disk (source); - - if (dev) - { - grub_disk_close (source); - return GRUB_ERR_NONE; - } - - sector = grub_disk_get_size (source); - if (sector == GRUB_DISK_SIZE_UNKNOWN) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli"); - - /* Read the LUKS header. */ - err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header); - if (err) - return err; - - newdev = configure_ciphers (&header); - if (!newdev) - { - grub_disk_close (source); - return grub_errno; - } - - newdev->total_length = grub_disk_get_size (source) - 1; - - err = grub_cryptodisk_cheat_insert (newdev, sourcedev, source, cheat); - grub_disk_close (source); - if (err) - grub_free (newdev); - - return err; -} -#endif - -static int -grub_geli_scan_device (const char *name) -{ - grub_err_t err; - grub_disk_t source; - - /* Try to open disk. */ - source = grub_disk_open (name); - if (!source) - return grub_errno; - - err = grub_geli_scan_device_real (name, source); - - grub_disk_close (source); - - if (err) - grub_print_error (); - return have_it && check_uuid ? 0 : 1; -} - -#ifdef GRUB_UTIL - -void -grub_util_geli_print_uuid (grub_disk_t disk) -{ - grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - grub_printf ("%s ", dev->uuid); -} -#endif - -static grub_err_t -grub_cmd_gelimount (grub_extcmd_context_t ctxt, int argc, char **args) -{ - struct grub_arg_list *state = ctxt->state; - - if (argc < 1 && !state[1].set && !state[2].set) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); - - have_it = 0; - if (state[0].set) - { - grub_cryptodisk_t dev; - - dev = grub_cryptodisk_get_by_uuid (args[0]); - if (dev) - { - grub_dprintf ("luks", "already mounted as crypto%lu\n", dev->id); - return GRUB_ERR_NONE; - } - - check_uuid = 1; - check_boot = state[2].set; - search_uuid = args[0]; - grub_device_iterate (&grub_geli_scan_device); - search_uuid = NULL; - - if (!have_it) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); - return GRUB_ERR_NONE; - } - else if (state[1].set || (argc == 0 && state[2].set)) - { - check_uuid = 0; - search_uuid = NULL; - check_boot = state[2].set; - grub_device_iterate (&grub_geli_scan_device); - search_uuid = NULL; - return GRUB_ERR_NONE; - } - else - { - grub_err_t err; - grub_disk_t disk; - grub_cryptodisk_t dev; - - check_uuid = 0; - search_uuid = NULL; - check_boot = state[2].set; - disk = grub_disk_open (args[0]); - if (!disk) - return grub_errno; - - dev = grub_cryptodisk_get_by_source_disk (disk); - if (dev) - { - grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); - grub_disk_close (disk); - return GRUB_ERR_NONE; - } - - err = grub_geli_scan_device_real (args[0], disk); - - grub_disk_close (disk); - - return err; - } -} - -static grub_extcmd_t cmd; +struct grub_cryptodisk_dev geli_crypto = { + .scan = configure_ciphers, + .recover_key = recover_key +}; GRUB_MOD_INIT (geli) { - cmd = grub_register_extcmd ("gelimount", grub_cmd_gelimount, 0, - N_("SOURCE|-u UUID|-a|-b"), - N_("Mount a GELI device."), options); + grub_cryptodisk_dev_register (&geli_crypto); } GRUB_MOD_FINI (geli) { - grub_unregister_extcmd (cmd); + grub_cryptodisk_dev_unregister (&geli_crypto); } diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index aa23e2e35..0ec95fccd 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -64,27 +64,19 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst, grub_size_t blocksize, grub_size_t blocknumbers); -static const struct grub_arg_option options[] = - { - {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, - {"all", 'a', 0, N_("Mount all."), 0, 0}, - {0, 0, 0, 0, 0, 0} - }; - -static int check_uuid, have_it; -static char *search_uuid; - static grub_cryptodisk_t -configure_ciphers (const struct grub_luks_phdr *header) +configure_ciphers (grub_disk_t disk, const char *check_uuid, + int check_boot) { grub_cryptodisk_t newdev; const char *iptr; + struct grub_luks_phdr header; char *optr; - char uuid[sizeof (header->uuid) + 1]; - char ciphername[sizeof (header->cipherName) + 1]; - char ciphermode[sizeof (header->cipherMode) + 1]; + char uuid[sizeof (header.uuid) + 1]; + char ciphername[sizeof (header.cipherName) + 1]; + char ciphermode[sizeof (header.cipherMode) + 1]; char *cipheriv = NULL; - char hashspec[sizeof (header->hashSpec) + 1]; + char hashspec[sizeof (header.hashSpec) + 1]; grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; grub_crypto_cipher_handle_t essiv_cipher = NULL; const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; @@ -92,14 +84,27 @@ configure_ciphers (const struct grub_luks_phdr *header) grub_cryptodisk_mode_t mode; grub_cryptodisk_mode_iv_t mode_iv; int benbi_log = 0; + grub_err_t err; + + if (check_boot) + return NULL; + + /* Read the LUKS header. */ + err = grub_disk_read (disk, 0, 0, sizeof (header), &header); + if (err) + { + if (err == GRUB_ERR_OUT_OF_RANGE) + grub_errno = GRUB_ERR_NONE; + return NULL; + } /* Look for LUKS magic sequence. */ - if (grub_memcmp (header->magic, LUKS_MAGIC, sizeof (header->magic)) - || grub_be_to_cpu16 (header->version) != 1) + if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic)) + || grub_be_to_cpu16 (header.version) != 1) return NULL; optr = uuid; - for (iptr = header->uuid; iptr < &header->uuid[ARRAY_SIZE (header->uuid)]; + for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)]; iptr++) { if (*iptr != '-') @@ -107,19 +112,19 @@ configure_ciphers (const struct grub_luks_phdr *header) } *optr = 0; - if (check_uuid && grub_strcasecmp (search_uuid, uuid) != 0) + if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0) { - grub_dprintf ("luks", "%s != %s\n", uuid, search_uuid); + grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid); return NULL; } /* Make sure that strings are null terminated. */ - grub_memcpy (ciphername, header->cipherName, sizeof (header->cipherName)); - ciphername[sizeof (header->cipherName)] = 0; - grub_memcpy (ciphermode, header->cipherMode, sizeof (header->cipherMode)); - ciphermode[sizeof (header->cipherMode)] = 0; - grub_memcpy (hashspec, header->hashSpec, sizeof (header->hashSpec)); - hashspec[sizeof (header->hashSpec)] = 0; + grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName)); + ciphername[sizeof (header.cipherName)] = 0; + grub_memcpy (ciphermode, header.cipherMode, sizeof (header.cipherMode)); + ciphermode[sizeof (header.cipherMode)] = 0; + grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec)); + hashspec[sizeof (header.hashSpec)] = 0; ciph = grub_crypto_lookup_cipher_by_name (ciphername); if (!ciph) @@ -134,10 +139,10 @@ configure_ciphers (const struct grub_luks_phdr *header) if (!cipher) return NULL; - if (grub_be_to_cpu32 (header->keyBytes) > 1024) + if (grub_be_to_cpu32 (header.keyBytes) > 1024) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", - grub_be_to_cpu32 (header->keyBytes)); + grub_be_to_cpu32 (header.keyBytes)); return NULL; } @@ -273,7 +278,7 @@ configure_ciphers (const struct grub_luks_phdr *header) if (!newdev) return NULL; newdev->cipher = cipher; - newdev->offset = grub_be_to_cpu32 (header->payloadOffset); + newdev->offset = grub_be_to_cpu32 (header.payloadOffset); newdev->source_disk = NULL; newdev->benbi_log = benbi_log; newdev->mode = mode; @@ -283,39 +288,54 @@ configure_ciphers (const struct grub_luks_phdr *header) newdev->essiv_hash = essiv_hash; newdev->hash = hash; newdev->log_sector_size = 9; + newdev->total_length = grub_disk_get_size (disk) - newdev->offset; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); +#ifdef GRUB_UTIL + newdev->modname = "luks"; +#endif COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid)); return newdev; } static grub_err_t -luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, - const char *name, grub_disk_t source) +luks_recover_key (grub_disk_t source, + grub_cryptodisk_t dev) { - grub_size_t keysize = grub_be_to_cpu32 (header->keyBytes); - grub_uint8_t candidate_key[keysize]; - grub_uint8_t digest[keysize]; + struct grub_luks_phdr header; + grub_size_t keysize; grub_uint8_t *split_key = NULL; char passphrase[MAX_PASSPHRASE] = ""; - grub_uint8_t candidate_digest[sizeof (header->mkDigest)]; + grub_uint8_t candidate_digest[sizeof (header.mkDigest)]; unsigned i; grub_size_t length; grub_err_t err; grub_size_t max_stripes = 1; + char *tmp; + + err = grub_disk_read (source, 0, 0, sizeof (header), &header); + if (err) + return err; grub_printf ("Attempting to decrypt master key...\n"); + keysize = grub_be_to_cpu32 (header.keyBytes); - for (i = 0; i < ARRAY_SIZE (header->keyblock); i++) - if (grub_be_to_cpu32 (header->keyblock[i].active) == LUKS_KEY_ENABLED - && grub_be_to_cpu32 (header->keyblock[i].stripes) > max_stripes) - max_stripes = grub_be_to_cpu32 (header->keyblock[i].stripes); + for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) + if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED + && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes) + max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes); split_key = grub_malloc (keysize * max_stripes); if (!split_key) return grub_errno; /* Get the passphrase from the user. */ - grub_printf ("Enter passphrase for %s (%s): ", name, dev->uuid); + tmp = NULL; + if (source->partition) + tmp = grub_partition_get_name (source->partition); + grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name, + source->partition ? "," : "", tmp ? : "", + dev->uuid); + grub_free (tmp); if (!grub_password_get (passphrase, MAX_PASSPHRASE)) { grub_free (split_key); @@ -323,12 +343,14 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, } /* Try to recover master key from each active keyslot. */ - for (i = 0; i < ARRAY_SIZE (header->keyblock); i++) + for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) { gcry_err_code_t gcry_err; + grub_uint8_t candidate_key[keysize]; + grub_uint8_t digest[keysize]; /* Check if keyslot is enabled. */ - if (grub_be_to_cpu32 (header->keyblock[i].active) != LUKS_KEY_ENABLED) + if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) continue; grub_dprintf ("luks", "Trying keyslot %d\n", i); @@ -336,9 +358,9 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, /* Calculate the PBKDF2 of the user supplied passphrase. */ gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, grub_strlen (passphrase), - header->keyblock[i].passwordSalt, - sizeof (header->keyblock[i].passwordSalt), - grub_be_to_cpu32 (header->keyblock[i]. + header.keyblock[i].passwordSalt, + sizeof (header.keyblock[i].passwordSalt), + grub_be_to_cpu32 (header.keyblock[i]. passwordIterations), digest, keysize); @@ -357,11 +379,11 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, return grub_crypto_gcry_error (gcry_err); } - length = (keysize * grub_be_to_cpu32 (header->keyblock[i].stripes)); + length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes)); /* Read and decrypt the key material from the disk. */ err = grub_disk_read (source, - grub_be_to_cpu32 (header->keyblock + grub_be_to_cpu32 (header.keyblock [i].keyMaterialOffset), 0, length, split_key); if (err) @@ -379,7 +401,7 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, /* Merge the decrypted key material to get the candidate master key. */ gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize, - grub_be_to_cpu32 (header->keyblock[i].stripes)); + grub_be_to_cpu32 (header.keyblock[i].stripes)); if (gcry_err) { grub_free (split_key); @@ -390,11 +412,11 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, /* Calculate the PBKDF2 of the candidate master key. */ gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key, - grub_be_to_cpu32 (header->keyBytes), - header->mkDigestSalt, - sizeof (header->mkDigestSalt), + grub_be_to_cpu32 (header.keyBytes), + header.mkDigestSalt, + sizeof (header.mkDigestSalt), grub_be_to_cpu32 - (header->mkDigestIterations), + (header.mkDigestIterations), candidate_digest, sizeof (candidate_digest)); if (gcry_err) @@ -405,8 +427,8 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, /* Compare the calculated PBKDF2 to the digest stored in the header to see if it's correct. */ - if (grub_memcmp (candidate_digest, header->mkDigest, - sizeof (header->mkDigest)) != 0) + if (grub_memcmp (candidate_digest, header.mkDigest, + sizeof (header.mkDigest)) != 0) { grub_dprintf ("luks", "bad digest\n"); continue; @@ -430,204 +452,19 @@ luks_recover_key (grub_cryptodisk_t dev, const struct grub_luks_phdr *header, return GRUB_ACCESS_DENIED; } -static void -luks_close (grub_cryptodisk_t luks) -{ - grub_crypto_cipher_close (luks->cipher); - grub_crypto_cipher_close (luks->secondary_cipher); - grub_crypto_cipher_close (luks->essiv_cipher); - grub_free (luks); -} - -static grub_err_t -grub_luks_scan_device_real (const char *name, grub_disk_t source) -{ - grub_err_t err; - struct grub_luks_phdr header; - grub_cryptodisk_t newdev, dev; - - dev = grub_cryptodisk_get_by_source_disk (source); - - if (dev) - return GRUB_ERR_NONE; - - /* Read the LUKS header. */ - err = grub_disk_read (source, 0, 0, sizeof (header), &header); - if (err) - return err; - - newdev = configure_ciphers (&header); - if (!newdev) - return grub_errno; - - newdev->total_length = grub_disk_get_size (source) - newdev->offset; - - err = luks_recover_key (newdev, &header, name, source); - if (err) - { - luks_close (newdev); - return err; - } - - grub_cryptodisk_insert (newdev, name, source); - - have_it = 1; - - return GRUB_ERR_NONE; -} - -#ifdef GRUB_UTIL -grub_err_t -grub_luks_cheat_mount (const char *sourcedev, const char *cheat) -{ - grub_err_t err; - struct grub_luks_phdr header; - grub_cryptodisk_t newdev, dev; - grub_disk_t source; - - /* Try to open disk. */ - source = grub_disk_open (sourcedev); - if (!source) - return grub_errno; - - dev = grub_cryptodisk_get_by_source_disk (source); - - if (dev) - { - grub_disk_close (source); - return GRUB_ERR_NONE; - } - - /* Read the LUKS header. */ - err = grub_disk_read (source, 0, 0, sizeof (header), &header); - if (err) - return err; - - newdev = configure_ciphers (&header); - if (!newdev) - { - grub_disk_close (source); - return grub_errno; - } - - newdev->total_length = grub_disk_get_size (source) - newdev->offset; - - err = grub_cryptodisk_cheat_insert (newdev, sourcedev, source, cheat); - grub_disk_close (source); - if (err) - grub_free (newdev); - - return err; -} -#endif - -static int -grub_luks_scan_device (const char *name) -{ - grub_err_t err; - grub_disk_t source; - - /* Try to open disk. */ - source = grub_disk_open (name); - if (!source) - return grub_errno; - - err = grub_luks_scan_device_real (name, source); - - grub_disk_close (source); - - if (err) - grub_print_error (); - return have_it && check_uuid ? 0 : 1; -} - -#ifdef GRUB_UTIL - -void -grub_util_luks_print_uuid (grub_disk_t disk) -{ - grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - grub_printf ("%s ", dev->uuid); -} -#endif - -static grub_err_t -grub_cmd_luksmount (grub_extcmd_context_t ctxt, int argc, char **args) -{ - struct grub_arg_list *state = ctxt->state; - - if (argc < 1 && !state[1].set) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); - - have_it = 0; - if (state[0].set) - { - grub_cryptodisk_t dev; - - dev = grub_cryptodisk_get_by_uuid (args[0]); - if (dev) - { - grub_dprintf ("luks", "already mounted as crypto%lu\n", dev->id); - return GRUB_ERR_NONE; - } - - check_uuid = 1; - search_uuid = args[0]; - grub_device_iterate (&grub_luks_scan_device); - search_uuid = NULL; - - if (!have_it) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such luks found"); - return GRUB_ERR_NONE; - } - else if (state[1].set) - { - check_uuid = 0; - search_uuid = NULL; - grub_device_iterate (&grub_luks_scan_device); - search_uuid = NULL; - return GRUB_ERR_NONE; - } - else - { - grub_err_t err; - grub_disk_t disk; - grub_cryptodisk_t dev; - - check_uuid = 0; - search_uuid = NULL; - disk = grub_disk_open (args[0]); - if (!disk) - return grub_errno; - - dev = grub_cryptodisk_get_by_source_disk (disk); - if (dev) - { - grub_dprintf ("luks", "already mounted as luks%lu\n", dev->id); - grub_disk_close (disk); - return GRUB_ERR_NONE; - } - - err = grub_luks_scan_device_real (args[0], disk); - - grub_disk_close (disk); - - return err; - } -} - -static grub_extcmd_t cmd; +struct grub_cryptodisk_dev luks_crypto = { + .scan = configure_ciphers, + .recover_key = luks_recover_key +}; GRUB_MOD_INIT (luks) { COMPILE_TIME_ASSERT (sizeof (((struct grub_luks_phdr *) 0)->uuid) < GRUB_CRYPTODISK_MAX_UUID_LENGTH); - cmd = grub_register_extcmd ("luksmount", grub_cmd_luksmount, 0, - N_("SOURCE|-u UUID|-a"), - N_("Mount a LUKS device."), options); + grub_cryptodisk_dev_register (&luks_crypto); } GRUB_MOD_FINI (luks) { - grub_unregister_extcmd (cmd); + grub_cryptodisk_dev_unregister (&luks_crypto); } diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index 642d77cf0..b6e8a673f 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef HAVE_DEVICE_MAPPER # include @@ -756,6 +757,94 @@ grub_util_get_dm_abstraction (const char *os_dev) #endif } +#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) +#include + +/* FIXME: geom actually gives us the whole container hierarchy. + It can be used more efficiently than this. */ +void +grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out) +{ + struct gmesh mesh; + struct gclass *class; + int error; + struct ggeom *geom; + + grub_util_info ("following geom '%s'", name); + + error = geom_gettree (&mesh); + if (error != 0) + grub_util_error ("couldn't open geom"); + + LIST_FOREACH (class, &mesh.lg_class, lg_class) + if (strcasecmp (class->lg_name, "part") == 0) + break; + if (!class) + grub_util_error ("couldn't open geom part"); + + LIST_FOREACH (geom, &class->lg_geom, lg_geom) + { + struct gprovider *provider; + LIST_FOREACH (provider, &geom->lg_provider, lg_provider) + if (strcmp (provider->lg_name, name) == 0) + { + char *name_tmp = xstrdup (geom->lg_name); + grub_disk_addr_t off = 0; + struct gconfig *config; + grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name); + + grub_util_follow_gpart_up (name_tmp, &off, name_out); + free (name_tmp); + LIST_FOREACH (config, &provider->lg_config, lg_config) + if (strcasecmp (config->lg_name, "start") == 0) + off += strtoull (config->lg_val, 0, 10); + if (off_out) + *off_out = off; + return; + } + } + grub_util_info ("geom '%s' has no parent", name); + if (name_out) + *name_out = xstrdup (name); + if (off_out) + *off_out = 0; +} + +static const char * +grub_util_get_geom_abstraction (const char *dev) +{ + char *whole; + struct gmesh mesh; + struct gclass *class; + const char *name; + int error; + + if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0) + return 0; + name = dev + sizeof ("/dev/") - 1; + grub_util_follow_gpart_up (name, NULL, &whole); + + grub_util_info ("following geom '%s'", name); + + error = geom_gettree (&mesh); + if (error != 0) + grub_util_error ("couldn't open geom"); + + LIST_FOREACH (class, &mesh.lg_class, lg_class) + { + struct ggeom *geom; + LIST_FOREACH (geom, &class->lg_geom, lg_geom) + { + struct gprovider *provider; + LIST_FOREACH (provider, &geom->lg_provider, lg_provider) + if (strcmp (provider->lg_name, name) == 0) + return class->lg_name; + } + } + return NULL; +} +#endif + int grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) { @@ -777,6 +866,14 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) return GRUB_DEV_ABSTRACTION_RAID; #endif +#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) + const char *abs; + abs = grub_util_get_geom_abstraction (os_dev); + grub_util_info ("abstraction of %s is %s", os_dev, abs); + if (abs && grub_strcasecmp (abs, "eli") == 0) + return GRUB_DEV_ABSTRACTION_GELI; +#endif + /* No abstraction found. */ return GRUB_DEV_ABSTRACTION_NONE; } @@ -869,6 +966,71 @@ grub_util_pull_device (const char *os_dev) ab = grub_util_get_dev_abstraction (os_dev); switch (ab) { + case GRUB_DEV_ABSTRACTION_GELI: + { + char *whole; + struct gmesh mesh; + struct gclass *class; + const char *name; + int error; + char *lastsubdev = NULL; + + if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) + return; + name = os_dev + sizeof ("/dev/") - 1; + grub_util_follow_gpart_up (name, NULL, &whole); + + grub_util_info ("following geom '%s'", name); + + error = geom_gettree (&mesh); + if (error != 0) + grub_util_error ("couldn't open geom"); + + LIST_FOREACH (class, &mesh.lg_class, lg_class) + { + struct ggeom *geom; + LIST_FOREACH (geom, &class->lg_geom, lg_geom) + { + struct gprovider *provider; + LIST_FOREACH (provider, &geom->lg_provider, lg_provider) + if (strcmp (provider->lg_name, name) == 0) + { + struct gconsumer *consumer; + char *fname; + char *uuid; + + LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer) + break; + if (!consumer) + grub_util_error ("couldn't find geli consumer"); + fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name); + grub_util_info ("consumer %s", consumer->lg_provider->lg_name); + lastsubdev = consumer->lg_provider->lg_name; + grub_util_pull_device (fname); + free (fname); + } + } + } + if (ab == GRUB_DEV_ABSTRACTION_GELI && lastsubdev) + { + char *fname = xasprintf ("/dev/%s", lastsubdev); + char *grdev = grub_util_get_grub_dev (fname); + free (fname); + + if (grdev) + { + grub_err_t err; + err = grub_cryptodisk_cheat_mount (grdev, os_dev); + if (err) + grub_util_error ("Can't mount crypto: %s", grub_errmsg); + } + + grub_free (grdev); + } + + } + break; + case GRUB_DEV_ABSTRACTION_LVM: case GRUB_DEV_ABSTRACTION_LUKS: #ifdef HAVE_DEVICE_MAPPER @@ -895,7 +1057,7 @@ grub_util_pull_device (const char *os_dev) grub_util_pull_device (subdev); } } - if (ab == GRUB_DEV_ABSTRACTION_LUKS && lastsubdev) + if (ab == GRUB_DEV_ABSTRACTION_CRYPTO && lastsubdev) { char *grdev = grub_util_get_grub_dev (lastsubdev); dm_tree_free (tree); @@ -904,7 +1066,7 @@ grub_util_pull_device (const char *os_dev) grub_err_t err; err = grub_luks_cheat_mount (grdev, os_dev); if (err) - grub_util_error ("Can't mount LUKS: %s", grub_errmsg); + grub_util_error ("Can't mount crypto: %s", grub_errmsg); } grub_free (grdev); } @@ -959,6 +1121,8 @@ grub_util_get_grub_dev (const char *os_dev) { char *uuid, *dash; uuid = get_dm_uuid (os_dev); + if (!uuid) + break; dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-'); if (dash) *dash = 0; @@ -968,6 +1132,55 @@ grub_util_get_grub_dev (const char *os_dev) } break; + case GRUB_DEV_ABSTRACTION_GELI: + { + char *whole; + struct gmesh mesh; + struct gclass *class; + const char *name; + int error; + + if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) + return 0; + name = os_dev + sizeof ("/dev/") - 1; + grub_util_follow_gpart_up (name, NULL, &whole); + + grub_util_info ("following geom '%s'", name); + + error = geom_gettree (&mesh); + if (error != 0) + grub_util_error ("couldn't open geom"); + + LIST_FOREACH (class, &mesh.lg_class, lg_class) + { + struct ggeom *geom; + LIST_FOREACH (geom, &class->lg_geom, lg_geom) + { + struct gprovider *provider; + LIST_FOREACH (provider, &geom->lg_provider, lg_provider) + if (strcmp (provider->lg_name, name) == 0) + { + struct gconsumer *consumer; + char *fname; + char *uuid; + + LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer) + break; + if (!consumer) + grub_util_error ("couldn't find geli consumer"); + fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name); + uuid = grub_util_get_geli_uuid (fname); + if (!uuid) + grub_util_error ("couldn't retrieve geli UUID"); + grub_dev = xasprintf ("cryptouuid/%s", uuid); + free (fname); + free (uuid); + } + } + } + } + break; + case GRUB_DEV_ABSTRACTION_RAID: if (os_dev[7] == '_' && os_dev[8] == 'd') diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 97e090222..6cace3746 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -106,9 +106,7 @@ struct hd_geometry # include #endif -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#include -#elif defined(__NetBSD__) +#if defined(__NetBSD__) # define HAVE_DIOCGDINFO # include # include /* struct disklabel */ @@ -226,6 +224,82 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), return 0; } +#if !defined(__MINGW32__) +grub_uint64_t +grub_util_get_fd_sectors (int fd, unsigned *log_secsize) +{ +#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) +# if defined(__NetBSD__) + struct disklabel label; +# else + unsigned long long nr; +# endif + unsigned sector_size, log_sector_size; + struct stat st; + + if (fstat (fd, &st) < 0) + grub_util_error ("fstat failed"); + +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) + if (! S_ISCHR (st.st_mode)) +# else + if (! S_ISBLK (st.st_mode)) +# endif + goto fail; + +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + if (ioctl (fd, DIOCGMEDIASIZE, &nr)) +# elif defined(__APPLE__) + if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr)) +# elif defined(__NetBSD__) + configure_device_driver (fd); + if (ioctl (fd, DIOCGDINFO, &label) == -1) +# else + if (ioctl (fd, BLKGETSIZE64, &nr)) +# endif + goto fail; + +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + if (ioctl (fd, DIOCGSECTORSIZE, §or_size)) +# else + if (ioctl (fd, BLKSSZGET, §or_size)) +# endif + goto fail; + + if (sector_size & (sector_size - 1) || !sector_size) + goto fail; + for (log_sector_size = 0; + (1 << log_sector_size) < sector_size; + log_sector_size++); + + if (log_secsize) + *log_secsize = log_sector_size; + +# if defined (__APPLE__) + return nr; +# elif defined(__NetBSD__) + return label.d_secperunit; +# else + if (nr & ((1 << log_sector_size) - 1)) + grub_util_error ("unaligned device size"); + + return (nr >> log_sector_size); +# endif + + fail: + /* In GNU/Hurd, stat() will return the right size. */ +#elif !defined (__GNU__) +# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." +#endif + + if (log_secsize) + *log_secsize = 9; + + return st.st_size >> 9; +} +#endif + static grub_err_t grub_util_biosdisk_open (const char *name, grub_disk_t disk, grub_disk_pull_t pull __attribute__ ((unused))) @@ -262,90 +336,30 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk, return GRUB_ERR_NONE; } -#elif defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) +#else { -# if defined(__NetBSD__) - struct disklabel label; -# else - unsigned long long nr; -# endif - int sector_size; int fd; fd = open (map[drive].device, O_RDONLY); if (fd == -1) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device); + disk->total_sectors = grub_util_get_fd_sectors (fd, &disk->log_sector_size); + # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) # else if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode)) # endif - { - close (fd); - goto fail; - } - data->is_disk = 1; - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (ioctl (fd, DIOCGMEDIASIZE, &nr)) -# elif defined(__APPLE__) - if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr)) -# elif defined(__NetBSD__) - configure_device_driver (fd); - if (ioctl (fd, DIOCGDINFO, &label) == -1) -# else - if (ioctl (fd, BLKGETSIZE64, &nr)) -# endif - { - close (fd); - goto fail; - } - - if (ioctl (fd, BLKSSZGET, §or_size)) - { - close (fd); - goto fail; - } + data->is_disk = 1; close (fd); - if (sector_size & (sector_size - 1) || !sector_size) - goto fail; - for (disk->log_sector_size = 0; - (1 << disk->log_sector_size) < sector_size; - disk->log_sector_size++); - -# if defined (__APPLE__) - disk->total_sectors = nr; -# elif defined(__NetBSD__) - disk->total_sectors = label.d_secperunit; -# else - disk->total_sectors = nr >> disk->log_sector_size; - - if (nr & ((1 << disk->log_sector_size) - 1)) - grub_util_error ("unaligned device size"); -# endif - grub_util_info ("the size of %s is %llu", name, disk->total_sectors); return GRUB_ERR_NONE; } - - fail: - /* In GNU/Hurd, stat() will return the right size. */ -#elif !defined (__GNU__) -# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." #endif - if (stat (map[drive].device, &st) < 0) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot stat `%s'", map[drive].device); - - disk->total_sectors = st.st_size >> disk->log_sector_size; - - grub_util_info ("the size of %s is %lu", name, disk->total_sectors); - - return GRUB_ERR_NONE; } int @@ -367,55 +381,6 @@ grub_util_device_is_mapped (const char *dev) } #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) -/* FIXME: geom actually gives us the whole container hierarchy. - It can be used more efficiently than this. */ -static void -follow_geom_up (const char *name, grub_disk_addr_t *off_out, char **name_out) -{ - struct gmesh mesh; - struct gclass *class; - int error; - struct ggeom *geom; - - grub_util_info ("following geom '%s'", name); - - error = geom_gettree (&mesh); - if (error != 0) - grub_util_error ("couldn't open geom"); - - LIST_FOREACH (class, &mesh.lg_class, lg_class) - if (strcasecmp (class->lg_name, "part") == 0) - break; - if (!class) - grub_util_error ("couldn't open geom part"); - - LIST_FOREACH (geom, &class->lg_geom, lg_geom) - { - struct gprovider *provider; - LIST_FOREACH (provider, &geom->lg_provider, lg_provider) - if (strcmp (provider->lg_name, name) == 0) - { - char *name_tmp = xstrdup (geom->lg_name); - grub_disk_addr_t off = 0; - struct gconfig *config; - grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name); - - follow_geom_up (name_tmp, &off, name_out); - free (name_tmp); - LIST_FOREACH (config, &provider->lg_config, lg_config) - if (strcasecmp (config->lg_name, "start") == 0) - off += strtoull (config->lg_val, 0, 10); - if (off_out) - *off_out = off; - return; - } - } - grub_util_info ("geom '%s' has no parent", name); - if (name_out) - *name_out = xstrdup (name); - if (off_out) - *off_out = 0; -} static grub_disk_addr_t find_partition_start (const char *dev) @@ -423,10 +388,11 @@ find_partition_start (const char *dev) grub_disk_addr_t out; if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0) return 0; - follow_geom_up (dev + sizeof ("/dev/") - 1, &out, NULL); + grub_util_follow_gpart_up (dev + sizeof ("/dev/") - 1, &out, NULL); return out; } + #elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) static grub_disk_addr_t find_partition_start (const char *dev) @@ -1508,7 +1474,7 @@ devmapper_out: char *out, *out2; if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) return xstrdup (os_dev); - follow_geom_up (os_dev + sizeof ("/dev/") - 1, NULL, &out); + grub_util_follow_gpart_up (os_dev + sizeof ("/dev/") - 1, NULL, &out); out2 = xasprintf ("/dev/%s", out); free (out); @@ -1667,6 +1633,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) struct stat st; int drive; + grub_util_info ("Looking for %s", os_dev); + if (stat (os_dev, &st) < 0) { grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev); diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index 169fb119d..c6d1ce8de 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -21,6 +21,7 @@ #include #include +#include typedef enum { @@ -57,6 +58,8 @@ typedef gcry_err_code_t struct grub_cryptodisk { + struct grub_cryptodisk *next; + char *source; grub_disk_addr_t offset; grub_disk_addr_t total_length; @@ -78,6 +81,7 @@ struct grub_cryptodisk grub_size_t iv_prefix_len; #ifdef GRUB_UTIL char *cheat; + const char *modname; int cheat_fd; #endif int log_sector_size; @@ -86,10 +90,37 @@ struct grub_cryptodisk grub_uint8_t rekey_key[64]; grub_uint64_t last_rekey; int rekey_derived_size; - struct grub_cryptodisk *next; }; typedef struct grub_cryptodisk *grub_cryptodisk_t; +struct grub_cryptodisk_dev +{ + struct grub_cryptodisk_dev *next; + + grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid, + int boot_only); + grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev); +}; +typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t; + +extern grub_cryptodisk_dev_t EXPORT_VAR (grub_cryptodisk_list); + +#ifndef GRUB_LST_GENERATOR +static inline void +grub_cryptodisk_dev_register (grub_cryptodisk_dev_t cr) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_cryptodisk_list), GRUB_AS_LIST (cr)); +} +#endif + +static inline void +grub_cryptodisk_dev_unregister (grub_cryptodisk_dev_t cr) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_cryptodisk_list), GRUB_AS_LIST (cr)); +} + +#define FOR_CRYPTODISK_DEVS(var) FOR_LIST_ELEMENTS((var), (grub_cryptodisk_list)) + gcry_err_code_t grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize); @@ -106,6 +137,8 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, grub_disk_t source, const char *cheat); void grub_util_cryptodisk_print_abstraction (grub_disk_t disk); +char * +grub_util_get_geli_uuid (const char *dev); #endif grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid); diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index 57cd911ef..6921e567c 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -26,6 +26,7 @@ enum grub_dev_abstraction_types { GRUB_DEV_ABSTRACTION_LVM, GRUB_DEV_ABSTRACTION_RAID, GRUB_DEV_ABSTRACTION_LUKS, + GRUB_DEV_ABSTRACTION_GELI, }; char *grub_find_device (const char *dir, dev_t dev); @@ -38,5 +39,9 @@ const char *grub_util_check_char_device (const char *blk_dev); #ifdef __linux__ char **grub_util_raid_getmembers (const char *name, int bootable); #endif +#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) +void grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, + char **name_out); +#endif #endif /* ! GRUB_UTIL_GETROOT_HEADER */ diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 18191c4eb..719faa29b 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -35,7 +35,11 @@ grub_err_t grub_util_fd_seek (int fd, const char *name, grub_uint64_t sector); ssize_t grub_util_fd_read (int fd, char *buf, size_t len); grub_err_t -grub_luks_cheat_mount (const char *sourcedev, const char *cheat); -void grub_util_luks_print_uuid (grub_disk_t disk); +grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat); +void grub_util_cryptodisk_print_uuid (grub_disk_t disk); +#if !defined(__MINGW32__) +grub_uint64_t +grub_util_get_fd_sectors (int fd, unsigned *log_secsize); +#endif #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 48a5be1ca..f5880626c 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -309,10 +309,8 @@ fstest (int n, char **args) char *argv[2] = { "-a", NULL}; if (mount_crypt) { - if (execute_command ("luksmount", 1, argv)) - grub_util_error (_("luksmount command fails: %s"), grub_errmsg); - if (execute_command ("gelimount", 1, argv)) - grub_util_error (_("gelimount command fails: %s"), grub_errmsg); + if (execute_command ("cryptomount", 1, argv)) + grub_util_error (_("cryptomount command fails: %s"), grub_errmsg); } } diff --git a/util/grub-install.in b/util/grub-install.in index 3b3383ab4..049444e93 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -538,9 +538,9 @@ if [ "x${devabstraction_module}" = "x" ] ; then exit 1 fi - if [ x$GRUB_LUKS_ENABLE = xy ]; then - for uuid in "`"${grub_probe}" --device "${device}" --target=luks_uuid`"; do - echo "luksmount -u $uuid" + if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then + for uuid in "`"${grub_probe}" --device "${device}" --target=cryptodisk_uuid`"; do + echo "cryptomount -u $uuid" done fi diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 41e68bc1b..ade7a558d 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -254,7 +254,7 @@ export GRUB_DEFAULT \ GRUB_DISABLE_OS_PROBER \ GRUB_INIT_TUNE \ GRUB_SAVEDEFAULT \ - GRUB_ENABLE_LUKS \ + GRUB_ENABLE_CRYPTODISK \ GRUB_BADRAM if test "x${grub_cfg}" != "x"; then diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 1664b6bbe..33ee7e432 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -69,12 +69,12 @@ is_path_readable_by_grub () return 1 fi - if [ x$GRUB_LUKS_ENABLE = xy ]; then + if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then return 0 fi for abstraction in $abstractions; do - if [ "x$abstraction" = xluks ]; then + if [ "x$abstraction" = xcryptodisk ]; then return 1 fi done @@ -138,9 +138,9 @@ prepare_grub_to_access_device () echo "insmod ${module}" done - if [ x$GRUB_LUKS_ENABLE = xy ]; then - for uuid in "`"${grub_probe}" --device "${device}" --target=luks_uuid`"; do - echo "luksmount -u $uuid" + if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then + for uuid in "`"${grub_probe}" --device "${device}" --target=cryptodisk_uuid`"; do + echo "cryptomount -u $uuid" done fi diff --git a/util/grub-probe.c b/util/grub-probe.c index f5d93ac4e..7c0a75123 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -56,7 +56,7 @@ enum { PRINT_DEVICE, PRINT_PARTMAP, PRINT_ABSTRACTION, - PRINT_LUKS_UUID + PRINT_CRYPTODISK_UUID }; int print = PRINT_FS; @@ -91,7 +91,7 @@ probe_partmap (grub_disk_t disk) } static void -probe_luks_uuid (grub_disk_t disk) +probe_cryptodisk_uuid (grub_disk_t disk) { grub_disk_memberlist_t list = NULL, tmp; @@ -102,14 +102,13 @@ probe_luks_uuid (grub_disk_t disk) } while (list) { - probe_luks_uuid (list->disk); + probe_cryptodisk_uuid (list->disk); tmp = list->next; free (list); list = tmp; } - /* FIXME: support non-LUKS. */ if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) - grub_util_luks_print_uuid (disk); + grub_util_cryptodisk_print_uuid (disk); } static int @@ -215,9 +214,9 @@ probe (const char *path, char *device_name) goto end; } - if (print == PRINT_LUKS_UUID) + if (print == PRINT_CRYPTODISK_UUID) { - probe_luks_uuid (dev->disk); + probe_cryptodisk_uuid (dev->disk); printf ("\n"); goto end; } @@ -295,8 +294,8 @@ Probe device information for a given path (or device, if the -d option is given) \n\ -d, --device given argument is a system device, not a path\n\ -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|luks_uuid)\n\ - print filesystem module, GRUB drive, system device, partition map module, abstraction module or LUKS UUID [default=fs]\n\ + -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|cryptodisk_uuid)\n\ + print filesystem module, GRUB drive, system device, partition map module, abstraction module or CRYPTO UUID [default=fs]\n\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ @@ -354,8 +353,8 @@ main (int argc, char *argv[]) print = PRINT_PARTMAP; else if (!strcmp (optarg, "abstraction")) print = PRINT_ABSTRACTION; - else if (!strcmp (optarg, "luks_uuid")) - print = PRINT_LUKS_UUID; + else if (!strcmp (optarg, "cryptodisk_uuid")) + print = PRINT_CRYPTODISK_UUID; else usage (1); break; From c5934345bea4070e56813c4064645240ff902f4a Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Fri, 6 May 2011 14:03:51 -0300 Subject: [PATCH 161/673] Free memory when removing packet. --- include/grub/net.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grub/net.h b/include/grub/net.h index 37b258f36..59974b94f 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -178,6 +178,7 @@ grub_net_remove_packet (grub_net_packet_t *pkt) pkt->next->prev = pkt->prev; else pkt->up->last = pkt->prev; + grub_free (pkt); } typedef struct grub_net_app_protocol *grub_net_app_level_t; From 4f7386025b3bc0e5da39e79062aaef02a924a86a Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:28:45 -0300 Subject: [PATCH 162/673] Correct expected argument numbers in del addr command. --- grub-core/net/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 636aaefaf..48fb350d2 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -200,7 +200,7 @@ grub_cmd_deladdr (struct grub_command *cmd __attribute__ ((unused)), { struct grub_net_network_level_interface *inter; - if (argc != 4) + if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) From 1893017d440b967cb977888ad1fbc4f4cf2df9a4 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:30:26 -0300 Subject: [PATCH 163/673] Mark file as not easily seekable on net open. --- grub-core/net/net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 48fb350d2..cdeaa5a32 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -609,6 +609,7 @@ grub_net_file_open_real (struct grub_file *file, const char *name) if ((err = file->device->net->protocol->open (file,name))) goto fail; + file->not_easily_seekable = 1; return GRUB_ERR_NONE; fail: From 4d6374ba7855abc9726d838258ec8093bc1238f1 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:32:38 -0300 Subject: [PATCH 164/673] Implement file close in network tranference. Stop receiving packets from card on error. --- grub-core/kern/file.c | 8 ++++++-- grub-core/net/net.c | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 6e7ed0e57..2b3e9d689 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -27,6 +27,7 @@ grub_ssize_t (*grub_file_net_read) (grub_file_t file, void *buf, grub_size_t len) = NULL; grub_err_t (*grub_file_net_open) (struct grub_file *file, const char *name) = NULL; +grub_err_t (*grub_file_net_close) (grub_file_t file) = NULL; grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; @@ -176,8 +177,11 @@ grub_err_t grub_file_close (grub_file_t file) { if (file->device->net) - return grub_errno; - + { + grub_file_net_close (file); + return grub_errno; + } + if (file->fs->close) (file->fs->close) (file); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index cdeaa5a32..6ccf20725 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -619,18 +619,35 @@ fail: } +static grub_err_t +grub_net_file_close_real (grub_file_t file) +{ + grub_net_socket_t sock = file->device->net->socket; + while (sock->packs->first) + { + grub_netbuff_free (sock->packs->first->nb); + grub_net_remove_packet (sock->packs->first); + } + grub_net_socket_unregister (sock); + grub_free (sock); + return GRUB_ERR_NONE; + +} + static grub_err_t receive_packets (struct grub_net_card *card) { /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; + grub_err_t err; nb = grub_netbuff_alloc (1500); if (!nb) return grub_errno; - card->driver->recv (card, nb); - return GRUB_ERR_NONE; + if ((err = card->driver->recv (card, nb)) != GRUB_ERR_NONE) + grub_netbuff_free (nb); + return err; } void @@ -642,7 +659,8 @@ grub_net_pool_cards (unsigned time) { start_time = grub_get_time_ms (); while( (grub_get_time_ms () - start_time) < time) - receive_packets (card); + if( receive_packets (card) != GRUB_ERR_NONE) + break; } } @@ -1018,6 +1036,7 @@ GRUB_MOD_INIT(net) grub_net_open = grub_net_open_real; grub_file_net_open = grub_net_file_open_real; + grub_file_net_close = grub_net_file_close_real; grub_file_net_read = grub_net_read_real; grub_file_net_seek = grub_net_seek_real; } @@ -1034,4 +1053,5 @@ GRUB_MOD_FINI(net) grub_net_open = NULL; grub_file_net_read = NULL; grub_file_net_open = NULL; + grub_file_net_close = NULL; } From a5184d629a4411f8c74eeb1b244523ddddf1512e Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:45:57 -0300 Subject: [PATCH 165/673] Prevente a bootp packet to be sent on open. --- grub-core/net/drivers/ieee1275/ofnet.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 10de81bc7..ce7ab32a8 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,17 +1,23 @@ #include #include #include +#include #include +#include static grub_err_t card_open (struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; - status = grub_ieee1275_open (data->path,&(data->handle)); + char path[grub_strlen(data->path) + grub_strlen(":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; + /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */ + grub_snprintf(path,sizeof(path),"%s%s",data->path,":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); + status = grub_ieee1275_open (path,&(data->handle)); if (status) - return grub_error (GRUB_ERR_IO, "couldn't open network card"); + return grub_error (GRUB_ERR_IO, "Couldn't open network card."); + return GRUB_ERR_NONE; } From 0f231af8ae44b6e4efe6b25794db21fbfd270718 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:50:18 -0300 Subject: [PATCH 166/673] Implement timeout when receiving packets. --- grub-core/net/drivers/ieee1275/ofnet.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index ce7ab32a8..a7b66261c 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -42,24 +42,29 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) pack->tail - pack->data, &actual); if (status) - return grub_error (GRUB_ERR_IO, "couldn't send network packet"); + return grub_error (GRUB_ERR_IO, "Couldn't send network packet."); return GRUB_ERR_NONE; } static grub_err_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack) +get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) { int actual, rc; struct grub_ofnetcard_data *data = dev->data; - grub_netbuff_clear(pack); + grub_uint64_t start_time; + grub_netbuff_clear (nb); + start_time = grub_get_time_ms (); do - rc = grub_ieee1275_read (data->handle, pack->data, 1500, &actual); - while (actual <= 0 || rc < 0); - grub_netbuff_put (pack, actual); - - return GRUB_ERR_NONE; + rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual); + while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); + if (actual) + { + grub_netbuff_put (nb, actual); + return grub_net_recv_ethernet_packet (nb); + } + return GRUB_ERR_TIMEOUT; } static struct grub_net_card_driver ofdriver = From 70c52f3e248a67ad809c1309095b59cfff9d6628 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:54:32 -0300 Subject: [PATCH 167/673] Remove cards with no associated driver. --- grub-core/net/drivers/ieee1275/ofnet.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index a7b66261c..e33622fe2 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -148,10 +148,12 @@ void grub_ofnet_findcards (void) lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; card->default_address = lla; + card->driver = NULL; card->data = ofdata; card->flags = 0; card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); - grub_net_card_register (card); + grub_net_card_register (card); + return 0; } return 0; } @@ -192,19 +194,24 @@ void grub_ofnet_probecards (void) net.ipv4.masksize = 24; grub_net_add_route ("bootp-router", net, inter); } - grub_free (bootp_pckt); break; - } + } } } + grub_free (bootp_pckt); + } GRUB_MOD_INIT (ofnet) { + struct grub_net_card *card; grub_getbootp = grub_getbootp_real; grub_net_card_driver_register (&ofdriver); grub_ofnet_findcards (); grub_ofnet_probecards (); + FOR_NET_CARDS (card) + if (card->driver == NULL) + grub_net_card_unregister (card); } GRUB_MOD_FINI (ofnet) From 36e2782dba154140c30ba77dabf67cea2df02719 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 09:55:20 -0300 Subject: [PATCH 168/673] Only setup network in the card we booted from. --- grub-core/net/drivers/ieee1275/ofnet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index e33622fe2..4067e36cf 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -171,6 +171,7 @@ void grub_ofnet_probecards (void) grub_bootp_t bootp_pckt; grub_net_network_level_address_t addr; grub_net_network_level_netaddress_t net; + bootp_pckt = grub_getbootp (); /* Assign correspondent driver for each device. */ FOR_NET_CARDS (card) @@ -180,8 +181,7 @@ void grub_ofnet_probecards (void) if (driver->init(card) == GRUB_ERR_NONE) { card->driver = driver; - bootp_pckt = grub_getbootp (); - if (bootp_pckt) + if (bootp_pckt && grub_memcmp(bootp_pckt->chaddr,card->default_address.mac,6) == 0) { addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bootp_pckt->yiaddr; From 0696f08f9238087edf5c1f1b91779f7515e7aeb5 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 14:07:20 -0300 Subject: [PATCH 169/673] Prevente error in broken cards by limiting data size. --- grub-core/net/tftp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index cafb30585..6cc281085 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -126,8 +126,12 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { data->block++; - if (nb->tail - nb->data < 1024) + unsigned size = nb->tail - nb->data; + if (size < 1024) sock->status = 2; + /* Prevent garbage in broken cards. */ + if (size > 1024) + grub_netbuff_unput (nb, size - 1024); } else grub_netbuff_clear(nb); From 31b5172bbd3cfa83f0cd9d83fce18a21e2796048 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 14:07:54 -0300 Subject: [PATCH 170/673] Implement close in TFTP --- grub-core/net/tftp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 6cc281085..13bd87d15 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -157,7 +157,8 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) static grub_err_t tftp_close (struct grub_file *file __attribute__ ((unused))) { - return 0; + grub_free (file->device->net->socket->data); + return GRUB_ERR_NONE; } static struct grub_net_app_protocol grub_tftp_protocol = From 8db3b0eca9704c93fde8e1b0d41741f2299cb2b3 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 10 May 2011 14:08:18 -0300 Subject: [PATCH 171/673] Remove unused file --- include/grub/net/disknet.h | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 include/grub/net/disknet.h diff --git a/include/grub/net/disknet.h b/include/grub/net/disknet.h deleted file mode 100644 index 59aa2a320..000000000 --- a/include/grub/net/disknet.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef GRUB_DISKNET_HEADER -#define GRUB_DISKNET_HEADER 1 - void grub_disknet_init(void); - void grub_disknet_fini(void); -#endif /* ! GRUB_NET_HEADER */ From d8123bfb54e92aff473edaac87b535cb81e1f778 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 12 May 2011 13:20:43 -0300 Subject: [PATCH 172/673] Correct some compile erros. --- grub-core/Makefile.core.def | 2 +- grub-core/kern/ieee1275/openfw.c | 1 - grub-core/net/drivers/ieee1275/ofnet.c | 1 + include/grub/net.h | 4 +--- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index e242d8ece..e1e1623e6 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1503,7 +1503,7 @@ module = { module = { name = emunet; emu = net/drivers/emu/emunet.c; - enable = ieee1275; + enable = emu; }; module = { diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index fed4f7e76..3473fe362 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -25,7 +25,6 @@ #include #include #include -#include #include grub_bootp_t (*grub_getbootp) (void); diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 4067e36cf..44738c67a 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/include/grub/net.h b/include/grub/net.h index 59974b94f..cb6db06d8 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -434,7 +434,5 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, void grub_net_pool_cards (unsigned time); -void -hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); - +extern grub_err_t (*EXPORT_VAR (grub_file_net_close)) (grub_file_t file); #endif /* ! GRUB_NET_HEADER */ From 48ac061ab6f4d685a1c93af59a0c366d3721a84d Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 12 May 2011 15:40:54 -0300 Subject: [PATCH 173/673] Prevent "incompatible license" error. --- grub-core/net/drivers/ieee1275/ofnet.c | 2 ++ grub-core/net/net.c | 2 ++ grub-core/net/tftp.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 44738c67a..cb3882ceb 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -6,6 +6,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t card_open (struct grub_net_card *dev) { diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 6ccf20725..be5279c99 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_net_route { struct grub_net_route *next; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 13bd87d15..278f6ed14 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -9,6 +9,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t tftp_open (struct grub_file *file, const char *filename) { From eea841440d27babefa8dbc1e1e7810875a06eef7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 May 2011 15:39:34 +0200 Subject: [PATCH 174/673] fix several bugs --- Makefile.util.def | 2 - grub-core/Makefile.am | 1 + grub-core/commands/ls.c | 22 +++--- grub-core/net/arp.c | 7 +- grub-core/net/drivers/emu/emunet.c | 8 +-- grub-core/net/drivers/ieee1275/ofnet.c | 7 +- grub-core/net/net.c | 96 +++++++++++++------------- grub-core/net/tftp.c | 17 +++-- grub-core/net/udp.c | 5 +- include/grub/net.h | 14 ++-- 10 files changed, 89 insertions(+), 90 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index 79ab040dd..058572f06 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -36,8 +36,6 @@ library = { common = grub-core/commands/blocklist.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; - common = grub-core/net/net.c; - common = grub-core/net/netbuff.c; common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/loopback.c; common = grub-core/disk/lvm.c; diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 0fdb4b1db..d5cd25a70 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -167,6 +167,7 @@ endif if COND_emu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h if COND_GRUB_EMU_SDL KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h endif diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 20a75733c..9df830612 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -48,9 +48,6 @@ static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; static grub_err_t grub_ls_list_devices (int longlist) { - grub_net_app_level_t proto; - int first = 1; - auto int grub_ls_print_devices (const char *name); int grub_ls_print_devices (const char *name) { @@ -65,15 +62,20 @@ grub_ls_list_devices (int longlist) grub_device_iterate (grub_ls_print_devices); grub_xputs ("\n"); - FOR_NET_APP_LEVEL (proto) +#ifndef GRUB_UTIL { - if (first) - grub_puts_ (N_ ("Network protocols:")); - first = 0; - grub_printf ("%s ", proto->name); + grub_net_app_level_t proto; + int first = 1; + FOR_NET_APP_LEVEL (proto) + { + if (first) + grub_puts_ (N_ ("Network protocols:")); + first = 0; + grub_printf ("%s ", proto->name); + } + grub_xputs ("\n"); } - - grub_xputs ("\n"); +#endif grub_refresh (); diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 8778a6e51..1300def25 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -87,11 +87,10 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr)); return GRUB_ERR_NONE; } - grub_net_pool_cards (200); + grub_net_poll_cards (200); + } - } - - return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address."); + return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address"); } grub_err_t diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index 9e4e66dce..d707d8015 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -26,7 +26,7 @@ send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), return GRUB_ERR_NONE; } -static grub_size_t +static grub_ssize_t get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { @@ -35,10 +35,7 @@ get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), grub_netbuff_clear(pack); actual = read (fd, pack->data, 1500); if (actual < 0) - { - grub_error (GRUB_ERR_IO, "couldn't receive packets"); - return -1; - } + return -1; grub_netbuff_put (pack, actual); return actual; @@ -65,7 +62,6 @@ static struct grub_net_card emucard = GRUB_MOD_INIT(emunet) { struct ifreq ifr; - // char fullname[64]; fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK); if (fd < 0) return; diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index cb3882ceb..10d0b979e 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -49,7 +48,7 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) return GRUB_ERR_NONE; } -static grub_err_t +static grub_ssize_t get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) { @@ -65,9 +64,9 @@ get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) if (actual) { grub_netbuff_put (nb, actual); - return grub_net_recv_ethernet_packet (nb); + return actual; } - return GRUB_ERR_TIMEOUT; + return -1; } static struct grub_net_card_driver ofdriver = diff --git a/grub-core/net/net.c b/grub-core/net/net.c index be5279c99..a82e73ab0 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -587,9 +588,13 @@ grub_net_file_open_real (struct grub_file *file, const char *name) grub_net_network_level_address_t gateway; grub_net_socket_t socket; static int port = 25300; + const char *comma; - err = grub_net_resolve_address (file->device->net->name - + sizeof (file->device->net->protocol->name) + 1, &addr); + comma = grub_strchr (file->device->net->name, ','); + if (!comma) + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no separator"); + + err = grub_net_resolve_address (comma + 1, &addr); if (err) return err; @@ -597,19 +602,22 @@ grub_net_file_open_real (struct grub_file *file, const char *name) if (err) return err; - if ((socket = (grub_net_socket_t) grub_malloc (sizeof (*socket))) == NULL) - return GRUB_ERR_OUT_OF_MEMORY; + socket = (grub_net_socket_t) grub_malloc (sizeof (*socket)); + if (socket == NULL) + return grub_errno; socket->inf = inf; socket->out_nla = addr; socket->in_port = port++; socket->status = 0; socket->app = file->device->net->protocol; - socket->packs = NULL; + socket->packs.first = NULL; + socket->packs.last = NULL; file->device->net->socket = socket; grub_net_socket_register (socket); - if ((err = file->device->net->protocol->open (file,name))) + err = file->device->net->protocol->open (file,name); + if (err) goto fail; file->not_easily_seekable = 1; @@ -625,10 +633,10 @@ static grub_err_t grub_net_file_close_real (grub_file_t file) { grub_net_socket_t sock = file->device->net->socket; - while (sock->packs->first) + while (sock->packs.first) { - grub_netbuff_free (sock->packs->first->nb); - grub_net_remove_packet (sock->packs->first); + grub_netbuff_free (sock->packs.first->nb); + grub_net_remove_packet (sock->packs.first); } grub_net_socket_unregister (sock); grub_free (sock); @@ -636,39 +644,44 @@ grub_net_file_close_real (grub_file_t file) } -static grub_err_t +static void receive_packets (struct grub_net_card *card) { /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; - grub_err_t err; + grub_ssize_t actual; nb = grub_netbuff_alloc (1500); if (!nb) - return grub_errno; + { + grub_print_error (); + return; + } - if ((err = card->driver->recv (card, nb)) != GRUB_ERR_NONE) + actual = card->driver->recv (card, nb); + if (actual < 0) grub_netbuff_free (nb); - return err; + else + grub_net_recv_ethernet_packet (nb); + grub_print_error (); } void -grub_net_pool_cards (unsigned time) +grub_net_poll_cards (unsigned time) { struct grub_net_card *card; grub_uint64_t start_time; FOR_NET_CARDS (card) { start_time = grub_get_time_ms (); - while( (grub_get_time_ms () - start_time) < time) - if( receive_packets (card) != GRUB_ERR_NONE) - break; + while ((grub_get_time_ms () - start_time) < time) + receive_packets (card); } } +/* Read from the packets list*/ static grub_ssize_t -process_packets (grub_file_t file, void *buf, grub_size_t len, - void *NESTED_FUNC_ATTR (hook) (void *dest, const void *src, grub_size_t n)) +grub_net_read_real (grub_file_t file, void *buf, grub_size_t len) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; @@ -677,19 +690,24 @@ process_packets (grub_file_t file, void *buf, grub_size_t len, int try = 0; while (try <= 3) { - while (sock->packs->first) + while (sock->packs.first) { try = 0; - nb = sock->packs->first->nb; - amount = (grub_size_t)(len <= (grub_size_t) (nb->tail - nb->data))? len :(grub_size_t)(nb->tail - nb->data); + nb = sock->packs.first->nb; + amount = nb->tail - nb->data; + if (amount > len) + amount = len; len -= amount; total += amount; - hook (ptr, nb->data, amount); - ptr += amount; + if (buf) + { + grub_memcpy (ptr, nb->data, amount); + ptr += amount; + } if (amount == (grub_size_t) (nb->tail - nb->data)) { grub_netbuff_free (nb); - grub_net_remove_packet (sock->packs->first); + grub_net_remove_packet (sock->packs.first); } else nb->data += amount; @@ -700,7 +718,7 @@ process_packets (grub_file_t file, void *buf, grub_size_t len, if (sock->status == 1) { try++; - grub_net_pool_cards (200); + grub_net_poll_cards (200); } else return total; @@ -708,20 +726,6 @@ process_packets (grub_file_t file, void *buf, grub_size_t len, return total; } - -/* Read from the packets list*/ -static grub_ssize_t -grub_net_read_real (grub_file_t file, void *buf, grub_size_t len ) -{ - auto void *NESTED_FUNC_ATTR memcpy_hook (void *dest, const void *src, grub_size_t n); - void *NESTED_FUNC_ATTR memcpy_hook (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), - grub_size_t n __attribute__ ((unused))) - { - return grub_memcpy (dest, src, n); - } - return process_packets (file, buf, len, memcpy_hook); -} - /* Read from the packets list*/ static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) @@ -736,17 +740,11 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) /* We cant seek backwards past the current packet. */ if (file->offset > offset) { - nb = sock->packs->first->nb; + nb = sock->packs.first->nb; return grub_netbuff_push (nb, file->offset - offset); } - auto void *NESTED_FUNC_ATTR dummy (void *dest, const void *src, grub_size_t n); - void *NESTED_FUNC_ATTR dummy (void *dest __attribute__ ((unused)), const void *src __attribute__ ((unused)), - grub_size_t n __attribute__ ((unused))) - { - return NULL; - } - process_packets (file, NULL, len, dummy); + grub_net_read_real (file, NULL, len); return GRUB_ERR_NONE; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 278f6ed14..1daf11bc7 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -21,8 +21,12 @@ tftp_open (struct grub_file *file, const char *filename) int hdrlen; char open_data[1500]; struct grub_net_buff nb; - tftp_data_t data = grub_malloc (sizeof *data); + tftp_data_t data; grub_err_t err; + + data = grub_malloc (sizeof *data); + if (!data) + return grub_errno; file->device->net->socket->data = (void *) data; nb.head = open_data; @@ -74,7 +78,7 @@ tftp_open (struct grub_file *file, const char *filename) /* Receive OACK packet. */ for ( i = 0; i < 3; i++) { - grub_net_pool_cards (100); + grub_net_poll_cards (100); if (grub_errno) return grub_errno; if (file->device->net->socket->status != 0) @@ -110,10 +114,13 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) switch (grub_be_to_cpu16 (tftph->opcode)) { case TFTP_OACK: - for (ptr = nb->data; ptr < nb->tail; ) + for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail; ) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) - data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, 0, 0); + { + data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, + 0, 0); + } while (ptr < nb->tail && *ptr) ptr++; ptr++; @@ -150,7 +157,7 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - tftph->u.ack.block = data->block; + tftph->u.ack.block = grub_cpu_to_be16 (data->block); err = grub_net_send_udp_packet (sock, &nb_ack); return err; diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 16b2011ff..4477b3c2b 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -36,15 +36,14 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) if (grub_be_to_cpu16 (udph->dst) == sock->in_port) { if (sock->status == 0) - sock->out_port = udph->src; + sock->out_port = grub_be_to_cpu16 (udph->src); - /* App protocol remove its own reader. */ sock->app->read (sock,nb); /* If there is data, puts packet in socket list */ if ((nb->tail - nb->data) > 0) - grub_net_put_packet (sock->packs, nb); + grub_net_put_packet (&sock->packs, nb); else grub_netbuff_free (nb); return GRUB_ERR_NONE; diff --git a/include/grub/net.h b/include/grub/net.h index cb6db06d8..1b113972b 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -63,7 +63,7 @@ struct grub_net_card_driver grub_err_t (*init) (struct grub_net_card *dev); grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (struct grub_net_card *dev, struct grub_net_buff *buf); - grub_size_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); + grub_ssize_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); }; extern struct grub_net_card_driver *grub_net_card_drivers; @@ -207,24 +207,24 @@ struct grub_net_socket grub_net_app_level_t app; grub_net_network_level_address_t out_nla; struct grub_net_network_level_interface *inf; - grub_net_packets_t *packs; + grub_net_packets_t packs; void *data; }; extern struct grub_net_socket *grub_net_sockets; static inline void -grub_net_socket_register (grub_net_socket_t socket) +grub_net_socket_register (grub_net_socket_t sock) { grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (socket)); + GRUB_AS_LIST (sock)); } static inline void -grub_net_socket_unregister (grub_net_socket_t socket) +grub_net_socket_unregister (grub_net_socket_t sock) { grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (socket)); + GRUB_AS_LIST (sock)); } #define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next) @@ -432,7 +432,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, #define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var) void -grub_net_pool_cards (unsigned time); +grub_net_poll_cards (unsigned time); extern grub_err_t (*EXPORT_VAR (grub_file_net_close)) (grub_file_t file); #endif /* ! GRUB_NET_HEADER */ From f35fa3a664474529be91252380eab589838add6d Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 20 May 2011 11:21:36 +0100 Subject: [PATCH 175/673] * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT. Reported by: Pawel Tecza. --- ChangeLog | 6 ++++++ util/grub-mkconfig.in | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1a68f911c..c94b7482d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-05-20 Colin Watson + + * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and + GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT. + Reported by: Pawel Tecza. + 2011-05-19 Vladimir Serbinenko * grub-core/Makefile.core.def (lsacpi): Fix ia64 mismerge. diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index afc66f886..4d627c057 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -239,6 +239,8 @@ export GRUB_DEFAULT \ GRUB_CMDLINE_LINUX_DEFAULT \ GRUB_CMDLINE_XEN \ GRUB_CMDLINE_XEN_DEFAULT \ + GRUB_CMDLINE_LINUX_XEN_REPLACE \ + GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT \ GRUB_CMDLINE_NETBSD \ GRUB_CMDLINE_NETBSD_DEFAULT \ GRUB_TERMINAL_INPUT \ From f767c929f2c430bb574a358e0ba8375d49c6ee64 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 21 May 2011 07:03:55 +0200 Subject: [PATCH 176/673] Don't stat devices unless we have to. * grub-core/kern/emu/getroot.c (grub_find_device): Recognize dir == /dev/mapper. (grub_guess_root_device): Use already known os_dev if possible. * grub-core/kern/emu/hostdisk.c (convert_system_partition_to_system_disk): Scan only in /dev/mapper if device is known to be a dm one. Also-By: Colin Watson --- ChangeLog | 12 ++++++++++++ grub-core/kern/emu/getroot.c | 33 ++++++++++++++++++++------------- grub-core/kern/emu/hostdisk.c | 3 ++- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index c94b7482d..a01d57576 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-05-21 Colin Watson +2011-05-21 Vladimir Serbinenko + + Don't stat devices unless we have to. + + * grub-core/kern/emu/getroot.c (grub_find_device): Recognize + dir == /dev/mapper. + (grub_guess_root_device): Use already known os_dev if possible. + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Scan only in /dev/mapper + if device is known to be a dm one. + 2011-05-20 Colin Watson * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index b1b4f188c..6e49cc31b 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -358,7 +358,7 @@ grub_find_device (const char *dir, dev_t dev) if (S_ISLNK (st.st_mode)) { #ifdef __linux__ - if (strcmp (dir, "mapper") == 0) { + if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) { /* Follow symbolic links under /dev/mapper/; the canonical name may be something like /dev/dm-0, but the names under /dev/mapper/ are more human-readable and so we prefer them if @@ -609,20 +609,27 @@ grub_guess_root_device (const char *dir) if (os_dev) { - if (stat (os_dev, &st) >= 0) - dev = st.st_rdev; - else - grub_util_error ("cannot stat `%s'", os_dev); - free (os_dev); - } - else - { - if (stat (dir, &st) >= 0) - dev = st.st_dev; - else - grub_util_error ("cannot stat `%s'", dir); + char *tmp = os_dev; + os_dev = canonicalize_file_name (os_dev); + free (tmp); } + if (os_dev) + { + if (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) != 0) + return os_dev; + if (stat (os_dev, &st) < 0) + grub_util_error ("cannot stat `%s'", os_dev); + free (os_dev); + dev = st.st_rdev; + return grub_find_device ("/dev/mapper", dev); + } + + if (stat (dir, &st) < 0) + grub_util_error ("cannot stat `%s'", dir); + + dev = st.st_dev; + #ifdef __CYGWIN__ /* Cygwin specific function. */ os_dev = grub_find_device (dir, dev); diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index d3db7e6be..d633059c3 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1408,7 +1408,8 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) if (tree) dm_tree_free (tree); free (path); - char *ret = grub_find_device (NULL, (major << 8) | minor); + char *ret = grub_find_device ("/dev/mapper", + (major << 8) | minor); return ret; } From 245f4aba489e3a21129253c28dc138571738a5e4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 May 2011 07:05:46 +0200 Subject: [PATCH 177/673] * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before opening new one. --- ChangeLog | 5 +++++ grub-core/disk/arc/arcdisk.c | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index a01d57576..198750f6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-21 Vladimir Serbinenko + + * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before + opening new one. + 2011-05-21 Colin Watson 2011-05-21 Vladimir Serbinenko diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index e8416634a..7dff30931 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -1,7 +1,7 @@ /* ofdisk.c - Open Firmware disk access. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2004,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2004,2006,2007,2008,2009,2011 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 @@ -105,11 +105,6 @@ reopen (const char *name) grub_dprintf ("arcdisk", "using already opened %s\n", name); return GRUB_ERR_NONE; } - if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle)) - { - grub_dprintf ("arcdisk", "couldn't open %s\n", name); - return grub_error (GRUB_ERR_IO, "couldn't open %s", name); - } if (last_path) { GRUB_ARC_FIRMWARE_VECTOR->close (last_handle); @@ -117,6 +112,11 @@ reopen (const char *name) last_path = NULL; last_handle = 0; } + if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle)) + { + grub_dprintf ("arcdisk", "couldn't open %s\n", name); + return grub_error (GRUB_ERR_IO, "couldn't open %s", name); + } last_path = grub_strdup (name); if (!last_path) return grub_errno; From f42313bdb07e5a9bb5f6ca92a37f342aae5a1bfa Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Wed, 25 May 2011 11:10:48 -0300 Subject: [PATCH 178/673] Remove unused structs and functions. --- include/grub/disk.h | 20 +------------------- include/grub/ieee1275/ofnet.h | 3 --- include/grub/net/ieee1275/interface.h | 10 ---------- include/grub/net/mem.h | 9 --------- 4 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 include/grub/net/ieee1275/interface.h delete mode 100644 include/grub/net/mem.h diff --git a/include/grub/disk.h b/include/grub/disk.h index 101303205..66db1149a 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -42,8 +42,7 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, GRUB_DISK_DEVICE_FILE_ID, - GRUB_DISK_DEVICE_LUKS_ID, - GRUB_DISK_DEVICE_OFNET_ID + GRUB_DISK_DEVICE_LUKS_ID }; struct grub_disk; @@ -117,23 +116,6 @@ struct grub_disk }; typedef struct grub_disk *grub_disk_t; -/* Net Disk */ -enum grub_netdisk_protocol -{ - GRUB_NETDISK_PROTOCOL_TFTP -}; -typedef enum grub_netdisk_protocol grub_netdisk_protocol_t; - -struct grub_netdisk_data -{ - grub_netdisk_protocol_t protocol; - grub_uint32_t server_ip; - grub_uint32_t port; - char *username; - char *password; -}; -typedef struct grub_netdisk_data *grub_netdisk_data_t; - #ifdef GRUB_UTIL struct grub_disk_memberlist { diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h index 9a0ae29e3..c7284df38 100644 --- a/include/grub/ieee1275/ofnet.h +++ b/include/grub/ieee1275/ofnet.h @@ -23,9 +23,6 @@ #include #include -void grub_ofnet_init(void); -void grub_ofnet_fini(void); - struct grub_ofnet { /* The net name. */ diff --git a/include/grub/net/ieee1275/interface.h b/include/grub/net/ieee1275/interface.h deleted file mode 100644 index c369e35a6..000000000 --- a/include/grub/net/ieee1275/interface.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef GRUB_IEEE1275_INTERFACE_HEADER -#define GRUB_IEEE1275_INTERFACE_HEADER 1 - -#include -#include -#include -#include - -grub_bootp_t bootp_pckt; -#endif diff --git a/include/grub/net/mem.h b/include/grub/net/mem.h deleted file mode 100644 index bbdac512b..000000000 --- a/include/grub/net/mem.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef GRUB_NETMM_H -#define GRUB_NETMM_H 1 - -#include -#include - -void *EXPORT_FUNC(grub_net_malloc) (grub_size_t size); - -#endif /* ! GRUB_MM_H */ From 7dd64f12368b8ee35eb32b52b0f6e69068053ab2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Fri, 27 May 2011 00:22:35 -0300 Subject: [PATCH 179/673] Use a net fs struct to handle open, reand and close in file. --- grub-core/kern/file.c | 25 ++--------------------- grub-core/kern/fs.c | 4 ++-- grub-core/kern/ieee1275/openfw.c | 1 - grub-core/net/net.c | 34 +++++++++++++++++++++----------- include/grub/net.h | 4 +--- 5 files changed, 27 insertions(+), 41 deletions(-) diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 2b3e9d689..749e72dfc 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -25,9 +25,6 @@ #include #include -grub_ssize_t (*grub_file_net_read) (grub_file_t file, void *buf, grub_size_t len) = NULL; -grub_err_t (*grub_file_net_open) (struct grub_file *file, const char *name) = NULL; -grub_err_t (*grub_file_net_close) (grub_file_t file) = NULL; grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; @@ -91,13 +88,6 @@ grub_file_open (const char *name) file->device = device; - if (device->net && grub_file_net_open) - { - if (grub_file_net_open (file, file_name)) - goto fail; - return file; - } - if (device->disk && file_name[0] != '/') /* This is a block list. */ file->fs = &grub_fs_blocklist; @@ -143,7 +133,7 @@ grub_file_open (const char *name) grub_ssize_t grub_file_read (grub_file_t file, void *buf, grub_size_t len) { - grub_ssize_t res = 0; + grub_ssize_t res; if (file->offset > file->size) { @@ -161,12 +151,7 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (len == 0) return 0; - if (file->device->disk) - res = (file->fs->read) (file, buf, len); - else - if (grub_file_net_read && file->device->net) - res = grub_file_net_read (file, buf, len); - + res = (file->fs->read) (file, buf, len); if (res > 0) file->offset += res; @@ -176,12 +161,6 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) grub_err_t grub_file_close (grub_file_t file) { - if (file->device->net) - { - grub_file_net_close (file); - return grub_errno; - } - if (file->fs->close) (file->fs->close) (file); diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index 7166648be..14d389e07 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -94,8 +94,8 @@ grub_fs_probe (grub_device_t device) count--; } } - else if (device->net) - return NULL; + else if (device->net && device->net->fs) + return device->net->fs; grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); return 0; diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 3473fe362..db4bec90a 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include diff --git a/grub-core/net/net.c b/grub-core/net/net.c index a82e73ab0..1232b3c74 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -49,6 +49,7 @@ struct grub_net_network_level_interface *grub_net_network_level_interfaces = NUL struct grub_net_card *grub_net_cards = NULL; struct grub_net_card_driver *grub_net_card_drivers = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; +static struct grub_fs grub_net_fs; static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) @@ -571,6 +572,7 @@ grub_net_open_real (const char *name) grub_free (ret); return NULL; } + ret->fs = &grub_net_fs; return ret; } } @@ -580,7 +582,7 @@ grub_net_open_real (const char *name) } static grub_err_t -grub_net_file_open_real (struct grub_file *file, const char *name) +grub_net_fs_open (struct grub_file *file, const char *name) { grub_err_t err; grub_net_network_level_address_t addr; @@ -620,7 +622,7 @@ grub_net_file_open_real (struct grub_file *file, const char *name) if (err) goto fail; file->not_easily_seekable = 1; - + return GRUB_ERR_NONE; fail: grub_net_socket_unregister (socket); @@ -630,7 +632,7 @@ fail: } static grub_err_t -grub_net_file_close_real (grub_file_t file) +grub_net_fs_close (grub_file_t file) { grub_net_socket_t sock = file->device->net->socket; while (sock->packs.first) @@ -681,11 +683,11 @@ grub_net_poll_cards (unsigned time) /* Read from the packets list*/ static grub_ssize_t -grub_net_read_real (grub_file_t file, void *buf, grub_size_t len) +grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; - char *ptr = (char *) buf; + char *ptr = buf; grub_size_t amount, total = 0; int try = 0; while (try <= 3) @@ -744,7 +746,7 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset) return grub_netbuff_push (nb, file->offset - offset); } - grub_net_read_real (file, NULL, len); + grub_net_fs_read (file, NULL, len); return GRUB_ERR_NONE; } @@ -1009,6 +1011,17 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), "unrecognised format specification %s", args[3]); } +static struct grub_fs grub_net_fs = + { + .name = "netfs", + .dir = NULL, + .open = grub_net_fs_open, + .read = grub_net_fs_read, + .close = grub_net_fs_close, + .label = NULL, + .uuid = NULL, + .mtime = NULL, + }; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp; @@ -1034,10 +1047,8 @@ GRUB_MOD_INIT(net) N_("VAR INTERFACE NUMBER DESCRIPTION"), N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); + grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; - grub_file_net_open = grub_net_file_open_real; - grub_file_net_close = grub_net_file_close_real; - grub_file_net_read = grub_net_read_real; grub_file_net_seek = grub_net_seek_real; } @@ -1050,8 +1061,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_getdhcp); + grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; - grub_file_net_read = NULL; - grub_file_net_open = NULL; - grub_file_net_close = NULL; + grub_file_net_seek = NULL; } diff --git a/include/grub/net.h b/include/grub/net.h index 1b113972b..f9745acec 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -234,11 +234,10 @@ typedef struct grub_net char *name; grub_net_app_level_t protocol; grub_net_socket_t socket; + grub_fs_t fs; } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); -extern grub_ssize_t (*EXPORT_VAR (grub_file_net_read)) (grub_file_t file, void *buf, grub_size_t len); -extern grub_err_t (*EXPORT_VAR (grub_file_net_open)) (struct grub_file *file, const char *name); extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); struct grub_net_network_level_interface @@ -434,5 +433,4 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, void grub_net_poll_cards (unsigned time); -extern grub_err_t (*EXPORT_VAR (grub_file_net_close)) (grub_file_t file); #endif /* ! GRUB_NET_HEADER */ From c64db050f7f8669fa0b7e27811c869febbeaa848 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 27 May 2011 13:52:21 +0100 Subject: [PATCH 180/673] * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up after ten consecutive open failures. Scanning all the way up to 10000 is excessive and can cause serious performance problems in some configurations. Fixes Ubuntu bug #787461. --- ChangeLog | 8 ++++++++ grub-core/kern/emu/hostdisk.c | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 198750f6a..351700803 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-05-27 Colin Watson + + * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up + after ten consecutive open failures. Scanning all the way up to + 10000 is excessive and can cause serious performance problems in + some configurations. + Fixes Ubuntu bug #787461. + 2011-05-21 Vladimir Serbinenko * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index d633059c3..e404c4fea 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -564,6 +564,7 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) int i; char real_dev[PATH_MAX]; struct linux_partition_cache *cache; + int missing = 0; strcpy(real_dev, dev); @@ -602,7 +603,13 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) fd = open (real_dev, O_RDONLY); if (fd == -1) - continue; + { + if (missing++ < 10) + continue; + else + return 0; + } + missing = 0; close (fd); start = find_partition_start (real_dev); From 6b4e643081999c9fe388ad5bd8ad96812777fc76 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 27 May 2011 13:57:22 +0100 Subject: [PATCH 181/673] * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle partitions under /dev/disk/by-id/. --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index 351700803..b9abcd07f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-27 Colin Watson + + * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle + partitions under /dev/disk/by-id/. + 2011-05-27 Colin Watson * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index e404c4fea..bb528d9bc 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -573,6 +573,12 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) p = real_dev + len - 4; format = "part%d"; } + else if (strncmp (real_dev, "/dev/disk/by-id/", + sizeof ("/dev/disk/by-id/") - 1) == 0) + { + p = real_dev + len; + format = "-part%d"; + } else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9') { p = real_dev + len; From 351c7c8a155d1c3ace2cbefb9682c5b862082d98 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 29 May 2011 22:15:08 +0100 Subject: [PATCH 182/673] * docs/grub.texi (Obtaining and Building GRUB): Substitute `ftp.gnu.org' for `alpha.gnu.org'. --- ChangeLog | 5 +++++ docs/grub.texi | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9abcd07f..fca980c1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-05-29 Colin Watson + + * docs/grub.texi (Obtaining and Building GRUB): Substitute + `ftp.gnu.org' for `alpha.gnu.org'. + 2011-05-27 Colin Watson * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle diff --git a/docs/grub.texi b/docs/grub.texi index 818417d41..45c93d69c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -4330,11 +4330,11 @@ how to get the latest version. @end quotation GRUB is available from the GNU alpha archive site -@uref{ftp://alpha.gnu.org/gnu/grub} or any of its mirrors. The file +@uref{ftp://ftp.gnu.org/gnu/grub} or any of its mirrors. The file will be named grub-version.tar.gz. The current version is @value{VERSION}, so the file you should grab is: -@uref{ftp://alpha.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz} +@uref{ftp://ftp.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz} To unbundle GRUB use the instruction: From 4f24b12e1fb7ad56b59dee6f545701a2864512a2 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Thu, 2 Jun 2011 15:13:33 -0300 Subject: [PATCH 183/673] Fix compilation in x86 --- grub-core/net/i386/pc/pxe.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index 8e7f75ed8..27c4af17f 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -193,7 +193,7 @@ grub_pxefs_open (struct grub_file *file, const char *name) } file->data = data; - file->not_easly_seekable = 1; + file->not_easily_seekable = 1; grub_memcpy (file_int, file, sizeof (struct grub_file)); curr_file = file_int; @@ -215,7 +215,8 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_pxenv_tftp_read c; struct grub_pxe_data *data; - grub_uint32_t pn, r; + grub_uint32_t pn; + grub_uint64_t r; data = file->data; @@ -292,7 +293,7 @@ grub_pxefs_label (grub_device_t device __attribute ((unused)), return GRUB_ERR_NONE; } -static struct grub_net_app_protocol grub_pxefs_fs = +static struct grub_fs grub_pxefs_fs = { .name = "pxe", .dir = grub_pxefs_dir, @@ -303,7 +304,7 @@ static struct grub_net_app_protocol grub_pxefs_fs = .next = 0 }; -static grub_size_t +static grub_ssize_t grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *buf __attribute__ ((unused))) { @@ -334,7 +335,7 @@ grub_pxe_unload (void) { if (grub_pxe_pxenv) { - grub_net_app_level_unregister (&grub_pxefs_fs); + grub_fs_unregister (&grub_pxefs_fs); grub_net_card_unregister (&grub_pxe_card); grub_pxe_pxenv = 0; } @@ -466,7 +467,7 @@ GRUB_MOD_INIT(pxe) ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - grub_net_app_level_register (&grub_pxefs_fs); + grub_fs_register (&grub_pxefs_fs); grub_net_card_register (&grub_pxe_card); grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, GRUB_NET_INTERFACE_PERMANENT From 423a1849ef2d4791e03ef6cd6cd94d5bf75144af Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 7 Jun 2011 11:47:31 -0300 Subject: [PATCH 184/673] Write ChangeLog. --- ChangeLog | 26 ++++++++++++++++++++++++++ grub-core/net/tftp.c | 6 +++--- grub-core/net/udp.c | 3 +-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 198750f6a..122ea029d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2011-06-07 Vladimir Serbinenko +2011-06-07 Manoel Rebelo Abranches + + Network infrastructure. + The ARP protocol was made by Paulo Pinatti + + * include/grub/net/arp.h: New file. + * include/grub/net/ethernet.h: New file. + * include/grub/net/ip.h: New file. + * include/grub/net/netbuff.h: New file. + * include/grub/net/tftp.h: New file. + * include/grub/net/udp.h: New file. + * include/grub/net.h: New file. + * grub-core/net/arp.c: New file. + * grub-core/net/ethernet.c: New file. + * grub-core/net/ip.c: New file. + * grub-core/net/netbuff.c: New file. + * grub-core/net/net.c: New file. + * grub-core/net/drivers/emu/emunet.c: New file. + * grub-core/net/drivers/ieee1275/ofnet.c: New file. + * grub-core/kern/device.c (grub_net_open) : New function. + (grub_device_open) : Handle Network device. + * grub-core/kern/file.c (grub_file_net_seek) : New function. + (grub_file_net_seek): Seek in network device. + + 2011-05-21 Vladimir Serbinenko * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 1daf11bc7..010a4a4bd 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -84,9 +84,9 @@ tftp_open (struct grub_file *file, const char *filename) if (file->device->net->socket->status != 0) break; /* Retry. */ - //err = grub_net_send_udp_packet (file->device->net->socket, &nb); - // if (err) - // return err; + /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); + if (err) + return err;*/ } if (file->device->net->socket->status == 0) diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 4477b3c2b..0b19c3098 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -25,7 +25,6 @@ grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb) { - //grub_err_t err; struct udphdr *udph; grub_net_socket_t sock; udph = (struct udphdr *) nb->data; @@ -41,7 +40,7 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) /* App protocol remove its own reader. */ sock->app->read (sock,nb); - /* If there is data, puts packet in socket list */ + /* If there is data, puts packet in socket list. */ if ((nb->tail - nb->data) > 0) grub_net_put_packet (&sock->packs, nb); else From 4700d08bb4ed597a9aa122340b06fba137327bb7 Mon Sep 17 00:00:00 2001 From: Manoel Rebelo Abranches Date: Tue, 7 Jun 2011 21:59:53 -0300 Subject: [PATCH 185/673] Run indent on files. --- grub-core/net/arp.c | 91 ++++++++------- grub-core/net/drivers/emu/emunet.c | 39 +++---- grub-core/net/drivers/ieee1275/ofnet.c | 154 +++++++++++++------------ grub-core/net/ethernet.c | 28 ++--- grub-core/net/ip.c | 53 ++++----- grub-core/net/netbuff.c | 59 ++++++---- grub-core/net/tftp.c | 118 +++++++++---------- grub-core/net/udp.c | 53 ++++----- 8 files changed, 307 insertions(+), 288 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 1300def25..0644d3d2e 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -9,10 +9,10 @@ static struct arp_entry arp_table[10]; static grub_int8_t new_table_entry = -1; -static -void arp_init_table(void) +static void +arp_init_table (void) { - grub_memset (arp_table, 0, sizeof (arp_table)); + grub_memset (arp_table, 0, sizeof (arp_table)); new_table_entry = 0; } @@ -20,19 +20,19 @@ static struct arp_entry * arp_find_entry (const grub_net_network_level_address_t *proto) { unsigned i; - for(i = 0; i < ARRAY_SIZE (arp_table); i++) + for (i = 0; i < ARRAY_SIZE (arp_table); i++) { - if(arp_table[i].avail == 1 && - arp_table[i].nl_address.ipv4 == proto->ipv4) - return &(arp_table[i]); + if (arp_table[i].avail == 1 && + arp_table[i].nl_address.ipv4 == proto->ipv4) + return &(arp_table[i]); } return NULL; } grub_err_t -grub_net_arp_resolve(struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *proto_addr, - grub_net_link_level_address_t *hw_addr) +grub_net_arp_resolve (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr, + grub_net_link_level_address_t *hw_addr) { struct arp_entry *entry; struct grub_net_buff nb; @@ -51,10 +51,10 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, /* Build a request packet. */ nb.head = arp_data; nb.end = arp_data + sizeof (arp_data); - grub_netbuff_clear (&nb); + grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb,128); - grub_netbuff_push (&nb, sizeof(*arp_header) + 2 * (6 + 4)); + grub_netbuff_reserve (&nb, 128); + grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); @@ -71,11 +71,11 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_memcpy (aux, &inf->address.ipv4, 4); aux += 4; /* Target hardware address */ - for(i = 0; i < 6; i++) + for (i = 0; i < 6; i++) aux[i] = 0x00; aux += 6; /* Target protocol address */ - grub_memcpy(aux, &proto_addr->ipv4, 4); + grub_memcpy (aux, &proto_addr->ipv4, 4); grub_memset (&target_hw_addr.mac, 0xff, 6); send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); @@ -96,56 +96,59 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf, grub_err_t grub_net_arp_receive (struct grub_net_buff *nb) { - struct arphdr *arp_header = (struct arphdr *)nb->data; + struct arphdr *arp_header = (struct arphdr *) nb->data; struct arp_entry *entry; grub_uint8_t *sender_hardware_address, *sender_protocol_address; grub_uint8_t *target_hardware_address, *target_protocol_address; grub_net_network_level_address_t hwaddress; struct grub_net_network_level_interface *inf; - sender_hardware_address = (grub_uint8_t *) arp_header + sizeof(*arp_header); + sender_hardware_address = + (grub_uint8_t *) arp_header + sizeof (*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4); - /* Check if the sender is in the cache table */ - entry = arp_find_entry(&hwaddress); - /* Update sender hardware address */ + /* Check if the sender is in the cache table. */ + entry = arp_find_entry (&hwaddress); + /* Update sender hardware address. */ if (entry) - grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); else { - /* Add sender to cache table */ + /* Add sender to cache table. */ if (new_table_entry == -1) - arp_init_table(); + arp_init_table (); entry = &(arp_table[new_table_entry]); entry->avail = 1; - grub_memcpy(&entry->nl_address.ipv4, sender_protocol_address, 4); - grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6); + grub_memcpy (&entry->nl_address.ipv4, sender_protocol_address, 4); + grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); new_table_entry++; if (new_table_entry == ARRAY_SIZE (arp_table)) new_table_entry = 0; } - FOR_NET_NETWORK_LEVEL_INTERFACES(inf) - { - /* Am I the protocol address target? */ - if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 - && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) - { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy (target_hardware_address, sender_hardware_address, arp_header->hln); - grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy (aux.mac, sender_protocol_address, 6); - grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); - /* Change operation to REPLY and send packet */ - arp_header->op = grub_be_to_cpu16 (ARP_REPLY); - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); - } - } + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + /* Am I the protocol address target? */ + if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 + && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) + { + grub_net_link_level_address_t aux; + /* Swap hardware fields */ + grub_memcpy (target_hardware_address, sender_hardware_address, + arp_header->hln); + grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); + grub_memcpy (aux.mac, sender_protocol_address, 6); + grub_memcpy (sender_protocol_address, target_protocol_address, + arp_header->pln); + grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); + /* Change operation to REPLY and send packet */ + arp_header->op = grub_be_to_cpu16 (ARP_REPLY); + grub_memcpy (aux.mac, target_hardware_address, 6); + send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index d707d8015..ee4ba4773 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -13,7 +13,7 @@ static int fd; -static grub_err_t +static grub_err_t send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { @@ -22,7 +22,7 @@ send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), actual = write (fd, pack->data, pack->tail - pack->data); if (actual < 0) return grub_error (GRUB_ERR_IO, "couldn't send packets"); - + return GRUB_ERR_NONE; } @@ -32,32 +32,32 @@ get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), { ssize_t actual; - grub_netbuff_clear(pack); + grub_netbuff_clear (pack); actual = read (fd, pack->data, 1500); if (actual < 0) return -1; grub_netbuff_put (pack, actual); - return actual; + return actual; } static struct grub_net_card_driver emudriver = -{ - .name = "emu", - .send = send_card_buffer, - .recv = get_card_packet -}; + { + .name = "emu", + .send = send_card_buffer, + .recv = get_card_packet + }; static struct grub_net_card emucard = -{ - .name = "emu0", - .driver = &emudriver, - .default_address = { - .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, - { .mac = { 0, 1, 2, 3, 4, 5} } - }, - .flags = 0 -}; + { + .name = "emu0", + .driver = &emudriver, + .default_address = { + .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, + {.mac = {0, 1, 2, 3, 4, 5}} + }, + .flags = 0 + }; GRUB_MOD_INIT(emunet) { @@ -84,6 +84,3 @@ GRUB_MOD_FINI(emunet) grub_net_card_unregister (&emucard); } } - - - diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 10d0b979e..751583e9d 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -7,15 +7,18 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t card_open (struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; - char path[grub_strlen(data->path) + grub_strlen(":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; + char path[grub_strlen (data->path) + + grub_strlen (":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512") + 1]; + /* The full string will prevent a bootp packet to be sent. Just put some valid ip in there. */ - grub_snprintf(path,sizeof(path),"%s%s",data->path,":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); - status = grub_ieee1275_open (path,&(data->handle)); + grub_snprintf (path, sizeof (path), "%s%s", data->path, + ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"); + status = grub_ieee1275_open (path, &(data->handle)); if (status) return grub_error (GRUB_ERR_IO, "Couldn't open network card."); @@ -23,23 +26,23 @@ card_open (struct grub_net_card *dev) return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t card_close (struct grub_net_card *dev) { struct grub_ofnetcard_data *data = dev->data; - + if (data->handle) grub_ieee1275_close (data->handle); return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) -{ +{ int actual; int status; struct grub_ofnetcard_data *data = dev->data; - + status = grub_ieee1275_write (data->handle, pack->data, pack->tail - pack->data, &actual); @@ -56,27 +59,27 @@ get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; - grub_netbuff_clear (nb); + grub_netbuff_clear (nb); start_time = grub_get_time_ms (); do rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual); while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); if (actual) { - grub_netbuff_put (nb, actual); + grub_netbuff_put (nb, actual); return actual; } return -1; } -static struct grub_net_card_driver ofdriver = -{ - .name = "ofnet", - .init = card_open, - .fini = card_close, - .send = send_card_buffer, - .recv = get_card_packet -}; +static struct grub_net_card_driver ofdriver = + { + .name = "ofnet", + .init = card_open, + .fini = card_close, + .send = send_card_buffer, + .recv = get_card_packet + }; static const struct { @@ -84,23 +87,23 @@ static const struct int offset; } -bootp_response_properties[] = -{ - { .name = "bootp-response", .offset = 0 }, - { .name = "dhcp-response", .offset = 0 }, - { .name = "bootpreply-packet", .offset = 0x2a }, -}; +bootp_response_properties[] = + { + { .name = "bootp-response", .offset = 0}, + { .name = "dhcp-response", .offset = 0}, + { .name = "bootpreply-packet", .offset = 0x2a}, + }; -static grub_bootp_t -grub_getbootp_real ( void ) +static grub_bootp_t +grub_getbootp_real (void) { grub_bootp_t packet = grub_malloc (sizeof *packet); - char *bootp_response; + char *bootp_response; grub_ssize_t size; unsigned int i; - for ( i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) - if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, bootp_response_properties[i].name, &size) >= 0) break; @@ -111,8 +114,7 @@ grub_getbootp_real ( void ) bootp_response = grub_malloc (size); if (grub_ieee1275_get_property (grub_ieee1275_chosen, bootp_response_properties[i].name, - bootp_response , - size, 0) < 0) + bootp_response, size, 0) < 0) return NULL; grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet)); @@ -120,52 +122,55 @@ grub_getbootp_real ( void ) return packet; } -static -void grub_ofnet_findcards (void) +static void +grub_ofnet_findcards (void) { struct grub_net_card *card; grub_ieee1275_phandle_t devhandle; - grub_net_link_level_address_t lla; + grub_net_link_level_address_t lla; int i = 0; auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) - { - if ( !grub_strcmp (alias->type,"network") ) - { - - card = grub_malloc (sizeof (struct grub_net_card)); - struct grub_ofnetcard_data *ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); - ofdata->path = grub_strdup (alias->path); - - grub_ieee1275_finddevice (ofdata->path, &devhandle); - - if (grub_ieee1275_get_integer_property - (devhandle, "max-frame-size", &(ofdata->mtu), sizeof (ofdata->mtu), 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + { + if (!grub_strcmp (alias->type, "network")) + { - if (grub_ieee1275_get_property (devhandle, "mac-address", &(lla.mac), 6, 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); - - lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - card->default_address = lla; + card = grub_malloc (sizeof (struct grub_net_card)); + struct grub_ofnetcard_data *ofdata = + grub_malloc (sizeof (struct grub_ofnetcard_data)); + ofdata->path = grub_strdup (alias->path); - card->driver = NULL; - card->data = ofdata; + grub_ieee1275_finddevice (ofdata->path, &devhandle); + + if (grub_ieee1275_get_integer_property + (devhandle, "max-frame-size", &(ofdata->mtu), + sizeof (ofdata->mtu), 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + + if (grub_ieee1275_get_property + (devhandle, "mac-address", &(lla.mac), 6, 0)) + return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + + lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + card->default_address = lla; + + card->driver = NULL; + card->data = ofdata; card->flags = 0; - card->name = grub_xasprintf("eth%d",i++); // grub_strdup (alias->name); - grub_net_card_register (card); + card->name = grub_xasprintf ("eth%d", i++); + grub_net_card_register (card); return 0; - } - return 0; + } + return 0; } /* Look at all nodes for devices of the type network. */ grub_ieee1275_devices_iterate (search_net_devices); } -static -void grub_ofnet_probecards (void) +static void +grub_ofnet_probecards (void) { struct grub_net_card *card; struct grub_net_card_driver *driver; @@ -175,19 +180,21 @@ void grub_ofnet_probecards (void) grub_net_network_level_netaddress_t net; bootp_pckt = grub_getbootp (); - /* Assign correspondent driver for each device. */ + /* Assign correspondent driver for each device. */ FOR_NET_CARDS (card) { FOR_NET_CARD_DRIVERS (driver) { - if (driver->init(card) == GRUB_ERR_NONE) + if (driver->init (card) == GRUB_ERR_NONE) { card->driver = driver; - if (bootp_pckt && grub_memcmp(bootp_pckt->chaddr,card->default_address.mac,6) == 0) + if (bootp_pckt + && grub_memcmp (bootp_pckt->chaddr, card->default_address.mac, 6) == 0) { addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bootp_pckt->yiaddr; - grub_net_add_addr ("bootp_cli_addr", card, addr, card->default_address, 0); + grub_net_add_addr ("bootp_cli_addr", card, addr, + card->default_address, 0); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) if (grub_strcmp (inter->name, "bootp_cli_addr") == 0) break; @@ -197,30 +204,27 @@ void grub_ofnet_probecards (void) grub_net_add_route ("bootp-router", net, inter); } break; - } + } } } grub_free (bootp_pckt); - + } -GRUB_MOD_INIT (ofnet) +GRUB_MOD_INIT(ofnet) { struct grub_net_card *card; grub_getbootp = grub_getbootp_real; grub_net_card_driver_register (&ofdriver); - grub_ofnet_findcards (); - grub_ofnet_probecards (); - FOR_NET_CARDS (card) + grub_ofnet_findcards (); + grub_ofnet_probecards (); + FOR_NET_CARDS (card) if (card->driver == NULL) grub_net_card_unregister (card); } -GRUB_MOD_FINI (ofnet) +GRUB_MOD_FINI(ofnet) { grub_net_card_driver_unregister (&ofdriver); grub_getbootp = NULL; } - - - diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index c96a65602..d29193afe 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -8,25 +8,25 @@ #include #include -grub_err_t +grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t target_addr, grub_uint16_t ethertype) { - struct etherhdr *eth; + struct etherhdr *eth; - grub_netbuff_push (nb,sizeof(*eth)); - eth = (struct etherhdr *) nb->data; - grub_memcpy(eth->dst, target_addr.mac, 6); - grub_memcpy(eth->src, inf->hwaddress.mac, 6); + grub_netbuff_push (nb, sizeof (*eth)); + eth = (struct etherhdr *) nb->data; + grub_memcpy (eth->dst, target_addr.mac, 6); + grub_memcpy (eth->src, inf->hwaddress.mac, 6); eth->type = grub_cpu_to_be16 (ethertype); return inf->card->driver->send (inf->card, nb); } -grub_err_t +grub_err_t grub_net_recv_ethernet_packet (struct grub_net_buff *nb) { struct etherhdr *eth; @@ -34,32 +34,32 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) struct snaphdr *snaph; grub_uint16_t type; - eth = (struct etherhdr *) nb->data; + eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); grub_netbuff_pull (nb, sizeof (*eth)); - + if (type <= 1500) { llch = (struct llchdr *) nb->data; type = llch->dsap & LLCADDRMASK; if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) - { - grub_netbuff_pull (nb,sizeof(*llch)); + { + grub_netbuff_pull (nb, sizeof (*llch)); snaph = (struct snaphdr *) nb->data; type = snaph->type; } } - /* ARP packet */ + /* ARP packet. */ if (type == GRUB_NET_ETHERTYPE_ARP) { grub_net_arp_receive (nb); grub_netbuff_free (nb); } - /* IP packet */ + /* IP packet. */ if (type == GRUB_NET_ETHERTYPE_IP) grub_net_recv_ip_packets (nb); - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; } diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index d6684c29e..4adc2b028 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -8,54 +8,55 @@ #include grub_uint16_t -ipchksum(void *ipv, int len) +ipchksum (void *ipv, int len) { - grub_uint16_t *ip = (grub_uint16_t *)ipv; - grub_uint32_t sum = 0; + grub_uint16_t *ip = (grub_uint16_t *) ipv; + grub_uint32_t sum = 0; - len >>= 1; - while (len--) - { - sum += grub_be_to_cpu16 (*(ip++)); - if (sum > 0xFFFF) - sum -= 0xFFFF; - } + len >>= 1; + while (len--) + { + sum += grub_be_to_cpu16 (*(ip++)); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } - return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); + return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); } grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, struct grub_net_buff *nb) -{ +{ struct iphdr *iph; - static int id = 0x2400; + static int id = 0x2400; grub_net_link_level_address_t ll_target_addr; grub_err_t err; - - grub_netbuff_push (nb, sizeof(*iph)); - iph = (struct iphdr *) nb->data; + + grub_netbuff_push (nb, sizeof (*iph)); + iph = (struct iphdr *) nb->data; iph->verhdrlen = ((4 << 4) | 5); iph->service = 0; - iph->len = grub_cpu_to_be16 (nb->tail - nb-> data); + iph->len = grub_cpu_to_be16 (nb->tail - nb->data); iph->ident = grub_cpu_to_be16 (++id); iph->frags = 0; iph->ttl = 0xff; iph->protocol = 0x11; iph->src = inf->address.ipv4; iph->dest = target->ipv4; - - iph->chksum = 0 ; - iph->chksum = ipchksum((void *)nb->data, sizeof(*iph)); - + + iph->chksum = 0; + iph->chksum = ipchksum ((void *) nb->data, sizeof (*iph)); + /* Determine link layer target address via ARP. */ err = grub_net_arp_resolve (inf, target, &ll_target_addr); if (err) return err; return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); } + /* static int ip_filter (struct grub_net_buff *nb) @@ -80,7 +81,7 @@ ip_filter (struct grub_net_buff *nb) return 1; } */ -grub_err_t +grub_err_t grub_net_recv_ip_packets (struct grub_net_buff *nb) { struct iphdr *iph = (struct iphdr *) nb->data; @@ -88,11 +89,11 @@ grub_net_recv_ip_packets (struct grub_net_buff *nb) switch (iph->protocol) { - case IP_UDP: - return grub_net_recv_udp_packet (nb); + case IP_UDP: + return grub_net_recv_udp_packet (nb); break; - default: - grub_netbuff_free (nb); + default: + grub_netbuff_free (nb); break; } diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index be9fc9de2..aae2f4d8f 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -22,73 +22,84 @@ #include -grub_err_t grub_netbuff_put (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_put (struct grub_net_buff *nb, grub_size_t len) { nb->tail += len; if (nb->tail > nb->end) return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_unput (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_unput (struct grub_net_buff *nb, grub_size_t len) { nb->tail -= len; if (nb->tail < nb->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "unput out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "unput out of the packet range."); + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_push (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_push (struct grub_net_buff *nb, grub_size_t len) { nb->data -= len; if (nb->data < nb->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "push out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "push out of the packet range."); + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_pull (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_pull (struct grub_net_buff *nb, grub_size_t len) { nb->data += len; if (nb->data > nb->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "pull out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "pull out of the packet range."); + return GRUB_ERR_NONE; } -grub_err_t grub_netbuff_reserve (struct grub_net_buff *nb ,grub_size_t len) +grub_err_t +grub_netbuff_reserve (struct grub_net_buff *nb, grub_size_t len) { nb->data += len; nb->tail += len; if ((nb->tail > nb->end) || (nb->data > nb->end)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "reserve out of the packet range."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "reserve out of the packet range."); + return GRUB_ERR_NONE; } -struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len ) +struct grub_net_buff * +grub_netbuff_alloc (grub_size_t len) { struct grub_net_buff *nb; void *data; - if (len < NETBUFFMINLEN) + if (len < NETBUFFMINLEN) len = NETBUFFMINLEN; - - len = ALIGN_UP (len,NETBUFF_ALIGN); + + len = ALIGN_UP (len, NETBUFF_ALIGN); data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); if (!data) return NULL; - nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); + nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); nb->head = nb->data = nb->tail = data; - nb->end = (char *) nb; - return nb; + nb->end = (char *) nb; + return nb; } -grub_err_t grub_netbuff_free (struct grub_net_buff *nb) +grub_err_t +grub_netbuff_free (struct grub_net_buff *nb) { grub_free (nb->head); return 0; - } -grub_err_t grub_netbuff_clear (struct grub_net_buff *nb) +grub_err_t +grub_netbuff_clear (struct grub_net_buff *nb) { nb->data = nb->tail = nb->head; return 0; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 010a4a4bd..ac3b3e9db 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -11,15 +11,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t tftp_open (struct grub_file *file, const char *filename) { - struct tftphdr *tftph; + struct tftphdr *tftph; char *rrq; int i; int rrqlen; int hdrlen; - char open_data[1500]; + char open_data[1500]; struct grub_net_buff nb; tftp_data_t data; grub_err_t err; @@ -27,47 +27,47 @@ tftp_open (struct grub_file *file, const char *filename) data = grub_malloc (sizeof *data); if (!data) return grub_errno; - + file->device->net->socket->data = (void *) data; nb.head = open_data; nb.end = open_data + sizeof (open_data); - grub_netbuff_clear (&nb); + grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb,1500); - grub_netbuff_push (&nb,sizeof (*tftph)); + grub_netbuff_reserve (&nb, 1500); + grub_netbuff_push (&nb, sizeof (*tftph)); + + tftph = (struct tftphdr *) nb.data; - tftph = (struct tftphdr *) nb.data; - rrq = (char *) tftph->u.rrq; rrqlen = 0; - + tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ); grub_strcpy (rrq, filename); rrqlen += grub_strlen (filename) + 1; - rrq += grub_strlen (filename) + 1; - - grub_strcpy (rrq,"octet"); + rrq += grub_strlen (filename) + 1; + + grub_strcpy (rrq, "octet"); rrqlen += grub_strlen ("octet") + 1; - rrq += grub_strlen ("octet") + 1; + rrq += grub_strlen ("octet") + 1; - grub_strcpy (rrq,"blksize"); - rrqlen += grub_strlen("blksize") + 1; - rrq += grub_strlen ("blksize") + 1; + grub_strcpy (rrq, "blksize"); + rrqlen += grub_strlen ("blksize") + 1; + rrq += grub_strlen ("blksize") + 1; - grub_strcpy (rrq,"1024"); + grub_strcpy (rrq, "1024"); rrqlen += grub_strlen ("1024") + 1; - rrq += grub_strlen ("1024") + 1; - - grub_strcpy (rrq,"tsize"); - rrqlen += grub_strlen ("tsize") + 1; - rrq += grub_strlen ("tsize") + 1; + rrq += grub_strlen ("1024") + 1; - grub_strcpy (rrq,"0"); + grub_strcpy (rrq, "tsize"); + rrqlen += grub_strlen ("tsize") + 1; + rrq += grub_strlen ("tsize") + 1; + + grub_strcpy (rrq, "0"); rrqlen += grub_strlen ("0") + 1; rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - - grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); + + grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); file->device->net->socket->out_port = TFTP_SERVER_PORT; @@ -76,7 +76,7 @@ tftp_open (struct grub_file *file, const char *filename) return err; /* Receive OACK packet. */ - for ( i = 0; i < 3; i++) + for (i = 0; i < 3; i++) { grub_net_poll_cards (100); if (grub_errno) @@ -85,22 +85,22 @@ tftp_open (struct grub_file *file, const char *filename) break; /* Retry. */ /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); - if (err) - return err;*/ + if (err) + return err; */ } if (file->device->net->socket->status == 0) - return grub_error (GRUB_ERR_TIMEOUT,"Time out opening tftp."); + return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); file->size = data->file_size; return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) { struct tftphdr *tftph; - char nbdata[128]; + char nbdata[128]; tftp_data_t data = sock->data; grub_err_t err; char *ptr; @@ -112,9 +112,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) - { + { case TFTP_OACK: - for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail; ) + for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) { @@ -125,13 +125,14 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) ptr++; ptr++; } - sock->status = 1; + sock->status = 1; data->block = 0; - grub_netbuff_clear(nb); - break; + grub_netbuff_clear (nb); + break; case TFTP_DATA: - grub_netbuff_pull (nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block)); - + grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { data->block++; @@ -140,22 +141,23 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) sock->status = 2; /* Prevent garbage in broken cards. */ if (size > 1024) - grub_netbuff_unput (nb, size - 1024); + grub_netbuff_unput (nb, size - 1024); } else - grub_netbuff_clear(nb); - - break; + grub_netbuff_clear (nb); + + break; case TFTP_ERROR: grub_netbuff_clear (nb); - return grub_error (GRUB_ERR_IO, (char *)tftph->u.err.errmsg); - break; - } + return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); + break; + } grub_netbuff_clear (&nb_ack); - grub_netbuff_reserve (&nb_ack,128); - grub_netbuff_push (&nb_ack,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block)); + grub_netbuff_reserve (&nb_ack, 128); + grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block)); - tftph = (struct tftphdr *) nb_ack.data; + tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); tftph->u.ack.block = grub_cpu_to_be16 (data->block); @@ -163,7 +165,7 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) return err; } -static grub_err_t +static grub_err_t tftp_close (struct grub_file *file __attribute__ ((unused))) { grub_free (file->device->net->socket->data); @@ -171,19 +173,19 @@ tftp_close (struct grub_file *file __attribute__ ((unused))) } static struct grub_net_app_protocol grub_tftp_protocol = -{ - .name = "tftp", - .open = tftp_open, - .read = tftp_receive, - .close = tftp_close -}; + { + .name = "tftp", + .open = tftp_open, + .read = tftp_receive, + .close = tftp_close + }; -GRUB_MOD_INIT (tftp) +GRUB_MOD_INIT(tftp) { grub_net_app_level_register (&grub_tftp_protocol); } -GRUB_MOD_FINI (tftp) +GRUB_MOD_FINI(tftp) { grub_net_app_level_unregister (&grub_tftp_protocol); } diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 0b19c3098..86220bf0f 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -5,24 +5,25 @@ #include grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb) +grub_net_send_udp_packet (const grub_net_socket_t socket, + struct grub_net_buff *nb) { struct udphdr *udph; - grub_netbuff_push (nb,sizeof(*udph)); - - udph = (struct udphdr *) nb->data; + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; udph->src = grub_cpu_to_be16 (socket->in_port); udph->dst = grub_cpu_to_be16 (socket->out_port); /* No chechksum. */ - udph->chksum = 0; + udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb); } -grub_err_t +grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb) { struct udphdr *udph; @@ -30,24 +31,24 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) udph = (struct udphdr *) nb->data; grub_netbuff_pull (nb, sizeof (*udph)); - FOR_NET_SOCKETS(sock) - { - if (grub_be_to_cpu16 (udph->dst) == sock->in_port) - { - if (sock->status == 0) - sock->out_port = grub_be_to_cpu16 (udph->src); - - /* App protocol remove its own reader. */ - sock->app->read (sock,nb); - - /* If there is data, puts packet in socket list. */ - if ((nb->tail - nb->data) > 0) - grub_net_put_packet (&sock->packs, nb); - else - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - } - grub_netbuff_free (nb); + FOR_NET_SOCKETS (sock) + { + if (grub_be_to_cpu16 (udph->dst) == sock->in_port) + { + if (sock->status == 0) + sock->out_port = grub_be_to_cpu16 (udph->src); + + /* App protocol remove its own reader. */ + sock->app->read (sock, nb); + + /* If there is data, puts packet in socket list. */ + if ((nb->tail - nb->data) > 0) + grub_net_put_packet (&sock->packs, nb); + else + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } From 338c7fab9be66bc5aa6cf093539a0aafa4010b83 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sat, 11 Jun 2011 16:57:19 +0200 Subject: [PATCH 186/673] fix grub-mount buildability on GNU/kFreeBSD --- Makefile.util.def | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.util.def b/Makefile.util.def index cd37d0d65..313339adc 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -223,7 +223,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)' '-lfuse'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse'; condition = COND_GRUB_MOUNT; }; diff --git a/configure.ac b/configure.ac index d1eaa0c84..26af7e7c3 100644 --- a/configure.ac +++ b/configure.ac @@ -871,7 +871,7 @@ fi if test x"$grub_mount_excuse" = x ; then # Check for fuse headers. SAVED_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26" AC_CHECK_HEADERS([fuse/fuse.h], [], [grub_mount_excuse=["need FUSE headers"]]) CPPFLAGS="$SAVED_CPPFLAGS" From 1e9aef7d963e86016cbb0568c5f9d01eee31fd99 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 13 Jun 2011 17:35:50 +0100 Subject: [PATCH 187/673] * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the input format. --- ChangeLog | 5 +++++ docs/man/grub-mklayout.h2m | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index fca980c1b..5ac0ffb5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-13 Colin Watson + + * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the + input format. + 2011-05-29 Colin Watson * docs/grub.texi (Obtaining and Building GRUB): Substitute diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m index cda6f3676..1e43409c0 100644 --- a/docs/man/grub-mklayout.h2m +++ b/docs/man/grub-mklayout.h2m @@ -1,4 +1,10 @@ [NAME] grub-mklayout \- generate a GRUB keyboard layout file +[DESCRIPTION] +grub-mklayout processes a keyboard layout description in +.BR keymaps (5) +format into a format that can be used by GRUB's +.B keymap +command. [SEE ALSO] .BR grub-mkconfig (8) From e23bc603f8e799dd85839ffe928b9e41d9a09d83 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Wed, 15 Jun 2011 15:11:26 -0300 Subject: [PATCH 188/673] Prevent crash when detecting fs. --- grub-core/net/net.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1232b3c74..380eec3b5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -581,6 +581,16 @@ grub_net_open_real (const char *name) return NULL; } +static grub_err_t +grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) __attribute__ ((unused))) +{ + if (!device->net) + return grub_error (GRUB_ERR_BAD_FS, "invalid extent"); + return GRUB_ERR_NONE; +} + static grub_err_t grub_net_fs_open (struct grub_file *file, const char *name) { @@ -1014,7 +1024,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), static struct grub_fs grub_net_fs = { .name = "netfs", - .dir = NULL, + .dir = grub_net_fs_dir, .open = grub_net_fs_open, .read = grub_net_fs_read, .close = grub_net_fs_close, From 881ac815d00ecf1aa9093b015edf8c2da334d191 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Thu, 16 Jun 2011 14:33:11 +0200 Subject: [PATCH 189/673] 2011-06-16 Robert Millan Detect `ataraid' devices on GNU/kFreeBSD. Fix for ATA devices using `ata' driver on kernel of FreeBSD 9. * util/deviceiter.c [__FreeBSD_kernel__] (get_ada_disk_name) (get_ataraid_disk_name): New functions. [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for ataraid (/dev/ar[0-9]+) and ada (/dev/ada[0-9]+) devices using get_ataraid_disk_name() and get_ada_disk_name(). --- ChangeLog | 11 +++++++++++ util/deviceiter.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5ac0ffb5c..043b858a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-06-16 Robert Millan + + Detect `ataraid' devices on GNU/kFreeBSD. Fix for ATA devices using + `ata' driver on kernel of FreeBSD 9. + + * util/deviceiter.c [__FreeBSD_kernel__] (get_ada_disk_name) + (get_ataraid_disk_name): New functions. + [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for ataraid + (/dev/ar[0-9]+) and ada (/dev/ada[0-9]+) devices using + get_ataraid_disk_name() and get_ada_disk_name(). + 2011-06-13 Colin Watson * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the diff --git a/util/deviceiter.c b/util/deviceiter.c index 30c18beea..2a8acec0e 100644 --- a/util/deviceiter.c +++ b/util/deviceiter.c @@ -1,7 +1,7 @@ /* deviceiter.c - iterate over system devices */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2011 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 @@ -286,6 +286,20 @@ get_scsi_disk_name (char *name, int unit) #endif } +#ifdef __FreeBSD_kernel__ +static void +get_ada_disk_name (char *name, int unit) +{ + sprintf (name, "/dev/ada%d", unit); +} + +static void +get_ataraid_disk_name (char *name, int unit) +{ + sprintf (name, "/dev/ar%d", unit); +} +#endif + #ifdef __linux__ static void get_virtio_disk_name (char *name, int unit) @@ -620,6 +634,35 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), } } +#ifdef __FreeBSD_kernel__ + /* IDE disks using ATA Direct Access driver. */ + if (get_kfreebsd_version () >= 800000) + for (i = 0; i < 96; i++) + { + char name[16]; + + get_ada_disk_name (name, i); + if (check_device_readable_unique (name)) + { + if (hook (name, 0)) + goto out; + } + } + + /* ATARAID disks. */ + for (i = 0; i < 8; i++) + { + char name[20]; + + get_ataraid_disk_name (name, i); + if (check_device_readable_unique (name)) + { + if (hook (name, 0)) + goto out; + } + } +#endif + #ifdef __linux__ /* Virtio disks. */ for (i = 0; i < 26; i++) From d6d205568f4ea7e6a49cd2ca745a8584d3bbca5d Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Sat, 18 Jun 2011 20:18:25 -0300 Subject: [PATCH 190/673] Close cards before boot. --- grub-core/kern/ieee1275/init.c | 2 ++ grub-core/net/drivers/ieee1275/ofnet.c | 4 ++++ grub-core/net/net.c | 11 +++++++++++ include/grub/net.h | 1 + 4 files changed, 18 insertions(+) diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index ad34ea188..3c55096a4 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -264,6 +264,8 @@ grub_machine_init (void) void grub_machine_fini (void) { + if (grub_grubnet_fini) + grub_grubnet_fini (); grub_ofdisk_fini (); grub_console_fini (); } diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 751583e9d..9789f2261 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -225,6 +225,10 @@ GRUB_MOD_INIT(ofnet) GRUB_MOD_FINI(ofnet) { + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->driver && !grub_strcmp (card->driver->name, "ofnet")) + card->driver->fini (card); grub_net_card_driver_unregister (&ofdriver); grub_getbootp = NULL; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 380eec3b5..c7732ecbf 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -1021,6 +1021,15 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), "unrecognised format specification %s", args[3]); } +static void +grub_grubnet_fini_real (void) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->driver) + card->driver->fini (card); +} + static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1060,6 +1069,7 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; grub_file_net_seek = grub_net_seek_real; + grub_grubnet_fini = grub_grubnet_fini_real; } GRUB_MOD_FINI(net) @@ -1074,4 +1084,5 @@ GRUB_MOD_FINI(net) grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; grub_file_net_seek = NULL; + grub_grubnet_fini = NULL; } diff --git a/include/grub/net.h b/include/grub/net.h index f9745acec..006ec0686 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -239,6 +239,7 @@ typedef struct grub_net extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); +void (*EXPORT_VAR (grub_grubnet_fini)) (void); struct grub_net_network_level_interface { From d855fbcf37fa97de08952aae80fc5bf704fdf149 Mon Sep 17 00:00:00 2001 From: "Manoel R. Abranches" Date: Sat, 18 Jun 2011 20:20:53 -0300 Subject: [PATCH 191/673] Add error verification in netbuff operations. --- grub-core/net/arp.c | 7 +++++-- grub-core/net/drivers/ieee1275/ofnet.c | 5 ++++- grub-core/net/ethernet.c | 11 ++++++++--- grub-core/net/ip.c | 5 ++++- grub-core/net/netbuff.c | 4 ++-- grub-core/net/tftp.c | 21 ++++++++++++--------- grub-core/net/udp.c | 4 +++- 7 files changed, 38 insertions(+), 19 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 0644d3d2e..6fc7554cd 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -39,6 +39,7 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; char *aux, arp_data[128]; + grub_err_t err; int i; /* Check cache table. */ @@ -52,9 +53,11 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, nb.head = arp_data; nb.end = arp_data + sizeof (arp_data); grub_netbuff_clear (&nb); - grub_netbuff_reserve (&nb, 128); - grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); + + if ((err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4))) != GRUB_ERR_NONE) + return err; + arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 9789f2261..2c264edb1 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -228,7 +228,10 @@ GRUB_MOD_FINI(ofnet) struct grub_net_card *card; FOR_NET_CARDS (card) if (card->driver && !grub_strcmp (card->driver->name, "ofnet")) - card->driver->fini (card); + { + card->driver->fini (card); + card->driver = NULL; + } grub_net_card_driver_unregister (&ofdriver); grub_getbootp = NULL; } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index d29193afe..d33a07010 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -15,8 +15,10 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_uint16_t ethertype) { struct etherhdr *eth; + grub_err_t err; - grub_netbuff_push (nb, sizeof (*eth)); + if ((err = grub_netbuff_push (nb, sizeof (*eth))) != GRUB_ERR_NONE) + return err; eth = (struct etherhdr *) nb->data; grub_memcpy (eth->dst, target_addr.mac, 6); grub_memcpy (eth->src, inf->hwaddress.mac, 6); @@ -33,10 +35,12 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) struct llchdr *llch; struct snaphdr *snaph; grub_uint16_t type; + grub_err_t err; eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); - grub_netbuff_pull (nb, sizeof (*eth)); + if ((err = grub_netbuff_pull (nb, sizeof (*eth))) != GRUB_ERR_NONE) + return err; if (type <= 1500) { @@ -45,7 +49,8 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3) { - grub_netbuff_pull (nb, sizeof (*llch)); + if ((err = grub_netbuff_pull (nb, sizeof (*llch))) != GRUB_ERR_NONE) + return err; snaph = (struct snaphdr *) nb->data; type = snaph->type; } diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 4adc2b028..749b41d02 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -85,7 +85,10 @@ grub_err_t grub_net_recv_ip_packets (struct grub_net_buff *nb) { struct iphdr *iph = (struct iphdr *) nb->data; - grub_netbuff_pull (nb, sizeof (*iph)); + grub_err_t err; + + if ((err = grub_netbuff_pull (nb, sizeof (*iph))) != GRUB_ERR_NONE) + return err; switch (iph->protocol) { diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index aae2f4d8f..d20104ab0 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -95,12 +95,12 @@ grub_err_t grub_netbuff_free (struct grub_net_buff *nb) { grub_free (nb->head); - return 0; + return GRUB_ERR_NONE; } grub_err_t grub_netbuff_clear (struct grub_net_buff *nb) { nb->data = nb->tail = nb->head; - return 0; + return GRUB_ERR_NONE; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index ac3b3e9db..138020b08 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -34,7 +34,8 @@ tftp_open (struct grub_file *file, const char *filename) grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 1500); - grub_netbuff_push (&nb, sizeof (*tftph)); + if ((err = grub_netbuff_push (&nb, sizeof (*tftph))) != GRUB_ERR_NONE) + return err; tftph = (struct tftphdr *) nb.data; @@ -67,8 +68,8 @@ tftp_open (struct grub_file *file, const char *filename) rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); - + if ((err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen))) != GRUB_ERR_NONE) + return err; file->device->net->socket->out_port = TFTP_SERVER_PORT; err = grub_net_send_udp_packet (file->device->net->socket, &nb); @@ -130,9 +131,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) grub_netbuff_clear (nb); break; case TFTP_DATA: - grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block)); - + if ((err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block))) != GRUB_ERR_NONE) + return err; if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { data->block++; @@ -141,7 +142,8 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) sock->status = 2; /* Prevent garbage in broken cards. */ if (size > 1024) - grub_netbuff_unput (nb, size - 1024); + if ((err = grub_netbuff_unput (nb, size - 1024)) != GRUB_ERR_NONE) + return err; } else grub_netbuff_clear (nb); @@ -154,8 +156,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) } grub_netbuff_clear (&nb_ack); grub_netbuff_reserve (&nb_ack, 128); - grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); + if ((err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block))) != GRUB_ERR_NONE) + return err; tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 86220bf0f..b070cbb64 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -9,8 +9,10 @@ grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb) { struct udphdr *udph; + grub_err_t err; - grub_netbuff_push (nb, sizeof (*udph)); + if ((err = grub_netbuff_push (nb, sizeof (*udph))) != GRUB_ERR_NONE) + return err; udph = (struct udphdr *) nb->data; udph->src = grub_cpu_to_be16 (socket->in_port); From 77ba5392d0e482de3618c00129c7bc2a35691cce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 08:45:12 +0200 Subject: [PATCH 192/673] New testload grub-fstest command --- Makefile.util.def | 1 + util/grub-fstest.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Makefile.util.def b/Makefile.util.def index 829b16fac..1fcd9465e 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -34,6 +34,7 @@ library = { common_nodist = grub_script.tab.h; common = grub-core/commands/blocklist.c; + common = grub-core/commands/testload.c; common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; common = grub-core/disk/dmraid_nvidia.c; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index f253a96f6..c2c8b1148 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -61,7 +61,8 @@ enum { CMD_CMP, CMD_HEX, CMD_CRC, - CMD_BLOCKLIST + CMD_BLOCKLIST, + CMD_TESTLOAD }; #define BUF_SIZE 32256 @@ -359,6 +360,9 @@ fstest (int n, char **args) case CMD_BLOCKLIST: execute_command ("blocklist", n, args); grub_printf ("\n"); + case CMD_TESTLOAD: + execute_command ("testload", n, args); + grub_printf ("\n"); } for (i = 0; i < num_disks; i++) @@ -520,6 +524,11 @@ argp_parser (int key, char *arg, struct argp_state *state) cmd = CMD_BLOCKLIST; nparm = 1; } + else if (!grub_strcmp (arg, "testload")) + { + cmd = CMD_TESTLOAD; + nparm = 1; + } else { fprintf (stderr, _("Invalid command %s.\n"), arg); From 2df2e89fee627a098b0192a526a2b6999699211c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 09:39:12 +0200 Subject: [PATCH 193/673] Fixed a cache collision bug. Thanks guufy1 for bugreport and test --- grub-core/kern/disk.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 30bc604f0..f1456defd 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -544,6 +544,17 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, break; } + if (data) + { + grub_memcpy ((char *) buf + + (agglomerate << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS)), + data, GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); + grub_disk_cache_unlock (disk->dev->id, disk->id, + sector + (agglomerate + << GRUB_DISK_CACHE_BITS)); + } + if (agglomerate) { grub_disk_addr_t i; @@ -568,17 +579,12 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, buf = (char *) buf + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); } - + if (data) { - grub_memcpy (buf, data, - GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); sector += GRUB_DISK_CACHE_SIZE; buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); - grub_disk_cache_unlock (disk->dev->id, disk->id, - sector + (agglomerate - << GRUB_DISK_CACHE_BITS)); } } From 8a5d6919e169d5839c474a5c0e8d8ed6b492fef1 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 23 Jun 2011 18:08:53 +0200 Subject: [PATCH 194/673] Avoid NULL deref in grub_device_open. * grub-core/kern/device.c (grub_device_open): Don't dereference a NULL pointer upon failed grub_env_get. --- ChangeLog | 6 ++++++ grub-core/kern/device.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e3ed5d13a..a7f6ce738 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Jim Meyering + + avoid NULL deref in grub_device_open + * grub-core/kern/device.c (grub_device_open): Don't dereference + a NULL pointer upon failed grub_env_get. + 2011-06-23 Vladimir Serbinenko Support non-512B sectors and agglomerate reads. diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 3db14f50e..50f49ae6b 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -35,7 +35,7 @@ grub_device_open (const char *name) if (! name) { name = grub_env_get ("root"); - if (*name == '\0') + if (name == NULL || *name == '\0') { grub_error (GRUB_ERR_BAD_DEVICE, "no device is set"); goto fail; From e2d1dba0ae8d87c9f9fc8ecbb4b10243507b2615 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 19:50:41 +0200 Subject: [PATCH 195/673] * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept /dev/root as a valid device. --- ChangeLog | 8 +++++++- grub-core/kern/emu/getroot.c | 6 ++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a7f6ce738..0ea09a0ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,12 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept + /dev/root as a valid device. + 2011-06-23 Jim Meyering - avoid NULL deref in grub_device_open + Avoid NULL deref in grub_device_open. + * grub-core/kern/device.c (grub_device_open): Don't dereference a NULL pointer upon failed grub_env_get. diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index 6e49cc31b..db27abf74 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -616,13 +616,15 @@ grub_guess_root_device (const char *dir) if (os_dev) { - if (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) != 0) + int dm = (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0); + int root = (strcmp (os_dev, "/dev/root") == 0); + if (!dm && !root) return os_dev; if (stat (os_dev, &st) < 0) grub_util_error ("cannot stat `%s'", os_dev); free (os_dev); dev = st.st_rdev; - return grub_find_device ("/dev/mapper", dev); + return grub_find_device (dm ? "/dev/mapper" : "/dev", dev); } if (stat (dir, &st) < 0) From a199a8cd1a5d01847e21bb40f21e044f4d728244 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:05:39 +0200 Subject: [PATCH 196/673] Fix spurious warning. * grub-core/partmap/acorn.c (grub_acorn_boot_block): Make a union. (acorn_partition_map_find): Use .bin member. --- ChangeLog | 7 +++++++ grub-core/partmap/acorn.c | 19 +++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ea09a0ab..a455d9b6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-23 Vladimir Serbinenko + + Fix spurious warning. + + * grub-core/partmap/acorn.c (grub_acorn_boot_block): Make a union. + (acorn_partition_map_find): Use .bin member. + 2011-06-23 Vladimir Serbinenko * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept diff --git a/grub-core/partmap/acorn.c b/grub-core/partmap/acorn.c index 9a68ddd92..341b8ac5f 100644 --- a/grub-core/partmap/acorn.c +++ b/grub-core/partmap/acorn.c @@ -34,11 +34,18 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct grub_acorn_boot_block { - grub_uint8_t misc[0x1C0]; - struct grub_filecore_disc_record disc_record; - grub_uint8_t flags; - grub_uint16_t start_cylinder; - grub_uint8_t checksum; + union + { + struct + { + grub_uint8_t misc[0x1C0]; + struct grub_filecore_disc_record disc_record; + grub_uint8_t flags; + grub_uint16_t start_cylinder; + grub_uint8_t checksum; + } __attribute__ ((packed, aligned)); + grub_uint8_t bin[0x200]; + }; } __attribute__ ((packed, aligned)); struct linux_part @@ -71,7 +78,7 @@ acorn_partition_map_find (grub_disk_t disk, struct linux_part *m, goto fail; for (i = 0; i != 0x1ff; ++i) - checksum = (checksum & 0xff) + (checksum >> 8) + boot.misc[i]; + checksum = ((checksum & 0xff) + (checksum >> 8) + boot.bin[i]); if ((grub_uint8_t) checksum != boot.checksum) goto fail; From e98c83e910e7fd3e39dd021213d111526e80775c Mon Sep 17 00:00:00 2001 From: David Volgyes Date: Thu, 23 Jun 2011 20:28:04 +0200 Subject: [PATCH 197/673] * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer dereference. --- ChangeLog | 5 +++++ grub-core/bus/usb/ohci.c | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index a455d9b6b..ad72c8da2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-23 David Volgyes + + * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer + dereference. + 2011-06-23 Vladimir Serbinenko Fix spurious warning. diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index df0d0f4af..7e8eaaac2 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -454,10 +454,12 @@ grub_ohci_pci_iter (grub_pci_device_t dev, fail: if (o) - grub_dma_free (o->td_chunk); - grub_dma_free (o->ed_bulk_chunk); - grub_dma_free (o->ed_ctrl_chunk); - grub_dma_free (o->hcca_chunk); + { + grub_dma_free (o->td_chunk); + grub_dma_free (o->ed_bulk_chunk); + grub_dma_free (o->ed_ctrl_chunk); + grub_dma_free (o->hcca_chunk); + } grub_free (o); return 0; From fbc626665f458d60cc3d19e1e8eedb68638cb4dc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:38:19 +0200 Subject: [PATCH 198/673] * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt to continue if allocation is failed. Reported by: David Volgyes . --- ChangeLog | 7 +++++++ grub-core/loader/i386/xnu.c | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad72c8da2..66c55d101 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt + to continue if allocation is failed. + + Reported by: David Volgyes . + 2011-06-23 David Volgyes * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index b877b0ea5..6128ec384 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -452,11 +452,11 @@ grub_cpu_xnu_fill_devprop (void) } devprop = grub_xnu_create_value (&(efikey->first_child), "device-properties"); - if (devprop) - { - devprop->data = grub_malloc (total_length); - devprop->datasize = total_length; - } + if (!devprop) + return grub_errno; + + devprop->data = grub_malloc (total_length); + devprop->datasize = total_length; ptr = devprop->data; head = ptr; From 1abe47dc9935106c0079d0e50388d2c6168864a5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:55:36 +0200 Subject: [PATCH 199/673] * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak. (main): Close file. --- ChangeLog | 5 +++++ grub-core/lib/reed_solomon.c | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 66c55d101..c267a8a0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak. + (main): Close file. + 2011-06-23 Vladimir Serbinenko * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index e500ba32d..8b5e8235a 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -265,6 +265,22 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) syndroms (m, s, rs, sy); + for (i = 0; i < (int) rs; i++) + if (sy[i] != 0) + break; + + /* No error detected. */ + if (i == (int) rs) + { +#ifndef STANDALONE + free (sigma); + free (errpot); + free (errpos); + free (sy); +#endif + return; + } + { gf_single_t *eq; @@ -275,14 +291,6 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) scratch += rs2 * (rs2 + 1) * sizeof (gf_single_t); #endif - for (i = 0; i < (int) rs; i++) - if (sy[i] != 0) - break; - - /* No error detected. */ - if (i == (int) rs) - return; - for (i = 0; i < (int) rs2; i++) for (j = 0; j < (int) rs2 + 1; j++) eq[i * (rs2 + 1) + j] = sy[i+j]; @@ -504,6 +512,7 @@ main (int argc, char **argv) rs = s / 3; buf = xmalloc (s + rs + SECTOR_SIZE); fread (buf, 1, s, in); + fclose (in); grub_reed_solomon_add_redundancy (buf, s, rs); From e061a1b537b1f8b719bfa69c49bdf39877fdf4d7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 20:58:35 +0200 Subject: [PATCH 200/673] * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]: Prevent memory leak. --- ChangeLog | 6 ++++++ grub-core/lib/reed_solomon.c | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/ChangeLog b/ChangeLog index c267a8a0f..327b52afc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,13 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]: + Prevent memory leak. + 2011-06-23 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak. (main): Close file. + Reported by: David Volgyes . 2011-06-23 Vladimir Serbinenko diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 8b5e8235a..365b76003 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -277,6 +277,11 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) free (errpot); free (errpos); free (sy); +#else + scratch -= rs2 * sizeof (gf_single_t); + scratch -= rs2 * sizeof (gf_single_t); + scratch -= rs2 * sizeof (int); + scratch -= rs * sizeof (gf_single_t); #endif return; } From 13548d26e9492450da911aa5b7c5d9e6850cb327 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 21:06:50 +0200 Subject: [PATCH 201/673] * util/raid.c (grub_util_raid_getmembers): Close fd before returning. Reported by: David Volgyes . --- ChangeLog | 6 ++++++ util/raid.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 327b52afc..058116fbb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Vladimir Serbinenko + + * util/raid.c (grub_util_raid_getmembers): Close fd before returning. + + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]: diff --git a/util/raid.c b/util/raid.c index a6aa5f95e..c1c32b959 100644 --- a/util/raid.c +++ b/util/raid.c @@ -80,6 +80,8 @@ grub_util_raid_getmembers (const char *name) devicelist[j] = NULL; + close (fd); + return devicelist; } From cad3237fb5ecf1a21f9e1bad957942a0cac8d6cc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 22:02:05 +0200 Subject: [PATCH 202/673] * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close file after stat. Reported by: David Volgyes . --- ChangeLog | 6 ++++++ grub-core/kern/emu/hostdisk.c | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 058116fbb..abe285ee9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close + file after stat. + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * util/raid.c (grub_util_raid_getmembers): Close fd before returning. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index e53a39c39..f4af73858 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1866,7 +1866,12 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk) /* Shouldn't happen either. */ if (fstat (fd, &st) < 0) - return 0; + { + close (fd); + return 0; + } + + close (fd); #if defined(__NetBSD__) if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) From 03147f46671e2270ef4849a710b20572462844ac Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 22:11:42 +0200 Subject: [PATCH 203/673] * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close. Reported by: David Volgyes . --- ChangeLog | 5 +++++ util/grub-mkpasswd-pbkdf2.c | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index abe285ee9..59cb3ec57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-23 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close. + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index dc2afdb6e..709ba7da7 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -270,7 +270,6 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - fclose (f); grub_util_error ("couldn't retrieve random data for salt"); } fclose (f); From fe12fd5b439956ab5354dde8699870cb0fd7c8bd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 23 Jun 2011 22:18:31 +0200 Subject: [PATCH 204/673] * util/ieee1275/ofpath.c (check_sas): Close fd. (main): Free of_path. Reported by: David Volgyes . --- ChangeLog | 6 ++++++ util/ieee1275/ofpath.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 59cb3ec57..062f66c00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-23 Vladimir Serbinenko + + * util/ieee1275/ofpath.c (check_sas): Close fd. + (main): Free of_path. + Reported by: David Volgyes . + 2011-06-23 Vladimir Serbinenko * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close. diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c index 1a433345d..f72bea8a5 100644 --- a/util/ieee1275/ofpath.c +++ b/util/ieee1275/ofpath.c @@ -297,6 +297,7 @@ check_sas (char *sysfs_path, int *tgt) free (path); free (p); + close (fd); } static void @@ -419,6 +420,7 @@ int main(int argc, char **argv) of_path = grub_util_devname_to_ofpath (argv[1]); printf("%s\n", of_path); + free (of_path); return 0; } From c31dc5f5e4291e2aa7fb9fbf5ed88640fb05cc83 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 23 Jun 2011 23:13:20 +0200 Subject: [PATCH 205/673] Add support for DRI and RSTn markers in JPEG files. * grub-core/video/readers/jpeg.c (JPEG_MARKER_DRI): New define. (JPEG_MARKER_RST0): Likewise. (JPEG_MARKER_RST1): Likewise. (JPEG_MARKER_RST2): Likewise. (JPEG_MARKER_RST3): Likewise. (JPEG_MARKER_RST4): Likewise. (JPEG_MARKER_RST5): Likewise. (JPEG_MARKER_RST6): Likewise. (JPEG_MARKER_RST7): Likewise. (grub_jpeg_data): New fields dri, r1, bitmap_ptr. (grub_jpeg_decode_dri): New function. (grub_jpeg_decode_sos): Move image data related part into grub_jpeg_decode_data function. (grub_jpeg_decode_data): New function. (grub_jpeg_reset): New function. (grub_jpeg_decode_jpeg): Handle new markers. --- ChangeLog | 21 +++++++++ grub-core/video/readers/jpeg.c | 78 ++++++++++++++++++++++++++++------ 2 files changed, 87 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 062f66c00..655cbe25e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2011-06-23 Szymon Janc + + Add support for DRI and RSTn markers in JPEG files. + + * grub-core/video/readers/jpeg.c (JPEG_MARKER_DRI): New define. + (JPEG_MARKER_RST0): Likewise. + (JPEG_MARKER_RST1): Likewise. + (JPEG_MARKER_RST2): Likewise. + (JPEG_MARKER_RST3): Likewise. + (JPEG_MARKER_RST4): Likewise. + (JPEG_MARKER_RST5): Likewise. + (JPEG_MARKER_RST6): Likewise. + (JPEG_MARKER_RST7): Likewise. + (grub_jpeg_data): New fields dri, r1, bitmap_ptr. + (grub_jpeg_decode_dri): New function. + (grub_jpeg_decode_sos): Move image data related part into + grub_jpeg_decode_data function. + (grub_jpeg_decode_data): New function. + (grub_jpeg_reset): New function. + (grub_jpeg_decode_jpeg): Handle new markers. + 2011-06-23 Vladimir Serbinenko * util/ieee1275/ofpath.c (check_sas): Close fd. diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c index 8cdb2f61d..d61c90ec9 100644 --- a/grub-core/video/readers/jpeg.c +++ b/grub-core/video/readers/jpeg.c @@ -39,6 +39,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define JPEG_MARKER_DQT 0xdb #define JPEG_MARKER_SOF0 0xc0 #define JPEG_MARKER_SOS 0xda +#define JPEG_MARKER_DRI 0xdd +#define JPEG_MARKER_RST0 0xd0 +#define JPEG_MARKER_RST1 0xd1 +#define JPEG_MARKER_RST2 0xd2 +#define JPEG_MARKER_RST3 0xd3 +#define JPEG_MARKER_RST4 0xd4 +#define JPEG_MARKER_RST5 0xd5 +#define JPEG_MARKER_RST6 0xd6 +#define JPEG_MARKER_RST7 0xd7 #define SHIFT_BITS 8 #define CONST(x) ((int) ((x) * (1L << SHIFT_BITS) + 0.5)) @@ -66,6 +75,7 @@ struct grub_jpeg_data { grub_file_t file; struct grub_video_bitmap **bitmap; + grub_uint8_t *bitmap_ptr; int image_width; int image_height; @@ -82,6 +92,8 @@ struct grub_jpeg_data jpeg_data_unit_t cbdu; int vs, hs; + int dri; + int r1; int dc_value[3]; @@ -315,6 +327,18 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data) return grub_errno; } +static grub_err_t +grub_jpeg_decode_dri (struct grub_jpeg_data *data) +{ + if (grub_jpeg_get_word (data) != 4) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "jpeg: DRI marker length must be 4"); + + data->dri = grub_jpeg_get_word (data); + + return grub_errno; +} + static void grub_jpeg_idct_transform (jpeg_data_unit_t du) { @@ -526,8 +550,7 @@ grub_jpeg_ycrcb_to_rgb (int yy, int cr, int cb, grub_uint8_t * rgb) static grub_err_t grub_jpeg_decode_sos (struct grub_jpeg_data *data) { - int i, cc, r1, c1, nr1, nc1, vb, hb; - grub_uint8_t *ptr1; + int i, cc; grub_uint32_t data_offset; data_offset = data->file->offset; @@ -563,17 +586,25 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) GRUB_VIDEO_BLIT_FORMAT_RGB_888)) return grub_errno; - data->bit_mask = 0x0; + data->bitmap_ptr = (*data->bitmap)->data; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_jpeg_decode_data (struct grub_jpeg_data *data) +{ + int c1, vb, hb, nr1, nc1; + int rst = data->dri; vb = data->vs * 8; hb = data->hs * 8; nr1 = (data->image_height + vb - 1) / vb; nc1 = (data->image_width + hb - 1) / hb; - ptr1 = (*data->bitmap)->data; - for (r1 = 0; r1 < nr1; - r1++, ptr1 += (vb * data->image_width - hb * nc1) * 3) - for (c1 = 0; c1 < nc1; c1++, ptr1 += hb * 3) + for (; data->r1 < nr1 && (!data->dri || rst); + data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3) + for (c1 = 0; c1 < nc1 && (!data->dri || rst); + c1++, rst--, data->bitmap_ptr += hb * 3) { int r2, c2, nr2, nc2; grub_uint8_t *ptr2; @@ -588,10 +619,10 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) if (grub_errno) return grub_errno; - nr2 = (r1 == nr1 - 1) ? (data->image_height - r1 * vb) : vb; + nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb; nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb; - ptr2 = ptr1; + ptr2 = data->bitmap_ptr; for (r2 = 0; r2 < nr2; r2++, ptr2 += (data->image_width - nc2) * 3) for (c2 = 0; c2 < nc2; c2++, ptr2 += 3) { @@ -600,8 +631,7 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) i0 = (r2 / data->vs) * 8 + (c2 / data->hs); cr = data->crdu[i0]; cb = data->cbdu[i0]; - yy = - data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)]; + yy = data->ydu[(r2 / 8) * 2 + (c2 / 8)][(r2 % 8) * 8 + (c2 % 8)]; grub_jpeg_ycrcb_to_rgb (yy, cr, cb, ptr2); } @@ -610,6 +640,16 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data) return grub_errno; } +static void +grub_jpeg_reset (struct grub_jpeg_data *data) +{ + data->bit_mask = 0x0; + + data->dc_value[0] = 0; + data->dc_value[1] = 0; + data->dc_value[2] = 0; +} + static grub_uint8_t grub_jpeg_get_marker (struct grub_jpeg_data *data) { @@ -655,8 +695,22 @@ grub_jpeg_decode_jpeg (struct grub_jpeg_data *data) case JPEG_MARKER_SOF0: /* Start Of Frame 0. */ grub_jpeg_decode_sof (data); break; + case JPEG_MARKER_DRI: /* Define Restart Interval. */ + grub_jpeg_decode_dri (data); + break; case JPEG_MARKER_SOS: /* Start Of Scan. */ - grub_jpeg_decode_sos (data); + if (grub_jpeg_decode_sos (data)) + break; + case JPEG_MARKER_RST0: /* Restart. */ + case JPEG_MARKER_RST1: + case JPEG_MARKER_RST2: + case JPEG_MARKER_RST3: + case JPEG_MARKER_RST4: + case JPEG_MARKER_RST5: + case JPEG_MARKER_RST6: + case JPEG_MARKER_RST7: + grub_jpeg_decode_data (data); + grub_jpeg_reset (data); break; case JPEG_MARKER_EOI: /* End Of Image. */ return grub_errno; From 005dd67cb68ece8ea1af43c5c11096d0d32614ea Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 00:29:21 +0200 Subject: [PATCH 206/673] * grub-core/disk/ahci.c: Add missing license statements. * grub-core/fs/romfs.c: Likewise. * grub-core/lib/ia64/setjmp.S: Likewise. * grub-core/loader/i386/pc/freedos.c: Likewise. * grub-core/loader/ia64/efi/linux.c: Likewise. * grub-core/video/colors.c: Likewise. * include/grub/dl.h (GRUB_MOD_DEP): New macro. --- grub-core/disk/ahci.c | 2 ++ grub-core/fs/romfs.c | 2 ++ grub-core/lib/ia64/setjmp.S | 6 ++++++ grub-core/loader/i386/pc/freedos.c | 2 ++ grub-core/loader/ia64/efi/linux.c | 2 ++ grub-core/video/colors.c | 3 +++ include/grub/dl.h | 3 +++ 7 files changed, 20 insertions(+) diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 699df767c..0f355aa53 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -27,6 +27,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_ahci_cmd_head { grub_uint32_t config; diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 07632e635..58dc98f34 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -24,6 +24,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + struct grub_romfs_superblock { char magic[8]; diff --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S index 0851885c5..190623d35 100644 --- a/grub-core/lib/ia64/setjmp.S +++ b/grub-core/lib/ia64/setjmp.S @@ -64,6 +64,12 @@ 0x1b0 f30 0x1c0 f31 */ +#include +#include + + .file "setjmp.S" + +GRUB_MOD_LICENSE ("GPLv2+") /* The following two entry points are the traditional entry points: */ diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c index 0ae815490..f796e08f4 100644 --- a/grub-core/loader/i386/pc/freedos.c +++ b/grub-core/loader/i386/pc/freedos.c @@ -33,6 +33,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static struct grub_relocator *rel; static grub_uint32_t ebx = 0xffffffff; diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index b018e4549..247eebae5 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -31,6 +31,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + #define ALIGN_MIN (256*1024*1024) #define GRUB_ELF_SEARCH 1024 diff --git a/grub-core/video/colors.c b/grub-core/video/colors.c index 0637c5508..3119c0249 100644 --- a/grub-core/video/colors.c +++ b/grub-core/video/colors.c @@ -21,6 +21,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); struct named_color { diff --git a/include/grub/dl.h b/include/grub/dl.h index 5ce01199c..75cd71758 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -90,6 +90,9 @@ static const char grub_module_name_##name[] \ #ifndef ASM_FILE #define GRUB_MOD_LICENSE(license) \ static char grub_module_license[] __attribute__ ((section (GRUB_MOD_SECTION (module_license)), used)) = "LICENSE=" license; +#define GRUB_MOD_DEP(name) \ +static const char grub_module_depend_##name[] \ + __attribute__((section(GRUB_MOD_SECTION(moddeps)), __used__)) = #name #else #define GRUB_MOD_LICENSE(license) \ .section GRUB_MOD_SECTION(module_license), "a"; \ From 290766fb770aa9d3ebd3ada989ae3b24d21a093a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 00:31:29 +0200 Subject: [PATCH 207/673] ZFS zlib support * grub-core/fs/zfs/zfs.c (zlib_decompress): New function. (decomp_table): Add zlib entries. (zio_read): USe 8 bits for compression function rather than 3. * include/grub/zfs/zio.h (zio_compress): Add zlib values. --- ChangeLog | 19 +++++++++++++++++++ grub-core/fs/zfs/zfs.c | 22 ++++++++++++++++++++-- include/grub/zfs/zio.h | 10 +++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6535b6e17..954166148 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-06-24 Vladimir Serbinenko + + ZFS zlib support + + * grub-core/fs/zfs/zfs.c (zlib_decompress): New function. + (decomp_table): Add zlib entries. + (zio_read): USe 8 bits for compression function rather than 3. + * include/grub/zfs/zio.h (zio_compress): Add zlib values. + +2011-06-24 Vladimir Serbinenko + + * grub-core/disk/ahci.c: Add missing license statements. + * grub-core/fs/romfs.c: Likewise. + * grub-core/lib/ia64/setjmp.S: Likewise. + * grub-core/loader/i386/pc/freedos.c: Likewise. + * grub-core/loader/ia64/efi/linux.c: Likewise. + * grub-core/video/colors.c: Likewise. + * include/grub/dl.h (GRUB_MOD_DEP): New macro. + 2011-06-23 Vladimir Serbinenko AHCI support. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 8d86cf9e5..1eea13b26 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -51,6 +51,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -163,13 +164,30 @@ struct grub_zfs_data grub_disk_addr_t vdev_phys_sector; }; +static grub_err_t +zlib_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) +{ + if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0) + return grub_errno; + return GRUB_ERR_NONE; +} + static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"inherit", NULL}, /* ZIO_COMPRESS_INHERIT */ {"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */ {"off", NULL}, /* ZIO_COMPRESS_OFF */ {"lzjb", lzjb_decompress}, /* ZIO_COMPRESS_LZJB */ {"empty", NULL}, /* ZIO_COMPRESS_EMPTY */ - {"gzip", NULL}, /* ZIO_COMPRESS_GZIP */ + {"gzip-1", zlib_decompress}, /* ZIO_COMPRESS_GZIP1 */ + {"gzip-2", zlib_decompress}, /* ZIO_COMPRESS_GZIP2 */ + {"gzip-3", zlib_decompress}, /* ZIO_COMPRESS_GZIP3 */ + {"gzip-4", zlib_decompress}, /* ZIO_COMPRESS_GZIP4 */ + {"gzip-5", zlib_decompress}, /* ZIO_COMPRESS_GZIP5 */ + {"gzip-6", zlib_decompress}, /* ZIO_COMPRESS_GZIP6 */ + {"gzip-7", zlib_decompress}, /* ZIO_COMPRESS_GZIP7 */ + {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ + {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ }; static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, @@ -527,7 +545,7 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, *buf = NULL; checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; - comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7; + comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; lsize = (BP_IS_HOLE(bp) ? 0 : (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) << SPA_MINBLOCKSHIFT)); diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h index 797d4f9b3..3dafb4028 100644 --- a/include/grub/zfs/zio.h +++ b/include/grub/zfs/zio.h @@ -77,7 +77,15 @@ enum zio_compress { ZIO_COMPRESS_OFF, ZIO_COMPRESS_LZJB, ZIO_COMPRESS_EMPTY, - ZIO_COMPRESS_GZIP, + ZIO_COMPRESS_GZIP1, + ZIO_COMPRESS_GZIP2, + ZIO_COMPRESS_GZIP3, + ZIO_COMPRESS_GZIP4, + ZIO_COMPRESS_GZIP5, + ZIO_COMPRESS_GZIP6, + ZIO_COMPRESS_GZIP7, + ZIO_COMPRESS_GZIP8, + ZIO_COMPRESS_GZIP9, ZIO_COMPRESS_FUNCTIONS }; From bc09e1a23804bd4132a51bca01851135d7307bff Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 04:32:54 +0200 Subject: [PATCH 208/673] * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to old method if mountinfo would return /dev/root and /dev/root doesn't exist. --- ChangeLog | 6 ++++++ grub-core/kern/emu/getroot.c | 10 ++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 954166148..1b63af871 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to + old method if mountinfo would return /dev/root and /dev/root doesn't + exist. + 2011-06-24 Vladimir Serbinenko ZFS zlib support diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index db27abf74..6d6c8ef8b 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -620,11 +620,13 @@ grub_guess_root_device (const char *dir) int root = (strcmp (os_dev, "/dev/root") == 0); if (!dm && !root) return os_dev; - if (stat (os_dev, &st) < 0) - grub_util_error ("cannot stat `%s'", os_dev); + if (stat (os_dev, &st) >= 0) + { + free (os_dev); + dev = st.st_rdev; + return grub_find_device (dm ? "/dev/mapper" : "/dev", dev); + } free (os_dev); - dev = st.st_rdev; - return grub_find_device (dm ? "/dev/mapper" : "/dev", dev); } if (stat (dir, &st) < 0) From 535c191059459b9212991f59aea494db1c1da767 Mon Sep 17 00:00:00 2001 From: Alexander Kurtz Date: Fri, 24 Jun 2011 12:38:24 +0200 Subject: [PATCH 209/673] * util/grub-mkconfig_lib.in: Add missing quotes. --- ChangeLog | 4 ++++ util/grub-mkconfig_lib.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1b63af871..d5c97b6e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-24 Alexander Kurtz + + * util/grub-mkconfig_lib.in: Add missing quotes. + 2011-06-24 Vladimir Serbinenko * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 2c5fd8c6f..759bcba1b 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -63,7 +63,7 @@ is_path_readable_by_grub () # ... or if we can't figure out the abstraction module, for example if # memberlist fails on an LVM volume group. - if ${grub_probe} -t abstraction $path > /dev/null 2>&1 ; then : ; else + if "${grub_probe}" -t abstraction "$path" > /dev/null 2>&1 ; then : ; else return 1 fi From 2a5e94d84abd9efad39e7eafe68fb766cea87314 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 12:41:05 +0200 Subject: [PATCH 210/673] * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load partmap before abstraction. --- ChangeLog | 5 +++++ util/grub-mkconfig_lib.in | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5c97b6e0..1e7a468ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-24 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load + partmap before abstraction. + 2011-06-24 Alexander Kurtz * util/grub-mkconfig_lib.in: Add missing quotes. diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 759bcba1b..090fcf314 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -105,12 +105,6 @@ prepare_grub_to_access_device () { device="$1" - # Abstraction modules aren't auto-loaded. - abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" - for module in ${abstraction} ; do - echo "insmod ${module}" - done - partmap="`"${grub_probe}" --device "${device}" --target=partmap`" for module in ${partmap} ; do case "${module}" in @@ -121,6 +115,12 @@ prepare_grub_to_access_device () esac done + # Abstraction modules aren't auto-loaded. + abstraction="`"${grub_probe}" --device "${device}" --target=abstraction`" + for module in ${abstraction} ; do + echo "insmod ${module}" + done + fs="`"${grub_probe}" --device "${device}" --target=fs`" for module in ${fs} ; do echo "insmod ${module}" From 98e2f50661b63494a7d94d3ad04d31669468f9b4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 13:02:49 +0200 Subject: [PATCH 211/673] * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and .. --- ChangeLog | 4 ++++ grub-core/fs/iso9660.c | 11 ++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1e7a468ec..d21fa1026 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and .. + 2011-06-24 Vladimir Serbinenko * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 508cc5b71..5b53ca597 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -598,7 +598,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, return 0; } - while (offset < dir->size) + for (; offset < dir->size; offset += dirent.len) { if (grub_disk_read (dir->data->disk, (dir->blk << GRUB_ISO9660_LOG2_BLKSZ) @@ -676,10 +676,9 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, if (filename) *filename = '\0'; - if (dirent.namelen == 1 && name[0] == 0) - filename = "."; - else if (dirent.namelen == 1 && name[0] == 1) - filename = ".."; + /* . and .. */ + if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1)) + continue; else filename = name; } @@ -712,8 +711,6 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, if (filename_alloc) grub_free (filename); } - - offset += dirent.len; } return 0; From 4388ca7224904dd35cafb7aa4a48fe60af1cdd4d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 13:43:10 +0200 Subject: [PATCH 212/673] * grub-core/commands/wildcard.c (match_files): Add a useful dprintf. (wildcard_expand): Don't stop on nonregexp parts after regexp ones since it truncates the output. Reported by: Ximin Luo. --- ChangeLog | 7 +++++++ grub-core/commands/wildcard.c | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d21fa1026..eaee6266a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/commands/wildcard.c (match_files): Add a useful dprintf. + (wildcard_expand): Don't stop on nonregexp parts after regexp ones since + it truncates the output. + Reported by: Ximin Luo. + 2011-06-24 Vladimir Serbinenko * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and .. diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 32561abe6..45d819a3e 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -288,6 +288,8 @@ match_files (const char *prefix, const char *suffix, const char *end, if (regexec (regexp, name, 0, 0, 0)) return 0; + grub_dprintf ("expand", "matched\n"); + buffer = grub_xasprintf ("%s%s", dir, name); if (! buffer) return 1; @@ -423,8 +425,6 @@ wildcard_expand (const char *s, char ***strs) while (*start) { split_path (start, &noregexop, ®exop); - if (noregexop >= regexop) /* no more wildcards */ - break; if (make_regex (noregexop, regexop, ®exp)) goto fail; From 031f22a01f81f3b65bdc8bc8fde473a5f847752e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 18:26:20 +0200 Subject: [PATCH 213/673] * grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable names. --- ChangeLog | 5 +++++ grub-core/disk/raid.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/ChangeLog b/ChangeLog index eaee6266a..d70c7c6c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-24 Vladimir Serbinenko + + * grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable + names. + 2011-06-24 Vladimir Serbinenko * grub-core/commands/wildcard.c (match_files): Add a useful dprintf. diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index c6be3efde..7c7dbc3dc 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -679,6 +679,49 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, scanner_name); #endif + { + int max_used_number = 0, len, need_new_name = 0; + int add_us = 0; + len = grub_strlen (array->name); + if (len && grub_isdigit (array->name[len-1])) + add_us = 1; + for (p = array_list; p != NULL; p = p->next) + { + int cur_num; + char *num, *end; + if (grub_strncmp (p->name, array->name, len) != 0) + continue; + if (p->name[len] == 0) + { + need_new_name = 1; + continue; + } + if (add_us && p->name[len] != '_') + continue; + if (add_us) + num = p->name + len + 1; + else + num = p->name + len; + if (!grub_isdigit (num[0])) + continue; + cur_num = grub_strtoull (num, &end, 10); + if (end[0]) + continue; + if (cur_num > max_used_number) + max_used_number = cur_num; + } + if (need_new_name) + { + char *tmp; + tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "", + max_used_number + 1); + if (!tmp) + return grub_errno; + grub_free (array->name); + array->name = tmp; + } + } + /* Add our new array to the list. */ array->next = array_list; array_list = array; From 8b51fd98b90531c9a3407ee0d00c935171f58e92 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 24 Jun 2011 20:35:25 +0200 Subject: [PATCH 214/673] bootp support --- grub-core/net/arp.c | 8 + grub-core/net/drivers/emu/emunet.c | 6 +- grub-core/net/ethernet.c | 11 +- grub-core/net/ip.c | 69 +++++--- grub-core/net/net.c | 268 ++++++++++++++++++++++++++--- grub-core/net/tftp.c | 12 +- grub-core/net/udp.c | 10 +- include/grub/emu/export.h | 6 + include/grub/net.h | 38 ++-- include/grub/net/ethernet.h | 16 +- include/grub/net/netbuff.h | 2 +- include/grub/net/udp.h | 5 +- 12 files changed, 360 insertions(+), 91 deletions(-) create mode 100644 include/grub/emu/export.h diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index 0644d3d2e..1dbd8a58f 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -41,6 +41,14 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, char *aux, arp_data[128]; int i; + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && proto_addr->ipv4 == 0xffffffff) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memset (hw_addr->mac, -1, 6); + return GRUB_ERR_NONE; + } + /* Check cache table. */ entry = arp_find_entry (proto_addr); if (entry) diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index ee4ba4773..d1e49a2f4 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -13,8 +13,8 @@ static int fd; -static grub_err_t -send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), +static grub_err_t +send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { ssize_t actual; @@ -27,7 +27,7 @@ send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)), } static grub_ssize_t -get_card_packet (struct grub_net_card *dev __attribute__ ((unused)), +get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *pack) { ssize_t actual; diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index d29193afe..f1bc8c1d0 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -27,12 +27,14 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, } grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_buff *nb) +grub_net_recv_ethernet_packet (struct grub_net_buff * nb, + const struct grub_net_card * card) { struct etherhdr *eth; struct llchdr *llch; struct snaphdr *snaph; grub_uint16_t type; + grub_net_link_level_address_t hwaddress; eth = (struct etherhdr *) nb->data; type = grub_be_to_cpu16 (eth->type); @@ -51,7 +53,10 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) } } - /* ARP packet. */ + hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); + + /* ARP packet. */ if (type == GRUB_NET_ETHERTYPE_ARP) { grub_net_arp_receive (nb); @@ -59,7 +64,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb) } /* IP packet. */ if (type == GRUB_NET_ETHERTYPE_IP) - grub_net_recv_ip_packets (nb); + grub_net_recv_ip_packets (nb, card, &hwaddress); return GRUB_ERR_NONE; } diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 4adc2b028..808532a4a 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -25,9 +25,9 @@ ipchksum (void *ipv, int len) } grub_err_t -grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *target, - struct grub_net_buff *nb) +grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, + const grub_net_network_level_address_t * target, + struct grub_net_buff * nb) { struct iphdr *iph; static int id = 0x2400; @@ -54,43 +54,58 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, err = grub_net_arp_resolve (inf, target, &ll_target_addr); if (err) return err; - return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); + return send_ethernet_packet (inf, nb, ll_target_addr, + GRUB_NET_ETHERTYPE_IP); } -/* -static int -ip_filter (struct grub_net_buff *nb) +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff * nb, + const struct grub_net_card * card, + const grub_net_link_level_address_t * hwaddress) { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; + struct grub_net_network_level_interface *inf; - if (nb->end - nb->data < (signed) sizeof (*iph)) - return 0; - - if (iph->protocol != 0x11 || - iph->dest != inf->address.ipv4) - return 0; - - grub_netbuff_pull (nb, sizeof (iph)); - err = grub_net_put_packet (&inf->nl_pending, nb); + err = grub_netbuff_pull (nb, sizeof (*iph)); if (err) + return err; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && inf->address.ipv4 == iph->dest + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + } + if (!inf) { - grub_print_error (); - return 0; + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + } + if (!inf) + { + if (iph->protocol == IP_UDP + && grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0) + { + struct udphdr *udph; + udph = (struct udphdr *) nb->data; + grub_netbuff_pull (nb, sizeof (*udph)); + if (grub_be_to_cpu16 (udph->dst) == 68) + grub_net_process_dhcp (nb, card); + } + grub_netbuff_free (nb); + return GRUB_ERR_NONE; } - return 1; -} -*/ -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb) -{ - struct iphdr *iph = (struct iphdr *) nb->data; - grub_netbuff_pull (nb, sizeof (*iph)); switch (iph->protocol) { case IP_UDP: - return grub_net_recv_udp_packet (nb); + return grub_net_recv_udp_packet (nb, inf); break; default: grub_netbuff_free (nb); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1232b3c74..2da60256c 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -16,6 +16,7 @@ * along with GRUB. If not, see . */ +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -54,8 +56,11 @@ static struct grub_fs grub_net_fs; static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { - grub_list_remove (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); + *inter->prev = inter->next; + if (inter->next) + inter->next->prev = inter->prev; + inter->next = 0; + inter->prev = 0; } static inline void @@ -112,6 +117,8 @@ match_net (const grub_net_network_level_netaddress_t *net, return 0; switch (net->type) { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + return 0; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize); @@ -229,6 +236,9 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) { switch (target->type) { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + grub_strcpy (buf, "promisc"); + return; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); @@ -270,6 +280,23 @@ hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) grub_printf ("Unsupported hw address type %d\n", addr->type); } +int +grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + const grub_net_link_level_address_t *b) +{ + if (a->type < b->type) + return -1; + if (a->type > b->type) + return +1; + switch (a->type) + { + case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: + return grub_memcmp (a->mac, b->mac, sizeof (a->mac)); + } + grub_printf ("Unsupported hw address type %d\n", a->type); + return 1; +} + /* FIXME: implement this. */ static char * hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)), @@ -307,12 +334,16 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa grub_register_variable_hook (name, 0, addr_set_env); } - grub_list_push (GRUB_AS_LIST_P (&grub_net_network_level_interfaces), - GRUB_AS_LIST (inter)); + inter->prev = &grub_net_network_level_interfaces; + inter->next = grub_net_network_level_interfaces; + if (inter->next) + inter->next->prev = &inter->next; + grub_net_network_level_interfaces = inter; } struct grub_net_network_level_interface * -grub_net_add_addr (const char *name, struct grub_net_card *card, +grub_net_add_addr (const char *name, + const struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags) @@ -488,6 +519,9 @@ print_net_address (const grub_net_network_level_netaddress_t *target) { switch (target->type) { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + grub_printf ("promisc\n"); + break; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base); @@ -546,6 +580,23 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +static grub_err_t +grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_net_network_level_interface *inf; + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + char bufh[MAX_STR_HWADDR_LEN]; + char bufn[GRUB_NET_MAX_STR_ADDR_LEN]; + hwaddr_to_str (&inf->hwaddress, bufh); + grub_net_addr_to_str (&inf->address, bufn); + grub_printf ("%s %s %s\n", inf->name, bufh, bufn); + } + return GRUB_ERR_NONE; +} + grub_net_app_level_t grub_net_app_level_list; struct grub_net_socket *grub_net_sockets; @@ -649,22 +700,27 @@ grub_net_fs_close (grub_file_t file) static void receive_packets (struct grub_net_card *card) { - /* Maybe should be better have a fixed number of packets for each card - and just mark them as used and not used. */ - struct grub_net_buff *nb; - grub_ssize_t actual; - nb = grub_netbuff_alloc (1500); - if (!nb) + while (1) { - grub_print_error (); - return; - } + /* Maybe should be better have a fixed number of packets for each card + and just mark them as used and not used. */ + struct grub_net_buff *nb; + grub_ssize_t actual; + nb = grub_netbuff_alloc (1500); + if (!nb) + { + grub_print_error (); + return; + } - actual = card->driver->recv (card, nb); - if (actual < 0) - grub_netbuff_free (nb); - else - grub_net_recv_ethernet_packet (nb); + actual = card->driver->recv (card, nb); + if (actual < 0) + { + grub_netbuff_free (nb); + break; + } + grub_net_recv_ethernet_packet (nb, card); + } grub_print_error (); } @@ -828,9 +884,10 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) #define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) struct grub_net_network_level_interface * -grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, +grub_net_configure_by_dhcp_ack (const char *name, + const struct grub_net_card *card, grub_net_interface_flags_t flags, - struct grub_net_bootp_ack *bp, + const struct grub_net_bootp_packet *bp, grub_size_t size) { grub_net_network_level_address_t addr; @@ -889,6 +946,38 @@ grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, return inter; } +void +grub_net_process_dhcp (struct grub_net_buff *nb, + const struct grub_net_card *card) +{ + char *name; + struct grub_net_network_level_interface *inf; + + name = grub_xasprintf ("%s:dhcp", card->name); + if (!name) + { + grub_print_error (); + return; + } + grub_net_configure_by_dhcp_ack (name, card, + 0, (const struct grub_net_bootp_packet *) nb->data, + (nb->tail - nb->data)); + grub_free (name); + if (grub_errno) + grub_print_error (); + else + { + FOR_NET_NETWORK_LEVEL_INTERFACES(inf) + if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0 + && grub_memcmp (inf->name + grub_strlen (card->name), + ":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0) + { + grub_net_network_level_interface_unregister (inf); + break; + } + } +} + static char hexdigit (grub_uint8_t val) { @@ -1011,6 +1100,131 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), "unrecognised format specification %s", args[3]); } +static grub_err_t +grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_interface *ifaces; + grub_size_t ncards = 0; + unsigned j = 0; + int interval; + grub_err_t err; + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ncards++; + } + + ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); + if (!ifaces) + return grub_errno; + + j = 0; + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ifaces[j].card = card; + ifaces[j].next = &ifaces[j+1]; + if (j) + ifaces[j].prev = &ifaces[j-1].next; + ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); + if (!ifaces[j].name) + { + unsigned i; + for (i = 0; i < j; i++) + grub_free (ifaces[i].name); + grub_free (ifaces); + return grub_errno; + } + ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC; + grub_memcpy (&ifaces[j].hwaddress, &card->default_address, + sizeof (ifaces[j].hwaddress)); + j++; + } + ifaces[ncards - 1].next = grub_net_network_level_interfaces; + if (grub_net_network_level_interfaces) + grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next; + grub_net_network_level_interfaces = &ifaces[0]; + ifaces[0].prev = &grub_net_network_level_interfaces; + for (interval = 200; interval < 10000; interval *= 2) + { + int done = 0; + for (j = 0; j < ncards; j++) + { + struct grub_net_bootp_packet *pack; + struct grub_datetime date; + grub_int32_t t; + struct grub_net_buff *nb; + struct udphdr *udph; + grub_net_network_level_address_t target; + + if (!ifaces[j].prev) + continue; + nb = grub_netbuff_alloc (sizeof (*pack)); + if (!nb) + return grub_errno; + err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); + if (err) + return err; + err = grub_netbuff_push (nb, sizeof (*pack) + 64); + if (err) + return err; + pack = (void *) nb->data; + done = 1; + grub_memset (pack, 0, sizeof (*pack) + 64); + pack->opcode = 1; + pack->hw_type = 1; + pack->hw_len = 6; + err = grub_get_datetime (&date); + if (err || !grub_datetime2unixtime (&date, &t)) + { + grub_errno = GRUB_ERR_NONE; + t = 0; + } + pack->ident = grub_cpu_to_be32 (t); + pack->seconds = 0;//grub_cpu_to_be16 (t); + + grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); + + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; + udph->src = grub_cpu_to_be16 (68); + udph->dst = grub_cpu_to_be16 (67); + udph->chksum = 0; + udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4 = 0xffffffff; + + err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + if (err) + return err; + } + if (!done) + break; + grub_net_poll_cards (interval); + } + + err = GRUB_ERR_NONE; + for (j = 0; j < ncards; j++) + { + if (!ifaces[j].prev) + continue; + grub_error_push (); + grub_net_network_level_interface_unregister (&ifaces[j]); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", + ifaces[j].card->name); + } + + return err; +} + + static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1023,7 +1237,8 @@ static struct grub_fs grub_net_fs = .mtime = NULL, }; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; -static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp; +static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp; +static grub_command_t cmd_dhcp, cmd_lsaddr; GRUB_MOD_INIT(net) { @@ -1043,6 +1258,14 @@ GRUB_MOD_INIT(net) "", N_("list network routes")); cmd_lscards = grub_register_command ("net_ls_cards", grub_cmd_listcards, "", N_("list network cards")); + cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs, + "", N_("list network addresses")); + cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); + cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, N_("VAR INTERFACE NUMBER DESCRIPTION"), N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); @@ -1060,6 +1283,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_delroute); grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); + grub_unregister_command (cmd_lsaddr); grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index ac3b3e9db..545862092 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -24,7 +24,7 @@ tftp_open (struct grub_file *file, const char *filename) tftp_data_t data; grub_err_t err; - data = grub_malloc (sizeof *data); + data = grub_malloc (sizeof (*data)); if (!data) return grub_errno; @@ -86,7 +86,7 @@ tftp_open (struct grub_file *file, const char *filename) /* Retry. */ /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); if (err) - return err; */ + return err; */ } if (file->device->net->socket->status == 0) @@ -154,8 +154,8 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) } grub_netbuff_clear (&nb_ack); grub_netbuff_reserve (&nb_ack, 128); - grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); + grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block)); tftph = (struct tftphdr *) nb_ack.data; tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); @@ -180,12 +180,12 @@ static struct grub_net_app_protocol grub_tftp_protocol = .close = tftp_close }; -GRUB_MOD_INIT(tftp) +GRUB_MOD_INIT (tftp) { grub_net_app_level_register (&grub_tftp_protocol); } -GRUB_MOD_FINI(tftp) +GRUB_MOD_FINI (tftp) { grub_net_app_level_unregister (&grub_tftp_protocol); } diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 86220bf0f..cc7534ea1 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -24,7 +24,8 @@ grub_net_send_udp_packet (const grub_net_socket_t socket, } grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff *nb) +grub_net_recv_udp_packet (struct grub_net_buff * nb, + struct grub_net_network_level_interface * inf) { struct udphdr *udph; grub_net_socket_t sock; @@ -33,7 +34,8 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) FOR_NET_SOCKETS (sock) { - if (grub_be_to_cpu16 (udph->dst) == sock->in_port) + if (grub_be_to_cpu16 (udph->dst) == sock->in_port + && inf == sock->inf && sock->app) { if (sock->status == 0) sock->out_port = grub_be_to_cpu16 (udph->src); @@ -41,7 +43,7 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) /* App protocol remove its own reader. */ sock->app->read (sock, nb); - /* If there is data, puts packet in socket list. */ + /* If there is data, puts packet in socket list. */ if ((nb->tail - nb->data) > 0) grub_net_put_packet (&sock->packs, nb); else @@ -49,6 +51,8 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb) return GRUB_ERR_NONE; } } + if (grub_be_to_cpu16 (udph->dst) == 68) + grub_net_process_dhcp (nb, inf->card); grub_netbuff_free (nb); return GRUB_ERR_NONE; } diff --git a/include/grub/emu/export.h b/include/grub/emu/export.h new file mode 100644 index 000000000..1e2f0432b --- /dev/null +++ b/include/grub/emu/export.h @@ -0,0 +1,6 @@ +void EXPORT_FUNC (open64) (void); +void EXPORT_FUNC (close) (void); +void EXPORT_FUNC (read) (void); +void EXPORT_FUNC (write) (void); +void EXPORT_FUNC (ioctl) (void); + diff --git a/include/grub/net.h b/include/grub/net.h index f9745acec..5d99cace3 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -62,8 +62,10 @@ struct grub_net_card_driver char *name; grub_err_t (*init) (struct grub_net_card *dev); grub_err_t (*fini) (struct grub_net_card *dev); - grub_err_t (*send) (struct grub_net_card *dev, struct grub_net_buff *buf); - grub_ssize_t (*recv) (struct grub_net_card *dev, struct grub_net_buff *buf); + grub_err_t (*send) (const struct grub_net_card *dev, + struct grub_net_buff *buf); + grub_ssize_t (*recv) (const struct grub_net_card *dev, + struct grub_net_buff *buf); }; extern struct grub_net_card_driver *grub_net_card_drivers; @@ -116,6 +118,7 @@ struct grub_net_network_level_interface; typedef enum grub_network_level_protocol_id { + GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC, GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 } grub_network_level_protocol_id_t; @@ -243,12 +246,13 @@ extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, gr struct grub_net_network_level_interface { struct grub_net_network_level_interface *next; + struct grub_net_network_level_interface **prev; char *name; - struct grub_net_card *card; + const struct grub_net_card *card; grub_net_network_level_address_t address; grub_net_link_level_address_t hwaddress; grub_net_interface_flags_t flags; - struct grub_net_bootp_ack *dhcp_ack; + struct grub_net_bootp_packet *dhcp_ack; grub_size_t dhcp_acklen; void *data; }; @@ -291,7 +295,8 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, } struct grub_net_network_level_interface * -grub_net_add_addr (const char *name, struct grub_net_card *card, +grub_net_add_addr (const char *name, + const struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags); @@ -369,7 +374,7 @@ grub_net_add_route_gw (const char *name, typedef grub_uint8_t grub_net_bootp_mac_addr_t[GRUB_NET_BOOTP_MAC_ADDR_LEN]; -struct grub_net_bootp_ack +struct grub_net_bootp_packet { grub_uint8_t opcode; grub_uint8_t hw_type; /* hardware type. */ @@ -391,11 +396,21 @@ struct grub_net_bootp_ack #define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L struct grub_net_network_level_interface * -grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, +grub_net_configure_by_dhcp_ack (const char *name, + const struct grub_net_card *card, grub_net_interface_flags_t flags, - struct grub_net_bootp_ack *bp, + const struct grub_net_bootp_packet *bp, grub_size_t size); +void +grub_net_process_dhcp (struct grub_net_buff *nb, + const struct grub_net_card *card); + +int +grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, + const grub_net_link_level_address_t *b); + + /* Currently suppoerted adresses: IPv4: XXX.XXX.XXX.XXX @@ -420,8 +435,11 @@ typedef int grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *inf, grub_net_packet_handler_t handler); -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb); + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff *nb, + const struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 7ff7a4562..a841dc12c 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -12,19 +12,6 @@ struct etherhdr grub_uint16_t type; } __attribute__ ((packed)); -#define PCP(x) x & 0xe000 -#define CFI(x) x & 0x1000 -#define VID(x) x & 0x0fff -#define PRINT_ETH_ADDR(name,addr) grub_printf("%s %x:%x:%x:%x:%x:%x\n",\ - name,\ - addr[0],\ - addr[1],\ - addr[2],\ - addr[3],\ - addr[4],\ - addr[5]\ - ) - struct llchdr { grub_uint8_t dsap; @@ -52,6 +39,7 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_net_link_level_address_t target_addr, grub_uint16_t ethertype); grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_buff *nb); +grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + const struct grub_net_card *card); #endif diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h index 8ce508ead..245e813c3 100644 --- a/include/grub/net/netbuff.h +++ b/include/grub/net/netbuff.h @@ -26,5 +26,5 @@ grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff); -grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); + #endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index 86311ccf1..eacf3325c 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -14,8 +14,9 @@ struct udphdr grub_err_t grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); -grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff *nb); +grub_err_t +grub_net_recv_udp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf); #define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var) From 40ea05dee4d26693cb03e3d3157626b64f671da4 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 24 Jun 2011 22:37:17 +0200 Subject: [PATCH 215/673] * grub-core/io/xzio.c: Fix code style issues --- ChangeLog | 4 ++++ grub-core/io/xzio.c | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4f42719bc..286648a46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-24 Szymon Janc + + * grub-core/io/xzio.c: Fix code style issues + 2011-06-24 Vladimir Serbinenko 2011-06-24 Manoel Rebelo Abranches diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c index 1f42cd242..1575ca236 100644 --- a/grub-core/io/xzio.c +++ b/grub-core/io/xzio.c @@ -48,7 +48,7 @@ static struct grub_fs grub_xzio_fs; static grub_size_t decode_vli (const grub_uint8_t buf[], grub_size_t size_max, - grub_uint64_t * num) + grub_uint64_t *num) { if (size_max == 0) return 0; @@ -71,7 +71,7 @@ decode_vli (const grub_uint8_t buf[], grub_size_t size_max, } static grub_ssize_t -read_vli (grub_file_t file, grub_uint64_t * num) +read_vli (grub_file_t file, grub_uint64_t *num) { grub_uint8_t buf[VLI_MAX_DIGITS]; grub_ssize_t read; @@ -92,6 +92,8 @@ static int test_header (grub_file_t file) { grub_xzio_t xzio = file->data; + enum xz_ret ret; + xzio->buf.in_size = grub_file_read (xzio->file, xzio->inbuf, STREAM_HEADER_SIZE); @@ -101,7 +103,7 @@ test_header (grub_file_t file) return 0; } - enum xz_ret ret = xz_dec_run (xzio->dec, &xzio->buf); + ret = xz_dec_run (xzio->dec, &xzio->buf); if (ret == XZ_FORMAT_ERROR) { @@ -132,8 +134,8 @@ test_footer (grub_file_t file) grub_uint64_t records; grub_file_seek (xzio->file, xzio->file->size - FOOTER_MAGIC_SIZE); - if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) != - FOOTER_MAGIC_SIZE + if (grub_file_read (xzio->file, footer, FOOTER_MAGIC_SIZE) + != FOOTER_MAGIC_SIZE || grub_memcmp (footer, FOOTER_MAGIC, FOOTER_MAGIC_SIZE) != 0) goto ERROR; @@ -150,8 +152,8 @@ test_footer (grub_file_t file) xzio->file->size - XZ_STREAM_FOOTER_SIZE - backsize); /* Test index marker. */ - if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) != - sizeof (imarker) && imarker != 0x00) + if (grub_file_read (xzio->file, &imarker, sizeof (imarker)) + != sizeof (imarker) && imarker != 0x00) goto ERROR; if (read_vli (xzio->file, &records) <= 0) From 77c0840ba67302031363479dfbf8bf44ef1ab6d0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 25 Jun 2011 00:18:36 +0200 Subject: [PATCH 216/673] * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration. (grub_pxe_send): Likewise. (GRUB_MOD_INIT): Fix types. --- ChangeLog | 6 ++++++ grub-core/net/i386/pc/pxe.c | 6 +++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 286648a46..4cac3cd65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-25 Vladimir Serbinenko + + * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration. + (grub_pxe_send): Likewise. + (GRUB_MOD_INIT): Fix types. + 2011-06-24 Szymon Janc * grub-core/io/xzio.c: Fix code style issues diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c index 27c4af17f..a23104bad 100644 --- a/grub-core/net/i386/pc/pxe.c +++ b/grub-core/net/i386/pc/pxe.c @@ -305,14 +305,14 @@ static struct grub_fs grub_pxefs_fs = }; static grub_ssize_t -grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), +grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *buf __attribute__ ((unused))) { return 0; } static grub_err_t -grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), +grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), struct grub_net_buff *buf __attribute__ ((unused))) { return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented"); @@ -424,7 +424,7 @@ GRUB_MOD_INIT(pxe) { struct grub_pxe_bangpxe *pxenv; struct grub_pxenv_get_cached_info ci; - struct grub_net_bootp_ack *bp; + struct grub_net_bootp_packet *bp; char *buf; pxenv = grub_pxe_scan (); From 6295b32f79acb93df2208321eec491aa6b214fa0 Mon Sep 17 00:00:00 2001 From: Patrick Date: Sat, 25 Jun 2011 01:09:32 +0200 Subject: [PATCH 217/673] * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment. --- ChangeLog | 4 ++++ grub-core/kern/main.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4cac3cd65..c639cb9de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-25 Patrick + + * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment. + 2011-06-25 Vladimir Serbinenko * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration. diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index cc9758988..447f0ae33 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -159,7 +159,7 @@ grub_load_normal_mode (void) /* Load the module. */ grub_dl_load ("normal"); - /* Something went wrong. Print errors here to let user know why we're entering rescue mode. */ + /* Print errors if any. */ grub_print_error (); grub_errno = 0; From cc4bfec8fac9a6fdea9ce38f5c7a92bc5579f22e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 04:18:45 +0200 Subject: [PATCH 218/673] Fix a memory leak --- grub-core/net/ethernet.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 863e659a8..175d0b65f 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -69,10 +69,14 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb, { grub_net_arp_receive (nb); grub_netbuff_free (nb); + return GRUB_ERR_NONE; } /* IP packet. */ if (type == GRUB_NET_ETHERTYPE_IP) - grub_net_recv_ip_packets (nb, card, &hwaddress); - + { + grub_net_recv_ip_packets (nb, card, &hwaddress); + return GRUB_ERR_NONE; + } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } From 8e60fc8f85b27fb513ef0b83efa07c531ec8e9a7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 04:19:12 +0200 Subject: [PATCH 219/673] Send network packets on PXE --- grub-core/Makefile.core.def | 2 +- grub-core/net/drivers/i386/pc/pxe.c | 304 ++++++++++++++++++ grub-core/net/i386/pc/pxe.c | 482 ---------------------------- 3 files changed, 305 insertions(+), 483 deletions(-) create mode 100644 grub-core/net/drivers/i386/pc/pxe.c delete mode 100644 grub-core/net/i386/pc/pxe.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 927718359..5c3ce99be 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1100,7 +1100,7 @@ module = { module = { name = pxe; - i386_pc = net/i386/pc/pxe.c; + i386_pc = net/drivers/i386/pc/pxe.c; enable = i386_pc; }; diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c new file mode 100644 index 000000000..7d6e3adca --- /dev/null +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -0,0 +1,304 @@ +/* pxe.c - Driver to provide access to the pxe filesystem */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009,2011 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define SEGMENT(x) ((x) >> 4) +#define OFFSET(x) ((x) & 0xF) +#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) +#define LINEAR(x) (void *) ((((x) >> 16) << 4) + ((x) & 0xFFFF)) + +struct grub_pxe_undi_open +{ + grub_uint16_t status; + grub_uint16_t open_flag; + grub_uint16_t pkt_filter; + grub_uint16_t mcast_count; + grub_uint8_t mcast[8][6]; +} __attribute__ ((packed)); + +struct grub_pxe_undi_isr +{ + grub_uint16_t status; + grub_uint16_t func_flag; + grub_uint16_t buffer_len; + grub_uint16_t frame_len; + grub_uint16_t frame_hdr_len; + grub_uint32_t buffer; + grub_uint8_t prot_type; + grub_uint8_t pkt_type; +} __attribute__ ((packed)); + +enum + { + GRUB_PXE_ISR_IN_START = 1, + GRUB_PXE_ISR_IN_PROCESS, + GRUB_PXE_ISR_IN_GET_NEXT + }; + +enum + { + GRUB_PXE_ISR_OUT_OURS = 0, + GRUB_PXE_ISR_OUT_NOT_OURS = 1 + }; + +enum + { + GRUB_PXE_ISR_OUT_DONE = 0, + GRUB_PXE_ISR_OUT_TRANSMIT = 2, + GRUB_PXE_ISR_OUT_RECEIVE = 3, + GRUB_PXE_ISR_OUT_BUSY = 4, + }; + +struct grub_pxe_undi_transmit +{ + grub_uint16_t status; + grub_uint8_t protocol; + grub_uint8_t xmitflag; + grub_uint32_t dest; + grub_uint32_t tbd; + grub_uint32_t reserved[2]; +} __attribute__ ((packed)); + +struct grub_pxe_undi_tbd +{ + grub_uint16_t len; + grub_uint32_t buf; + grub_uint16_t blk_count; + struct + { + grub_uint8_t ptr_type; + grub_uint8_t reserved; + grub_uint16_t len; + grub_uint32_t ptr; + } blocks[8]; +} __attribute__ ((packed)); + +struct grub_pxe_bangpxe *grub_pxe_pxenv; +static grub_uint32_t pxe_rm_entry = 0; + +static struct grub_pxe_bangpxe * +grub_pxe_scan (void) +{ + struct grub_bios_int_registers regs; + struct grub_pxenv *pxenv; + struct grub_pxe_bangpxe *bangpxe; + + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + + regs.ebx = 0; + regs.ecx = 0; + regs.eax = 0x5650; + regs.es = 0; + + grub_bios_interrupt (0x1a, ®s); + + if ((regs.eax & 0xffff) != 0x564e) + return NULL; + + pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff)); + if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE, + sizeof (pxenv->signature)) + != 0) + return NULL; + + if (pxenv->version < 0x201) + return NULL; + + bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4) + + (pxenv->pxe_ptr & 0xffff)); + + if (!bangpxe) + return NULL; + + if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE, + sizeof (bangpxe->signature)) != 0) + return NULL; + + pxe_rm_entry = bangpxe->rm_entry; + + return bangpxe; +} + +static grub_ssize_t +grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *buf) +{ + struct grub_pxe_undi_isr *isr; + static int in_progress = 0; + char *ptr, *end; + int len; + + isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + + if (!in_progress) + { + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_START; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS) + return -1; + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + } + else + { + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + } + + while (isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) + { + if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE) + return -1; + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + } + + grub_netbuff_put (buf, isr->frame_len); + ptr = buf->data; + end = ptr + isr->frame_len; + len = isr->frame_len; + grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); + ptr += isr->buffer_len; + while (ptr < end) + { + grub_memset (isr, 0, sizeof (*isr)); + isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; + grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); + if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) + return -1; + + grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); + ptr += isr->buffer_len; + } + + grub_printf ("<%d>\n", len); + return len; +} + +static grub_err_t +grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), + struct grub_net_buff *pack) +{ + struct grub_pxe_undi_transmit *trans; + struct grub_pxe_undi_tbd *tbd; + char *buf; + + trans = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (trans, 0, sizeof (*trans)); + tbd = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 128); + grub_memset (tbd, 0, sizeof (*tbd)); + buf = (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + 256); + grub_memcpy (buf, pack->data, pack->tail - pack->data); + + trans->tbd = SEGOFS ((grub_addr_t) tbd); + trans->protocol = 0; + tbd->len = pack->tail - pack->data; + tbd->buf = SEGOFS ((grub_addr_t) buf); + + grub_pxe_call (GRUB_PXENV_UNDI_TRANSMIT, trans, pxe_rm_entry); + if (trans->status) + return grub_error (GRUB_ERR_IO, "PXE send failed (status 0x%x)", + trans->status); + return 0; +} + +struct grub_net_card_driver grub_pxe_card_driver = +{ + .send = grub_pxe_send, + .recv = grub_pxe_recv +}; + +struct grub_net_card grub_pxe_card = +{ + .driver = &grub_pxe_card_driver, + .name = "pxe" +}; + +void +grub_pxe_unload (void) +{ + if (grub_pxe_pxenv) + { + grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, + (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, + pxe_rm_entry); + grub_net_card_unregister (&grub_pxe_card); + grub_pxe_pxenv = 0; + } +} + +GRUB_MOD_INIT(pxe) +{ + struct grub_pxe_bangpxe *pxenv; + struct grub_pxenv_get_cached_info ci; + struct grub_net_bootp_packet *bp; + struct grub_pxe_undi_open *ou; + + pxenv = grub_pxe_scan (); + if (! pxenv) + return; + + ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; + ci.buffer = 0; + ci.buffer_size = 0; + grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); + if (ci.status) + return; + + bp = LINEAR (ci.buffer); + + grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, + bp->hw_len < sizeof (grub_pxe_card.default_address.mac) + ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (ou, 0, sizeof (ou)); + ou->pkt_filter = 4; + grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); + + if (ou->status) + return; + + grub_net_card_register (&grub_pxe_card); + grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, + bp, GRUB_PXE_BOOTP_SIZE); +} + +GRUB_MOD_FINI(pxe) +{ + grub_pxe_unload (); +} diff --git a/grub-core/net/i386/pc/pxe.c b/grub-core/net/i386/pc/pxe.c deleted file mode 100644 index 27c4af17f..000000000 --- a/grub-core/net/i386/pc/pxe.c +++ /dev/null @@ -1,482 +0,0 @@ -/* pxe.c - Driver to provide access to the pxe filesystem */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define SEGMENT(x) ((x) >> 4) -#define OFFSET(x) ((x) & 0xF) -#define SEGOFS(x) ((SEGMENT(x) << 16) + OFFSET(x)) -#define LINEAR(x) (void *) (((x >> 16) << 4) + (x & 0xFFFF)) - -struct grub_pxe_bangpxe *grub_pxe_pxenv; -static grub_uint32_t grub_pxe_default_server_ip; -#if 0 -static grub_uint32_t grub_pxe_default_gateway_ip; -#endif -static unsigned grub_pxe_blksize = GRUB_PXE_MIN_BLKSIZE; -static grub_uint32_t pxe_rm_entry = 0; -static grub_file_t curr_file = 0; - -struct grub_pxe_data -{ - grub_uint32_t packet_number; - grub_uint32_t block_size; - grub_uint32_t server_ip; - grub_uint32_t gateway_ip; - char filename[0]; -}; - - -static struct grub_pxe_bangpxe * -grub_pxe_scan (void) -{ - struct grub_bios_int_registers regs; - struct grub_pxenv *pxenv; - struct grub_pxe_bangpxe *bangpxe; - - regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; - - regs.ebx = 0; - regs.ecx = 0; - regs.eax = 0x5650; - regs.es = 0; - - grub_bios_interrupt (0x1a, ®s); - - if ((regs.eax & 0xffff) != 0x564e) - return NULL; - - pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff)); - if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE, - sizeof (pxenv->signature)) - != 0) - return NULL; - - if (pxenv->version < 0x201) - return NULL; - - bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4) - + (pxenv->pxe_ptr & 0xffff)); - - if (!bangpxe) - return NULL; - - if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE, - sizeof (bangpxe->signature)) != 0) - return NULL; - - pxe_rm_entry = bangpxe->rm_entry; - - return bangpxe; -} - -static grub_err_t -grub_pxefs_dir (grub_device_t device __attribute__ ((unused)), - const char *path __attribute__ ((unused)), - int (*hook) (const char *filename, - const struct grub_dirhook_info *info) - __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_pxefs_open (struct grub_file *file, const char *name) -{ - union - { - struct grub_pxenv_tftp_get_fsize c1; - struct grub_pxenv_tftp_open c2; - } c; - struct grub_pxe_data *data; - grub_file_t file_int, bufio; - - data = grub_zalloc (sizeof (*data) + grub_strlen (name) + 1); - if (!data) - return grub_errno; - - { - grub_net_network_level_address_t addr; - grub_net_network_level_address_t gateway; - struct grub_net_network_level_interface *interf; - grub_err_t err; - - if (grub_strncmp (file->device->net->name, - "pxe,", sizeof ("pxe,") - 1) == 0 - || grub_strncmp (file->device->net->name, - "pxe:", sizeof ("pxe:") - 1) == 0) - { - err = grub_net_resolve_address (file->device->net->name - + sizeof ("pxe,") - 1, &addr); - if (err) - { - grub_free (data); - return err; - } - } - else - { - addr.ipv4 = grub_pxe_default_server_ip; - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - } - err = grub_net_route_address (addr, &gateway, &interf); - if (err) - { - grub_free (data); - return err; - } - data->server_ip = addr.ipv4; - data->gateway_ip = gateway.ipv4; - } - - if (curr_file != 0) - { - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry); - curr_file = 0; - } - - c.c1.server_ip = data->server_ip; - c.c1.gateway_ip = data->gateway_ip; - grub_strcpy ((char *)&c.c1.filename[0], name); - grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry); - if (c.c1.status) - { - grub_free (data); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); - } - - file->size = c.c1.file_size; - - c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); - c.c2.packet_size = grub_pxe_blksize; - grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry); - if (c.c2.status) - { - grub_free (data); - return grub_error (GRUB_ERR_BAD_FS, "open fails"); - } - - data->block_size = c.c2.packet_size; - grub_strcpy (data->filename, name); - - file_int = grub_malloc (sizeof (*file_int)); - if (! file_int) - { - grub_free (data); - return grub_errno; - } - - file->data = data; - file->not_easily_seekable = 1; - grub_memcpy (file_int, file, sizeof (struct grub_file)); - curr_file = file_int; - - bufio = grub_bufio_open (file_int, data->block_size); - if (! bufio) - { - grub_free (file_int); - grub_free (data); - return grub_errno; - } - - grub_memcpy (file, bufio, sizeof (struct grub_file)); - - return GRUB_ERR_NONE; -} - -static grub_ssize_t -grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len) -{ - struct grub_pxenv_tftp_read c; - struct grub_pxe_data *data; - grub_uint32_t pn; - grub_uint64_t r; - - data = file->data; - - pn = grub_divmod64 (file->offset, data->block_size, &r); - if (r) - { - grub_error (GRUB_ERR_BAD_FS, - "read access must be aligned to packet size"); - return -1; - } - - if ((curr_file != file) || (data->packet_number > pn)) - { - struct grub_pxenv_tftp_open o; - - if (curr_file != 0) - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry); - - o.server_ip = data->server_ip; - o.gateway_ip = data->gateway_ip; - grub_strcpy ((char *)&o.filename[0], data->filename); - o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT); - o.packet_size = data->block_size; - grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry); - if (o.status) - { - grub_error (GRUB_ERR_BAD_FS, "open fails"); - return -1; - } - data->block_size = o.packet_size; - data->packet_number = 0; - curr_file = file; - } - - c.buffer = SEGOFS (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); - while (pn >= data->packet_number) - { - c.buffer_size = data->block_size; - grub_pxe_call (GRUB_PXENV_TFTP_READ, &c, pxe_rm_entry); - if (c.status) - { - grub_error (GRUB_ERR_BAD_FS, "read fails"); - return -1; - } - data->packet_number++; - } - - grub_memcpy (buf, (char *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, len); - - return len; -} - -static grub_err_t -grub_pxefs_close (grub_file_t file) -{ - struct grub_pxenv_tftp_close c; - - if (curr_file == file) - { - grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c, pxe_rm_entry); - curr_file = 0; - } - - grub_free (file->data); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_pxefs_label (grub_device_t device __attribute ((unused)), - char **label __attribute ((unused))) -{ - *label = 0; - return GRUB_ERR_NONE; -} - -static struct grub_fs grub_pxefs_fs = - { - .name = "pxe", - .dir = grub_pxefs_dir, - .open = grub_pxefs_open, - .read = grub_pxefs_read, - .close = grub_pxefs_close, - .label = grub_pxefs_label, - .next = 0 - }; - -static grub_ssize_t -grub_pxe_recv (struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *buf __attribute__ ((unused))) -{ - return 0; -} - -static grub_err_t -grub_pxe_send (struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *buf __attribute__ ((unused))) -{ - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "not implemented"); -} - -struct grub_net_card_driver grub_pxe_card_driver = -{ - .send = grub_pxe_send, - .recv = grub_pxe_recv -}; - -struct grub_net_card grub_pxe_card = -{ - .driver = &grub_pxe_card_driver, - .name = "pxe" -}; - -void -grub_pxe_unload (void) -{ - if (grub_pxe_pxenv) - { - grub_fs_unregister (&grub_pxefs_fs); - grub_net_card_unregister (&grub_pxe_card); - grub_pxe_pxenv = 0; - } -} - -static void -set_ip_env (char *varname, grub_uint32_t ip) -{ - char buf[GRUB_NET_MAX_STR_ADDR_LEN]; - grub_net_network_level_address_t addr; - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = ip; - - grub_net_addr_to_str (&addr, buf); - grub_env_set (varname, buf); -} - -static char * -write_ip_env (grub_uint32_t *ip, const char *val) -{ - char *buf; - grub_err_t err; - grub_net_network_level_address_t addr; - - err = grub_net_resolve_address (val, &addr); - if (err) - return 0; - if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) - return NULL; - - /* Normalize the IP. */ - buf = grub_malloc (GRUB_NET_MAX_STR_ADDR_LEN); - if (!buf) - return 0; - grub_net_addr_to_str (&addr, buf); - - *ip = addr.ipv4; - - return buf; -} - -static char * -grub_env_write_pxe_default_server (struct grub_env_var *var - __attribute__ ((unused)), - const char *val) -{ - return write_ip_env (&grub_pxe_default_server_ip, val); -} - -#if 0 -static char * -grub_env_write_pxe_default_gateway (struct grub_env_var *var - __attribute__ ((unused)), - const char *val) -{ - return write_ip_env (&grub_pxe_default_gateway_ip, val); -} -#endif - -static char * -grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), - const char *val) -{ - unsigned size; - char *buf; - - size = grub_strtoul (val, 0, 0); - if (grub_errno) - return 0; - - if (size < GRUB_PXE_MIN_BLKSIZE) - size = GRUB_PXE_MIN_BLKSIZE; - else if (size > GRUB_PXE_MAX_BLKSIZE) - size = GRUB_PXE_MAX_BLKSIZE; - - buf = grub_xasprintf ("%d", size); - if (!buf) - return 0; - - grub_pxe_blksize = size; - - return buf; -} - -GRUB_MOD_INIT(pxe) -{ - struct grub_pxe_bangpxe *pxenv; - struct grub_pxenv_get_cached_info ci; - struct grub_net_bootp_ack *bp; - char *buf; - - pxenv = grub_pxe_scan (); - if (! pxenv) - return; - - ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; - ci.buffer = 0; - ci.buffer_size = 0; - grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); - if (ci.status) - return; - - bp = LINEAR (ci.buffer); - - grub_pxe_default_server_ip = bp->server_ip; - grub_pxe_pxenv = pxenv; - - set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); - grub_register_variable_hook ("pxe_default_server", 0, - grub_env_write_pxe_default_server); - -#if 0 - grub_pxe_default_gateway_ip = bp->gateway_ip; - - grub_register_variable_hook ("pxe_default_gateway", 0, - grub_env_write_pxe_default_gateway); -#endif - - buf = grub_xasprintf ("%d", grub_pxe_blksize); - if (buf) - grub_env_set ("pxe_blksize", buf); - grub_free (buf); - - grub_register_variable_hook ("pxe_blksize", 0, - grub_env_write_pxe_blocksize); - - grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, - bp->hw_len < sizeof (grub_pxe_card.default_address.mac) - ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); - grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - - grub_fs_register (&grub_pxefs_fs); - grub_net_card_register (&grub_pxe_card); - grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, - GRUB_NET_INTERFACE_PERMANENT - | GRUB_NET_INTERFACE_ADDRESS_IMMUTABLE - | GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE, - bp, GRUB_PXE_BOOTP_SIZE); -} - -GRUB_MOD_FINI(pxe) -{ - grub_pxe_unload (); -} From bf651f790717fd5b73c80e6bedd9df66069c847e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 14:47:38 +0200 Subject: [PATCH 220/673] Fix incorrect memset --- grub-core/net/drivers/i386/pc/pxe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 7d6e3adca..e667d42ef 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -286,7 +286,7 @@ GRUB_MOD_INIT(pxe) grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - grub_memset (ou, 0, sizeof (ou)); + grub_memset (ou, 0, sizeof (*ou)); ou->pkt_filter = 4; grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); From 80ca250565745aa1f587216ed8af6dc70e036e92 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:06:18 +0200 Subject: [PATCH 221/673] Add backward compatibiulity with old (pxe) syntax. Several cleanups --- grub-core/commands/probe.c | 2 +- grub-core/kern/device.c | 2 +- grub-core/net/drivers/i386/pc/pxe.c | 1 - grub-core/net/net.c | 114 ++++++++++++++++++++-------- include/grub/net.h | 6 +- 5 files changed, 87 insertions(+), 38 deletions(-) diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index 7ed2a4e51..ce1e9aac0 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -74,7 +74,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) { const char *val = "none"; if (dev->net) - val = dev->net->name; + val = dev->net->protocol->name; if (dev->disk) val = dev->disk->dev->name; if (state[0].set) diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 45bcd8210..c998d4d4b 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -79,7 +79,7 @@ grub_device_close (grub_device_t device) if (device->net) { - grub_free (device->net->name); + grub_free (device->net->server); grub_free (device->net); } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index e667d42ef..084cdb876 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -204,7 +204,6 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), ptr += isr->buffer_len; } - grub_printf ("<%d>\n", len); return len; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 5c7d00991..2932986b2 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011 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 @@ -32,6 +32,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); +static char *default_server; + struct grub_net_route { struct grub_net_route *next; @@ -603,26 +605,63 @@ struct grub_net_socket *grub_net_sockets; static grub_net_t grub_net_open_real (const char *name) { - const char *comma = grub_strchr (name, ','); grub_net_app_level_t proto; + const char *protname, *server; + grub_size_t protnamelen; + + if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0) + { + protname = "tftp"; + protnamelen = sizeof ("tftp") - 1; + server = name + sizeof ("pxe:") - 1; + } + else if (grub_strcmp (name, "pxe") == 0) + { + protname = "tftp"; + protnamelen = sizeof ("tftp") - 1; + server = default_server; + } + else + { + const char *comma; + comma = grub_strchr (name, ','); + if (comma) + { + protnamelen = comma - name; + server = comma + 1; + } + else + { + protnamelen = grub_strlen (name); + server = default_server; + } + } + if (!server) + { + grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no server"); + return NULL; + } - if (!comma) - comma = name + grub_strlen (name); FOR_NET_APP_LEVEL (proto) { - if (comma - name == (grub_ssize_t) grub_strlen (proto->name) - && grub_memcmp (proto->name, name, comma - name) == 0) + if (grub_memcmp (proto->name, protname, protnamelen) == 0 + && proto->name[protnamelen] == 0) { grub_net_t ret = grub_malloc (sizeof (*ret)); if (!ret) return NULL; ret->protocol = proto; - ret->name = grub_strdup (name); - if (!ret->name) + if (server) { - grub_free (ret); - return NULL; + ret->server = grub_strdup (server); + if (!ret->server) + { + grub_free (ret); + return NULL; + } } + else + ret->server = NULL; ret->fs = &grub_net_fs; return ret; } @@ -651,13 +690,8 @@ grub_net_fs_open (struct grub_file *file, const char *name) grub_net_network_level_address_t gateway; grub_net_socket_t socket; static int port = 25300; - const char *comma; - comma = grub_strchr (file->device->net->name, ','); - if (!comma) - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no separator"); - - err = grub_net_resolve_address (comma + 1, &addr); + err = grub_net_resolve_address (file->device->net->server, &addr); if (err) return err; @@ -913,20 +947,19 @@ grub_net_configure_by_dhcp_ack (const char *name, hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; inter = grub_net_add_addr (name, card, addr, hwaddr, flags); - if (bp->gateway_ip != bp->server_ip) - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - char rname[grub_strlen (name) + sizeof ("_gw")]; + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof ("_gw")]; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = bp->gateway_ip; - grub_snprintf (rname, sizeof (rname), "%s_gw", name); - grub_net_add_route_gw (rname, target, gw); - } + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s_gw", name); + grub_net_add_route_gw (rname, target, gw); + } { grub_net_network_level_netaddress_t target; target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; @@ -938,9 +971,26 @@ grub_net_configure_by_dhcp_ack (const char *name, if (size > OFFSET_OF (boot_file, bp)) set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, sizeof (bp->boot_file)); - if (size > OFFSET_OF (server_name, bp)) - set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, - sizeof (bp->server_name)); + if (size > OFFSET_OF (server_name, bp) + && bp->server_name[0]) + { + set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, + sizeof (bp->server_name)); + if (!default_server) + { + default_server = grub_strdup (bp->server_name); + grub_errno = GRUB_ERR_NONE; + } + } + if (!default_server) + { + default_server = grub_xasprintf ("%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_errno = GRUB_ERR_NONE; + } if (size > OFFSET_OF (vendor, bp)) parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); diff --git a/include/grub/net.h b/include/grub/net.h index 068ccec41..6595a8276 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -234,7 +234,7 @@ grub_net_socket_unregister (grub_net_socket_t sock) typedef struct grub_net { - char *name; + char *server; grub_net_app_level_t protocol; grub_net_socket_t socket; grub_fs_t fs; @@ -389,8 +389,8 @@ struct grub_net_bootp_packet grub_uint32_t server_ip; grub_uint32_t gateway_ip; grub_net_bootp_mac_addr_t mac_addr; - grub_uint8_t server_name[64]; - grub_uint8_t boot_file[128]; + char server_name[64]; + char boot_file[128]; grub_uint8_t vendor[0]; } __attribute__ ((packed)); From cbf597afb158a54ff1d35d4e21f0f6df3c1a01b9 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 26 Jun 2011 17:17:41 +0200 Subject: [PATCH 222/673] * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL pointer checks before calling grub_free(). * grub-core/commands/wildcard.c (match_devices): Likewise. * grub-core/commands/wildcard.c (match_files): Likewise. * grub-core/fs/cpio.c (grub_cpio_dir): Likewise. * grub-core/fs/cpio.c (grub_cpio_open): Likewise. * grub-core/fs/udf.c (grub_udf_read_block): Likewise. * grub-core/fs/xfs.c (grub_xfs_read_block): Likewise. * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Likewise. * grub-core/normal/cmdline.c (grub_cmdline_get): Likewise. * grub-core/script/yylex.l (grub_lexer_unput): Likewise. * grub-core/video/readers/jpeg.c (grub_video_reader_jpeg): Likewise. * grub-core/video/readers/png.c (grub_png_output_byte): Likewise. --- ChangeLog | 16 ++++++++++++++++ grub-core/commands/cmp.c | 6 ++---- grub-core/commands/wildcard.c | 12 ++++-------- grub-core/fs/cpio.c | 13 ++++--------- grub-core/fs/udf.c | 3 +-- grub-core/fs/xfs.c | 3 +-- grub-core/loader/efi/chainloader.c | 3 +-- grub-core/normal/cmdline.c | 6 ++---- grub-core/script/yylex.l | 3 +-- grub-core/video/readers/jpeg.c | 3 +-- grub-core/video/readers/png.c | 3 +-- 11 files changed, 34 insertions(+), 37 deletions(-) diff --git a/ChangeLog b/ChangeLog index c639cb9de..17be445af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-06-26 Szymon Janc + + * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL + pointer checks before calling grub_free(). + * grub-core/commands/wildcard.c (match_devices): Likewise. + * grub-core/commands/wildcard.c (match_files): Likewise. + * grub-core/fs/cpio.c (grub_cpio_dir): Likewise. + * grub-core/fs/cpio.c (grub_cpio_open): Likewise. + * grub-core/fs/udf.c (grub_udf_read_block): Likewise. + * grub-core/fs/xfs.c (grub_xfs_read_block): Likewise. + * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Likewise. + * grub-core/normal/cmdline.c (grub_cmdline_get): Likewise. + * grub-core/script/yylex.l (grub_lexer_unput): Likewise. + * grub-core/video/readers/jpeg.c (grub_video_reader_jpeg): Likewise. + * grub-core/video/readers/png.c (grub_png_output_byte): Likewise. + 2011-06-25 Patrick * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment. diff --git a/grub-core/commands/cmp.c b/grub-core/commands/cmp.c index 0222927b6..526459311 100644 --- a/grub-core/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -94,10 +94,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), cleanup: - if (buf1) - grub_free (buf1); - if (buf2) - grub_free (buf2); + grub_free (buf1); + grub_free (buf2); if (file1) grub_file_close (file1); if (file2) diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 45d819a3e..d2f4347d5 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -255,8 +255,7 @@ match_devices (const regex_t *regexp, int noparts) for (i = 0; devs && devs[i]; i++) grub_free (devs[i]); - if (devs) - grub_free (devs); + grub_free (devs); return 0; } @@ -342,20 +341,17 @@ match_files (const char *prefix, const char *suffix, const char *end, fail: - if (dir) - grub_free (dir); + grub_free (dir); for (i = 0; files && files[i]; i++) grub_free (files[i]); - if (files) - grub_free (files); + grub_free (files); if (dev) grub_device_close (dev); - if (device_name) - grub_free (device_name); + grub_free (device_name); grub_error_pop (); return 0; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 3a07873ec..0d84382ac 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -239,8 +239,7 @@ grub_cpio_dir (grub_device_t device, const char *path, info.mtimeset = 1; hook (name + len, &info); - if (prev) - grub_free (prev); + grub_free (prev); prev = name; } else @@ -251,11 +250,8 @@ grub_cpio_dir (grub_device_t device, const char *path, fail: - if (prev) - grub_free (prev); - - if (data) - grub_free (data); + grub_free (prev); + grub_free (data); grub_dl_unref (my_mod); @@ -326,8 +322,7 @@ grub_cpio_open (grub_file_t file, const char *name) fail: - if (data) - grub_free (data); + grub_free (data); grub_dl_unref (my_mod); diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 48906f84f..e1f115015 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -546,8 +546,7 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } fail: - if (buf) - grub_free (buf); + grub_free (buf); return 0; } diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 1e466465b..eb0783407 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -324,8 +324,7 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } } - if (leaf) - grub_free (leaf); + grub_free (leaf); return GRUB_XFS_FSB_TO_BLOCK(node->data, ret); } diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index 5dd5adab2..3ecdca534 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -329,8 +329,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), if (file) grub_file_close (file); - if (file_path) - grub_free (file_path); + grub_free (file_path); if (address) efi_call_2 (b->free_pages, address, pages); diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c index 09f2271ea..ea06b4cc7 100644 --- a/grub-core/normal/cmdline.c +++ b/grub-core/normal/cmdline.c @@ -500,8 +500,7 @@ grub_cmdline_get (const char *prompt) case GRUB_TERM_CTRL | 'k': if (lpos < llen) { - if (kill_buf) - grub_free (kill_buf); + grub_free (kill_buf); kill_buf = grub_malloc ((llen - lpos + 1) * sizeof (grub_uint32_t)); @@ -566,8 +565,7 @@ grub_cmdline_get (const char *prompt) { grub_size_t n = lpos; - if (kill_buf) - grub_free (kill_buf); + grub_free (kill_buf); kill_buf = grub_malloc (n + 1); if (grub_errno) diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index 53ae4c54f..96f57dbe6 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -355,8 +355,7 @@ grub_lexer_unput (const char *text, yyscan_t yyscanner) { struct grub_lexer_param *lexerstate = yyget_extra (yyscanner)->lexerstate; - if (lexerstate->prefix) - grub_free (lexerstate->prefix); + grub_free (lexerstate->prefix); lexerstate->prefix = grub_strdup (text); if (! lexerstate->prefix) diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c index d61c90ec9..f2351dee9 100644 --- a/grub-core/video/readers/jpeg.c +++ b/grub-core/video/readers/jpeg.c @@ -750,8 +750,7 @@ grub_video_reader_jpeg (struct grub_video_bitmap **bitmap, grub_jpeg_decode_jpeg (data); for (i = 0; i < 4; i++) - if (data->huff_value[i]) - grub_free (data->huff_value[i]); + grub_free (data->huff_value[i]); grub_free (data); } diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c index 5728651e0..ae9879b16 100644 --- a/grub-core/video/readers/png.c +++ b/grub-core/video/readers/png.c @@ -625,8 +625,7 @@ grub_png_output_byte (struct grub_png_data *data, grub_uint8_t n) } } - if (blank_line) - grub_free (blank_line); + grub_free (blank_line); data->cur_column = 0; data->first_line = 0; From a8fae12c5be48b4dafeec7c47d99132630be51cb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:18:53 +0200 Subject: [PATCH 223/673] minor cleanups --- grub-core/net/tftp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index d0ed7c43a..24f30eb7a 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -131,8 +131,9 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) grub_netbuff_clear (nb); break; case TFTP_DATA: - if ((err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block))) != GRUB_ERR_NONE) + err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (err) return err; if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) { @@ -142,8 +143,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) sock->status = 2; /* Prevent garbage in broken cards. */ if (size > 1024) - if ((err = grub_netbuff_unput (nb, size - 1024)) != GRUB_ERR_NONE) - return err; + { + err = grub_netbuff_unput (nb, size - 1024); + if (err) + return err; + } } else grub_netbuff_clear (nb); From b1f9b7249afa234d64454b3db3c5a77a64db1e87 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:28:19 +0200 Subject: [PATCH 224/673] mknetdir support for ieee1275 --- util/grub-mknetdir.in | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index 61a7ec3ad..3b4f051c5 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -196,11 +196,17 @@ process_input_dir () config_opt="-c ${grubdir}/load.cfg " fi + prefix="/${subdir}/${platform}"; case "${platform}" in i386-pc) mkimage_target=i386-pc-pxe; netmodules="pxe"; - prefix="(pxe)/${subdir}/${platform}"; ext=0 ;; + sparc64-ieee1275) mkimage_target=sparc64-ieee1275-aout; + netmodules=""; + ext=img ;; + *-ieee1275) mkimage_target="${platform}"; + netmodules=""; + ext=elf ;; *) echo Unsupported platform ${platform}; exit 1;; esac From 2f804a7ff6cf37ac69584b88c63e6e5cc209da73 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:28:57 +0200 Subject: [PATCH 225/673] remove leftover directory From a27fe54f96b3dc19f3222b2872cd0e365059e1a6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 17:51:46 +0200 Subject: [PATCH 226/673] missing part of previous commit --- util/grub-mknetdir.in | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index 3b4f051c5..a561004e6 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -45,6 +45,9 @@ debug=no debug_image= subdir=`echo /boot/grub | sed ${transform}` pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc +ppc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275 +sparc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275 +i386_ieee1275_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275 # Usage: usage # Print the usage. @@ -223,6 +226,15 @@ if [ "${override_dir}" = "" ] ; then if test -e "${pc_dir}" ; then process_input_dir ${pc_dir} i386-pc fi + if test -e "${ppc_dir}" ; then + process_input_dir ${ppc_dir} powerpc-ieee1275 + fi + if test -e "${sparc_dir}" ; then + process_input_dir ${sparc_dir} sparc64-ieee1275 + fi + if test -e "${i386_ieee1275_dir}" ; then + process_input_dir ${sparc_dir} i386-ieee1275 + fi else source "${override_dir}"/modinfo.sh process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} From cf2bba0ef43bd2708d705ab3bf40fb841310b398 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 18:23:12 +0200 Subject: [PATCH 227/673] add missing quotes and fix variable name --- util/grub-mknetdir.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index a561004e6..fa0cafe54 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -224,16 +224,16 @@ EOF if [ "${override_dir}" = "" ] ; then if test -e "${pc_dir}" ; then - process_input_dir ${pc_dir} i386-pc + process_input_dir "${pc_dir}" i386-pc fi if test -e "${ppc_dir}" ; then - process_input_dir ${ppc_dir} powerpc-ieee1275 + process_input_dir "${ppc_dir}" powerpc-ieee1275 fi if test -e "${sparc_dir}" ; then process_input_dir ${sparc_dir} sparc64-ieee1275 fi if test -e "${i386_ieee1275_dir}" ; then - process_input_dir ${sparc_dir} i386-ieee1275 + process_input_dir "${i386_ieee1275_dir}" i386-ieee1275 fi else source "${override_dir}"/modinfo.sh From e552d93a8b28cac6fd1a1b4116980f80794a80ca Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 19:52:50 +0200 Subject: [PATCH 228/673] Add ofnet and tftp modules --- util/grub-mknetdir.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index fa0cafe54..a36e33cab 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -205,10 +205,10 @@ process_input_dir () netmodules="pxe"; ext=0 ;; sparc64-ieee1275) mkimage_target=sparc64-ieee1275-aout; - netmodules=""; + netmodules="ofnet"; ext=img ;; *-ieee1275) mkimage_target="${platform}"; - netmodules=""; + netmodules="ofnet"; ext=elf ;; *) echo Unsupported platform ${platform}; exit 1;; @@ -218,7 +218,7 @@ process_input_dir () source ${subdir}/grub.cfg EOF - $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules || exit 1 + $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules tftp || exit 1 echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext" } From 9e322ce8de8526c2c752362749663e6c186f60e3 Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Sun, 26 Jun 2011 21:48:52 +0200 Subject: [PATCH 229/673] Display the path of the file when file is not found * grub-core/fs/fat.c: Display the filename when file is not found. * grub-core/fs/fshelp.c: Likewise. * grub-core/fs/hfs.c: Likewise. * grub-core/fs/jfs.c: Likewise. * grub-core/fs/minix.c: Likewise. * grub-core/fs/ufs.c: Likewise. * grub-core/fs/btrfs.c: Likewise. * grub-core/commands/i386/pc/play.c: Likewise. --- ChangeLog | 13 +++++++++++++ grub-core/commands/i386/pc/play.c | 4 ++-- grub-core/fs/btrfs.c | 32 +++++++++++++++++++++++++++---- grub-core/fs/fat.c | 11 +++++++++-- grub-core/fs/fshelp.c | 2 +- grub-core/fs/hfs.c | 2 +- grub-core/fs/jfs.c | 2 +- grub-core/fs/minix.c | 2 +- grub-core/fs/ufs.c | 2 +- 9 files changed, 57 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17be445af..bd6e311bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-06-26 Yves Blusseau + + Display the path of the file when file is not found + + * grub-core/fs/fat.c: Display the filename when file is not found. + * grub-core/fs/fshelp.c: Likewise. + * grub-core/fs/hfs.c: Likewise. + * grub-core/fs/jfs.c: Likewise. + * grub-core/fs/minix.c: Likewise. + * grub-core/fs/ufs.c: Likewise. + * grub-core/fs/btrfs.c: Likewise. + * grub-core/commands/i386/pc/play.c: Likewise. + 2011-06-26 Szymon Janc * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c index 57980eb92..1adf296ec 100644 --- a/grub-core/commands/i386/pc/play.c +++ b/grub-core/commands/i386/pc/play.c @@ -192,7 +192,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), file = grub_file_open (args[0]); if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]); if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo)) { @@ -227,7 +227,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), if (*end) /* Was not a number either, assume it was supposed to be a file name. */ - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]); grub_dprintf ("play","tempo = %d\n", tempo); diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 533529e3f..6470c9819 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1054,6 +1054,7 @@ find_path (struct grub_btrfs_data *data, const char *ctoken; grub_size_t ctokenlen; char *path_alloc = NULL; + char *origpath = NULL; unsigned symlinks_max = 32; *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; @@ -1062,6 +1063,9 @@ find_path (struct grub_btrfs_data *data, key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; key->offset = 0; skip_default = 1; + origpath = grub_strdup (path); + if (!origpath) + return grub_errno; while (1) { @@ -1086,6 +1090,7 @@ find_path (struct grub_btrfs_data *data, if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) { grub_free (path_alloc); + grub_free (origpath); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); } @@ -1098,13 +1103,16 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } if (key_cmp (key, &key_out) != 0) { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } struct grub_btrfs_dir_item *cdirel; @@ -1116,6 +1124,7 @@ find_path (struct grub_btrfs_data *data, if (!direl) { grub_free (path_alloc); + grub_free (origpath); return grub_errno; } } @@ -1125,6 +1134,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } @@ -1144,7 +1154,9 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } if (!skip_default) @@ -1158,6 +1170,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); } @@ -1168,6 +1181,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } tmp = grub_malloc (grub_le_to_cpu64 (inode.size) @@ -1176,6 +1190,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return grub_errno; } @@ -1186,12 +1201,14 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); grub_free (tmp); return grub_errno; } grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path, grub_strlen (path) + 1); grub_free (path_alloc); + grub_free (origpath); path = path_alloc = tmp; if (path[0] == '/') { @@ -1218,6 +1235,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } if (cdirel->key.object_id != key_out.object_id @@ -1225,7 +1243,9 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri)); @@ -1233,6 +1253,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); + grub_free (origpath); return err; } key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; @@ -1246,7 +1267,9 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_free (origpath); + return err; } *key = cdirel->key; if (*type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) @@ -1254,6 +1277,7 @@ find_path (struct grub_btrfs_data *data, break; default: grub_free (path_alloc); + grub_free (origpath); grub_free (direl); return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x", cdirel->key.type); diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index f617bb0f4..c78d3fbe6 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -565,6 +565,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, const struct grub_dirhook_info *info)) { char *dirname, *dirp; + char *origpath = NULL; int call_hook; int found = 0; @@ -605,6 +606,10 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, return 0; } + origpath = grub_strdup (path); + if (!origpath) + return 0; + /* Extract a directory name. */ while (*path == '/') path++; @@ -616,7 +621,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, dirname = grub_malloc (len + 1); if (! dirname) - return 0; + goto fail; grub_memcpy (dirname, path, len); dirname[len] = '\0'; @@ -629,9 +634,11 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir (disk, data, iter_hook); if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + fail: grub_free (dirname); + grub_free (origpath); return found ? dirp : 0; } diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index f879885ac..2ff78c423 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -197,7 +197,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, name = next; } - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); } if (!path || path[0] != '/') diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index cb7679ecb..6f27c69c4 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -921,7 +921,7 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, if (! grub_hfs_find_node (data, (char *) &key, data->cat_root, 0, (char *) &fdrec.frec, sizeof (fdrec.frec))) { - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); goto fail; } diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index c131169d8..36ec5fd25 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -699,7 +699,7 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path) } grub_jfs_closedir (diro); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); return grub_errno; } diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 64a64cca0..055f89095 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -424,7 +424,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) pos += sizeof (ino) + data->filename_size; } while (pos < GRUB_MINIX_INODE_SIZE (data)); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); return grub_errno; } diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index 86fe8af65..0f4ea0019 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -514,7 +514,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path) pos += grub_le_to_cpu16 (dirent.direntlen); } while (pos < INODE_SIZE (data)); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); return grub_errno; } From d36f20db4608fa7a8e66bdc86993fcd813e22c08 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:37:19 +0200 Subject: [PATCH 230/673] Don't do unaligned access when parsing DHCP packet --- grub-core/net/net.c | 11 ++++++++--- include/grub/net.h | 5 ++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 2932986b2..560fa7a31 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -879,7 +879,10 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) ptr = ptr0 = vend; - if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) != GRUB_NET_BOOTP_RFC1048_MAGIC) + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) return; ptr = ptr + sizeof (grub_uint32_t); while (ptr - ptr0 < limit) @@ -1078,8 +1081,10 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), ptr = inter->dhcp_ack->vendor; - if (grub_be_to_cpu32 (*(grub_uint32_t *) ptr) - != GRUB_NET_BOOTP_RFC1048_MAGIC) + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); ptr = ptr + sizeof (grub_uint32_t); while (1) diff --git a/include/grub/net.h b/include/grub/net.h index 6595a8276..ee94ebcc6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -394,7 +394,10 @@ struct grub_net_bootp_packet grub_uint8_t vendor[0]; } __attribute__ ((packed)); -#define GRUB_NET_BOOTP_RFC1048_MAGIC 0x63825363L +#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 +#define GRUB_NET_BOOTP_RFC1048_MAGIC_3 0x63 struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, From 14f0752dcf5f55f9b50f0b6dce3362d53b180cce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:37:49 +0200 Subject: [PATCH 231/673] Print MAC address when listing cards --- grub-core/net/net.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 560fa7a31..34148f52c 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -576,9 +576,10 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_card *card; FOR_NET_CARDS(card) { - grub_printf ("%s ", card->name); + char buf[MAX_STR_HWADDR_LEN]; + hwaddr_to_str (&card->default_address, buf); + grub_printf ("%s %s\n", card->name, buf); } - grub_printf ("\n"); return GRUB_ERR_NONE; } From f8614119a02110e8ccd69499b5a03147e9535372 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:38:43 +0200 Subject: [PATCH 232/673] Few ofnet cleanups --- grub-core/net/drivers/ieee1275/ofnet.c | 47 ++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 2c264edb1..48c3cd635 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #include #include #include @@ -37,7 +55,8 @@ card_close (struct grub_net_card *dev) } static grub_err_t -send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +send_card_buffer (const struct grub_net_card *dev, + struct grub_net_buff *pack) { int actual; int status; @@ -52,7 +71,8 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) } static grub_ssize_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) +get_card_packet (const struct grub_net_card *dev, + struct grub_net_buff *nb) { int actual, rc; @@ -125,20 +145,33 @@ grub_getbootp_real (void) static void grub_ofnet_findcards (void) { - struct grub_net_card *card; - grub_ieee1275_phandle_t devhandle; - grub_net_link_level_address_t lla; int i = 0; + auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) { if (!grub_strcmp (alias->type, "network")) { + struct grub_ofnetcard_data *ofdata; + struct grub_net_card *card; + grub_ieee1275_phandle_t devhandle; + grub_net_link_level_address_t lla; + ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); + if (!ofdata) + { + grub_print_error (); + return 1; + } card = grub_malloc (sizeof (struct grub_net_card)); - struct grub_ofnetcard_data *ofdata = - grub_malloc (sizeof (struct grub_ofnetcard_data)); + if (!card) + { + grub_free (ofdata); + grub_print_error (); + return 1; + } + ofdata->path = grub_strdup (alias->path); grub_ieee1275_finddevice (ofdata->path, &devhandle); From 9d22909b8561f72a6503a1f26eab9652670db43f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:42:04 +0200 Subject: [PATCH 233/673] efinet support --- grub-core/Makefile.core.def | 8 +- grub-core/kern/x86_64/efi/callwrap.S | 14 +++ grub-core/net/drivers/efi/efinet.c | 165 +++++++++++++++++++++++++++ include/grub/efi/api.h | 81 +++++++++++++ 4 files changed, 267 insertions(+), 1 deletion(-) create mode 100644 grub-core/net/drivers/efi/efinet.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 5c3ce99be..ac969e09c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1588,10 +1588,16 @@ module = { module = { name = ofnet; - ieee1275 = net/drivers/ieee1275/ofnet.c; + common = net/drivers/ieee1275/ofnet.c; enable = ieee1275; }; +module = { + name = efinet; + common = net/drivers/efi/efinet.c; + enable = efi; +}; + module = { name = emunet; emu = net/drivers/emu/emunet.c; diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S index aae267872..cc2c8aa05 100644 --- a/grub-core/kern/x86_64/efi/callwrap.S +++ b/grub-core/kern/x86_64/efi/callwrap.S @@ -95,6 +95,20 @@ FUNCTION(efi_wrap_6) addq $64, %rsp ret +FUNCTION(efi_wrap_7) + subq $96, %rsp + mov 96+16(%rsp), %rax + mov %rax, 48(%rsp) + mov 96+8(%rsp), %rax + mov %rax, 40(%rsp) + mov %r9, 32(%rsp) + mov %r8, %r9 + mov %rcx, %r8 + mov %rsi, %rcx + call *%rdi + addq $96, %rsp + ret + FUNCTION(efi_wrap_10) subq $96, %rsp mov 96+40(%rsp), %rax diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c new file mode 100644 index 000000000..a6e005601 --- /dev/null +++ b/grub-core/net/drivers/efi/efinet.c @@ -0,0 +1,165 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* GUID. */ +static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; + + +static grub_err_t +send_card_buffer (const struct grub_net_card *dev, + struct grub_net_buff *pack) +{ + grub_efi_status_t st; + grub_efi_simple_network_t *net = dev->data; + st = efi_call_7 (net->transmit, net, 0, pack->tail - pack->data, + pack->data, NULL, NULL, NULL); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, "Couldn't send network packet."); + return GRUB_ERR_NONE; +} + +static grub_ssize_t +get_card_packet (const struct grub_net_card *dev, + struct grub_net_buff *nb) +{ + grub_efi_simple_network_t *net = dev->data; + grub_err_t err; + grub_efi_status_t st; + grub_efi_uintn_t bufsize = 1500; + + err = grub_netbuff_clear (nb); + if (err) + return -1; + + err = grub_netbuff_put (nb, 1500); + if (err) + return -1; + + st = efi_call_7 (net->receive, net, NULL, &bufsize, + nb->data, NULL, NULL, NULL); + if (st == GRUB_EFI_BUFFER_TOO_SMALL) + { + err = grub_netbuff_put (nb, bufsize - 1500); + if (err) + return -1; + st = efi_call_7 (net->receive, net, NULL, &bufsize, + nb->data, NULL, NULL, NULL); + } + if (st != GRUB_EFI_SUCCESS) + { + grub_netbuff_clear (nb); + return -1; + } + err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize); + if (err) + return -1; + + return bufsize; +} + +static struct grub_net_card_driver efidriver = + { + .name = "efinet", + .send = send_card_buffer, + .recv = get_card_packet + }; + + +static void +grub_efinet_findcards (void) +{ + grub_efi_uintn_t num_handles; + grub_efi_handle_t *handles; + grub_efi_handle_t *handle; + int i = 0; + + /* Find handles which support the disk io interface. */ + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &net_io_guid, + 0, &num_handles); + if (! handles) + return; + for (handle = handles; num_handles--; handle++) + { + grub_efi_simple_network_t *net; + struct grub_net_card *card; + + net = grub_efi_open_protocol (*handle, &net_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (! net) + /* This should not happen... Why? */ + continue; + + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED + && efi_call_1 (net->start, net) != GRUB_EFI_SUCCESS) + continue; + + if (net->mode->state == GRUB_EFI_NETWORK_STOPPED) + continue; + + if (net->mode->state == GRUB_EFI_NETWORK_STARTED + && efi_call_3 (net->initialize, net, 0, 0) != GRUB_EFI_SUCCESS) + continue; + + card = grub_zalloc (sizeof (struct grub_net_card)); + if (!card) + { + grub_print_error (); + grub_free (handles); + return; + } + + card->name = grub_xasprintf ("efinet%d", i++); + card->driver = &efidriver; + card->flags = 0; + card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (card->default_address.mac, + net->mode->current_address, + sizeof (card->default_address.mac)); + card->data = net; + + grub_net_card_register (card); + } + grub_free (handles); +} + +GRUB_MOD_INIT(efinet) +{ + grub_efinet_findcards (); +} + +GRUB_MOD_FINI(ofnet) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->driver && !grub_strcmp (card->driver->name, "efinet")) + { + card->driver->fini (card); + card->driver = NULL; + } + grub_net_card_driver_unregister (&efidriver); +} + diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index ded03a1b3..a3dde0eff 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -84,6 +84,11 @@ { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ } +#define GRUB_EFI_SIMPLE_NETWORK_GUID \ + { 0xa19832b9, 0xac25, 0x11d3, \ + { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + #define GRUB_EFI_DEVICE_PATH_GUID \ { 0x09576e91, 0x6d3f, 0x11d2, \ { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ @@ -1214,6 +1219,74 @@ struct grub_efi_block_io_media }; typedef struct grub_efi_block_io_media grub_efi_block_io_media_t; +typedef grub_uint8_t grub_efi_mac_t[32]; + +struct grub_efi_simple_network_mode +{ + grub_uint32_t state; + grub_uint32_t hwaddr_size; + grub_uint32_t media_header_size; + grub_uint32_t max_packet_size; + grub_uint32_t nvram_size; + grub_uint32_t nvram_access_size; + grub_uint32_t receive_filter_mask; + grub_uint32_t receive_filter_setting; + grub_uint32_t max_mcast_filter_count; + grub_uint32_t mcast_filter_count; + grub_efi_mac_t mcast_filter[16]; + grub_efi_mac_t current_address; + grub_efi_mac_t broadcast_address; + grub_efi_mac_t permanent_address; + grub_uint8_t if_type; + grub_uint8_t mac_changeable; + grub_uint8_t multitx_supported; + grub_uint8_t media_present_supported; + grub_uint8_t media_present; +}; + +enum + { + GRUB_EFI_NETWORK_STOPPED, + GRUB_EFI_NETWORK_STARTED, + GRUB_EFI_NETWORK_INITIALIZED, + }; + +struct grub_efi_simple_network +{ + grub_uint64_t revision; + grub_efi_status_t (*start) (struct grub_efi_simple_network *this); + void (*stop) (void); + grub_efi_status_t (*initialize) (struct grub_efi_simple_network *this, + grub_efi_uintn_t extra_rx, + grub_efi_uintn_t extra_tx); + void (*reset) (void); + void (*shutdown) (void); + void (*receive_filters) (void); + void (*station_address) (void); + void (*statistics) (void); + void (*mcastiptomac) (void); + void (*nvdata) (void); + void (*getstatus) (void); + grub_efi_status_t (*transmit) (struct grub_efi_simple_network *this, + grub_efi_uintn_t header_size, + grub_efi_uintn_t buffer_size, + void *buffer, + grub_efi_mac_t *src_addr, + grub_efi_mac_t *dest_addr, + grub_efi_uint16_t *protocol); + grub_efi_status_t (*receive) (struct grub_efi_simple_network *this, + grub_efi_uintn_t *header_size, + grub_efi_uintn_t *buffer_size, + void *buffer, + grub_efi_mac_t *src_addr, + grub_efi_mac_t *dest_addr, + grub_uint16_t *protocol); + void (*waitforpacket) (void); + struct grub_efi_simple_network_mode *mode; +}; +typedef struct grub_efi_simple_network grub_efi_simple_network_t; + + struct grub_efi_block_io { grub_efi_uint64_t revision; @@ -1243,6 +1316,7 @@ typedef struct grub_efi_block_io grub_efi_block_io_t; #define efi_call_4(func, a, b, c, d) func(a, b, c, d) #define efi_call_5(func, a, b, c, d, e) func(a, b, c, d, e) #define efi_call_6(func, a, b, c, d, e, f) func(a, b, c, d, e, f) +#define efi_call_7(func, a, b, c, d, e, f, g) func(a, b, c, d, e, f, g) #define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) func(a, b, c, d, e, f, g, h, i, j) #else @@ -1264,6 +1338,9 @@ typedef struct grub_efi_block_io grub_efi_block_io_t; #define efi_call_6(func, a, b, c, d, e, f) \ efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f) +#define efi_call_7(func, a, b, c, d, e, f, g) \ + efi_wrap_7(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ + (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g) #define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) \ efi_wrap_10(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g, \ @@ -1285,6 +1362,10 @@ grub_uint64_t EXPORT_FUNC(efi_wrap_6) (void *func, grub_uint64_t arg1, grub_uint64_t arg2, grub_uint64_t arg3, grub_uint64_t arg4, grub_uint64_t arg5, grub_uint64_t arg6); +grub_uint64_t EXPORT_FUNC(efi_wrap_7) (void *func, grub_uint64_t arg1, + grub_uint64_t arg2, grub_uint64_t arg3, + grub_uint64_t arg4, grub_uint64_t arg5, + grub_uint64_t arg6, grub_uint64_t arg7); grub_uint64_t EXPORT_FUNC(efi_wrap_10) (void *func, grub_uint64_t arg1, grub_uint64_t arg2, grub_uint64_t arg3, grub_uint64_t arg4, grub_uint64_t arg5, From 0ff2c51b82c629e93fff4cc53c129b4d05a73667 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 26 Jun 2011 22:47:05 +0200 Subject: [PATCH 234/673] mknetdir support for EFI --- util/grub-mknetdir.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index a36e33cab..52598a8c9 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -48,6 +48,9 @@ pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc ppc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275 sparc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275 i386_ieee1275_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275 +efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi +efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi +itanium_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/ia64-efi # Usage: usage # Print the usage. @@ -210,6 +213,9 @@ process_input_dir () *-ieee1275) mkimage_target="${platform}"; netmodules="ofnet"; ext=elf ;; + *-efi) mkimage_target="${platform}"; + netmodules="efinet"; + ext=efi ;; *) echo Unsupported platform ${platform}; exit 1;; esac @@ -235,6 +241,15 @@ if [ "${override_dir}" = "" ] ; then if test -e "${i386_ieee1275_dir}" ; then process_input_dir "${i386_ieee1275_dir}" i386-ieee1275 fi + if test -e "${efi32_dir}" ; then + process_input_dir "${efi32_dir}" i386-efi + fi + if test -e "${efi64_dir}" ; then + process_input_dir "${efi64_dir}" x86_64-efi + fi + if test -e "${itanium_dir}" ; then + process_input_dir "${itanium_dir}" ia64-efi + fi else source "${override_dir}"/modinfo.sh process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} From 59b455fceaee233e7221831e520c2dd76d42a466 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 06:31:25 +0200 Subject: [PATCH 235/673] Fix incorrect ISR PXE calls --- grub-core/net/drivers/i386/pc/pxe.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 084cdb876..144df964c 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -165,7 +165,10 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), isr->func_flag = GRUB_PXE_ISR_IN_START; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS) - return -1; + { + in_progress = 0; + return -1; + } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); @@ -180,7 +183,10 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), while (isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) { if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE) - return -1; + { + in_progress = 0; + return -1; + } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); @@ -198,11 +204,15 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) - return -1; + { + in_progress = 1; + return -1; + } grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); ptr += isr->buffer_len; } + in_progress = 1; return len; } From ca80309d32c9d8890d5a16888eac80043a9a16ec Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 08:40:17 +0200 Subject: [PATCH 236/673] * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix prototype. (get_card_packet): Likewise. --- ChangeLog | 6 ++++++ grub-core/net/drivers/ieee1275/ofnet.c | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd6e311bd..62976120f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix + prototype. + (get_card_packet): Likewise. + 2011-06-26 Yves Blusseau Display the path of the file when file is not found diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 2c264edb1..0394e0dc0 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -37,7 +37,7 @@ card_close (struct grub_net_card *dev) } static grub_err_t -send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) +send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) { int actual; int status; @@ -52,9 +52,8 @@ send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack) } static grub_ssize_t -get_card_packet (struct grub_net_card *dev, struct grub_net_buff *nb) +get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) { - int actual, rc; struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; From 41bec7fec9b8a56172ab99997d5c86de9cffd405 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 08:43:13 +0200 Subject: [PATCH 237/673] * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper definitions for dprintf. * grub-core/disk/pata.c (grub_pata_readwrite): Likewise. --- ChangeLog | 6 ++++++ grub-core/disk/ahci.c | 3 ++- grub-core/disk/pata.c | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 62976120f..df640a0ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper + definitions for dprintf. + * grub-core/disk/pata.c (grub_pata_readwrite): Likewise. + 2011-06-27 Vladimir Serbinenko * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 0f355aa53..415004fcf 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -590,7 +590,8 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) | GRUB_AHCI_INTERRUPT_ON_COMPLETE; - grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%x)\n", + grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%" + PRIuGRUB_SIZE ")\n", dev->command_table[0].prdt[0].data_base, dev->command_table[0].prdt[0].unused, dev->command_table[0].prdt[0].size, diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 1cb42d04b..ac3b91a41 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -156,7 +156,8 @@ grub_pata_readwrite (struct grub_ata *disk, parms->taskfile.cmd, parms->taskfile.features, parms->taskfile.sectors); - grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n", + grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%" + PRIuGRUB_SIZE "\n", parms->taskfile.lba_high, parms->taskfile.lba_mid, parms->taskfile.lba_low, parms->size); From 9fc9ce3795196effead800fecffff70c0b3415bd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 08:54:55 +0200 Subject: [PATCH 238/673] Coreboot video support. * grub-core/Makefile.core.def (vga): Extend to coreboot and multiboot. (vbe): Likewise. * grub-core/kern/i386/coreboot/startup.S: Include int.S. * grub-core/kern/i386/pc/startup.S (grub_bios_interrupt): Moved from here ... * grub-core/kern/i386/int.S: ... here. * grub-core/video/i386/pc/vbe.c: Updated includes. * grub-core/video/i386/pc/vga.c: Likewise. * include/grub/i386/coreboot/memory.h (GRUB_MEMORY_MACHINE_SCRATCH_ADDR): New definition. (GRUB_MEMORY_MACHINE_SCRATCH_SEG): Likewise. (GRUB_MEMORY_MACHINE_SCRATCH_SIZE): Likewise. * include/grub/i386/pc/int.h (GRUB_CPU_INT_FLAGS_DEFAULT) [!PCBIOS]: Disable interrupts. * include/grub/i386/pc/vga.h: Removed. All users updated. --- ChangeLog | 20 ++++ grub-core/Makefile.am | 2 + grub-core/Makefile.core.def | 8 +- grub-core/kern/i386/coreboot/startup.S | 1 + grub-core/kern/i386/int.S | 140 +++++++++++++++++++++++++ grub-core/kern/i386/pc/startup.S | 100 +----------------- grub-core/video/i386/pc/vbe.c | 7 +- grub-core/video/i386/pc/vga.c | 5 +- include/grub/i386/coreboot/memory.h | 4 + include/grub/i386/pc/int.h | 5 + include/grub/i386/pc/vga.h | 28 ----- 11 files changed, 184 insertions(+), 136 deletions(-) create mode 100644 grub-core/kern/i386/int.S delete mode 100644 include/grub/i386/pc/vga.h diff --git a/ChangeLog b/ChangeLog index df640a0ef..311e65b05 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2011-06-27 Vladimir Serbinenko + + Coreboot video support. + + * grub-core/Makefile.core.def (vga): Extend to coreboot and multiboot. + (vbe): Likewise. + * grub-core/kern/i386/coreboot/startup.S: Include int.S. + * grub-core/kern/i386/pc/startup.S (grub_bios_interrupt): Moved from + here ... + * grub-core/kern/i386/int.S: ... here. + * grub-core/video/i386/pc/vbe.c: Updated includes. + * grub-core/video/i386/pc/vga.c: Likewise. + * include/grub/i386/coreboot/memory.h + (GRUB_MEMORY_MACHINE_SCRATCH_ADDR): New definition. + (GRUB_MEMORY_MACHINE_SCRATCH_SEG): Likewise. + (GRUB_MEMORY_MACHINE_SCRATCH_SIZE): Likewise. + * include/grub/i386/pc/int.h (GRUB_CPU_INT_FLAGS_DEFAULT) [!PCBIOS]: + Disable interrupts. + * include/grub/i386/pc/vga.h: Removed. All users updated. + 2011-06-27 Vladimir Serbinenko * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index a8862b309..c3ecba9cf 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -100,10 +100,12 @@ endif if COND_i386_coreboot KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_multiboot KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h endif if COND_i386_qemu diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 927718359..7a0536b97 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1454,8 +1454,10 @@ module = { module = { name = vga; - i386_pc = video/i386/pc/vga.c; + common = video/i386/pc/vga.c; enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; }; module = { @@ -1533,8 +1535,10 @@ module = { module = { name = vbe; - i386_pc = video/i386/pc/vbe.c; + common = video/i386/pc/vbe.c; enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; }; module = { diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S index cac023ddf..07c5437c0 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -87,3 +87,4 @@ codestart: */ #include "../realmode.S" +#include "../int.S" diff --git a/grub-core/kern/i386/int.S b/grub-core/kern/i386/int.S new file mode 100644 index 000000000..58ccfdaab --- /dev/null +++ b/grub-core/kern/i386/int.S @@ -0,0 +1,140 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +FUNCTION(grub_bios_interrupt) + pushf + cli +#ifndef GRUB_MACHINE_PCBIOS + sidt protidt +#endif + popf + pushl %ebp + pushl %ecx + pushl %eax + pushl %ebx + pushl %esi + pushl %edi + pushl %edx + + movb %al, intno + movl (%edx), %eax + movl %eax, LOCAL(bios_register_eax) + movw 4(%edx), %ax + movw %ax, LOCAL(bios_register_es) + movw 6(%edx), %ax + movw %ax, LOCAL(bios_register_ds) + movw 8(%edx), %ax + movw %ax, LOCAL(bios_register_flags) + + movl 12(%edx), %ebx + movl 16(%edx), %ecx + movl 20(%edx), %edi + movl 24(%edx), %esi + movl 28(%edx), %edx + + call prot_to_real + .code16 + pushf + cli +#ifndef GRUB_MACHINE_PCBIOS + lidt realidt +#endif + + mov %ds, %ax + push %ax + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_es): + .short 0 + movw %ax, %es + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_ds): + .short 0 + movw %ax, %ds + + /* movw imm16, %ax*/ + .byte 0xb8 +LOCAL(bios_register_flags): + .short 0 + push %ax + popf + + /* movl imm32, %eax*/ + .byte 0x66, 0xb8 +LOCAL(bios_register_eax): + .long 0 + + /* int imm8. */ + .byte 0xcd +intno: + .byte 0 + + movl %eax, %cs:LOCAL(bios_register_eax) + movw %ds, %ax + movw %ax, %cs:LOCAL(bios_register_ds) + pop %ax + mov %ax, %ds + pushf + pop %ax + movw %ax, LOCAL(bios_register_flags) + mov %es, %ax + movw %ax, LOCAL(bios_register_es) + + popf + DATA32 call real_to_prot + .code32 + + popl %eax + + movl %ebx, 12(%eax) + movl %ecx, 16(%eax) + movl %edi, 20(%eax) + movl %esi, 24(%eax) + movl %edx, 28(%eax) + + movl %eax, %edx + + movl LOCAL(bios_register_eax), %eax + movl %eax, (%edx) + movw LOCAL(bios_register_es), %ax + movw %ax, 4(%edx) + movw LOCAL(bios_register_ds), %ax + movw %ax, 6(%edx) + movw LOCAL(bios_register_flags), %ax + movw %ax, 8(%edx) + + popl %edi + popl %esi + popl %ebx + popl %eax + popl %ecx + popl %ebp +#ifndef GRUB_MACHINE_PCBIOS + lidt protidt +#endif + ret +#ifndef GRUB_MACHINE_PCBIOS +realidt: + .word 0x100 + .long 0 +protidt: + .word 0 + .long 0 +#endif diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index e78a0aa9a..0fe114add 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -910,102 +910,4 @@ FUNCTION(grub_pxe_call) popl %ebp ret -FUNCTION(grub_bios_interrupt) - pushl %ebp - pushl %ecx - pushl %eax - pushl %ebx - pushl %esi - pushl %edi - pushl %edx - - movb %al, intno - movl (%edx), %eax - movl %eax, LOCAL(bios_register_eax) - movw 4(%edx), %ax - movw %ax, LOCAL(bios_register_es) - movw 6(%edx), %ax - movw %ax, LOCAL(bios_register_ds) - movw 8(%edx), %ax - movw %ax, LOCAL(bios_register_flags) - - movl 12(%edx), %ebx - movl 16(%edx), %ecx - movl 20(%edx), %edi - movl 24(%edx), %esi - movl 28(%edx), %edx - - call prot_to_real - .code16 - - mov %ds, %ax - push %ax - - /* movw imm16, %ax*/ - .byte 0xb8 -LOCAL(bios_register_es): - .short 0 - movw %ax, %es - /* movw imm16, %ax*/ - .byte 0xb8 -LOCAL(bios_register_ds): - .short 0 - movw %ax, %ds - - /* movw imm16, %ax*/ - .byte 0xb8 -LOCAL(bios_register_flags): - .short 0 - push %ax - popf - - /* movl imm32, %eax*/ - .byte 0x66, 0xb8 -LOCAL(bios_register_eax): - .long 0 - - /* int imm8. */ - .byte 0xcd -intno: - .byte 0 - - movl %eax, %cs:LOCAL(bios_register_eax) - movw %ds, %ax - movw %ax, %cs:LOCAL(bios_register_ds) - pop %ax - mov %ax, %ds - pushf - pop %ax - movw %ax, LOCAL(bios_register_flags) - mov %es, %ax - movw %ax, LOCAL(bios_register_es) - - DATA32 call real_to_prot - .code32 - - popl %eax - - movl %ebx, 12(%eax) - movl %ecx, 16(%eax) - movl %edi, 20(%eax) - movl %esi, 24(%eax) - movl %edx, 28(%eax) - - movl %eax, %edx - - movl LOCAL(bios_register_eax), %eax - movl %eax, (%edx) - movw LOCAL(bios_register_es), %ax - movw %ax, 4(%edx) - movw LOCAL(bios_register_ds), %ax - movw %ax, 6(%edx) - movw LOCAL(bios_register_flags), %ax - movw %ax, 8(%edx) - - popl %edi - popl %esi - popl %ebx - popl %eax - popl %ecx - popl %ebp - ret +#include "../int.S" diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index a109bcf43..c11b9a627 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -20,15 +20,14 @@ #include #include -#include -#include +#include #include #include #include #include #include #include -#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -377,7 +376,7 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, if (vbe_mode < 0x100) { /* If this is not a VESA mode, guess address. */ - framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR; + framebuffer.ptr = (grub_uint8_t *) 0xa0000; } else { diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c index fe387a26b..08c9ca37d 100644 --- a/grub-core/video/i386/pc/vga.c +++ b/grub-core/video/i386/pc/vga.c @@ -18,8 +18,7 @@ #define grub_video_render_target grub_video_fbrender_target -#include -#include +#include #include #include #include @@ -34,7 +33,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define VGA_WIDTH 640 #define VGA_HEIGHT 350 -#define VGA_MEM ((grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR) +#define VGA_MEM ((grub_uint8_t *) 0xa0000) #define PAGE_OFFSET(x) ((x) * (VGA_WIDTH * VGA_HEIGHT / 8)) static unsigned char text_mode; diff --git a/include/grub/i386/coreboot/memory.h b/include/grub/i386/coreboot/memory.h index 0642280b9..2859b1d7c 100644 --- a/include/grub/i386/coreboot/memory.h +++ b/include/grub/i386/coreboot/memory.h @@ -28,6 +28,10 @@ #include #endif +#define GRUB_MEMORY_MACHINE_SCRATCH_ADDR 0x68000 +#define GRUB_MEMORY_MACHINE_SCRATCH_SEG (GRUB_MEMORY_MACHINE_SCRATCH_ADDR >> 4) +#define GRUB_MEMORY_MACHINE_SCRATCH_SIZE 0x10000 + #define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */ #define GRUB_MEMORY_MACHINE_UPPER_START 0x100000 /* 1 MiB */ diff --git a/include/grub/i386/pc/int.h b/include/grub/i386/pc/int.h index de23775d0..337752587 100644 --- a/include/grub/i386/pc/int.h +++ b/include/grub/i386/pc/int.h @@ -45,7 +45,12 @@ struct grub_bios_int_registers #define GRUB_CPU_INT_FLAGS_INTERRUPT 0x200 #define GRUB_CPU_INT_FLAGS_DIRECTION 0x400 #define GRUB_CPU_INT_FLAGS_OVERFLOW 0x800 +#ifdef GRUB_MACHINE_PCBIOS #define GRUB_CPU_INT_FLAGS_DEFAULT GRUB_CPU_INT_FLAGS_INTERRUPT +#else +#define GRUB_CPU_INT_FLAGS_DEFAULT 0 +#endif + void EXPORT_FUNC (grub_bios_interrupt) (grub_uint8_t intno, struct grub_bios_int_registers *regs); diff --git a/include/grub/i386/pc/vga.h b/include/grub/i386/pc/vga.h deleted file mode 100644 index ecc169022..000000000 --- a/include/grub/i386/pc/vga.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,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 . - */ - -#ifndef GRUB_VGA_MACHINE_HEADER -#define GRUB_VGA_MACHINE_HEADER 1 - -#include -#include - -/* The VGA (at the beginning of upper memory). */ -#define GRUB_MEMORY_MACHINE_VGA_ADDR GRUB_MEMORY_MACHINE_UPPER - -#endif /* ! GRUB_VGA_MACHINE_HEADER */ From efff4b1cc3e390533a7333420cf980d304bd10bc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 09:06:15 +0200 Subject: [PATCH 239/673] * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when necessary. --- ChangeLog | 5 +++++ util/grub-mkrescue.in | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 311e65b05..ca4145e33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when + necessary. + 2011-06-27 Vladimir Serbinenko Coreboot video support. diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 8367c4dd4..f054c43a9 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -275,7 +275,7 @@ if test -e "${pc_dir}" ; then fi # build multiboot core.img -make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "ata at_keyboard" +make_image "${multiboot_dir}" i386-multiboot "${iso9660_dir}/boot/multiboot.img" "pata ahci at_keyboard" if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then efi_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 @@ -296,11 +296,11 @@ if test -e "${efi64_dir}" || test -e "${efi32_dir}"; then grub_mkisofs_arguments="${grub_mkisofs_arguments} --efi-boot efi.img" fi -make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/qemu.img" "ata at_keyboard" +make_image "${qemu_dir}" i386-qemu "${iso9660_dir}/boot/qemu.img" "pata at_keyboard" if [ -e "${iso9660_dir}/boot/qemu.img" ] && [ -d "${rom_directory}" ]; then cp "${iso9660_dir}/boot/qemu.img" "${rom_directory}/qemu.img" fi -make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/coreboot.elf" "ata at_keyboard" +make_image "${coreboot_dir}" i386-coreboot "${iso9660_dir}/boot/coreboot.elf" "pata ahci at_keyboard" if [ -e "${iso9660_dir}/boot/coreboot.elf" ] && [ -d "${rom_directory}" ]; then cp "${iso9660_dir}/boot/coreboot.elf" "${rom_directory}/coreboot.elf" fi From 1e3d9b8612a3f2a4c907b98d6465fcf4e7a53c4e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 10:12:35 +0200 Subject: [PATCH 240/673] * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K because of underlying system restrictions. --- ChangeLog | 5 +++++ grub-core/disk/scsi.c | 33 ++++++++++++++++++++++++++------- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index ca4145e33..360842279 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K + because of underlying system restrictions. + 2011-06-27 Vladimir Serbinenko * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 35b8525c2..902564164 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -524,17 +524,36 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, scsi = disk->data; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) + while (size) { - case grub_scsi_devtype_direct: - return grub_scsi_read10 (disk, sector, size, buf); + /* PATA doesn't support more than 32K reads. + Not sure about AHCI and USB. If it's confirmed that either of + them can do bigger reads reliably this value can be moved to 'scsi' + structure. */ + grub_size_t len = 32768 >> disk->log_sector_size; + grub_err_t err; + if (len > size) + len = size; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) + { + case grub_scsi_devtype_direct: + err = grub_scsi_read10 (disk, sector, len, buf); + if (err) + return err; + break; - case grub_scsi_devtype_cdrom: - return grub_scsi_read12 (disk, sector, size, buf); + case grub_scsi_devtype_cdrom: + err = grub_scsi_read12 (disk, sector, len, buf); + if (err) + return err; + break; + } + size -= len; + sector += len; + buf += len << disk->log_sector_size; } - /* XXX: Never reached. */ return GRUB_ERR_NONE; #if 0 /* Workaround - it works - but very slowly, from some reason From f9b75e8a67f54b425b64c62ea68d7ced88c566bd Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 27 Jun 2011 10:47:02 +0100 Subject: [PATCH 241/673] * grub-core/commands/videoinfo.c (hook): Indicate current video mode with `*'. (grub_cmd_videoinfo): Fetch current video mode. --- ChangeLog | 6 ++++++ grub-core/commands/videoinfo.c | 25 +++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 360842279..1aabd6b18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Colin Watson + + * grub-core/commands/videoinfo.c (hook): Indicate current video mode + with `*'. + (grub_cmd_videoinfo): Fetch current video mode. + 2011-06-27 Vladimir Serbinenko * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 3e0c1a12e..91a87fecc 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -28,6 +28,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); static unsigned height, width, depth; +static struct grub_video_mode_info *current_mode; static int hook (const struct grub_video_mode_info *info) @@ -41,7 +42,13 @@ hook (const struct grub_video_mode_info *info) if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) grub_printf (" "); else - grub_printf (" 0x%03x ", info->mode_number); + { + if (current_mode && info->mode_number == current_mode->mode_number) + grub_printf ("*"); + else + grub_printf (" "); + grub_printf (" 0x%03x ", info->mode_number); + } grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) @@ -122,6 +129,8 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), FOR_VIDEO_ADAPTERS (adapter) { + struct grub_video_mode_info info; + grub_printf ("Adapter '%s':\n", adapter->name); if (!adapter->iterate) @@ -130,7 +139,17 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), continue; } - if (adapter->id != id) + current_mode = NULL; + + if (adapter->id == id) + { + if (grub_video_get_info (&info) == GRUB_ERR_NONE) + current_mode = &info; + else + /* Don't worry about errors. */ + grub_errno = GRUB_ERR_NONE; + } + else { if (adapter->init ()) { @@ -145,6 +164,8 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), adapter->iterate (hook); + current_mode = NULL; + if (adapter->id != id) { if (adapter->fini ()) From b6f945dccbf99c7126cca5b01f4cea807ccffc9e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:13:21 +0200 Subject: [PATCH 242/673] * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right type in pointers on sparc64. (get_card_packet): Likewise. --- ChangeLog | 6 ++++++ grub-core/net/drivers/ieee1275/ofnet.c | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1aabd6b18..1a3237f88 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right + type in pointers on sparc64. + (get_card_packet): Likewise. + 2011-06-27 Colin Watson * grub-core/commands/videoinfo.c (hook): Indicate current video mode diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 0394e0dc0..b5bb03dc8 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -39,7 +39,7 @@ card_close (struct grub_net_card *dev) static grub_err_t send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) { - int actual; + grub_ssize_t actual; int status; struct grub_ofnetcard_data *data = dev->data; @@ -54,7 +54,8 @@ send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) static grub_ssize_t get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) { - int actual, rc; + grub_ssize_t actual; + int rc; struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; From b28c56559b446bdc824fe650a641aa9e11923448 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:16:00 +0200 Subject: [PATCH 243/673] * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version so that help2man doesn't fail. --- ChangeLog | 5 +++++ util/ieee1275/grub-ofpathname.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1a3237f88..37446af70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version + so that help2man doesn't fail. + 2011-06-27 Vladimir Serbinenko * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right diff --git a/util/ieee1275/grub-ofpathname.c b/util/ieee1275/grub-ofpathname.c index 3ac6fce8b..a9bc2cfda 100644 --- a/util/ieee1275/grub-ofpathname.c +++ b/util/ieee1275/grub-ofpathname.c @@ -32,11 +32,16 @@ int main(int argc, char **argv) grub_util_init_nls (); - if (argc != 2) + if (argc != 2 || strcmp (argv[1], "--help") == 0) { printf("Usage: %s DEVICE\n", program_name); return 1; } + if (strcmp (argv[1], "--version") == 0) + { + printf ("%s\n", PACKAGE_STRING); + return 1; + } of_path = grub_util_devname_to_ofpath (argv[1]); printf("%s\n", of_path); From bdea37983323f19d0cf8d2ef529d4d0f88ba2d81 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:18:44 +0200 Subject: [PATCH 244/673] * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption when handling leftovers. --- ChangeLog | 5 +++++ grub-core/lib/relocator.c | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 37446af70..e35b7c7ff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption + when handling leftovers. + 2011-06-27 Vladimir Serbinenko * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c index 6eb20b865..aa404731f 100644 --- a/grub-core/lib/relocator.c +++ b/grub-core/lib/relocator.c @@ -764,6 +764,9 @@ malloc_in_range (struct grub_relocator *rel, int inreg = 0, regbeg = 0, ncol = 0; #if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS int fwin = 0, fwb = 0, fwlefto = 0; +#endif +#if GRUB_RELOCATOR_HAVE_LEFTOVERS + int last_lo = 0; #endif int last_start = 0; for (j = 0; j < N; j++) @@ -855,7 +858,7 @@ malloc_in_range (struct grub_relocator *rel, unsigned offend = alloc_end % GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT; struct grub_relocator_fw_leftover *lo - = events[last_start].leftover; + = events[last_lo].leftover; lo->freebytes[offstart / 8] &= ((1 << (8 - (start % 8))) - 1); grub_memset (lo->freebytes + (offstart + 7) / 8, 0, @@ -910,6 +913,7 @@ malloc_in_range (struct grub_relocator *rel, #if GRUB_RELOCATOR_HAVE_LEFTOVERS case REG_LEFTOVER_START: fwlefto++; + last_lo = j; break; case REG_LEFTOVER_END: @@ -1009,7 +1013,8 @@ malloc_in_range (struct grub_relocator *rel, curschu->extra = ne; } } -#if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS + +#if GRUB_RELOCATOR_HAVE_LEFTOVERS if (!oom && typepre == CHUNK_TYPE_FIRMWARE) { grub_addr_t fstart, fend; @@ -1021,7 +1026,6 @@ malloc_in_range (struct grub_relocator *rel, = ALIGN_UP (alloc_end, GRUB_RELOCATOR_FIRMWARE_REQUESTS_QUANT); -#if GRUB_RELOCATOR_HAVE_LEFTOVERS { struct grub_relocator_fw_leftover *lo1 = NULL; struct grub_relocator_fw_leftover *lo2 = NULL; @@ -1081,10 +1085,8 @@ malloc_in_range (struct grub_relocator *rel, curschu->pre = lo1; curschu->post = lo2; } -#endif } -#if GRUB_RELOCATOR_HAVE_LEFTOVERS if (typepre == CHUNK_TYPE_LEFTOVER) { curschu->pre = events[last_start].leftover; @@ -1092,7 +1094,6 @@ malloc_in_range (struct grub_relocator *rel, } #endif -#endif if (!oom) cural++; else From 5ebaad7eec21a1d209d781b8c0b17f993a238380 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:28:47 +0200 Subject: [PATCH 245/673] * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export. --- ChangeLog | 4 ++++ include/grub/loader.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e35b7c7ff..866e2ccaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-27 Vladimir Serbinenko + + * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export. + 2011-06-27 Vladimir Serbinenko * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption diff --git a/include/grub/loader.h b/include/grub/loader.h index c71e8dd10..f38deb96a 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -61,6 +61,6 @@ void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) grub_loader_preboot_hook_prio_t prio); /* Unregister given preboot hook. */ -void grub_loader_unregister_preboot_hook (void *hnd); +void EXPORT_FUNC (grub_loader_unregister_preboot_hook) (void *hnd); #endif /* ! GRUB_LOADER_HEADER */ From 5ff1d945ed89aa6203fdc005a55dbb83b3380ea1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 12:31:37 +0200 Subject: [PATCH 246/673] Implement time command. * grub-core/Makefile.core.def (time): New module. * grub-core/commands/time.c: New file. * grub-core/script/parser.y: Remove "time" keyword. * grub-core/script/yylex.l: Likewise. --- ChangeLog | 9 +++++ grub-core/Makefile.core.def | 5 +++ grub-core/commands/time.c | 68 +++++++++++++++++++++++++++++++++++++ grub-core/script/parser.y | 2 -- grub-core/script/yylex.l | 1 - 5 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 grub-core/commands/time.c diff --git a/ChangeLog b/ChangeLog index 866e2ccaf..4cdbc2b15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-06-27 Vladimir Serbinenko + + Implement time command. + + * grub-core/Makefile.core.def (time): New module. + * grub-core/commands/time.c: New file. + * grub-core/script/parser.y: Remove "time" keyword. + * grub-core/script/yylex.l: Likewise. + 2011-06-27 Vladimir Serbinenko * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7a0536b97..b10c16d55 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1641,3 +1641,8 @@ module = { common = commands/keylayouts.c; enable = videomodules; }; + +module = { + name = time; + common = commands/time.c; +}; diff --git a/grub-core/commands/time.c b/grub-core/commands/time.c new file mode 100644 index 000000000..687495964 --- /dev/null +++ b/grub-core/commands/time.c @@ -0,0 +1,68 @@ +/* echo.c - Command to display a line of text */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + + +static grub_err_t +grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)), + int argc, char **args) +{ + grub_command_t cmd; + grub_uint32_t start; + grub_uint32_t end; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command expected"); + + cmd = grub_command_find (args[0]); + + if (!cmd) + return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Unknown command `%s'\n", + args[0]); + + start = grub_get_time_ms (); + (cmd->func) (cmd, argc - 1, &args[1]); + end = grub_get_time_ms (); + + grub_printf ("Elapsed time: %d.%03d seconds \n", (end - start) / 1000, + (end - start) % 1000); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(time) +{ + cmd = grub_register_command ("time", grub_cmd_time, + N_("COMMAND [ARGS]"), + N_("Measure time used by COMMAND")); +} + +GRUB_MOD_FINI(time) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y index 683b3ac4b..cc20b5479 100644 --- a/grub-core/script/parser.y +++ b/grub-core/script/parser.y @@ -74,7 +74,6 @@ %token GRUB_PARSER_TOKEN_THEN "then" %token GRUB_PARSER_TOKEN_UNTIL "until" %token GRUB_PARSER_TOKEN_WHILE "while" -%token GRUB_PARSER_TOKEN_TIME "time" %token GRUB_PARSER_TOKEN_FUNCTION "function" %token GRUB_PARSER_TOKEN_NAME "name" %token GRUB_PARSER_TOKEN_WORD "word" @@ -147,7 +146,6 @@ argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); } | "until" { $$ = grub_script_add_arglist (state, 0, $1); } | "while" { $$ = grub_script_add_arglist (state, 0, $1); } | "function" { $$ = grub_script_add_arglist (state, 0, $1); } - | "time" { $$ = grub_script_add_arglist (state, 0, $1); } | word { $$ = $1; } ; diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index 96f57dbe6..7195a880d 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -161,7 +161,6 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n)) "}" { RECORD; return GRUB_PARSER_TOKEN_RBR; } "[[" { RECORD; return GRUB_PARSER_TOKEN_RSQBR2; } "]]" { RECORD; return GRUB_PARSER_TOKEN_LSQBR2; } -"time" { RECORD; return GRUB_PARSER_TOKEN_TIME; } "case" { RECORD; return GRUB_PARSER_TOKEN_CASE; } "do" { RECORD; return GRUB_PARSER_TOKEN_DO; } "done" { RECORD; return GRUB_PARSER_TOKEN_DONE; } From d0b526b2778db75c5cfd01182de7f3808f466a1a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 13:57:03 +0200 Subject: [PATCH 247/673] * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure if it happens. --- ChangeLog | 5 +++++ grub-core/loader/i386/bsd.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4cdbc2b15..c097af2f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure + if it happens. + 2011-06-27 Vladimir Serbinenko Implement time command. diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 6487dc3df..dffe48257 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -1322,6 +1322,11 @@ grub_bsd_load (int argc, char *argv[]) goto fail; relocator = grub_relocator_new (); + if (!relocator) + { + grub_file_close (file); + goto fail; + } elf = grub_elf_file (file); if (elf) @@ -1343,7 +1348,7 @@ grub_bsd_load (int argc, char *argv[]) fail: if (grub_errno != GRUB_ERR_NONE) - grub_dl_unref (my_mod); + grub_dl_unref (my_mod); return grub_errno; } From ba7df45ee6be05bb9fd781041f915f112fa8e52c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 14:14:11 +0200 Subject: [PATCH 248/673] Chainloading on coreboot support. * grub-core/Makefile.core.def (chain): Add coreboot. * grub-core/loader/i386/coreboot/chainloader.c: New file. --- ChangeLog | 7 + grub-core/Makefile.core.def | 2 + grub-core/loader/i386/coreboot/chainloader.c | 145 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 grub-core/loader/i386/coreboot/chainloader.c diff --git a/ChangeLog b/ChangeLog index c097af2f7..9922f2a2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-06-27 Vladimir Serbinenko + + Chainloading on coreboot support. + + * grub-core/Makefile.core.def (chain): Add coreboot. + * grub-core/loader/i386/coreboot/chainloader.c: New file. + 2011-06-27 Vladimir Serbinenko * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index b10c16d55..faed6cc85 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1298,7 +1298,9 @@ module = { name = chain; efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; + i386_coreboot = loader/i386/corepayload.c; enable = i386_pc; + enable = i386_coreboot; enable = efi; }; diff --git a/grub-core/loader/i386/coreboot/chainloader.c b/grub-core/loader/i386/coreboot/chainloader.c new file mode 100644 index 000000000..3f85aa3a9 --- /dev/null +++ b/grub-core/loader/i386/coreboot/chainloader.c @@ -0,0 +1,145 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_addr_t entry; +static struct grub_relocator *relocator = NULL; + +static grub_err_t +grub_chain_boot (void) +{ + struct grub_relocator32_state state; + + grub_video_set_mode ("text", 0, 0); + + state.eip = entry; + return grub_relocator32_boot (relocator, state); +} + +static grub_err_t +grub_chain_unload (void) +{ + grub_relocator_unload (relocator); + relocator = NULL; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_chain_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load) +{ + grub_err_t err; + grub_relocator_chunk_t ch; + + if (phdr->p_type != PT_LOAD) + { + *do_load = 0; + return 0; + } + + *do_load = 1; + err = grub_relocator_alloc_chunk_addr (relocator, &ch, + phdr->p_paddr, phdr->p_memsz); + if (err) + return err; + + *addr = (grub_addr_t) get_virtual_current_address (ch); + + return GRUB_ERR_NONE; +} + + +static grub_err_t +grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_err_t err; + grub_file_t file; + grub_elf_t elf; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename expected"); + + grub_loader_unset (); + + file = grub_file_open (argv[0]); + if (!file) + return grub_errno; + + relocator = grub_relocator_new (); + if (!relocator) + { + grub_file_close (file); + return grub_errno; + } + + elf = grub_elf_file (file); + if (!elf) + { + grub_relocator_unload (relocator); + relocator = 0; + grub_file_close (file); + } + + if (!grub_elf_is_elf32 (elf)) + { + grub_relocator_unload (relocator); + relocator = 0; + grub_elf_close (elf); + } + + entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; + + err = grub_elf32_load (elf, grub_chain_elf32_hook, 0, 0); + + grub_elf_close (elf); + if (err) + return err; + + grub_loader_set (grub_chain_boot, grub_chain_unload, 0); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_chain; + +GRUB_MOD_INIT (chain) +{ + cmd_chain = grub_register_command ("chainloader", grub_cmd_chain, + N_("FILE"), N_("Load another payload")); +} + +GRUB_MOD_FINI (chain) +{ + grub_unregister_command (cmd_chain); + grub_chain_unload (); +} From 5afeb5bdd615f18ef58316132112a3a9b6e4c823 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 19:26:52 +0200 Subject: [PATCH 249/673] * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a mismerge. --- ChangeLog | 5 +++++ grub-core/disk/pata.c | 8 +++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9922f2a2b..a9dacd42b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a + mismerge. + 2011-06-27 Vladimir Serbinenko Chainloading on coreboot support. diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index ac3b91a41..95828e8f6 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -438,15 +438,13 @@ grub_pata_initialize (void) } #else static grub_err_t -grub_ata_initialize (void) +grub_pata_initialize (void) { int i; for (i = 0; i < 2; i++) { - grub_ata_device_initialize (i, 0, grub_ata_ioaddress[i], - grub_ata_ioaddress2[i]); - grub_ata_device_initialize (i, 1, grub_ata_ioaddress[i], - grub_ata_ioaddress2[i]); + grub_pata_device_initialize (i, 0, grub_pata_ioaddress[i]); + grub_pata_device_initialize (i, 1, grub_pata_ioaddress[i]); } return 0; } From 8d5d8444bd95338d487e715e9c93fa3328137b9d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 27 Jun 2011 19:30:16 +0200 Subject: [PATCH 250/673] * grub-core/Makefile.core.def (chain): Fix coreboot filename. --- ChangeLog | 4 ++++ grub-core/Makefile.core.def | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a9dacd42b..81d98716d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-06-27 Vladimir Serbinenko + + * grub-core/Makefile.core.def (chain): Fix coreboot filename. + 2011-06-27 Vladimir Serbinenko * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index faed6cc85..fd69e9c22 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1298,7 +1298,7 @@ module = { name = chain; efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; - i386_coreboot = loader/i386/corepayload.c; + i386_coreboot = loader/i386/coreboot/chainloader.c; enable = i386_pc; enable = i386_coreboot; enable = efi; From 548947916b74f8b4b66f88a4cf08b233fd31047c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 28 Jun 2011 17:05:41 +0100 Subject: [PATCH 251/673] * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use default_bg_color rather than black. (grub_gfxterm_fullscreen): Likewise. (grub_gfxterm_background_color_cmd): Save new background color in default_bg_color. --- ChangeLog | 8 ++++++++ grub-core/term/gfxterm.c | 16 +++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81d98716d..4b8d8f149 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-06-28 Colin Watson + + * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use + default_bg_color rather than black. + (grub_gfxterm_fullscreen): Likewise. + (grub_gfxterm_background_color_cmd): Save new background color in + default_bg_color. + 2011-06-27 Vladimir Serbinenko * grub-core/Makefile.core.def (chain): Fix coreboot filename. diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 9e3d8eeb1..2f8deac18 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -131,6 +131,7 @@ static unsigned int bitmap_width; static unsigned int bitmap_height; static struct grub_video_bitmap *bitmap; static int blend_text_bg; +static grub_video_rgba_color_t default_bg_color = { 0, 0, 0, 0 }; static struct grub_dirty_region dirty_region; @@ -266,7 +267,8 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, grub_video_set_active_render_target (render_target); - virtual_screen.bg_color_display = grub_video_map_rgba(0, 0, 0, 0); + virtual_screen.bg_color_display = + grub_video_map_rgba_color (default_bg_color); /* Clear out text buffer. */ for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++) @@ -338,8 +340,8 @@ grub_gfxterm_fullscreen (void) double_redraw = mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - /* Make sure screen is black. */ - color = grub_video_map_rgb (0, 0, 0); + /* Make sure screen is set to the default background color. */ + color = grub_video_map_rgba_color (default_bg_color); grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); if (double_redraw) { @@ -1189,7 +1191,6 @@ static grub_err_t grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { - grub_video_rgba_color_t color; struct grub_video_render_target *old_target; if (argc != 1) @@ -1199,7 +1200,7 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), if (grub_video_get_info (NULL) != GRUB_ERR_NONE) return grub_errno; - if (grub_video_parse_color (args[0], &color) != GRUB_ERR_NONE) + if (grub_video_parse_color (args[0], &default_bg_color) != GRUB_ERR_NONE) return grub_errno; /* Destroy existing background bitmap if loaded. */ @@ -1216,9 +1217,10 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), compatible with the text layer. */ grub_video_get_active_render_target (&old_target); grub_video_set_active_render_target (text_layer); - virtual_screen.bg_color = grub_video_map_rgba_color (color); + virtual_screen.bg_color = grub_video_map_rgba_color (default_bg_color); grub_video_set_active_render_target (old_target); - virtual_screen.bg_color_display = grub_video_map_rgba_color (color); + virtual_screen.bg_color_display = + grub_video_map_rgba_color (default_bg_color); blend_text_bg = 1; /* Mark whole screen as dirty. */ From 574618a2e9a1dc8daf46c0e929acb0353f5f0101 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 14:09:36 +0200 Subject: [PATCH 252/673] unify prefix handling across platforms --- grub-core/Makefile.core.def | 5 +- grub-core/boot/i386/pc/diskboot.S | 2 +- grub-core/disk/efi/efidisk.c | 30 +++-- grub-core/kern/efi/init.c | 84 ++---------- grub-core/kern/emu/main.c | 16 +-- grub-core/kern/i386/coreboot/init.c | 5 +- grub-core/kern/i386/efi/init.c | 6 - grub-core/kern/i386/pc/init.c | 78 +++++------ grub-core/kern/ia64/efi/init.c | 6 - grub-core/kern/ieee1275/cmain.c | 4 + grub-core/kern/ieee1275/init.c | 90 ++++++------- grub-core/kern/ieee1275/openfw.c | 5 + grub-core/kern/main.c | 70 ++++++++-- grub-core/kern/mips/init.c | 4 +- grub-core/kern/sparc64/ieee1275/init.c | 174 ------------------------- include/grub/kernel.h | 5 +- include/grub/offsets.h | 4 +- 17 files changed, 189 insertions(+), 399 deletions(-) delete mode 100644 grub-core/kern/sparc64/ieee1275/init.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index ac969e09c..df852e09e 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -102,6 +102,7 @@ kernel = { ieee1275 = kern/ieee1275/mmap.c; ieee1275 = kern/ieee1275/openfw.c; ieee1275 = term/ieee1275/ofconsole.c; + ieee1275 = kern/ieee1275/init.c; terminfoinkernel = term/terminfo.c; terminfoinkernel = term/tparm.c; @@ -153,8 +154,6 @@ kernel = { i386_multiboot = kern/i386/multiboot_mmap.c; i386_multiboot = kern/i386/tsc.c; - i386_ieee1275 = kern/ieee1275/init.c; - mips = kern/mips/cache.S; mips = kern/mips/dl.c; mips = kern/mips/init.c; @@ -179,14 +178,12 @@ kernel = { extra_dist = video/sm712_init.c; mips_loongson = commands/keylayouts.c; - powerpc_ieee1275 = kern/ieee1275/init.c; powerpc_ieee1275 = kern/powerpc/cache.S; powerpc_ieee1275 = kern/powerpc/dl.c; sparc64_ieee1275 = kern/sparc64/cache.S; sparc64_ieee1275 = kern/sparc64/dl.c; sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; - sparc64_ieee1275 = kern/sparc64/ieee1275/init.c; emu = disk/host.c; emu = gnulib/progname.c; diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S index 92f223f0d..336c3bcca 100644 --- a/grub-core/boot/i386/pc/diskboot.S +++ b/grub-core/boot/i386/pc/diskboot.S @@ -83,7 +83,7 @@ LOCAL(setup_sectors): /* the maximum is limited to 0x7f because of Phoenix EDD */ xorl %eax, %eax - movb $0x7f, %al + movb $0x1, %al /* how many do we really want to read? */ cmpw %ax, 8(%di) /* compare against total number of sectors */ diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 35602513e..5dc753046 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -530,7 +530,7 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) and total sectors should be replaced with total blocks. */ grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", m, (unsigned long long) m->last_block, m->block_size); - disk->total_sectors = m->last_block; + disk->total_sectors = m->last_block + 1; if (m->block_size & (m->block_size - 1) || !m->block_size) return grub_error (GRUB_ERR_IO, "invalid sector size %d", m->block_size); @@ -788,19 +788,27 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) /* Find a partition which matches the hard drive device path. */ grub_memcpy (&hd, ldp, sizeof (hd)); - grub_partition_iterate (parent, find_partition); - - if (! tpart) + if (hd.partition_start == 0 + && hd.partition_size == grub_disk_get_size (parent)) { - grub_disk_close (parent); - return 0; + device_name = grub_strdup (parent->name); } + else + { + char *partition_name; - { - char *partition_name = grub_partition_get_name (tpart); - device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); - grub_free (partition_name); - } + grub_partition_iterate (parent, find_partition); + + if (! tpart) + { + grub_disk_close (parent); + return 0; + } + + partition_name = grub_partition_get_name (tpart); + device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); + grub_free (partition_name); + } grub_disk_close (parent); return device_name; diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 1b0a872b4..a7325acc6 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -43,83 +43,21 @@ grub_efi_init (void) } void -grub_efi_set_prefix (void) +grub_machine_get_bootlocation (char **device, char **path) { grub_efi_loaded_image_t *image = NULL; - char *device = NULL; - char *path = NULL; + char *p; - { - char *pptr = NULL; - if (grub_prefix[0] == '(') - { - pptr = grub_strrchr (grub_prefix, ')'); - if (pptr) - { - device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1); - pptr++; - } - } - if (!pptr) - pptr = grub_prefix; - if (pptr[0]) - path = grub_strdup (pptr); - } + image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (!image) + return; + *device = grub_efidisk_get_device_name (image->device_handle); + *path = grub_efi_get_filename (image->file_path); - if ((!device || device[0] == ',' || !device[0]) || !path) - image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (image) - { - if (!device) - device = grub_efidisk_get_device_name (image->device_handle); - else if (device[0] == ',' || !device[0]) - { - /* We have a partition, but still need to fill in the drive. */ - char *image_device, *comma, *new_device; - - image_device = grub_efidisk_get_device_name (image->device_handle); - comma = grub_strchr (image_device, ','); - if (comma) - { - char *drive = grub_strndup (image_device, comma - image_device); - new_device = grub_xasprintf ("%s%s", drive, device); - grub_free (drive); - } - else - new_device = grub_xasprintf ("%s%s", image_device, device); - - grub_free (image_device); - grub_free (device); - device = new_device; - } - } - - if (image && !path) - { - char *p; - - path = grub_efi_get_filename (image->file_path); - - /* Get the directory. */ - p = grub_strrchr (path, '/'); - if (p) - *p = '\0'; - } - - if (device && path) - { - char *prefix; - - prefix = grub_xasprintf ("(%s)%s", device, path); - if (prefix) - { - grub_env_set ("prefix", prefix); - grub_free (prefix); - } - } - - grub_free (device); - grub_free (path); + /* Get the directory. */ + p = grub_strrchr (*path, '/'); + if (p) + *p = '\0'; } void diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 0a7645992..096e97090 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -49,7 +49,7 @@ static jmp_buf main_env; /* Store the prefix specified by an argument. */ -static char *prefix = NULL; +static char *root_dev = NULL, *dir = DEFAULT_DIRECTORY; int grub_no_autoload; @@ -71,11 +71,10 @@ grub_machine_init (void) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device, char **path) { - grub_env_set ("prefix", prefix); - free (prefix); - prefix = 0; + *device = root_dev; + *path = dir; } void @@ -84,6 +83,8 @@ grub_machine_fini (void) grub_console_fini (); } +char grub_prefix[64] = ""; + static struct option options[] = @@ -132,8 +133,6 @@ void grub_emu_init (void); int main (int argc, char *argv[]) { - char *root_dev = 0; - char *dir = DEFAULT_DIRECTORY; char *dev_map = DEFAULT_DEVICE_MAP; volatile int hold = 0; int opt; @@ -219,9 +218,6 @@ main (int argc, char *argv[]) dir = xstrdup (dir); else dir = grub_make_system_path_relative_to_its_root (dir); - prefix = xmalloc (strlen (root_dev) + 2 + strlen (dir) + 1); - sprintf (prefix, "(%s)%s", root_dev, dir); - free (dir); /* Start GRUB! */ if (setjmp (main_env) == 0) diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index 434b9b5a8..ebbea2523 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -107,10 +107,9 @@ grub_machine_init (void) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) { - /* Initialize the prefix. */ - grub_env_set ("prefix", grub_prefix); } void diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c index f73f828c6..6bd8f3e87 100644 --- a/grub-core/kern/i386/efi/init.c +++ b/grub-core/kern/i386/efi/init.c @@ -39,9 +39,3 @@ grub_machine_fini (void) { grub_efi_fini (); } - -void -grub_machine_set_prefix (void) -{ - grub_efi_set_prefix (); -} diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index d8c337bde..3aedaf6d8 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -45,52 +45,39 @@ struct mem_region static struct mem_region mem_regions[MAX_REGIONS]; static int num_regions; -static char * -make_install_device (void) +void +grub_machine_get_bootlocation (char **device, + char **path __attribute__ ((unused))) { + char *ptr; + + /* No hardcoded root partition - make it from the boot drive and the + partition number encoded at the install time. */ + if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) + { + *device = grub_strdup ("pxe"); + return; + } + /* XXX: This should be enough. */ - char dev[100], *ptr = dev; +#define DEV_SIZE 100 + *device = grub_malloc (DEV_SIZE); + ptr = *device; + grub_snprintf (*device, DEV_SIZE, + "%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', + grub_boot_drive & 0x7f); + ptr += grub_strlen (ptr); - if (grub_prefix[0] != '(') - { - /* No hardcoded root partition - make it from the boot drive and the - partition number encoded at the install time. */ - if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) - { - grub_strcpy (dev, "(pxe"); - ptr += sizeof ("(pxe") - 1; - } - else - { - grub_snprintf (dev, sizeof (dev), - "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', - grub_boot_drive & 0x7f); - ptr += grub_strlen (ptr); + if (grub_install_dos_part >= 0) + grub_snprintf (ptr, DEV_SIZE - (ptr - *device), + ",%u", grub_install_dos_part + 1); + ptr += grub_strlen (ptr); - if (grub_install_dos_part >= 0) - grub_snprintf (ptr, sizeof (dev) - (ptr - dev), - ",%u", grub_install_dos_part + 1); - ptr += grub_strlen (ptr); - - if (grub_install_bsd_part >= 0) - grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u", - grub_install_bsd_part + 1); - ptr += grub_strlen (ptr); - } - - grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix); - grub_strcpy (grub_prefix, dev); - } - else if (grub_prefix[1] == ',' || grub_prefix[1] == ')') - { - /* We have a prefix, but still need to fill in the boot drive. */ - grub_snprintf (dev, sizeof (dev), - "(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f', - grub_boot_drive & 0x7f, grub_prefix + 1); - grub_strcpy (grub_prefix, dev); - } - - return grub_prefix; + if (grub_install_bsd_part >= 0) + grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u", + grub_install_bsd_part + 1); + ptr += grub_strlen (ptr); + *ptr = 0; } /* Add a memory region. */ @@ -211,13 +198,6 @@ grub_machine_init (void) grub_tsc_init (); } -void -grub_machine_set_prefix (void) -{ - /* Initialize the prefix. */ - grub_env_set ("prefix", make_install_device ()); -} - void grub_machine_fini (void) { diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c index 6bb4219ac..e2fa58090 100644 --- a/grub-core/kern/ia64/efi/init.c +++ b/grub-core/kern/ia64/efi/init.c @@ -40,12 +40,6 @@ grub_machine_fini (void) grub_efi_fini (); } -void -grub_machine_set_prefix (void) -{ - grub_efi_set_prefix (); -} - void grub_arch_sync_caches (void *address, grub_size_t len) { diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index 2fbe809b2..eeb462c5e 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -60,6 +60,10 @@ grub_ieee1275_find_options (void) int is_olpc = 0; int is_qemu = 0; +#ifdef _sparc64 + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0); +#endif + grub_ieee1275_finddevice ("/", &root); grub_ieee1275_finddevice ("/options", &options); grub_ieee1275_finddevice ("/openprom", &openprom); diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 3c55096a4..3c6332553 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -35,6 +35,9 @@ #include #include #include +#ifdef __sparc__ +#include +#endif /* The minimal heap size we can live with. */ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) @@ -49,6 +52,10 @@ extern char _start[]; extern char _end[]; +#ifdef __sparc__ +grub_addr_t grub_ieee1275_original_stack; +#endif + void grub_exit (void) { @@ -71,51 +78,39 @@ grub_translate_ieee1275_path (char *filepath) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device, char **path) { char bootpath[64]; /* XXX check length */ char *filename; - char *prefix; grub_bootp_t bootp_pckt; - char addr[GRUB_NET_MAX_STR_ADDR_LEN]; /* Set the net prefix when possible. */ if (grub_getbootp && (bootp_pckt = grub_getbootp())) { - grub_uint32_t n = bootp_pckt->siaddr; - grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", - ((n >> 24) & 0xff), ((n >> 16) & 0xff), - ((n >> 8) & 0xff), ((n >> 0) & 0xff)); - prefix = grub_xasprintf ("(tftp,%s)%s", addr,grub_prefix); - grub_env_set ("prefix", prefix); - grub_free (prefix); + grub_uint32_t n = bootp_pckt->siaddr; + char addr[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", + ((n >> 24) & 0xff), ((n >> 16) & 0xff), + ((n >> 8) & 0xff), ((n >> 0) & 0xff)); + *device = grub_xasprintf ("(tftp,%s)", addr); return; } - 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); + *device = grub_ieee1275_encode_devname (bootpath); filename = grub_ieee1275_get_filename (bootpath); if (filename) { - char *newprefix; char *lastslash = grub_strrchr (filename, '\\'); /* Truncate at last directory. */ @@ -124,23 +119,22 @@ grub_machine_set_prefix (void) *lastslash = '\0'; grub_translate_ieee1275_path (filename); - newprefix = grub_xasprintf ("%s%s", prefix, filename); - if (newprefix) - { - grub_free (prefix); - prefix = newprefix; - } + *path = filename; } } - - 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) +#ifdef __sparc__ +static void +grub_claim_heap (void) +{ + grub_mm_init_region ((void *) (grub_modules_get_end () + + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); +} +#else +static void +grub_claim_heap (void) { unsigned long total = 0; @@ -208,23 +202,14 @@ static void grub_claim_heap (void) else grub_machine_mmap_iterate (heap_init); } +#endif -static grub_uint64_t ieee1275_get_time_ms (void); - -void -grub_machine_init (void) +static void +grub_parse_cmdline (void) { - char args[256]; grub_ssize_t actual; + char args[256]; - grub_ieee1275_init (); - - grub_console_init_early (); - grub_claim_heap (); - grub_console_init_lately (); - grub_ofdisk_init (); - - /* Process commandline. */ if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args, sizeof args, &actual) == 0 && actual > 1) @@ -257,6 +242,21 @@ grub_machine_init (void) } } } +} + +static grub_uint64_t ieee1275_get_time_ms (void); + +void +grub_machine_init (void) +{ + grub_ieee1275_init (); + + grub_console_init_early (); + grub_claim_heap (); + grub_console_init_lately (); + grub_ofdisk_init (); + + grub_parse_cmdline (); grub_install_get_time_ms (ieee1275_get_time_ms); } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index db4bec90a..8fc373c55 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -369,6 +369,11 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) ret = grub_strdup (args); else ret = grub_strndup (args, (grub_size_t)(comma - args)); + /* Consistently provide numbered partitions to GRUB. + OpenBOOT traditionally uses alphabetical partition + specifiers. */ + if (ret[0] >= 'a' && ret[0] <= 'z') + ret[0] = '1' + (ret[0] - 'a'); } } diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index cc9758988..4818d6af3 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -129,27 +129,74 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)), return grub_strdup (val); } -/* Set the root device according to the dl prefix. */ static void -grub_set_root_dev (void) +grub_set_prefix_and_root (void) { - const char *prefix; + char *device = NULL; + char *path = NULL; + char *fwdevice = NULL; + char *fwpath = NULL; grub_register_variable_hook ("root", 0, grub_env_write_root); - prefix = grub_env_get ("prefix"); + { + char *pptr = NULL; + if (grub_prefix[0] == '(') + { + pptr = grub_strrchr (grub_prefix, ')'); + if (pptr) + { + device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1); + pptr++; + } + } + if (!pptr) + pptr = grub_prefix; + if (pptr[0]) + path = grub_strdup (pptr); + } + if ((!device || device[0] == ',' || !device[0]) || !path) + grub_machine_get_bootlocation (&fwdevice, &fwpath); - if (prefix) + if (!device && fwdevice) + device = fwdevice; + else if (fwdevice && (device[0] == ',' || !device[0])) { - char *dev; + /* We have a partition, but still need to fill in the drive. */ + char *comma, *new_device; - dev = grub_file_get_device_name (prefix); - if (dev) + comma = grub_strchr (fwdevice, ','); + if (comma) { - grub_env_set ("root", dev); - grub_free (dev); + char *drive = grub_strndup (fwdevice, comma - fwdevice); + new_device = grub_xasprintf ("%s%s", drive, device); + grub_free (drive); } + else + new_device = grub_xasprintf ("%s%s", fwdevice, device); + + grub_free (fwdevice); + grub_free (device); + device = new_device; } + if (fwpath && !path) + path = fwpath; + if (device) + { + char *prefix; + + prefix = grub_xasprintf ("(%s)%s", device, path ? : ""); + if (prefix) + { + grub_env_set ("prefix", prefix); + grub_free (prefix); + } + grub_env_set ("root", device); + } + + grub_free (device); + grub_free (path); + grub_print_error (); } /* Load the normal mode module and execute the normal mode if possible. */ @@ -187,8 +234,7 @@ grub_main (void) /* It is better to set the root device as soon as possible, for convenience. */ - grub_machine_set_prefix (); - grub_set_root_dev (); + grub_set_prefix_and_root (); grub_env_export ("root"); grub_env_export ("prefix"); diff --git a/grub-core/kern/mips/init.c b/grub-core/kern/mips/init.c index bfa08f56a..353f679e6 100644 --- a/grub-core/kern/mips/init.c +++ b/grub-core/kern/mips/init.c @@ -38,7 +38,7 @@ grub_get_rtc (void) } void -grub_machine_set_prefix (void) +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) { - grub_env_set ("prefix", grub_prefix); } diff --git a/grub-core/kern/sparc64/ieee1275/init.c b/grub-core/kern/sparc64/ieee1275/init.c deleted file mode 100644 index 72ee1f136..000000000 --- a/grub-core/kern/sparc64/ieee1275/init.c +++ /dev/null @@ -1,174 +0,0 @@ -/* init.c -- Initialize GRUB on SPARC64. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -grub_addr_t grub_ieee1275_original_stack; - -void -grub_exit (void) -{ - grub_ieee1275_exit (); -} - -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) -{ - extern char _end[]; - return (grub_addr_t) _end; -} - -void -grub_machine_set_prefix (void) -{ - if (grub_prefix[0] != '(') - { - char bootpath[IEEE1275_MAX_PATH_LEN]; - char *prefix, *path, *colon; - grub_ssize_t actual; - - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", - &bootpath, sizeof (bootpath), &actual)) - { - /* Should never happen. */ - grub_printf ("/chosen/bootpath property missing!\n"); - grub_env_set ("prefix", ""); - return; - } - - /* Transform an OF device path to a GRUB path. */ - colon = grub_strchr (bootpath, ':'); - if (colon) - { - char *part = colon + 1; - - /* Consistently provide numbered partitions to GRUB. - OpenBOOT traditionally uses alphabetical partition - specifiers. */ - if (part[0] >= 'a' && part[0] <= 'z') - part[0] = '1' + (part[0] - 'a'); - } - prefix = grub_ieee1275_encode_devname (bootpath); - - path = grub_xasprintf("%s%s", prefix, grub_prefix); - - grub_strcpy (grub_prefix, path); - - grub_free (path); - grub_free (prefix); - } - - grub_env_set ("prefix", grub_prefix); -} - -static void -grub_heap_init (void) -{ - grub_mm_init_region ((void *) (grub_modules_get_end () - + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); -} - -static void -grub_parse_cmdline (void) -{ - grub_ssize_t actual; - char args[256]; - - 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); - } - } - } -} - -void -grub_machine_init (void) -{ - grub_ieee1275_init (); - grub_console_init_early (); - grub_heap_init (); - grub_console_init_lately (); - - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0); - grub_ofdisk_init (); - - grub_parse_cmdline (); - grub_install_get_time_ms (ieee1275_get_time_ms); -} - -void -grub_machine_fini (void) -{ - grub_ofdisk_fini (); - grub_console_fini (); -} diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 2ecc73df4..6a5f91c3d 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -84,12 +84,13 @@ void grub_machine_init (void); void EXPORT_FUNC(grub_machine_fini) (void); /* The machine-specific prefix initialization. */ -void grub_machine_set_prefix (void); +void +grub_machine_get_bootlocation (char **device, char **path); /* Register all the exported symbols. This is automatically generated. */ void grub_register_exported_symbols (void); -#if ! defined (ASM_FILE) && !defined (GRUB_MACHINE_EMU) +#if ! defined (ASM_FILE) extern char grub_prefix[]; #endif diff --git a/include/grub/offsets.h b/include/grub/offsets.h index af724096d..c04961fc6 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -169,8 +169,10 @@ /* Non-zero value is only needed for PowerMacs. */ #define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0 +#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 +#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1 #define GRUB_KERNEL_MIPS_LOONGSON_MOD_ALIGN 0x1 #define GRUB_KERNEL_MIPS_ARC_MOD_ALIGN 0x1 @@ -179,7 +181,7 @@ /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to rewrite grub-mkimage to generate valid ELF files. */ -#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x8000 +#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x8000 #ifdef GRUB_MACHINE #define GRUB_OFFSETS_CONCAT_(a,b,c) a ## b ## c From cae730b4526f250a3d5073c00911e35b7abdd7d7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 16:56:35 +0200 Subject: [PATCH 253/673] Automatically determine prefix when netbooted on EFI --- grub-core/disk/efi/efidisk.c | 153 ++++++++--------------------- grub-core/kern/efi/efi.c | 48 +++++++++ grub-core/kern/efi/init.c | 6 ++ grub-core/net/drivers/efi/efinet.c | 49 ++++++++- grub-core/net/net.c | 53 ++++++++-- include/grub/efi/api.h | 35 +++++++ include/grub/efi/efi.h | 8 ++ include/grub/net.h | 8 +- 8 files changed, 237 insertions(+), 123 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 5dc753046..07f0f6859 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -84,54 +84,6 @@ find_last_device_path (const grub_efi_device_path_t *dp) return p; } -/* Compare device paths. */ -static int -compare_device_paths (const grub_efi_device_path_t *dp1, - const grub_efi_device_path_t *dp2) -{ - if (! dp1 || ! dp2) - /* Return non-zero. */ - return 1; - - while (1) - { - grub_efi_uint8_t type1, type2; - grub_efi_uint8_t subtype1, subtype2; - grub_efi_uint16_t len1, len2; - int ret; - - type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1); - type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2); - - if (type1 != type2) - return (int) type2 - (int) type1; - - subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1); - subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2); - - if (subtype1 != subtype2) - return (int) subtype1 - (int) subtype2; - - len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1); - len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2); - - if (len1 != len2) - return (int) len1 - (int) len2; - - ret = grub_memcmp (dp1, dp2, len1); - if (ret != 0) - return ret; - - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1)) - break; - - dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1); - dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2); - } - - return 0; -} - static struct grub_efidisk_data * make_devices (void) { @@ -214,7 +166,7 @@ find_parent_device (struct grub_efidisk_data *devices, if (parent == d) continue; - if (compare_device_paths (parent->device_path, dp) == 0) + if (grub_efi_compare_device_paths (parent->device_path, dp) == 0) { /* Found. */ if (! parent->last_device_path) @@ -249,7 +201,7 @@ iterate_child_devices (struct grub_efidisk_data *devices, ldp->length[0] = sizeof (*ldp); ldp->length[1] = 0; - if (compare_device_paths (dp, d->device_path) == 0) + if (grub_efi_compare_device_paths (dp, d->device_path) == 0) if (hook (p)) { grub_free (dp); @@ -273,11 +225,11 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) { int ret; - ret = compare_device_paths (find_last_device_path ((*p)->device_path), - find_last_device_path (d->device_path)); + ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path), + find_last_device_path (d->device_path)); if (ret == 0) - ret = compare_device_paths ((*p)->device_path, - d->device_path); + ret = grub_efi_compare_device_paths ((*p)->device_path, + d->device_path); if (ret == 0) return; else if (ret > 0) @@ -706,7 +658,35 @@ grub_efidisk_get_device_handle (grub_disk_t disk) char * grub_efidisk_get_device_name (grub_efi_handle_t *handle) { - grub_efi_device_path_t *dp, *ldp; + grub_efi_device_path_t *dp, *ldp, *sdp; + /* This is a hard disk partition. */ + grub_disk_t parent = 0; + auto int find_parent_disk (const char *name); + + /* Find the disk which is the parent of a given hard disk partition. */ + int find_parent_disk (const char *name) + { + grub_disk_t disk; + + disk = grub_disk_open (name); + if (! disk) + return 1; + + if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) + { + struct grub_efidisk_data *d; + + d = disk->data; + if (grub_efi_compare_device_paths (d->device_path, sdp) == 0) + { + parent = disk; + return 1; + } + } + + grub_disk_close (disk); + return 0; + } dp = grub_efi_get_device_path (handle); if (! dp) @@ -720,40 +700,12 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) { - /* This is a hard disk partition. */ - grub_disk_t parent = 0; grub_partition_t tpart = NULL; char *device_name; grub_efi_device_path_t *dup_dp, *dup_ldp; grub_efi_hard_drive_device_path_t hd; - auto int find_parent_disk (const char *name); auto int find_partition (grub_disk_t disk, const grub_partition_t part); - /* Find the disk which is the parent of a given hard disk partition. */ - int find_parent_disk (const char *name) - { - grub_disk_t disk; - - disk = grub_disk_open (name); - if (! disk) - return 1; - - if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) - { - struct grub_efidisk_data *d; - - d = disk->data; - if (compare_device_paths (d->device_path, dup_dp) == 0) - { - parent = disk; - return 1; - } - } - - grub_disk_close (disk); - return 0; - } - /* Find the identical partition. */ int find_partition (grub_disk_t disk __attribute__ ((unused)), const grub_partition_t part) @@ -780,6 +732,8 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) dup_ldp->length[0] = sizeof (*dup_ldp); dup_ldp->length[1] = 0; + sdp = dup_dp; + grub_efidisk_iterate (find_parent_disk); grub_free (dup_dp); @@ -816,36 +770,15 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) else { /* This should be an entire disk. */ - auto int find_disk (const char *name); char *device_name = 0; - int find_disk (const char *name) - { - grub_disk_t disk; + sdp = dp; - disk = grub_disk_open (name); - if (! disk) - return 1; - - if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) - { - struct grub_efidisk_data *d; - - d = disk->data; - if (compare_device_paths (d->device_path, dp) == 0) - { - device_name = grub_strdup (disk->name); - grub_disk_close (disk); - return 1; - } - } - - grub_disk_close (disk); - return 0; - - } - - grub_efidisk_iterate (find_disk); + grub_efidisk_iterate (find_parent_disk); + if (!parent) + return NULL; + device_name = grub_strdup (parent->name); + grub_disk_close (parent); return device_name; } diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index c95058733..d0994a940 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -746,3 +746,51 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) dp = (grub_efi_device_path_t *) ((char *) dp + len); } } + +/* Compare device paths. */ +int +grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2) +{ + if (! dp1 || ! dp2) + /* Return non-zero. */ + return 1; + + while (1) + { + grub_efi_uint8_t type1, type2; + grub_efi_uint8_t subtype1, subtype2; + grub_efi_uint16_t len1, len2; + int ret; + + type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1); + type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2); + + if (type1 != type2) + return (int) type2 - (int) type1; + + subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1); + subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2); + + if (subtype1 != subtype2) + return (int) subtype1 - (int) subtype2; + + len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1); + len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2); + + if (len1 != len2) + return (int) len1 - (int) len2; + + ret = grub_memcmp (dp1, dp2, len1); + if (ret != 0) + return ret; + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1)) + break; + + dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1); + dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2); + } + + return 0; +} diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index a7325acc6..4dfb06284 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -42,6 +42,10 @@ grub_efi_init (void) grub_efidisk_init (); } +void (*grub_efi_net_config) (grub_efi_handle_t hnd, + char **device, + char **path); + void grub_machine_get_bootlocation (char **device, char **path) { @@ -53,6 +57,8 @@ grub_machine_get_bootlocation (char **device, char **path) return; *device = grub_efidisk_get_device_name (image->device_handle); *path = grub_efi_get_filename (image->file_path); + if (!*device && grub_efi_net_config) + grub_efi_net_config (image->device_handle, device, path); /* Get the directory. */ p = grub_strrchr (*path, '/'); diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index a6e005601..29bc66183 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -27,14 +27,14 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* GUID. */ static grub_efi_guid_t net_io_guid = GRUB_EFI_SIMPLE_NETWORK_GUID; - +static grub_efi_guid_t pxe_io_guid = GRUB_EFI_PXE_GUID; static grub_err_t send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) { grub_efi_status_t st; - grub_efi_simple_network_t *net = dev->data; + grub_efi_simple_network_t *net = dev->efi_net; st = efi_call_7 (net->transmit, net, 0, pack->tail - pack->data, pack->data, NULL, NULL, NULL); if (st != GRUB_EFI_SUCCESS) @@ -46,7 +46,7 @@ static grub_ssize_t get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) { - grub_efi_simple_network_t *net = dev->data; + grub_efi_simple_network_t *net = dev->efi_net; grub_err_t err; grub_efi_status_t st; grub_efi_uintn_t bufsize = 1500; @@ -139,21 +139,62 @@ grub_efinet_findcards (void) grub_memcpy (card->default_address.mac, net->mode->current_address, sizeof (card->default_address.mac)); - card->data = net; + card->efi_net = net; + card->efi_handle = *handle; grub_net_card_register (card); } grub_free (handles); } +static void +grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, + char **path) +{ + struct grub_net_card *card; + grub_efi_device_path_t *dp; + + dp = grub_efi_get_device_path (hnd); + if (! dp) + return; + + FOR_NET_CARDS (card) + { + grub_efi_device_path_t *cdp; + struct grub_efi_pxe *pxe; + struct grub_efi_pxe_mode *pxe_mode; + if (card->driver != &efidriver) + continue; + cdp = grub_efi_get_device_path (card->efi_handle); + if (! cdp) + continue; + if (grub_efi_compare_device_paths (dp, cdp) != 0) + continue; + pxe = grub_efi_open_protocol (hnd, &pxe_io_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (! pxe) + continue; + pxe_mode = pxe->mode; + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) + &pxe_mode->dhcp_ack, + sizeof (pxe_mode->dhcp_ack), + 1, device, path); + return; + } +} + + GRUB_MOD_INIT(efinet) { grub_efinet_findcards (); + grub_efi_net_config = grub_efi_net_config_real; } GRUB_MOD_FINI(ofnet) { struct grub_net_card *card; + grub_efi_net_config = 0; FOR_NET_CARDS (card) if (card->driver && !grub_strcmp (card->driver->name, "efinet")) { diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 34148f52c..2ecb709b9 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -936,7 +936,8 @@ grub_net_configure_by_dhcp_ack (const char *name, const struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, - grub_size_t size) + grub_size_t size, + int is_def, char **device, char **path) { grub_net_network_level_address_t addr; grub_net_link_level_address_t hwaddr; @@ -945,6 +946,11 @@ grub_net_configure_by_dhcp_ack (const char *name, addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bp->your_ip; + if (device) + *device = 0; + if (path) + *path = 0; + grub_memcpy (hwaddr.mac, bp->mac_addr, bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len : sizeof (hwaddr.mac)); @@ -975,26 +981,57 @@ grub_net_configure_by_dhcp_ack (const char *name, if (size > OFFSET_OF (boot_file, bp)) set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, sizeof (bp->boot_file)); + if (is_def) + default_server = 0; if (size > OFFSET_OF (server_name, bp) && bp->server_name[0]) { set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, sizeof (bp->server_name)); - if (!default_server) + if (is_def && !default_server) { default_server = grub_strdup (bp->server_name); - grub_errno = GRUB_ERR_NONE; - } + grub_print_error (); + } + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%s", bp->server_name); + grub_print_error (); + } } - if (!default_server) + if (is_def && !default_server) { default_server = grub_xasprintf ("%d.%d.%d.%d", ((grub_uint8_t *) &bp->server_ip)[0], ((grub_uint8_t *) &bp->server_ip)[1], ((grub_uint8_t *) &bp->server_ip)[2], ((grub_uint8_t *) &bp->server_ip)[3]); - grub_errno = GRUB_ERR_NONE; - } + grub_print_error (); + } + + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_print_error (); + } + if (size > OFFSET_OF (boot_file, bp) && path) + { + *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); + grub_print_error (); + if (*path) + { + char *slash; + slash = grub_strrchr (*path, '/'); + if (slash) + *slash = 0; + else + **path = 0; + } + } if (size > OFFSET_OF (vendor, bp)) parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); @@ -1025,7 +1062,7 @@ grub_net_process_dhcp (struct grub_net_buff *nb, } grub_net_configure_by_dhcp_ack (name, card, 0, (const struct grub_net_bootp_packet *) nb->data, - (nb->tail - nb->data)); + (nb->tail - nb->data), 0, 0, 0); grub_free (name); if (grub_errno) grub_print_error (); diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index a3dde0eff..5cd1686ea 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -89,6 +89,11 @@ { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ } +#define GRUB_EFI_PXE_GUID \ + { 0x03c4e603, 0xac28, 0x11d3, \ + { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + #define GRUB_EFI_DEVICE_PATH_GUID \ { 0x09576e91, 0x6d3f, 0x11d2, \ { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ @@ -1118,6 +1123,36 @@ struct grub_efi_simple_text_output_interface }; typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t; +typedef grub_uint8_t grub_efi_pxe_packet_t[1472]; + +typedef struct grub_efi_pxe_mode +{ + grub_uint8_t unused[52]; + grub_efi_pxe_packet_t dhcp_discover; + grub_efi_pxe_packet_t dhcp_ack; + grub_efi_pxe_packet_t proxy_offer; + grub_efi_pxe_packet_t pxe_discover; + grub_efi_pxe_packet_t pxe_reply; +} grub_efi_pxe_mode_t; + +typedef struct grub_efi_pxe +{ + grub_uint64_t rev; + void (*start) (void); + void (*stop) (void); + void (*dhcp) (void); + void (*discover) (void); + void (*mftp) (void); + void (*udpwrite) (void); + void (*udpread) (void); + void (*setipfilter) (void); + void (*arp) (void); + void (*setparams) (void); + void (*setstationip) (void); + void (*setpackets) (void); + struct grub_efi_pxe_mode *mode; +} grub_efi_pxe_t; + #define GRUB_EFI_BLACK 0x00 #define GRUB_EFI_BLUE 0x01 #define GRUB_EFI_GREEN 0x02 diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index e9c57dd11..e98f99507 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -62,6 +62,14 @@ grub_err_t EXPORT_FUNC (grub_efi_set_virtual_address_map) (grub_efi_uintn_t memo grub_efi_uint32_t descriptor_version, grub_efi_memory_descriptor_t *virtual_map); +int +EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1, + const grub_efi_device_path_t *dp2); + +extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, + char **device, + char **path); + void grub_efi_mm_init (void); void grub_efi_mm_fini (void); void grub_efi_init (void); diff --git a/include/grub/net.h b/include/grub/net.h index ee94ebcc6..6aaf391d5 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -109,6 +109,11 @@ struct grub_net_card grub_net_card_flags_t flags; union { + struct + { + struct grub_efi_simple_network *efi_net; + void *efi_handle; + }; void *data; int data_num; }; @@ -404,7 +409,8 @@ grub_net_configure_by_dhcp_ack (const char *name, const struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, - grub_size_t size); + grub_size_t size, + int is_def, char **device, char **path); void grub_net_process_dhcp (struct grub_net_buff *nb, From 6708faafdea4e3b27879e089e772babb78bfe7f2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 17:58:23 +0200 Subject: [PATCH 254/673] Fix broken blksize negotiation, fix broken seek and change a way net device is filled n i386-pc --- grub-core/kern/file.c | 4 -- grub-core/kern/i386/pc/init.c | 8 ++-- grub-core/net/drivers/i386/pc/pxe.c | 73 +++++++++++++++++++++++------ grub-core/net/net.c | 28 +++++++---- grub-core/net/tftp.c | 26 +++++++--- include/grub/i386/pc/kernel.h | 2 + include/grub/net.h | 2 +- include/grub/net/tftp.h | 6 --- 8 files changed, 105 insertions(+), 44 deletions(-) diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 2407e72c5..f69ef6fd4 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -25,7 +25,6 @@ #include #include -grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL; void (*EXPORT_VAR (grub_grubnet_fini)) (void); grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; @@ -183,9 +182,6 @@ grub_file_seek (grub_file_t file, grub_off_t offset) return -1; } - if (file->device->net && grub_file_net_seek) - grub_file_net_seek (file, offset); - old = file->offset; file->offset = offset; diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 3aedaf6d8..24fe8fed9 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -45,9 +45,10 @@ struct mem_region static struct mem_region mem_regions[MAX_REGIONS]; static int num_regions; +void (*grub_pc_net_config) (char **device, char **path); + void -grub_machine_get_bootlocation (char **device, - char **path __attribute__ ((unused))) +grub_machine_get_bootlocation (char **device, char **path) { char *ptr; @@ -55,7 +56,8 @@ grub_machine_get_bootlocation (char **device, partition number encoded at the install time. */ if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) { - *device = grub_strdup ("pxe"); + if (grub_pc_net_config) + grub_pc_net_config (device, path); return; } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 144df964c..51f4023a6 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -45,6 +46,22 @@ struct grub_pxe_undi_open grub_uint8_t mcast[8][6]; } __attribute__ ((packed)); +struct grub_pxe_undi_info +{ + grub_uint16_t status; + grub_uint16_t base_io; + grub_uint16_t int_number; + grub_uint16_t mtu; + grub_uint16_t hwtype; + grub_uint16_t hwaddrlen; + grub_uint8_t current_addr[16]; + grub_uint8_t permanent_addr[16]; + grub_uint32_t romaddr; + grub_uint16_t rxbufct; + grub_uint16_t txbufct; +} __attribute__ ((packed)); + + struct grub_pxe_undi_isr { grub_uint16_t status; @@ -259,7 +276,7 @@ struct grub_net_card grub_pxe_card = void grub_pxe_unload (void) { - if (grub_pxe_pxenv) + if (pxe_rm_entry) { grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, @@ -269,17 +286,11 @@ grub_pxe_unload (void) } } -GRUB_MOD_INIT(pxe) +static void +grub_pc_net_config_real (char **device, char **path) { - struct grub_pxe_bangpxe *pxenv; - struct grub_pxenv_get_cached_info ci; struct grub_net_bootp_packet *bp; - struct grub_pxe_undi_open *ou; - - pxenv = grub_pxe_scan (); - if (! pxenv) - return; - + struct grub_pxenv_get_cached_info ci; ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; ci.buffer = 0; ci.buffer_size = 0; @@ -289,9 +300,41 @@ GRUB_MOD_INIT(pxe) bp = LINEAR (ci.buffer); - grub_memcpy (grub_pxe_card.default_address.mac, bp->mac_addr, - bp->hw_len < sizeof (grub_pxe_card.default_address.mac) - ? bp->hw_len : sizeof (grub_pxe_card.default_address.mac)); + grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, + bp, GRUB_PXE_BOOTP_SIZE, + 1, device, path); +} + +GRUB_MOD_INIT(pxe) +{ + struct grub_pxe_bangpxe *pxenv; + struct grub_pxe_undi_open *ou; + struct grub_pxe_undi_info *ui; + unsigned i; + + pxenv = grub_pxe_scan (); + if (! pxenv) + return; + + ui = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (ui, 0, sizeof (*ui)); + grub_pxe_call (GRUB_PXENV_UNDI_GET_INFORMATION, ui, pxe_rm_entry); + + grub_memcpy (grub_pxe_card.default_address.mac, ui->current_addr, + sizeof (grub_pxe_card.default_address.mac)); + for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) + if (grub_pxe_card.default_address.mac[i] != 0) + break; + if (i != sizeof (grub_pxe_card.default_address.mac)) + { + for (i = 0; i < sizeof (grub_pxe_card.default_address.mac); i++) + if (grub_pxe_card.default_address.mac[i] != 0xff) + break; + } + if (i == sizeof (grub_pxe_card.default_address.mac)) + grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr, + sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -303,11 +346,11 @@ GRUB_MOD_INIT(pxe) return; grub_net_card_register (&grub_pxe_card); - grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, - bp, GRUB_PXE_BOOTP_SIZE); + grub_pc_net_config = grub_pc_net_config_real; } GRUB_MOD_FINI(pxe) { + grub_pc_net_config = 0; grub_pxe_unload (); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 2ecb709b9..a56860eed 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -664,6 +664,7 @@ grub_net_open_real (const char *name) else ret->server = NULL; ret->fs = &grub_net_fs; + ret->offset = 0; return ret; } } @@ -784,7 +785,7 @@ grub_net_poll_cards (unsigned time) /* Read from the packets list*/ static grub_ssize_t -grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) +grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; @@ -802,6 +803,7 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) amount = len; len -= amount; total += amount; + file->device->net->offset += amount; if (buf) { grub_memcpy (ptr, nb->data, amount); @@ -829,28 +831,40 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) return total; } -/* Read from the packets list*/ static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) { grub_net_socket_t sock = file->device->net->socket; struct grub_net_buff *nb; - grub_size_t len = offset - file->offset; + grub_size_t len = offset - file->device->net->offset; if (!len) return GRUB_ERR_NONE; /* We cant seek backwards past the current packet. */ - if (file->offset > offset) + if (file->device->net->offset > offset) { nb = sock->packs.first->nb; - return grub_netbuff_push (nb, file->offset - offset); + return grub_netbuff_push (nb, file->device->net->offset - offset); } - grub_net_fs_read (file, NULL, len); + grub_net_fs_read_real (file, NULL, len); return GRUB_ERR_NONE; } +static grub_ssize_t +grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) +{ + if (file->offset != file->device->net->offset) + { + grub_err_t err; + err = grub_net_seek_real (file, file->offset); + if (err) + return err; + } + return grub_net_fs_read_real (file, buf, len); +} + static char * grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), const char *val __attribute__ ((unused))) @@ -1384,7 +1398,6 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; - grub_file_net_seek = grub_net_seek_real; grub_grubnet_fini = grub_grubnet_fini_real; } @@ -1400,6 +1413,5 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; - grub_file_net_seek = NULL; grub_grubnet_fini = NULL; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 24f30eb7a..b112f643e 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -11,6 +11,13 @@ GRUB_MOD_LICENSE ("GPLv3+"); +typedef struct tftp_data +{ + grub_uint64_t file_size; + grub_uint64_t block; + grub_uint32_t block_size; +} *tftp_data_t; + static grub_err_t tftp_open (struct grub_file *file, const char *filename) { @@ -85,9 +92,9 @@ tftp_open (struct grub_file *file, const char *filename) if (file->device->net->socket->status != 0) break; /* Retry. */ - /*err = grub_net_send_udp_packet (file->device->net->socket, &nb); - if (err) - return err; */ + err = grub_net_send_udp_packet (file->device->net->socket, &nb); + if (err) + return err; } if (file->device->net->socket->status == 0) @@ -110,11 +117,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) nb_ack.head = nbdata; nb_ack.end = nbdata + sizeof (nbdata); - tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) { case TFTP_OACK: + data->block_size = 512; for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) @@ -122,6 +129,11 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, 0, 0); } + if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) + { + data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, + 0, 0); + } while (ptr < nb->tail && *ptr) ptr++; ptr++; @@ -139,12 +151,12 @@ tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) { data->block++; unsigned size = nb->tail - nb->data; - if (size < 1024) + if (size < data->block_size) sock->status = 2; /* Prevent garbage in broken cards. */ - if (size > 1024) + if (size > data->block_size) { - err = grub_netbuff_unput (nb, size - 1024); + err = grub_netbuff_unput (nb, size - data->block_size); if (err) return err; } diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index 1de37a5d5..dd50aa833 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -44,6 +44,8 @@ extern grub_int32_t grub_install_bsd_part; /* The boot BIOS drive number. */ extern grub_uint8_t EXPORT_VAR(grub_boot_drive); +extern void (*EXPORT_VAR(grub_pc_net_config)) (char **device, char **path); + #endif /* ! ASM_FILE */ #endif /* ! KERNEL_MACHINE_HEADER */ diff --git a/include/grub/net.h b/include/grub/net.h index 6aaf391d5..494826625 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -242,11 +242,11 @@ typedef struct grub_net char *server; grub_net_app_level_t protocol; grub_net_socket_t socket; + grub_off_t offset; grub_fs_t fs; } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); -extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset); extern void (*EXPORT_VAR (grub_grubnet_fini)) (void); struct grub_net_network_level_interface diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h index c67380817..0d8cbd1de 100644 --- a/include/grub/net/tftp.h +++ b/include/grub/net/tftp.h @@ -43,12 +43,6 @@ /* * own here because this is cleaner, and maps to the same data layout. * */ -typedef struct tftp_data - { - int file_size; - int block; - } *tftp_data_t; - struct tftphdr { grub_uint16_t opcode; From cbe20661f64d0820c3768ec1fe319436be192f22 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 18:05:40 +0200 Subject: [PATCH 255/673] minor stylistic cleanup --- grub-core/net/tftp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index b112f643e..700f0effd 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -75,7 +75,8 @@ tftp_open (struct grub_file *file, const char *filename) rrq += grub_strlen ("0") + 1; hdrlen = sizeof (tftph->opcode) + rrqlen; - if ((err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen))) != GRUB_ERR_NONE) + err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); + if (err) return err; file->device->net->socket->out_port = TFTP_SERVER_PORT; From 0c51bb63c5ef4555dab8aeedcaed309160111cd7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 18:57:24 +0200 Subject: [PATCH 256/673] add missing brackets in efi_wrap macroses --- include/grub/efi/api.h | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 5cd1686ea..b20baa015 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -1359,27 +1359,31 @@ typedef struct grub_efi_block_io grub_efi_block_io_t; #define efi_call_0(func) \ efi_wrap_0(func) #define efi_call_1(func, a) \ - efi_wrap_1(func, (grub_uint64_t) a) + efi_wrap_1(func, (grub_uint64_t) (a)) #define efi_call_2(func, a, b) \ - efi_wrap_2(func, (grub_uint64_t) a, (grub_uint64_t) b) + efi_wrap_2(func, (grub_uint64_t) (a), (grub_uint64_t) (b)) #define efi_call_3(func, a, b, c) \ - efi_wrap_3(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c) + efi_wrap_3(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c)) #define efi_call_4(func, a, b, c, d) \ - efi_wrap_4(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d) + efi_wrap_4(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d)) #define efi_call_5(func, a, b, c, d, e) \ - efi_wrap_5(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e) + efi_wrap_5(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e)) #define efi_call_6(func, a, b, c, d, e, f) \ - efi_wrap_6(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f) + efi_wrap_6(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \ + (grub_uint64_t) (f)) #define efi_call_7(func, a, b, c, d, e, f, g) \ - efi_wrap_7(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g) + efi_wrap_7(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \ + (grub_uint64_t) (f), (grub_uint64_t) (g)) #define efi_call_10(func, a, b, c, d, e, f, g, h, i, j) \ - efi_wrap_10(func, (grub_uint64_t) a, (grub_uint64_t) b, (grub_uint64_t) c, \ - (grub_uint64_t) d, (grub_uint64_t) e, (grub_uint64_t) f, (grub_uint64_t) g, \ - (grub_uint64_t) h, (grub_uint64_t) i, (grub_uint64_t) j) + efi_wrap_10(func, (grub_uint64_t) (a), (grub_uint64_t) (b), \ + (grub_uint64_t) (c), (grub_uint64_t) (d), (grub_uint64_t) (e), \ + (grub_uint64_t) (f), (grub_uint64_t) (g), (grub_uint64_t) (h), \ + (grub_uint64_t) (i), (grub_uint64_t) (j)) grub_uint64_t EXPORT_FUNC(efi_wrap_0) (void *func); grub_uint64_t EXPORT_FUNC(efi_wrap_1) (void *func, grub_uint64_t arg1); From c4d038f632e39faba9506122af29d926cff9267e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 20:11:29 +0200 Subject: [PATCH 257/673] Don't react to adressed bootp packets unless in bootp transaction --- grub-core/kern/emu/main.c | 10 +++++--- grub-core/net/ip.c | 51 +++++++++++++++++++-------------------- grub-core/net/net.c | 12 ++++----- grub-core/net/udp.c | 7 +++--- include/grub/net.h | 2 +- 5 files changed, 43 insertions(+), 39 deletions(-) diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 096e97090..2092d03cb 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -49,7 +49,7 @@ static jmp_buf main_env; /* Store the prefix specified by an argument. */ -static char *root_dev = NULL, *dir = DEFAULT_DIRECTORY; +static char *root_dev = NULL, *dir = NULL; int grub_no_autoload; @@ -139,14 +139,18 @@ main (int argc, char *argv[]) set_program_name (argv[0]); + dir = xstrdup (DEFAULT_DIRECTORY); + while ((opt = getopt_long (argc, argv, "r:d:m:vH:hV", options, 0)) != -1) switch (opt) { case 'r': - root_dev = optarg; + free (root_dev); + root_dev = xstrdup (optarg); break; case 'd': - dir = optarg; + free (dir); + dir = xstrdup (optarg); break; case 'm': dev_map = optarg; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 776937a6e..8b06f7d11 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -65,50 +65,49 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; - struct grub_net_network_level_interface *inf; + struct grub_net_network_level_interface *inf = NULL; err = grub_netbuff_pull (nb, sizeof (*iph)); if (err) return err; - FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + /* DHCP needs special treatment since we don't know IP yet. */ { - if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && inf->address.ipv4 == iph->dest - && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) - break; + struct udphdr *udph; + udph = (struct udphdr *) nb->data; + if (iph->protocol == IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) + { + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + { + err = grub_netbuff_pull (nb, sizeof (*udph)); + if (err) + return err; + grub_net_process_dhcp (nb, inf->card); + grub_netbuff_free (nb); + } + return GRUB_ERR_NONE; + } } + if (!inf) { FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && inf->address.ipv4 == iph->dest && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) - break; - } - if (!inf) - { - if (iph->protocol == IP_UDP - && grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0) - { - struct udphdr *udph; - udph = (struct udphdr *) nb->data; - err = grub_netbuff_pull (nb, sizeof (*udph)); - if (err) - return err; - if (grub_be_to_cpu16 (udph->dst) == 68) - grub_net_process_dhcp (nb, card); - } - grub_netbuff_free (nb); - return GRUB_ERR_NONE; + break; + } } switch (iph->protocol) { case IP_UDP: return grub_net_recv_udp_packet (nb, inf); - break; default: grub_netbuff_free (nb); break; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index a56860eed..d5f9e374e 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -119,7 +119,7 @@ match_net (const grub_net_network_level_netaddress_t *net, return 0; switch (net->type) { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: return 0; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { @@ -238,8 +238,8 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) { switch (target->type) { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: - grub_strcpy (buf, "promisc"); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + grub_strcpy (buf, "temporary"); return; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { @@ -521,8 +521,8 @@ print_net_address (const grub_net_network_level_netaddress_t *target) { switch (target->type) { - case GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC: - grub_printf ("promisc\n"); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + grub_printf ("temporary\n"); break; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { @@ -1257,7 +1257,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), grub_free (ifaces); return grub_errno; } - ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC; + ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV; grub_memcpy (&ifaces[j].hwaddress, &card->default_address, sizeof (ifaces[j].hwaddress)); j++; diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 95134c0cf..b9339e49a 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -32,8 +32,11 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb, { struct udphdr *udph; grub_net_socket_t sock; + grub_err_t err; udph = (struct udphdr *) nb->data; - grub_netbuff_pull (nb, sizeof (*udph)); + err = grub_netbuff_pull (nb, sizeof (*udph)); + if (err) + return err; FOR_NET_SOCKETS (sock) { @@ -54,8 +57,6 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb, return GRUB_ERR_NONE; } } - if (grub_be_to_cpu16 (udph->dst) == 68) - grub_net_process_dhcp (nb, inf->card); grub_netbuff_free (nb); return GRUB_ERR_NONE; } diff --git a/include/grub/net.h b/include/grub/net.h index 494826625..630fd33fb 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -123,7 +123,7 @@ struct grub_net_network_level_interface; typedef enum grub_network_level_protocol_id { - GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC, + GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV, GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 } grub_network_level_protocol_id_t; From 77546584e1466b4702a60b83df674ca4337b2627 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Sutre?= Date: Sat, 2 Jul 2011 21:22:19 +0200 Subject: [PATCH 258/673] Use @PACKAGE@ instead of hardcoded name when sourcing grub-mkconfig_lib. --- ChangeLog | 14 ++++++++++++++ util/grub-mkconfig.in | 2 +- util/grub.d/00_header.in | 2 +- util/grub.d/10_hurd.in | 2 +- util/grub.d/10_kfreebsd.in | 2 +- util/grub.d/10_linux.in | 2 +- util/grub.d/10_netbsd.in | 2 +- util/grub.d/10_windows.in | 2 +- util/grub.d/20_linux_xen.in | 2 +- util/grub.d/30_os-prober.in | 2 +- util/update-grub_lib.in | 2 +- 11 files changed, 24 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b8d8f149..e091265d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-07-02 Grégoire Sutre + + * util/grub-mkconfig.in: Use @PACKAGE@ instead of hardcoded name when + sourcing grub-mkconfig_lib. + * util/update-grub_lib.in: Likewise. + * util/grub.d/00_header.in: Likewise. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/10_netbsd.in: Likewise. + * util/grub.d/10_windows.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + * util/grub.d/30_os-prober.in: Likewise. + 2011-06-28 Colin Watson * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 4d627c057..cf94d1065 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -95,7 +95,7 @@ do esac done -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib if [ "x$EUID" = "x" ] ; then EUID=`id -u` diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 9da1511f5..7b8871d4d 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -25,7 +25,7 @@ libdir=@libdir@ locale_dir=`echo ${GRUB_PREFIX}/locale | sed ${transform}` grub_lang=`echo $LANG | cut -d . -f 1` -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib # Do this as early as possible, since other commands might depend on it. # (e.g. the `loadfont' command might need lvm or raid modules) diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 8c54eab97..9ca01f0a8 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -20,7 +20,7 @@ set -e prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib CLASS="--class gnu --class os" diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 3600c74f9..2ade4ea35 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 1d1eb403f..97e7c6523 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in index ffd31ad93..c257aeb3c 100644 --- a/util/grub.d/10_netbsd.in +++ b/util/grub.d/10_netbsd.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index fd068dd2d..941267a9f 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -20,7 +20,7 @@ set -e prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib case "`uname 2>/dev/null`" in CYGWIN*) ;; diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index 083391c40..c0b255598 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ export TEXTDOMAINDIR=@localedir@ diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index d9d4b0a96..c0b5d7cd7 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -21,7 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then exit 0 diff --git a/util/update-grub_lib.in b/util/update-grub_lib.in index 998452e67..430ce1308 100644 --- a/util/update-grub_lib.in +++ b/util/update-grub_lib.in @@ -18,6 +18,6 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -. ${libdir}/grub/grub-mkconfig_lib +. ${libdir}/@PACKAGE@/grub-mkconfig_lib grub_warn "update-grub_lib is deprecated, use grub-mkconfig_lib instead" From 7e0c2d162afd175580074eb7386811e0694aaed3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 2 Jul 2011 22:13:33 +0200 Subject: [PATCH 259/673] Restructurisations, cleanups and few bugfixes --- grub-core/net/arp.c | 3 +- grub-core/net/net.c | 94 +++++++---------- grub-core/net/tftp.c | 226 ++++++++++++++++++++++++----------------- grub-core/net/udp.c | 65 +++++++++--- include/grub/net.h | 25 +++-- include/grub/net/udp.h | 16 +++ 6 files changed, 251 insertions(+), 178 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index fecde3282..d726f2c3a 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -144,7 +144,8 @@ grub_net_arp_receive (struct grub_net_buff *nb) FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { /* Am I the protocol address target? */ - if (grub_memcmp (target_protocol_address, &inf->address.ipv4, 6) == 0 + if (inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && grub_memcmp (target_protocol_address, &inf->address.ipv4, 4) == 0 && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) { grub_net_link_level_address_t aux; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index d5f9e374e..595379a99 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -630,25 +631,27 @@ grub_net_open_real (const char *name) { protnamelen = comma - name; server = comma + 1; + protname = name; } else { protnamelen = grub_strlen (name); server = default_server; + protname = name; } } if (!server) { grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no server"); return NULL; - } + } FOR_NET_APP_LEVEL (proto) { if (grub_memcmp (proto->name, protname, protnamelen) == 0 && proto->name[protnamelen] == 0) { - grub_net_t ret = grub_malloc (sizeof (*ret)); + grub_net_t ret = grub_zalloc (sizeof (*ret)); if (!ret) return NULL; ret->protocol = proto; @@ -665,6 +668,7 @@ grub_net_open_real (const char *name) ret->server = NULL; ret->fs = &grub_net_fs; ret->offset = 0; + ret->eof = 0; return ret; } } @@ -686,61 +690,26 @@ grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)) static grub_err_t grub_net_fs_open (struct grub_file *file, const char *name) { - grub_err_t err; - grub_net_network_level_address_t addr; - struct grub_net_network_level_interface *inf; - grub_net_network_level_address_t gateway; - grub_net_socket_t socket; - static int port = 25300; - - err = grub_net_resolve_address (file->device->net->server, &addr); - if (err) - return err; - - err = grub_net_route_address (addr, &gateway, &inf); - if (err) - return err; - - socket = (grub_net_socket_t) grub_malloc (sizeof (*socket)); - if (socket == NULL) - return grub_errno; - - socket->inf = inf; - socket->out_nla = addr; - socket->in_port = port++; - socket->status = 0; - socket->app = file->device->net->protocol; - socket->packs.first = NULL; - socket->packs.last = NULL; - file->device->net->socket = socket; - grub_net_socket_register (socket); - - err = file->device->net->protocol->open (file,name); - if (err) - goto fail; - file->not_easily_seekable = 1; - - return GRUB_ERR_NONE; -fail: - grub_net_socket_unregister (socket); - grub_free (socket); - return err; + file->device->net->packs.first = NULL; + file->device->net->packs.last = NULL; + file->device->net->name = grub_strdup (name); + if (!file->device->net->name) + return grub_errno; + return file->device->net->protocol->open (file, name); } static grub_err_t grub_net_fs_close (grub_file_t file) { - grub_net_socket_t sock = file->device->net->socket; - while (sock->packs.first) + while (file->device->net->packs.first) { - grub_netbuff_free (sock->packs.first->nb); - grub_net_remove_packet (sock->packs.first); + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); } - grub_net_socket_unregister (sock); - grub_free (sock); + file->device->net->protocol->close (file); + grub_free (file->device->net->name); return GRUB_ERR_NONE; - } static void @@ -787,9 +756,9 @@ grub_net_poll_cards (unsigned time) static grub_ssize_t grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) { - grub_net_socket_t sock = file->device->net->socket; + grub_net_t sock = file->device->net; struct grub_net_buff *nb; - char *ptr = buf; + char *ptr = buf; grub_size_t amount, total = 0; int try = 0; while (try <= 3) @@ -820,7 +789,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (!len) return total; } - if (sock->status == 1) + if (!sock->eof) { try++; grub_net_poll_cards (200); @@ -834,18 +803,29 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) { - grub_net_socket_t sock = file->device->net->socket; - struct grub_net_buff *nb; grub_size_t len = offset - file->device->net->offset; if (!len) return GRUB_ERR_NONE; - /* We cant seek backwards past the current packet. */ if (file->device->net->offset > offset) - { - nb = sock->packs.first->nb; - return grub_netbuff_push (nb, file->device->net->offset - offset); + { + grub_err_t err; + while (file->device->net->packs.first) + { + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } + file->device->net->protocol->close (file); + + file->device->net->packs.first = NULL; + file->device->net->packs.last = NULL; + file->device->net->offset = 0; + file->device->net->eof = 0; + err = file->device->net->protocol->open (file, file->device->net->name); + if (err) + return err; + len = offset; } grub_net_fs_read_real (file, NULL, len); diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 700f0effd..6ffe27669 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -16,8 +16,107 @@ typedef struct tftp_data grub_uint64_t file_size; grub_uint64_t block; grub_uint32_t block_size; + int have_oack; + grub_net_socket_t sock; } *tftp_data_t; +static grub_err_t +tftp_receive (grub_net_socket_t sock __attribute__ ((unused)), + struct grub_net_buff *nb, + void *f) +{ + grub_file_t file = f; + struct tftphdr *tftph = (void *) nb->data; + char nbdata[512]; + tftp_data_t data = file->data; + grub_err_t err; + char *ptr; + struct grub_net_buff nb_ack; + + nb_ack.head = nbdata; + nb_ack.end = nbdata + sizeof (nbdata); + + tftph = (struct tftphdr *) nb->data; + switch (grub_be_to_cpu16 (tftph->opcode)) + { + case TFTP_OACK: + data->block_size = 512; + data->have_oack = 1; + for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) + { + if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) + { + data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, + 0, 0); + } + if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) + { + data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, + 0, 0); + } + while (ptr < nb->tail && *ptr) + ptr++; + ptr++; + } + data->block = 0; + grub_netbuff_free (nb); + break; + case TFTP_DATA: + err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (err) + return err; + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + { + unsigned size = nb->tail - nb->data; + data->block++; + if (size < data->block_size) + { + file->device->net->eof = 1; + } + /* Prevent garbage in broken cards. */ + if (size > data->block_size) + { + err = grub_netbuff_unput (nb, size - data->block_size); + if (err) + return err; + } + /* If there is data, puts packet in socket list. */ + if ((nb->tail - nb->data) > 0) + grub_net_put_packet (&file->device->net->packs, nb); + else + grub_netbuff_free (nb); + } + else + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + break; + case TFTP_ERROR: + grub_netbuff_free (nb); + return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); + } + grub_netbuff_clear (&nb_ack); + grub_netbuff_reserve (&nb_ack, 512); + err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) + + sizeof (tftph->u.ack.block)); + if (err) + return err; + + tftph = (struct tftphdr *) nb_ack.data; + tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); + tftph->u.ack.block = grub_cpu_to_be16 (data->block); + + err = grub_net_send_udp_packet (data->sock, &nb_ack); + if (file->device->net->eof) + { + grub_net_udp_close (data->sock); + data->sock = NULL; + } + return err; +} + static grub_err_t tftp_open (struct grub_file *file, const char *filename) { @@ -31,17 +130,17 @@ tftp_open (struct grub_file *file, const char *filename) tftp_data_t data; grub_err_t err; - data = grub_malloc (sizeof (*data)); + data = grub_zalloc (sizeof (*data)); if (!data) return grub_errno; - file->device->net->socket->data = (void *) data; nb.head = open_data; nb.end = open_data + sizeof (open_data); grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 1500); - if ((err = grub_netbuff_push (&nb, sizeof (*tftph))) != GRUB_ERR_NONE) + err = grub_netbuff_push (&nb, sizeof (*tftph)); + if (err) return err; tftph = (struct tftphdr *) nb.data; @@ -78,11 +177,21 @@ tftp_open (struct grub_file *file, const char *filename) err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen)); if (err) return err; - file->device->net->socket->out_port = TFTP_SERVER_PORT; - err = grub_net_send_udp_packet (file->device->net->socket, &nb); + file->not_easily_seekable = 1; + file->data = data; + data->sock = grub_net_udp_open (file->device->net->server, + TFTP_SERVER_PORT, tftp_receive, + file); + if (!data->sock) + return grub_errno; + + err = grub_net_send_udp_packet (data->sock, &nb); if (err) - return err; + { + grub_net_udp_close (data->sock); + return err; + } /* Receive OACK packet. */ for (i = 0; i < 3; i++) @@ -90,106 +199,34 @@ tftp_open (struct grub_file *file, const char *filename) grub_net_poll_cards (100); if (grub_errno) return grub_errno; - if (file->device->net->socket->status != 0) + if (data->have_oack) break; /* Retry. */ - err = grub_net_send_udp_packet (file->device->net->socket, &nb); + err = grub_net_send_udp_packet (data->sock, &nb); if (err) - return err; + { + grub_net_udp_close (data->sock); + return err; + } } - if (file->device->net->socket->status == 0) - return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); + if (!data->have_oack) + { + grub_net_udp_close (data->sock); + return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); + } file->size = data->file_size; return GRUB_ERR_NONE; } static grub_err_t -tftp_receive (grub_net_socket_t sock, struct grub_net_buff *nb) +tftp_close (struct grub_file *file) { - struct tftphdr *tftph; - char nbdata[128]; - tftp_data_t data = sock->data; - grub_err_t err; - char *ptr; - struct grub_net_buff nb_ack; - - nb_ack.head = nbdata; - nb_ack.end = nbdata + sizeof (nbdata); - - tftph = (struct tftphdr *) nb->data; - switch (grub_be_to_cpu16 (tftph->opcode)) - { - case TFTP_OACK: - data->block_size = 512; - for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) - { - if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) - { - data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, - 0, 0); - } - if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) - { - data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, - 0, 0); - } - while (ptr < nb->tail && *ptr) - ptr++; - ptr++; - } - sock->status = 1; - data->block = 0; - grub_netbuff_clear (nb); - break; - case TFTP_DATA: - err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block)); - if (err) - return err; - if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) - { - data->block++; - unsigned size = nb->tail - nb->data; - if (size < data->block_size) - sock->status = 2; - /* Prevent garbage in broken cards. */ - if (size > data->block_size) - { - err = grub_netbuff_unput (nb, size - data->block_size); - if (err) - return err; - } - } - else - grub_netbuff_clear (nb); - - break; - case TFTP_ERROR: - grub_netbuff_clear (nb); - return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); - break; - } - grub_netbuff_clear (&nb_ack); - grub_netbuff_reserve (&nb_ack, 128); - err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); - if (err) - return err; - - tftph = (struct tftphdr *) nb_ack.data; - tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - tftph->u.ack.block = grub_cpu_to_be16 (data->block); - - err = grub_net_send_udp_packet (sock, &nb_ack); - return err; -} - -static grub_err_t -tftp_close (struct grub_file *file __attribute__ ((unused))) -{ - grub_free (file->device->net->socket->data); + tftp_data_t data = file->data; + if (data->sock) + grub_net_udp_close (data->sock); + grub_free (data); return GRUB_ERR_NONE; } @@ -197,7 +234,6 @@ static struct grub_net_app_protocol grub_tftp_protocol = { .name = "tftp", .open = tftp_open, - .read = tftp_receive, .close = tftp_close }; diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index b9339e49a..47a67a967 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -4,6 +4,46 @@ #include #include +grub_net_socket_t +grub_net_udp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_socket_t sock, + struct grub_net_buff *nb, + void *data), + void *recv_hook_data) +{ + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + grub_net_socket_t socket; + static int in_port = 25300; + + err = grub_net_resolve_address (server, &addr); + if (err) + return NULL; + + err = grub_net_route_address (addr, &gateway, &inf); + if (err) + return NULL; + + socket = grub_zalloc (sizeof (*socket)); + if (socket == NULL) + return NULL; + + socket->x_out_port = out_port; + socket->x_inf = inf; + socket->x_out_nla = addr; + socket->x_in_port = in_port++; + socket->x_status = GRUB_NET_SOCKET_START; + socket->recv_hook = recv_hook; + socket->recv_hook_data = recv_hook_data; + + grub_net_socket_register (socket); + + return socket; +} + grub_err_t grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb) @@ -16,14 +56,14 @@ grub_net_send_udp_packet (const grub_net_socket_t socket, return err; udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (socket->in_port); - udph->dst = grub_cpu_to_be16 (socket->out_port); + udph->src = grub_cpu_to_be16 (socket->x_in_port); + udph->dst = grub_cpu_to_be16 (socket->x_out_port); /* No chechksum. */ udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb); + return grub_net_send_ip_packet (socket->x_inf, &(socket->x_out_nla), nb); } grub_err_t @@ -40,20 +80,17 @@ grub_net_recv_udp_packet (struct grub_net_buff * nb, FOR_NET_SOCKETS (sock) { - if (grub_be_to_cpu16 (udph->dst) == sock->in_port - && inf == sock->inf && sock->app) + if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port + && inf == sock->x_inf && sock->recv_hook) { - if (sock->status == 0) - sock->out_port = grub_be_to_cpu16 (udph->src); + if (sock->x_status == GRUB_NET_SOCKET_START) + { + sock->x_out_port = grub_be_to_cpu16 (udph->src); + sock->x_status = GRUB_NET_SOCKET_ESTABLISHED; + } /* App protocol remove its own reader. */ - sock->app->read (sock, nb); - - /* If there is data, puts packet in socket list. */ - if ((nb->tail - nb->data) > 0) - grub_net_put_packet (&sock->packs, nb); - else - grub_netbuff_free (nb); + sock->recv_hook (sock, nb, sock->recv_hook_data); return GRUB_ERR_NONE; } } diff --git a/include/grub/net.h b/include/grub/net.h index 630fd33fb..0656787a6 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -201,22 +201,23 @@ struct grub_net_app_protocol int (*hook) (const char *filename, const struct grub_dirhook_info *info)); grub_err_t (*open) (struct grub_file *file, const char *filename); - grub_err_t (*read) (grub_net_socket_t sock, struct grub_net_buff *nb); grub_err_t (*close) (struct grub_file *file); - grub_err_t (*label) (grub_device_t device, char **label); }; struct grub_net_socket { struct grub_net_socket *next; - int status; - int in_port; - int out_port; - grub_net_app_level_t app; - grub_net_network_level_address_t out_nla; - struct grub_net_network_level_interface *inf; - grub_net_packets_t packs; - void *data; + + enum { GRUB_NET_SOCKET_START, + GRUB_NET_SOCKET_ESTABLISHED, + GRUB_NET_SOCKET_CLOSED } x_status; + int x_in_port; + int x_out_port; + grub_err_t (*recv_hook) (grub_net_socket_t sock, struct grub_net_buff *nb, + void *recv); + void *recv_hook_data; + grub_net_network_level_address_t x_out_nla; + struct grub_net_network_level_interface *x_inf; }; extern struct grub_net_socket *grub_net_sockets; @@ -240,10 +241,12 @@ grub_net_socket_unregister (grub_net_socket_t sock) typedef struct grub_net { char *server; + char *name; grub_net_app_level_t protocol; - grub_net_socket_t socket; + grub_net_packets_t packs; grub_off_t offset; grub_fs_t fs; + int eof; } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index eacf3325c..272612299 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -11,6 +11,22 @@ struct udphdr grub_uint16_t chksum; } __attribute__ ((packed)); + +grub_net_socket_t +grub_net_udp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_socket_t sock, + struct grub_net_buff *nb, + void *data), + void *recv_hook_data); + +static inline void +grub_net_udp_close (grub_net_socket_t sock) +{ + grub_net_socket_unregister (sock); + grub_free (sock); +} + grub_err_t grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); From 671a78acb0648d3d73c95ab0f021f907499aacc0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 14:34:10 +0200 Subject: [PATCH 260/673] cleanup pxe and efi network release --- grub-core/Makefile.core.def | 6 ---- grub-core/commands/i386/pc/pxecmd.c | 54 ----------------------------- grub-core/net/drivers/efi/efinet.c | 17 ++++----- grub-core/net/drivers/i386/pc/pxe.c | 50 ++++++++++++++++++++------ grub-core/net/net.c | 13 ------- include/grub/net.h | 23 ++---------- 6 files changed, 47 insertions(+), 116 deletions(-) delete mode 100644 grub-core/commands/i386/pc/pxecmd.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2c9f48076..7004aaf23 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -714,12 +714,6 @@ module = { common = commands/probe.c; }; -module = { - name = pxecmd; - i386_pc = commands/i386/pc/pxecmd.c; - enable = i386_pc; -}; - module = { name = read; common = commands/read.c; diff --git a/grub-core/commands/i386/pc/pxecmd.c b/grub-core/commands/i386/pc/pxecmd.c deleted file mode 100644 index dffa15a3a..000000000 --- a/grub-core/commands/i386/pc/pxecmd.c +++ /dev/null @@ -1,54 +0,0 @@ -/* pxe.c - command to control the pxe driver */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#include -#include -#include -#include -#include -#include - -GRUB_MOD_LICENSE ("GPLv3+"); - -static grub_err_t -grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - if (! grub_pxe_pxenv) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment"); - - grub_pxe_unload (); - - return 0; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(pxecmd) -{ - cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload, - 0, - N_("Unload PXE environment.")); -} - -GRUB_MOD_FINI(pxecmd) -{ - grub_unregister_command (cmd); -} diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 1328cd57c..4b2ffc038 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -184,23 +184,18 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device, } } - GRUB_MOD_INIT(efinet) { grub_efinet_findcards (); grub_efi_net_config = grub_efi_net_config_real; } -GRUB_MOD_FINI(ofnet) +GRUB_MOD_FINI(efinet) { - struct grub_net_card *card; - grub_efi_net_config = 0; - FOR_NET_CARDS (card) - if (card->driver && !grub_strcmp (card->driver->name, "efinet")) - { - card->driver->fini (card); - card->driver = NULL; - } - grub_net_card_driver_unregister (&efidriver); + struct grub_net_card *card, *next; + + FOR_NET_CARDS_SAFE (card, next) + if (card->driver && grub_strcmp (card->driver->name, "efinet") == 0) + grub_net_card_unregister (card); } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 51f4023a6..81607eb57 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -22,8 +22,8 @@ #include #include #include -#include #include +#include #include #include @@ -273,19 +273,36 @@ struct grub_net_card grub_pxe_card = .name = "pxe" }; -void -grub_pxe_unload (void) +static grub_err_t +grub_pxe_fini_hw (int noreturn __attribute__ ((unused))) { if (pxe_rm_entry) - { - grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, - (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, - pxe_rm_entry); - grub_net_card_unregister (&grub_pxe_card); - grub_pxe_pxenv = 0; - } + grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, + (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, + pxe_rm_entry); + + return GRUB_ERR_NONE; } +static grub_err_t +grub_pxe_restore_hw (void) +{ + struct grub_pxe_undi_open *ou; + ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (ou, 0, sizeof (*ou)); + ou->pkt_filter = 4; + grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); + + if (ou->status) + { + grub_net_card_unregister (&grub_pxe_card); + return grub_error (GRUB_ERR_IO, "can't open UNDI"); + } + return GRUB_ERR_NONE; +} + +static void *fini_hnd; + static void grub_pc_net_config_real (char **device, char **path) { @@ -303,6 +320,7 @@ grub_pc_net_config_real (char **device, char **path) grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, bp, GRUB_PXE_BOOTP_SIZE, 1, device, path); + } GRUB_MOD_INIT(pxe) @@ -347,10 +365,20 @@ GRUB_MOD_INIT(pxe) grub_net_card_register (&grub_pxe_card); grub_pc_net_config = grub_pc_net_config_real; + fini_hnd = grub_loader_register_preboot_hook (grub_pxe_fini_hw, + grub_pxe_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(pxe) { + struct grub_net_card *card, *next; + grub_pc_net_config = 0; - grub_pxe_unload (); + grub_pxe_fini_hw (0); + grub_net_card_unregister (&grub_pxe_card); + FOR_NET_CARDS_SAFE (card, next) + if (card->driver && grub_strcmp (card->driver->name, "pxe") == 0) + grub_net_card_unregister (card); + grub_loader_unregister_preboot_hook (fini_hnd); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 595379a99..96bbd1712 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -52,7 +52,6 @@ struct grub_net_route struct grub_net_route *grub_net_routes = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_card *grub_net_cards = NULL; -struct grub_net_card_driver *grub_net_card_drivers = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static struct grub_fs grub_net_fs; @@ -1321,16 +1320,6 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), return err; } -static void -grub_grubnet_fini_real (void) -{ - struct grub_net_card *card; - - FOR_NET_CARDS (card) - if (card->driver) - card->driver->fini (card); -} - static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1378,7 +1367,6 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; - grub_grubnet_fini = grub_grubnet_fini_real; } GRUB_MOD_FINI(net) @@ -1393,5 +1381,4 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; - grub_grubnet_fini = NULL; } diff --git a/include/grub/net.h b/include/grub/net.h index 0656787a6..e9a3793db 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -60,32 +60,12 @@ struct grub_net_card_driver { struct grub_net_card_driver *next; char *name; - grub_err_t (*init) (struct grub_net_card *dev); - grub_err_t (*fini) (struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, struct grub_net_buff *buf); grub_ssize_t (*recv) (const struct grub_net_card *dev, struct grub_net_buff *buf); }; -extern struct grub_net_card_driver *grub_net_card_drivers; - -static inline void -grub_net_card_driver_register (struct grub_net_card_driver *driver) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_card_drivers), - GRUB_AS_LIST (driver)); -} - -static inline void -grub_net_card_driver_unregister (struct grub_net_card_driver *driver) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_card_drivers), - GRUB_AS_LIST (driver)); -} - -#define FOR_NET_CARD_DRIVERS(var) for (var = grub_net_card_drivers; var; var = var->next) - typedef struct grub_net_packet { struct grub_net_packet *next; @@ -250,7 +230,6 @@ typedef struct grub_net } *grub_net_t; extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name); -extern void (*EXPORT_VAR (grub_grubnet_fini)) (void); struct grub_net_network_level_interface { @@ -350,6 +329,8 @@ grub_net_card_unregister (struct grub_net_card *card) } #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) +#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next) + struct grub_net_session * grub_net_open_tcp (char *address, grub_uint16_t port); From 275f8264e42781db403a26871462a6a25e53bb50 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 14:55:28 +0200 Subject: [PATCH 261/673] Prevent garbage from getting into aout header --- util/grub-mkimage.c | 1 + 1 file changed, 1 insertion(+) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 9fc37df2b..042bcf2df 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1278,6 +1278,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], aout_size = core_size + sizeof (*aout_head); aout_img = xmalloc (aout_size); aout_head = aout_img; + grub_memset (aout_head, 0, sizeof (*aout_head)); aout_head->a_midmag = grub_host_to_target32 ((AOUT_MID_SUN << 16) | AOUT32_OMAGIC); aout_head->a_text = grub_host_to_target32 (core_size); From 382077365b92c5727f748dcd87f90ea30dd320ad Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 15:10:47 +0200 Subject: [PATCH 262/673] Fix mod_gap definition --- include/grub/offsets.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/grub/offsets.h b/include/grub/offsets.h index c04961fc6..e8170fcbe 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -169,7 +169,7 @@ /* Non-zero value is only needed for PowerMacs. */ #define GRUB_KERNEL_I386_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_I386_COREBOOT_MOD_GAP 0x0 -#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x0 +#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x0 #define GRUB_KERNEL_POWERPC_IEEE1275_MOD_ALIGN 0x1000 #define GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN 0x1 @@ -181,7 +181,7 @@ /* Minimal gap between _end and the start of the modules. It's a hack for PowerMac to prevent "CLAIM failed" error. The real fix is to rewrite grub-mkimage to generate valid ELF files. */ -#define GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP 0x8000 +#define GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP 0x8000 #ifdef GRUB_MACHINE #define GRUB_OFFSETS_CONCAT_(a,b,c) a ## b ## c From 0bc2cd0f82b274ab67fea73da9c5ead92b63a05f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 16:37:14 +0200 Subject: [PATCH 263/673] Reintroduce open/close of net cards. Clean up ofnet. --- grub-core/Makefile.am | 3 - grub-core/kern/ieee1275/init.c | 44 +++--- grub-core/kern/ieee1275/openfw.c | 111 ++++++++------ grub-core/net/drivers/efi/efinet.c | 2 +- grub-core/net/drivers/i386/pc/pxe.c | 54 ++----- grub-core/net/drivers/ieee1275/ofnet.c | 203 +++++++++++++------------ grub-core/net/ethernet.c | 10 +- grub-core/net/net.c | 71 ++++++++- include/grub/i386/pc/pxe.h | 2 - include/grub/ieee1275/ieee1275.h | 10 +- include/grub/ieee1275/ofnet.h | 66 -------- include/grub/net.h | 22 +-- 12 files changed, 313 insertions(+), 285 deletions(-) delete mode 100644 include/grub/ieee1275/ofnet.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index c3ecba9cf..2edf85a50 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -115,7 +115,6 @@ endif if COND_i386_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -175,7 +174,6 @@ endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -183,7 +181,6 @@ endif if COND_sparc64_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ofnet.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 3c6332553..81b06c88e 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -77,25 +76,16 @@ grub_translate_ieee1275_path (char *filepath) } } +void (*grub_ieee1275_net_config) (const char *dev, + char **device, + char **path); void grub_machine_get_bootlocation (char **device, char **path) { char bootpath[64]; /* XXX check length */ char *filename; - grub_bootp_t bootp_pckt; - - /* Set the net prefix when possible. */ - if (grub_getbootp && (bootp_pckt = grub_getbootp())) - { - grub_uint32_t n = bootp_pckt->siaddr; - char addr[GRUB_NET_MAX_STR_ADDR_LEN]; - grub_snprintf (addr, GRUB_NET_MAX_STR_ADDR_LEN, "%d.%d.%d.%d", - ((n >> 24) & 0xff), ((n >> 16) & 0xff), - ((n >> 8) & 0xff), ((n >> 0) & 0xff)); - *device = grub_xasprintf ("(tftp,%s)", addr); - return; - } - + char *type; + if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, sizeof (bootpath), 0)) { @@ -106,7 +96,27 @@ grub_machine_get_bootlocation (char **device, char **path) /* Transform an OF device path to a GRUB path. */ - *device = grub_ieee1275_encode_devname (bootpath); + type = grub_ieee1275_get_device_type (bootpath); + if (type && grub_strcmp (type, "network") == 0) + { + char *dev, *canon; + char *ptr; + dev = grub_ieee1275_get_aliasdevname (bootpath); + canon = grub_ieee1275_canonicalise_devname (dev); + ptr = canon + grub_strlen (canon) - 1; + while (ptr > canon && (*ptr == ',' || *ptr == ':')) + ptr--; + ptr++; + *ptr = 0; + + if (grub_ieee1275_net_config) + grub_ieee1275_net_config (canon, device, path); + grub_free (dev); + grub_free (canon); + } + else + *device = grub_ieee1275_encode_devname (bootpath); + grub_free (type); filename = grub_ieee1275_get_filename (bootpath); if (filename) @@ -264,8 +274,6 @@ grub_machine_init (void) void grub_machine_fini (void) { - if (grub_grubnet_fini) - grub_grubnet_fini (); grub_ofdisk_fini (); grub_console_fini (); } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 8fc373c55..2cecd8c7f 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -22,16 +22,15 @@ #include #include #include -#include #include #include -grub_bootp_t (*grub_getbootp) (void); enum grub_ieee1275_parse_type { GRUB_PARSE_FILENAME, GRUB_PARSE_PARTITION, - GRUB_PARSE_DEVICE + GRUB_PARSE_DEVICE, + GRUB_PARSE_DEVICE_TYPE }; /* Walk children of 'devpath', calling hook for each. */ @@ -322,14 +321,9 @@ 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)) @@ -344,55 +338,86 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) goto fail; } - if (!grub_strcmp ("block", type)) + switch (ptype) { - /* The syntax of the device arguments is defined in the CHRP and PReP - IEEE1275 bindings: "[partition][,[filename]]". */ - char *comma = grub_strchr (args, ','); + case GRUB_PARSE_DEVICE: + ret = grub_strdup (device); + break; + case GRUB_PARSE_DEVICE_TYPE: + ret = grub_strdup (type); + break; + case GRUB_PARSE_FILENAME: + { + char *comma; + char *args; - if (ptype == GRUB_PARSE_FILENAME) - { - if (comma) - { - char *filepath = comma + 1; + if (grub_strcmp ("block", type) != 0) + goto unknown; - /* Make sure filepath has leading backslash. */ - if (filepath[0] != '\\') - ret = grub_xasprintf ("\\%s", filepath); - else - ret = grub_strdup (filepath); + args = grub_ieee1275_get_devargs (path); + if (!args) + /* Shouldn't happen. */ + return 0; + + /* The syntax of the device arguments is defined in the CHRP and PReP + IEEE1275 bindings: "[partition][,[filename]]". */ + comma = grub_strchr (args, ','); + + 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); } + grub_free (args); } - else if (ptype == GRUB_PARSE_PARTITION) - { - if (!comma) - ret = grub_strdup (args); - else - ret = grub_strndup (args, (grub_size_t)(comma - args)); - /* Consistently provide numbered partitions to GRUB. - OpenBOOT traditionally uses alphabetical partition - specifiers. */ - if (ret[0] >= 'a' && ret[0] <= 'z') - ret[0] = '1' + (ret[0] - 'a'); - } - } + break; + case GRUB_PARSE_PARTITION: + { + char *comma; + char *args; - else if (!grub_strcmp ("network", type)) - { - if (ptype == GRUB_PARSE_DEVICE) - ret = grub_strdup(device); - } - else - { + if (grub_strcmp ("block", type) != 0) + goto unknown; + + args = grub_ieee1275_get_devargs (path); + if (!args) + /* Shouldn't happen. */ + return 0; + + comma = grub_strchr (args, ','); + if (!comma) + ret = grub_strdup (args); + else + ret = grub_strndup (args, (grub_size_t)(comma - args)); + /* Consistently provide numbered partitions to GRUB. + OpenBOOT traditionally uses alphabetical partition + specifiers. */ + if (ret[0] >= 'a' && ret[0] <= 'z') + ret[0] = '1' + (ret[0] - 'a'); + grub_free (args); + } + break; + default: + unknown: grub_printf ("Unsupported type %s for device %s\n", type, device); } fail: grub_free (device); - grub_free (args); return ret; } +char * +grub_ieee1275_get_device_type (const char *path) +{ + return grub_ieee1275_parse_args (path, GRUB_PARSE_DEVICE_TYPE); +} + char * grub_ieee1275_get_aliasdevname (const char *path) { diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 4b2ffc038..5c6aac608 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -195,7 +195,7 @@ GRUB_MOD_FINI(efinet) struct grub_net_card *card, *next; FOR_NET_CARDS_SAFE (card, next) - if (card->driver && grub_strcmp (card->driver->name, "efinet") == 0) + if (card->driver == &efidriver) grub_net_card_unregister (card); } diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 81607eb57..aa10cbbfa 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -261,20 +260,8 @@ grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), return 0; } -struct grub_net_card_driver grub_pxe_card_driver = -{ - .send = grub_pxe_send, - .recv = grub_pxe_recv -}; - -struct grub_net_card grub_pxe_card = -{ - .driver = &grub_pxe_card_driver, - .name = "pxe" -}; - static grub_err_t -grub_pxe_fini_hw (int noreturn __attribute__ ((unused))) +grub_pxe_close (const struct grub_net_card *dev __attribute__ ((unused))) { if (pxe_rm_entry) grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, @@ -285,7 +272,7 @@ grub_pxe_fini_hw (int noreturn __attribute__ ((unused))) } static grub_err_t -grub_pxe_restore_hw (void) +grub_pxe_open (const struct grub_net_card *dev __attribute__ ((unused))) { struct grub_pxe_undi_open *ou; ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -294,14 +281,23 @@ grub_pxe_restore_hw (void) grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); if (ou->status) - { - grub_net_card_unregister (&grub_pxe_card); - return grub_error (GRUB_ERR_IO, "can't open UNDI"); - } + return grub_error (GRUB_ERR_IO, "can't open UNDI"); return GRUB_ERR_NONE; } -static void *fini_hnd; +struct grub_net_card_driver grub_pxe_card_driver = +{ + .open = grub_pxe_open, + .close = grub_pxe_close, + .send = grub_pxe_send, + .recv = grub_pxe_recv +}; + +struct grub_net_card grub_pxe_card = +{ + .driver = &grub_pxe_card_driver, + .name = "pxe" +}; static void grub_pc_net_config_real (char **device, char **path) @@ -355,30 +351,12 @@ GRUB_MOD_INIT(pxe) grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - ou = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; - grub_memset (ou, 0, sizeof (*ou)); - ou->pkt_filter = 4; - grub_pxe_call (GRUB_PXENV_UNDI_OPEN, ou, pxe_rm_entry); - - if (ou->status) - return; - grub_net_card_register (&grub_pxe_card); grub_pc_net_config = grub_pc_net_config_real; - fini_hnd = grub_loader_register_preboot_hook (grub_pxe_fini_hw, - grub_pxe_restore_hw, - GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(pxe) { - struct grub_net_card *card, *next; - grub_pc_net_config = 0; - grub_pxe_fini_hw (0); grub_net_card_unregister (&grub_pxe_card); - FOR_NET_CARDS_SAFE (card, next) - if (card->driver && grub_strcmp (card->driver->name, "pxe") == 0) - grub_net_card_unregister (card); - grub_loader_unregister_preboot_hook (fini_hnd); } diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index e5a6bfcad..cc29d0987 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -25,8 +24,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); +struct grub_ofnetcard_data +{ + char *path; + grub_ieee1275_ihandle_t handle; + grub_uint32_t mtu; +}; + static grub_err_t -card_open (struct grub_net_card *dev) +card_open (const struct grub_net_card *dev) { int status; struct grub_ofnetcard_data *data = dev->data; @@ -44,14 +50,13 @@ card_open (struct grub_net_card *dev) return GRUB_ERR_NONE; } -static grub_err_t -card_close (struct grub_net_card *dev) +static void +card_close (const struct grub_net_card *dev) { struct grub_ofnetcard_data *data = dev->data; if (data->handle) grub_ieee1275_close (data->handle); - return GRUB_ERR_NONE; } static grub_err_t @@ -93,8 +98,8 @@ get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) static struct grub_net_card_driver ofdriver = { .name = "ofnet", - .init = card_open, - .fini = card_close, + .open = card_open, + .close = card_close, .send = send_card_buffer, .recv = get_card_packet }; @@ -112,39 +117,87 @@ bootp_response_properties[] = { .name = "bootpreply-packet", .offset = 0x2a}, }; -static grub_bootp_t -grub_getbootp_real (void) +static void +grub_ieee1275_net_config_real (const char *devpath, char **device, char **path) { - grub_bootp_t packet = grub_malloc (sizeof *packet); - char *bootp_response; - grub_ssize_t size; - unsigned int i; + struct grub_net_card *card; - for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) - if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, - bootp_response_properties[i].name, - &size) >= 0) - break; + /* FIXME: Check that it's the right card. */ + FOR_NET_CARDS (card) + { + char *bootp_response; + char *cardpath; + char *canon; - if (size < 0) - return NULL; + grub_ssize_t size = -1; + unsigned int i; - bootp_response = grub_malloc (size); - if (grub_ieee1275_get_property (grub_ieee1275_chosen, - bootp_response_properties[i].name, - bootp_response, size, 0) < 0) - return NULL; + if (card->driver != &ofdriver) + continue; - grub_memcpy (packet, bootp_response + bootp_response_properties[i].offset, sizeof (*packet)); - grub_free (bootp_response); - return packet; + cardpath = ((struct grub_ofnetcard_data *) card->data)->path; + canon = grub_ieee1275_canonicalise_devname (cardpath); + if (grub_strcmp (devpath, canon) != 0) + { + grub_free (canon); + continue; + } + grub_free (canon); + + for (i = 0; i < ARRAY_SIZE (bootp_response_properties); i++) + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, + bootp_response_properties[i].name, + &size) >= 0) + break; + + if (size < 0) + return; + + bootp_response = grub_malloc (size); + if (!bootp_response) + { + grub_print_error (); + return; + } + if (grub_ieee1275_get_property (grub_ieee1275_chosen, + bootp_response_properties[i].name, + bootp_response, size, 0) < 0) + return; + + grub_net_configure_by_dhcp_ack (card->name, card, 0, + (struct grub_net_bootp_packet *) + &bootp_response + + bootp_response_properties[i].offset, + size - bootp_response_properties[i].offset, + 1, device, path); + return; + } +} + +static char * +find_alias (const char *fullname) +{ + char *ret = NULL; + auto int find_alias_hook (struct grub_ieee1275_devalias *alias); + + int find_alias_hook (struct grub_ieee1275_devalias *alias) + { + if (grub_strcmp (alias->path, fullname) == 0) + { + ret = grub_strdup (alias->name); + return 1; + } + return 0; + } + + grub_devalias_iterate (find_alias_hook); + grub_errno = GRUB_ERR_NONE; + return ret; } static void grub_ofnet_findcards (void) { - int i = 0; - auto int search_net_devices (struct grub_ieee1275_devalias *alias); int search_net_devices (struct grub_ieee1275_devalias *alias) @@ -155,6 +208,7 @@ grub_ofnet_findcards (void) struct grub_net_card *card; grub_ieee1275_phandle_t devhandle; grub_net_link_level_address_t lla; + char *shortname; ofdata = grub_malloc (sizeof (struct grub_ofnetcard_data)); if (!ofdata) @@ -162,7 +216,7 @@ grub_ofnet_findcards (void) grub_print_error (); return 1; } - card = grub_malloc (sizeof (struct grub_net_card)); + card = grub_zalloc (sizeof (struct grub_net_card)); if (!card) { grub_free (ofdata); @@ -177,11 +231,19 @@ grub_ofnet_findcards (void) if (grub_ieee1275_get_integer_property (devhandle, "max-frame-size", &(ofdata->mtu), sizeof (ofdata->mtu), 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mtu size."); + { + ofdata->mtu = 1500; + } - if (grub_ieee1275_get_property - (devhandle, "mac-address", &(lla.mac), 6, 0)) - return grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + if (grub_ieee1275_get_property (devhandle, "mac-address", + &(lla.mac), 6, 0) + && grub_ieee1275_get_property (devhandle, "local-mac-address", + &(lla.mac), 6, 0)) + { + grub_error (GRUB_ERR_IO, "Couldn't retrieve mac address."); + grub_print_error (); + return 0; + } lla.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; card->default_address = lla; @@ -189,7 +251,11 @@ grub_ofnet_findcards (void) card->driver = NULL; card->data = ofdata; card->flags = 0; - card->name = grub_xasprintf ("eth%d", i++); + shortname = find_alias (alias->path); + card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path); + grub_free (shortname); + + card->driver = &ofdriver; grub_net_card_register (card); return 0; } @@ -200,69 +266,18 @@ grub_ofnet_findcards (void) grub_ieee1275_devices_iterate (search_net_devices); } -static void -grub_ofnet_probecards (void) -{ - struct grub_net_card *card; - struct grub_net_card_driver *driver; - struct grub_net_network_level_interface *inter; - grub_bootp_t bootp_pckt; - grub_net_network_level_address_t addr; - grub_net_network_level_netaddress_t net; - bootp_pckt = grub_getbootp (); - - /* Assign correspondent driver for each device. */ - FOR_NET_CARDS (card) - { - FOR_NET_CARD_DRIVERS (driver) - { - if (driver->init (card) == GRUB_ERR_NONE) - { - card->driver = driver; - if (bootp_pckt - && grub_memcmp (bootp_pckt->chaddr, card->default_address.mac, 6) == 0) - { - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = bootp_pckt->yiaddr; - grub_net_add_addr ("bootp_cli_addr", card, addr, - card->default_address, 0); - FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, "bootp_cli_addr") == 0) - break; - net.type = addr.type; - net.ipv4.base = addr.ipv4; - net.ipv4.masksize = 24; - grub_net_add_route ("bootp-router", net, inter); - } - break; - } - } - } - grub_free (bootp_pckt); - -} - GRUB_MOD_INIT(ofnet) { - struct grub_net_card *card; - grub_getbootp = grub_getbootp_real; - grub_net_card_driver_register (&ofdriver); grub_ofnet_findcards (); - grub_ofnet_probecards (); - FOR_NET_CARDS (card) - if (card->driver == NULL) - grub_net_card_unregister (card); + grub_ieee1275_net_config = grub_ieee1275_net_config_real; } GRUB_MOD_FINI(ofnet) { - struct grub_net_card *card; - FOR_NET_CARDS (card) - if (card->driver && !grub_strcmp (card->driver->name, "ofnet")) - { - card->driver->fini (card); - card->driver = NULL; - } - grub_net_card_driver_unregister (&ofdriver); - grub_getbootp = NULL; + struct grub_net_card *card, *next; + + FOR_NET_CARDS_SAFE (card, next) + if (card->driver && grub_strcmp (card->driver->name, "ofnet") == 0) + grub_net_card_unregister (card); + grub_ieee1275_net_config = 0; } diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 175d0b65f..3006c9d93 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -25,7 +25,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_memcpy (eth->src, inf->hwaddress.mac, 6); eth->type = grub_cpu_to_be16 (ethertype); - + if (!inf->card->opened) + { + err = GRUB_ERR_NONE; + if (inf->card->driver->open) + err = inf->card->driver->open (inf->card); + if (err) + return err; + inf->card->opened = 1; + } return inf->card->driver->send (inf->card, nb); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 96bbd1712..a3b76cae0 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -30,6 +30,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -58,6 +59,7 @@ static struct grub_fs grub_net_fs; static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { + inter->card->num_ifaces--; *inter->prev = inter->next; if (inter->next) inter->next->prev = inter->prev; @@ -65,6 +67,24 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter inter->prev = 0; } +void +grub_net_card_unregister (struct grub_net_card *card) +{ + struct grub_net_network_level_interface *inf, *next; + FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(inf, next) + if (inf->card == card) + grub_net_network_level_interface_unregister (inf); + if (card->opened) + { + if (card->driver->close) + card->driver->close (card); + card->opened = 0; + } + grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), + GRUB_AS_LIST (card)); +} + + static inline void grub_net_route_register (struct grub_net_route *route) { @@ -336,6 +356,7 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa grub_register_variable_hook (name, 0, addr_set_env); } + inter->card->num_ifaces++; inter->prev = &grub_net_network_level_interfaces; inter->next = grub_net_network_level_interfaces; if (inter->next) @@ -345,7 +366,7 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa struct grub_net_network_level_interface * grub_net_add_addr (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags) @@ -714,6 +735,20 @@ grub_net_fs_close (grub_file_t file) static void receive_packets (struct grub_net_card *card) { + if (card->num_ifaces == 0) + return; + if (!card->opened) + { + grub_err_t err = GRUB_ERR_NONE; + if (card->driver->open) + err = card->driver->open (card); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return; + } + card->opened = 1; + } while (1) { /* Maybe should be better have a fixed number of packets for each card @@ -926,7 +961,7 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, grub_size_t size, @@ -1042,7 +1077,7 @@ grub_net_configure_by_dhcp_ack (const char *name, void grub_net_process_dhcp (struct grub_net_buff *nb, - const struct grub_net_card *card) + struct grub_net_card *card) { char *name; struct grub_net_network_level_interface *inf; @@ -1228,6 +1263,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), if (j) ifaces[j].prev = &ifaces[j-1].next; ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); + card->num_ifaces++; if (!ifaces[j].name) { unsigned i; @@ -1331,6 +1367,29 @@ static struct grub_fs grub_net_fs = .uuid = NULL, .mtime = NULL, }; + +static grub_err_t +grub_net_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + if (card->opened) + { + if (card->driver->close) + card->driver->close (card); + card->opened = 0; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_net_restore_hw (void) +{ + return GRUB_ERR_NONE; +} + +static void *fini_hnd; + static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp; static grub_command_t cmd_dhcp, cmd_lsaddr; @@ -1367,6 +1426,11 @@ GRUB_MOD_INIT(net) grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; + fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw, + grub_net_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + grub_net_fini_hw (0); + grub_loader_unregister_preboot_hook (fini_hnd); } GRUB_MOD_FINI(net) @@ -1381,4 +1445,5 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; + grub_loader_unregister_preboot_hook (fini_hnd); } diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h index 781b53df5..376a18962 100644 --- a/include/grub/i386/pc/pxe.h +++ b/include/grub/i386/pc/pxe.h @@ -287,8 +287,6 @@ int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entr extern struct grub_pxe_bangpxe *grub_pxe_pxenv; -void grub_pxe_unload (void); - #endif #endif /* GRUB_CPU_PXE_H */ diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 87294610d..81590ee4b 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -64,12 +64,9 @@ struct grub_ieee1275_common_hdr typedef grub_uint32_t grub_ieee1275_ihandle_t; typedef grub_uint32_t grub_ieee1275_phandle_t; -struct grub_ofnetcard_data -{ - char *path; - grub_ieee1275_ihandle_t handle; - grub_uint32_t mtu; -}; +extern void (*EXPORT_VAR(grub_ieee1275_net_config)) (const char *dev, + char **device, + char **path); /* Maps a device alias to a pathname. */ extern grub_ieee1275_phandle_t EXPORT_VAR(grub_ieee1275_chosen); @@ -203,5 +200,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) alias)); char *EXPORT_FUNC(grub_ieee1275_get_aliasdevname) (const char *path); char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path); +char *EXPORT_FUNC(grub_ieee1275_get_device_type) (const char *path); #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/include/grub/ieee1275/ofnet.h b/include/grub/ieee1275/ofnet.h deleted file mode 100644 index c7284df38..000000000 --- a/include/grub/ieee1275/ofnet.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2007 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 . - */ - -#ifndef GRUB_OFNET_HEADER -#define GRUB_OFNET_HEADER 1 - -#include -#include -#include - -struct grub_ofnet -{ - /* The net name. */ - const char *name; - - /* The OF device string. */ - char *dev; - /*server ip*/ - char *sip; - /*client ip*/ - char *cip; - /*gateway*/ - char *gat; - /**/ - int type; -}; - -typedef struct grub_ofnet *grub_ofnet_t; - -struct grub_bootp { - grub_uint8_t op; /* 1 = BOOTREQUEST, 2 = BOOTREPLY */ - grub_uint8_t htype; /* Hardware address type. */ - grub_uint8_t hlen; /* Hardware address length */ - grub_uint8_t hops; /* Used by gateways in cross-gateway booting. */ - grub_uint32_t xid; /* Transaction ID */ - grub_uint16_t secs; /* Seconds elapsed. */ - grub_uint16_t unused; /* Unused. */ - grub_uint32_t ciaddr; /* Client IP address, */ - grub_uint32_t yiaddr; /* Client IP address filled by server. */ - grub_uint32_t siaddr; /* Server IP address. */ - grub_uint32_t giaddr; /* Gateway IP address. */ - unsigned char chaddr [16]; /* Client hardware address */ - char sname [64]; /* Server name */ - char file [128]; /* Boot filename */ - unsigned char vend [64]; -}; - -typedef struct grub_bootp* grub_bootp_t; - -extern grub_bootp_t (*EXPORT_VAR (grub_getbootp)) (void); -#endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net.h b/include/grub/net.h index e9a3793db..85fdef365 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -60,6 +60,8 @@ struct grub_net_card_driver { struct grub_net_card_driver *next; char *name; + grub_err_t (*open) (const struct grub_net_card *dev); + void (*close) (const struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, struct grub_net_buff *buf); grub_ssize_t (*recv) (const struct grub_net_card *dev, @@ -87,6 +89,8 @@ struct grub_net_card struct grub_net_card_driver *driver; grub_net_link_level_address_t default_address; grub_net_card_flags_t flags; + int num_ifaces; + int opened; union { struct @@ -236,7 +240,7 @@ struct grub_net_network_level_interface struct grub_net_network_level_interface *next; struct grub_net_network_level_interface **prev; char *name; - const struct grub_net_card *card; + struct grub_net_card *card; grub_net_network_level_address_t address; grub_net_link_level_address_t hwaddress; grub_net_interface_flags_t flags; @@ -284,7 +288,7 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, struct grub_net_network_level_interface * grub_net_add_addr (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_network_level_address_t addr, grub_net_link_level_address_t hwaddress, grub_net_interface_flags_t flags); @@ -321,12 +325,8 @@ grub_net_card_register (struct grub_net_card *card) GRUB_AS_LIST (card)); } -static inline void -grub_net_card_unregister (struct grub_net_card *card) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), - GRUB_AS_LIST (card)); -} +void +grub_net_card_unregister (struct grub_net_card *card); #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) #define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next) @@ -390,7 +390,7 @@ struct grub_net_bootp_packet struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, - const struct grub_net_card *card, + struct grub_net_card *card, grub_net_interface_flags_t flags, const struct grub_net_bootp_packet *bp, grub_size_t size, @@ -398,7 +398,7 @@ grub_net_configure_by_dhcp_ack (const char *name, void grub_net_process_dhcp (struct grub_net_buff *nb, - const struct grub_net_card *card); + struct grub_net_card *card); int grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, @@ -418,6 +418,8 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next) + grub_err_t grub_net_send_link_layer (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t *target); From a07a81b33550ed050cbd70b18f8eb0d9177559fc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 20:24:20 +0200 Subject: [PATCH 264/673] CMOS support on sparc. * gentpl.py (cmos): Add powerpc and sparc. * grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on powerpc and sparc. * grub-core/lib/cmos_datetime.c (grub_get_datetime) [__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos. (grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to grub_set_datetime_cmos. * grub-core/lib/ieee1275/cmos.c: New file. * grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable. (find_rtc): Set no_ieee1275_rtc on error. (grub_get_datetime): Call grub_get_datetime_cmos on error. (grub_set_datetime): Call grub_set_datetime_cmos on error. * include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may fail. Move value to argument. All users updated (grub_cmos_write): Likewise. (grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten. (grub_cmos_write) [__powerpc__ || __sparc__]: Likewise. * include/grub/datetime.h [__powerpc__ || __sparc__]: Declare grub_get_datetime_cmos and grub_set_datetime_cmos. --- ChangeLog | 24 ++++++++++ gentpl.py | 4 +- grub-core/Makefile.core.def | 3 ++ grub-core/commands/i386/cmostest.c | 14 ++++-- grub-core/lib/cmos_datetime.c | 68 ++++++++++++++++++++------- grub-core/lib/ieee1275/cmos.c | 75 ++++++++++++++++++++++++++++++ grub-core/lib/ieee1275/datetime.c | 14 +++++- include/grub/cmos.h | 48 +++++++++++++++++-- include/grub/datetime.h | 7 +++ 9 files changed, 231 insertions(+), 26 deletions(-) create mode 100644 grub-core/lib/ieee1275/cmos.c diff --git a/ChangeLog b/ChangeLog index e091265d4..694a97972 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2011-07-05 Vladimir Serbinenko + + CMOS support on sparc. + + * gentpl.py (cmos): Add powerpc and sparc. + * grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on + powerpc and sparc. + * grub-core/lib/cmos_datetime.c (grub_get_datetime) + [__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos. + (grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to + grub_set_datetime_cmos. + * grub-core/lib/ieee1275/cmos.c: New file. + * grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable. + (find_rtc): Set no_ieee1275_rtc on error. + (grub_get_datetime): Call grub_get_datetime_cmos on error. + (grub_set_datetime): Call grub_set_datetime_cmos on error. + * include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may + fail. Move value to argument. All users updated + (grub_cmos_write): Likewise. + (grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten. + (grub_cmos_write) [__powerpc__ || __sparc__]: Likewise. + * include/grub/datetime.h [__powerpc__ || __sparc__]: Declare + grub_get_datetime_cmos and grub_set_datetime_cmos. + 2011-07-02 Grégoire Sutre * util/grub-mkconfig.in: Use @PACKAGE@ instead of hardcoded name when diff --git a/gentpl.py b/gentpl.py index 6e2df076b..31cde1e81 100644 --- a/gentpl.py +++ b/gentpl.py @@ -30,7 +30,9 @@ GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") # Groups based on hardware features -GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") +GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips", + "sparc64_ieee1275", "powerpc_ieee1275"] +GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"] GROUPS["usb"] = GROUPS["pci"] diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index fd69e9c22..16c940c61 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1192,6 +1192,9 @@ module = { efi = lib/efi/datetime.c; sparc64_ieee1275 = lib/ieee1275/datetime.c; powerpc_ieee1275 = lib/ieee1275/datetime.c; + sparc64_ieee1275 = lib/ieee1275/cmos.c; + powerpc_ieee1275 = lib/ieee1275/cmos.c; + mips_arc = lib/arc/datetime.c; enable = noemu; }; diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index c79bd0387..6439159bd 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -46,12 +46,17 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), { int byte, bit; grub_err_t err; + grub_uint8_t value; err = parse_args (argc, argv, &byte, &bit); if (err) return err; - if (grub_cmos_read (byte) & (1 << bit)) + err = grub_cmos_read (byte, &value); + if (err) + return err; + + if (value & (1 << bit)) return GRUB_ERR_NONE; return grub_error (GRUB_ERR_TEST_FAILURE, "false"); @@ -63,13 +68,16 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), { int byte, bit; grub_err_t err; + grub_uint8_t value; err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; + err = grub_cmos_read (byte, &value); if (err) return err; - grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit))); - return GRUB_ERR_NONE; + return grub_cmos_write (byte, value & (~(1 << bit))); } static grub_command_t cmd, cmd_clean; diff --git a/grub-core/lib/cmos_datetime.c b/grub-core/lib/cmos_datetime.c index 73c5a03c0..86cd91180 100644 --- a/grub-core/lib/cmos_datetime.c +++ b/grub-core/lib/cmos_datetime.c @@ -23,30 +23,44 @@ GRUB_MOD_LICENSE ("GPLv3+"); +#if !defined (__powerpc__) && !defined (__sparc__) +#define grub_get_datetime_cmos grub_get_datetime +#define grub_set_datetime_cmos grub_set_datetime +#endif + grub_err_t -grub_get_datetime (struct grub_datetime *datetime) +grub_get_datetime_cmos (struct grub_datetime *datetime) { int is_bcd, is_12hour; grub_uint8_t value, flag; + grub_err_t err; - flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B); + err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag); + if (err) + return err; is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY); - value = grub_cmos_read (GRUB_CMOS_INDEX_YEAR); + err = grub_cmos_read (GRUB_CMOS_INDEX_YEAR, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); datetime->year = value; datetime->year += (value < 80) ? 2000 : 1900; - value = grub_cmos_read (GRUB_CMOS_INDEX_MONTH); + err = grub_cmos_read (GRUB_CMOS_INDEX_MONTH, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); datetime->month = value; - value = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH); + err = grub_cmos_read (GRUB_CMOS_INDEX_DAY_OF_MONTH, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); @@ -54,7 +68,9 @@ grub_get_datetime (struct grub_datetime *datetime) is_12hour = ! (flag & GRUB_CMOS_STATUS_B_24HOUR); - value = grub_cmos_read (GRUB_CMOS_INDEX_HOUR); + err = grub_cmos_read (GRUB_CMOS_INDEX_HOUR, &value); + if (err) + return err; if (is_12hour) { is_12hour = (value & 0x80); @@ -71,13 +87,18 @@ grub_get_datetime (struct grub_datetime *datetime) datetime->hour = value; - value = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE); + err = grub_cmos_read (GRUB_CMOS_INDEX_MINUTE, &value); + if (err) + return err; + if (is_bcd) value = grub_bcd_to_num (value); datetime->minute = value; - value = grub_cmos_read (GRUB_CMOS_INDEX_SECOND); + err = grub_cmos_read (GRUB_CMOS_INDEX_SECOND, &value); + if (err) + return err; if (is_bcd) value = grub_bcd_to_num (value); @@ -87,12 +108,15 @@ grub_get_datetime (struct grub_datetime *datetime) } grub_err_t -grub_set_datetime (struct grub_datetime *datetime) +grub_set_datetime_cmos (struct grub_datetime *datetime) { int is_bcd, is_12hour; grub_uint8_t value, flag; + grub_err_t err; - flag = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B); + err = grub_cmos_read (GRUB_CMOS_INDEX_STATUS_B, &flag); + if (err) + return err; is_bcd = ! (flag & GRUB_CMOS_STATUS_B_BINARY); @@ -102,21 +126,27 @@ grub_set_datetime (struct grub_datetime *datetime) if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_YEAR, value); + if (err) + return err; value = datetime->month; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_MONTH, value); + if (err) + return err; value = datetime->day; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_DAY_OF_MONTH, value); + if (err) + return err; value = datetime->hour; @@ -138,21 +168,27 @@ grub_set_datetime (struct grub_datetime *datetime) if (is_12hour) value |= 0x80; - grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_HOUR, value); + if (err) + return err; value = datetime->minute; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_MINUTE, value); + if (err) + return err; value = datetime->second; if (is_bcd) value = grub_num_to_bcd (value); - grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value); + err = grub_cmos_write (GRUB_CMOS_INDEX_SECOND, value); + if (err) + return err; return 0; } diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c new file mode 100644 index 000000000..fa57db9e7 --- /dev/null +++ b/grub-core/lib/ieee1275/cmos.c @@ -0,0 +1,75 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include + +volatile grub_uint8_t *grub_cmos_port = 0; +grub_err_t +grub_cmos_find_port (void) +{ + auto int hook (struct grub_ieee1275_devalias *alias); + int hook (struct grub_ieee1275_devalias *alias) + { + grub_ieee1275_phandle_t dev; + grub_uint32_t addr[2]; + grub_ssize_t actual; + /* Enough to check if it's "m5819" */ + char compat[100]; + if (grub_ieee1275_finddevice (alias->path, &dev)) + return 0; + if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat), + 0)) + return 0; + if (grub_strcmp (compat, "m5819") != 0) + return 0; + if (grub_ieee1275_get_integer_property (dev, "address", + addr, sizeof (addr), &actual)) + return 0; + if (actual == 4) + { + grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0]; + return 1; + } + +#if GRUB_CPU_SIZEOF_VOID_P == 8 + if (actual == 8) + { + grub_cmos_port = (volatile grub_uint8_t *) + ((((grub_addr_t) addr[0]) << 32) | addr[1]); + return 1; + } +#else + if (actual == 8 && addr[0] == 0) + { + grub_cmos_port = (volatile grub_uint8_t *) addr[1]; + return 1; + } +#endif + return 0; + } + + grub_ieee1275_devices_iterate (hook); + if (!grub_cmos_port) + return grub_error (GRUB_ERR_IO, "no cmos found"); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c index 4105c639b..1947135fe 100644 --- a/grub-core/lib/ieee1275/datetime.c +++ b/grub-core/lib/ieee1275/datetime.c @@ -21,10 +21,14 @@ #include #include #include +#if defined (__powerpc__) || defined (__sparc__) +#include +#endif GRUB_MOD_LICENSE ("GPLv3+"); static char *rtc = 0; +static int no_ieee1275_rtc = 0; static void find_rtc (void) @@ -42,6 +46,8 @@ find_rtc (void) } grub_ieee1275_devices_iterate (hook); + if (!rtc) + no_ieee1275_rtc = 1; } grub_err_t @@ -64,10 +70,12 @@ grub_get_datetime (struct grub_datetime *datetime) int status; grub_ieee1275_ihandle_t ihandle; + if (no_ieee1275_rtc) + return grub_get_datetime_cmos (datetime); if (!rtc) find_rtc (); if (!rtc) - return grub_error (GRUB_ERR_IO, "no RTC found"); + return grub_get_datetime_cmos (datetime); status = grub_ieee1275_open (rtc, &ihandle); if (status == -1) @@ -114,10 +122,12 @@ grub_set_datetime (struct grub_datetime *datetime) int status; grub_ieee1275_ihandle_t ihandle; + if (no_ieee1275_rtc) + return grub_set_datetime_cmos (datetime); if (!rtc) find_rtc (); if (!rtc) - return grub_error (GRUB_ERR_IO, "no RTC found"); + return grub_set_datetime_cmos (datetime); status = grub_ieee1275_open (rtc, &ihandle); if (status == -1) diff --git a/include/grub/cmos.h b/include/grub/cmos.h index f508e3bf6..331513cd7 100644 --- a/include/grub/cmos.h +++ b/include/grub/cmos.h @@ -20,8 +20,10 @@ #define GRUB_CMOS_H 1 #include +#if !defined (__powerpc__) && !defined (__sparc__) #include #include +#endif #define GRUB_CMOS_INDEX_SECOND 0 #define GRUB_CMOS_INDEX_SECOND_ALARM 1 @@ -55,18 +57,56 @@ grub_num_to_bcd (grub_uint8_t a) return (((a / 10) << 4) + (a % 10)); } -static inline grub_uint8_t -grub_cmos_read (grub_uint8_t index) +#if !defined (__powerpc__) && !defined (__sparc__) +static inline grub_err_t +grub_cmos_read (grub_uint8_t index, grub_uint8_t *val) { grub_outb (index, GRUB_CMOS_ADDR_REG); - return grub_inb (GRUB_CMOS_DATA_REG); + *val = grub_inb (GRUB_CMOS_DATA_REG); + return GRUB_ERR_NONE; } -static inline void +static inline grub_err_t grub_cmos_write (grub_uint8_t index, grub_uint8_t value) { grub_outb (index, GRUB_CMOS_ADDR_REG); grub_outb (value, GRUB_CMOS_DATA_REG); + return GRUB_ERR_NONE; +} +#else +grub_err_t grub_cmos_find_port (void); +extern volatile grub_uint8_t *grub_cmos_port; + +static inline grub_err_t +grub_cmos_read (grub_uint8_t index, grub_uint8_t *val) +{ + if (!grub_cmos_port) + { + grub_err_t err; + err = grub_cmos_find_port (); + if (err) + return err; + } + grub_cmos_port[0] = index; + *val = grub_cmos_port[1]; + return GRUB_ERR_NONE; } +static inline grub_err_t +grub_cmos_write (grub_uint8_t index, grub_uint8_t val) +{ + if (!grub_cmos_port) + { + grub_err_t err; + err = grub_cmos_find_port (); + if (err) + return err; + } + grub_cmos_port[0] = index; + grub_cmos_port[1] = val; + return GRUB_ERR_NONE; +} + +#endif + #endif /* GRUB_CMOS_H */ diff --git a/include/grub/datetime.h b/include/grub/datetime.h index c20fc8c36..dea0f8ea9 100644 --- a/include/grub/datetime.h +++ b/include/grub/datetime.h @@ -125,4 +125,11 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) return 1; } +#if defined (__powerpc__) || defined (__sparc__) +grub_err_t +grub_get_datetime_cmos (struct grub_datetime *datetime); +grub_err_t +grub_set_datetime_cmos (struct grub_datetime *datetime); +#endif + #endif /* ! KERNEL_DATETIME_HEADER */ From d73459943924af0345797052934ab61417a5f84d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 21:00:01 +0200 Subject: [PATCH 265/673] MIPS qemu at_keyboard support. * gentpl.py (videoinkernel): Add qemu-mips. * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add necessary headers. * grub-core/Makefile.core.def (kernel): Add at_keyboard and layout. * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init new modules. * grub-core/term/at_keyboard.c (grub_keyboard_controller_init) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't consider original set. * grub-core/term/serial.c (grub_serial_register) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Make com0 explicitly active. --- ChangeLog | 14 +++++++++++++ gentpl.py | 2 +- grub-core/Makefile.am | 13 ++++++++++++ grub-core/Makefile.core.def | 2 ++ grub-core/kern/mips/qemu_mips/init.c | 20 ++++++++++++++++++ grub-core/term/at_keyboard.c | 4 ++-- grub-core/term/serial.c | 11 ++++++++++ include/grub/mips/qemu_mips/at_keyboard.h | 25 +++++++++++++++++++++++ 8 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 include/grub/mips/qemu_mips/at_keyboard.h diff --git a/ChangeLog b/ChangeLog index 694a97972..644a7cf6a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-07-05 Vladimir Serbinenko + + MIPS qemu at_keyboard support. + + * gentpl.py (videoinkernel): Add qemu-mips. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add necessary headers. + * grub-core/Makefile.core.def (kernel): Add at_keyboard and layout. + * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init new + modules. + * grub-core/term/at_keyboard.c (grub_keyboard_controller_init) + [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't consider original set. + * grub-core/term/serial.c (grub_serial_register) + [GRUB_MACHINE_MIPS_QEMU_MIPS]: Make com0 explicitly active. + 2011-07-05 Vladimir Serbinenko CMOS support on sparc. diff --git a/gentpl.py b/gentpl.py index 31cde1e81..e431293eb 100644 --- a/gentpl.py +++ b/gentpl.py @@ -37,7 +37,7 @@ GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"] GROUPS["usb"] = GROUPS["pci"] # If gfxterm is main output console integrate it into kernel -GROUPS["videoinkernel"] = ["mips_loongson"] +GROUPS["videoinkernel"] = ["mips_loongson", "mips_qemu_mips"] GROUPS["videomodules"] = GRUB_PLATFORMS[:]; for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index c3ecba9cf..28a143413 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -145,7 +145,20 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h endif if COND_mips_qemu_mips +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h endif if COND_mips_loongson diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 16c940c61..328f7186f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -162,6 +162,8 @@ kernel = { mips_qemu_mips = kern/mips/qemu_mips/init.c; mips_qemu_mips = term/ns8250.c; mips_qemu_mips = term/serial.c; + mips_qemu_mips = term/at_keyboard.c; + mips_qemu_mips = commands/keylayouts.c; mips_arc = kern/mips/arc/init.c; mips_arc = term/arc/console.c; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 2180b347a..2016aeb3d 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -12,6 +12,16 @@ extern void grub_serial_init (void); extern void grub_terminfo_init (void); +extern void grub_at_keyboard_init (void); +extern void grub_video_init (void); +extern void grub_bitmap_init (void); +extern void grub_font_init (void); +extern void grub_gfxterm_init (void); +extern void grub_at_keyboard_init (void); +extern void grub_serial_init (void); +extern void grub_terminfo_init (void); +extern void grub_keylayouts_init (void); +extern void grub_boot_init (void); void grub_machine_init (void) @@ -27,8 +37,18 @@ grub_machine_init (void) grub_install_get_time_ms (grub_rtc_get_time_ms); + grub_video_init (); + grub_bitmap_init (); + grub_font_init (); + grub_gfxterm_init (); + + grub_keylayouts_init (); + grub_at_keyboard_init (); + grub_terminfo_init (); grub_serial_init (); + + grub_boot_init (); } void diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index e86df6f35..b81e76230 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -259,7 +259,7 @@ grub_keyboard_controller_write (grub_uint8_t c) grub_outb (c, KEYBOARD_REG_DATA); } -#if !defined (GRUB_MACHINE_MIPS_LOONGSON) && !defined (GRUB_MACHINE_QEMU) +#if !defined (GRUB_MACHINE_MIPS_LOONGSON) && !defined (GRUB_MACHINE_QEMU) && !defined (GRUB_MACHINE_MIPS_QEMU_MIPS) static grub_uint8_t grub_keyboard_controller_read (void) @@ -569,7 +569,7 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus keyboard_controller_wait_until_ready (); grub_inb (KEYBOARD_REG_DATA); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) grub_keyboard_controller_orig = 0; grub_keyboard_orig_set = 2; #else diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index add112f4a..0381349a4 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -313,6 +313,17 @@ grub_serial_register (struct grub_serial_port *port) grub_term_register_input_inactive ("serial_*", in); grub_term_register_output_inactive ("serial_*", out); } +#elif defined (GRUB_MACHINE_MIPS_QEMU_MIPS) + if (grub_strcmp (port->name, "com0") == 0) + { + grub_term_register_input_active ("serial_*", in); + grub_term_register_output_active ("serial_*", out); + } + else + { + grub_term_register_input_inactive ("serial_*", in); + grub_term_register_output_inactive ("serial_*", out); + } #else grub_term_register_input ("serial_*", in); grub_term_register_output ("serial_*", out); diff --git a/include/grub/mips/qemu_mips/at_keyboard.h b/include/grub/mips/qemu_mips/at_keyboard.h new file mode 100644 index 000000000..37cc625d1 --- /dev/null +++ b/include/grub/mips/qemu_mips/at_keyboard.h @@ -0,0 +1,25 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 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 . + */ + +#ifndef GRUB_MACHINE_AT_KEYBOARD_HEADER +#define GRUB_MACHINE_AT_KEYBOARD_HEADER 1 + +#define KEYBOARD_REG_DATA 0xb4000060 +#define KEYBOARD_REG_STATUS 0xb4000064 + +#endif From 748ccabea1fe40d6240f1abaa5e0612920b366ea Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 21:42:36 +0200 Subject: [PATCH 266/673] MIPS qemu flash support. * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: Check magic. * grub-core/kern/mips/qemu_mips/init.c (probe_mem): New function. (grub_machine_init): Probe memory if its size isn't known. * util/grub-mkimage.c (image_targets): Add flash targets. (generate_image): Handle flash targets. --- ChangeLog | 11 +++++ grub-core/boot/mips/startup_raw.S | 16 ++++++- grub-core/kern/mips/qemu_mips/init.c | 28 ++++++++++- util/grub-mkimage.c | 69 +++++++++++++++++++++++++++- 4 files changed, 121 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 644a7cf6a..3772dc028 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-07-05 Vladimir Serbinenko + + MIPS qemu flash support. + + * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: Check + magic. + * grub-core/kern/mips/qemu_mips/init.c (probe_mem): New function. + (grub_machine_init): Probe memory if its size isn't known. + * util/grub-mkimage.c (image_targets): Add flash targets. + (generate_image): Handle flash targets. + 2011-07-05 Vladimir Serbinenko MIPS qemu at_keyboard support. diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index e6dfadaf9..4ecff5efd 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -54,8 +54,22 @@ codestart: /* Parse arguments. Has to be done before relocation. So need to do it in asm. */ #ifdef GRUB_MACHINE_MIPS_QEMU_MIPS + lui $t0, %hi (((16 << 20) - 264 + 4) | 0x80000000) + lw $t1, %lo (((16 << 20) - 264 + 4) | 0x80000000) ($t0) + + lui $t2, 0x1234 + ori $t2, 0x5678 + + bne $t1, $t2, 1f + nop + lui $t0, %hi (((16 << 20) - 264) | 0x80000000) - lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0) + b 2f + lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0) + +1: + li $s4, 0 +2: #endif #ifdef GRUB_MACHINE_MIPS_LOONGSON diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 2016aeb3d..0c3113fe2 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -23,11 +23,36 @@ extern void grub_terminfo_init (void); extern void grub_keylayouts_init (void); extern void grub_boot_init (void); +static inline int +probe_mem (grub_addr_t addr) +{ + volatile grub_uint8_t *ptr = (grub_uint8_t *) (0xa0000000 | addr); + grub_uint8_t c = *ptr; + *ptr = 0xAA; + if (*ptr != 0xAA) + return 0; + *ptr = 0x55; + if (*ptr != 0x55) + return 0; + *ptr = c; + return 1; +} + void grub_machine_init (void) { grub_addr_t modend; + if (grub_arch_memsize == 0) + { + int i; + + for (i = 27; i >= 0; i--) + if (probe_mem (grub_arch_memsize | (1 << i))) + grub_arch_memsize |= (1 << i); + grub_arch_memsize++; + } + /* FIXME: measure this. */ grub_arch_cpuclock = 64000000; @@ -40,7 +65,6 @@ grub_machine_init (void) grub_video_init (); grub_bitmap_init (); grub_font_init (); - grub_gfxterm_init (); grub_keylayouts_init (); grub_at_keyboard_init (); @@ -49,6 +73,8 @@ grub_machine_init (void) grub_serial_init (); grub_boot_init (); + + grub_gfxterm_init (); } void diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 9fc37df2b..002696d07 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -67,7 +67,8 @@ struct image_target_desc IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT, IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, - IMAGE_FULOONG_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC + IMAGE_FULOONG_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC, + IMAGE_QEMU_MIPS_FLASH } id; enum { @@ -466,6 +467,50 @@ struct image_target_desc image_targets[] = .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, .default_compression = COMPRESSION_NONE }, + { + .dirname = "mips-qemu_mips", + .names = { "mips-qemu_mips-flash", NULL }, + .voidp_sizeof = 4, + .bigendian = 1, + .id = IMAGE_QEMU_MIPS_FLASH, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, + .raw_size = 0, + .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, + .elf_target = EM_MIPS, + .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, + .default_compression = COMPRESSION_NONE + }, + { + .dirname = "mipsel-qemu_mips", + .names = { "mipsel-qemu_mips-flash", NULL }, + .voidp_sizeof = 4, + .bigendian = 0, + .id = IMAGE_QEMU_MIPS_FLASH, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, + .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, + .raw_size = 0, + .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, + .compressed_size = TARGET_NO_FIELD, + .kernel_image_size = TARGET_NO_FIELD, + .section_align = 1, + .vaddr_offset = 0, + .install_dos_part = TARGET_NO_FIELD, + .install_bsd_part = TARGET_NO_FIELD, + .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, + .elf_target = EM_MIPS, + .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, + .default_compression = COMPRESSION_NONE + }, { .dirname = "mips-qemu_mips", .names = { "mips-qemu_mips-elf", NULL }, @@ -1389,6 +1434,28 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], core_size = rom_size; } break; + case IMAGE_QEMU_MIPS_FLASH: + { + char *rom_img; + size_t rom_size; + + if (core_size > 512 * 1024) + grub_util_error ("firmware image is too big"); + rom_size = 512 * 1024; + + rom_img = xmalloc (rom_size); + memset (rom_img, 0, rom_size); + + memcpy (rom_img, core_img, core_size); + + memset (rom_img + core_size, 0, + rom_size - core_size); + + free (core_img); + core_img = rom_img; + core_size = rom_size; + } + break; case IMAGE_MIPS_ARC: { char *ecoff_img; From 93c06ff9c6490af246ce3620c11d5cc638903e7f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 5 Jul 2011 23:46:15 +0200 Subject: [PATCH 267/673] VGA text support in qemu-mips * grub-core/Makefile.core.def (kernel): Add term/i386/pc/vga_text.c, term/i386/vga_common.c and kern/vga_init.c on qemu-mips. * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init vga text. * grub-core/kern/i386/qemu/init.c: Renamed to ... * grub-core/kern/vga_init.c: ... this. * grub-core/kern/vga_init.c (VGA_ADDR) [__mips__]: Adjust. (grub_qemu_init_cirrus) [__mips__]: Skip PCI and adjust the I/O base. * grub-core/term/i386/pc/vga_text.c (VGA_TEXT_SCREEN) [__mips__]: Adjust. * include/grub/vga.h [GRUB_MACHINE_MIPS_QEMU_MIPS]: Declare GRUB_MACHINE_PCI_IO_BASE. --- ChangeLog | 17 ++++++++++++++ grub-core/Makefile.core.def | 5 +++- grub-core/kern/mips/qemu_mips/init.c | 5 ++++ .../kern/{i386/qemu/init.c => vga_init.c} | 23 +++++++++++++++---- grub-core/term/i386/pc/vga_text.c | 6 ++++- include/grub/mips/qemu_mips/kernel.h | 1 + include/grub/vga.h | 5 ++++ 7 files changed, 56 insertions(+), 6 deletions(-) rename grub-core/kern/{i386/qemu/init.c => vga_init.c} (90%) diff --git a/ChangeLog b/ChangeLog index 3772dc028..c2d386032 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-07-05 Vladimir Serbinenko + + VGA text support in qemu-mips + + * grub-core/Makefile.core.def (kernel): Add term/i386/pc/vga_text.c, + term/i386/vga_common.c and kern/vga_init.c on qemu-mips. + * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init vga + text. + * grub-core/kern/i386/qemu/init.c: Renamed to ... + * grub-core/kern/vga_init.c: ... this. + * grub-core/kern/vga_init.c (VGA_ADDR) [__mips__]: Adjust. + (grub_qemu_init_cirrus) [__mips__]: Skip PCI and adjust the I/O base. + * grub-core/term/i386/pc/vga_text.c (VGA_TEXT_SCREEN) [__mips__]: + Adjust. + * include/grub/vga.h [GRUB_MACHINE_MIPS_QEMU_MIPS]: Declare + GRUB_MACHINE_PCI_IO_BASE. + 2011-07-05 Vladimir Serbinenko MIPS qemu flash support. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 328f7186f..807f5b357 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -143,7 +143,7 @@ kernel = { i386_pc = term/i386/pc/console.c; i386_qemu = bus/pci.c; - i386_qemu = kern/i386/qemu/init.c; + i386_qemu = kern/vga_init.c; i386_qemu = kern/i386/qemu/mmap.c; i386_qemu = kern/i386/tsc.c; @@ -164,6 +164,9 @@ kernel = { mips_qemu_mips = term/serial.c; mips_qemu_mips = term/at_keyboard.c; mips_qemu_mips = commands/keylayouts.c; + mips_qemu_mips = term/i386/pc/vga_text.c; + mips_qemu_mips = term/i386/vga_common.c; + mips_qemu_mips = kern/vga_init.c; mips_arc = kern/mips/arc/init.c; mips_arc = term/arc/console.c; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 0c3113fe2..db9cc796a 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,7 @@ extern void grub_serial_init (void); extern void grub_terminfo_init (void); extern void grub_keylayouts_init (void); extern void grub_boot_init (void); +extern void grub_vga_text_init (void); static inline int probe_mem (grub_addr_t addr) @@ -69,6 +71,9 @@ grub_machine_init (void) grub_keylayouts_init (); grub_at_keyboard_init (); + grub_qemu_init_cirrus (); + grub_vga_text_init (); + grub_terminfo_init (); grub_serial_init (); diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/vga_init.c similarity index 90% rename from grub-core/kern/i386/qemu/init.c rename to grub-core/kern/vga_init.c index 054dfa86b..889d0128e 100644 --- a/grub-core/kern/i386/qemu/init.c +++ b/grub-core/kern/vga_init.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011 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 @@ -16,7 +16,9 @@ * along with GRUB. If not, see . */ +#ifndef __mips__ #include +#endif #include #include #include @@ -43,7 +45,17 @@ static struct {grub_uint8_t r, g, b, a; } colors[] = {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white }; +#ifdef __mips__ +extern unsigned char ascii_bitmaps[]; +#else #include +#endif + +#ifdef __mips__ +#define VGA_ADDR 0xb00a0000 +#else +#define VGA_ADDR 0xa0000 +#endif static void load_font (void) @@ -61,7 +73,7 @@ load_font (void) grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK); for (i = 0; i < 128; i++) - grub_memcpy ((void *) (0xa0000 + 32 * i), ascii_bitmaps + 16 * i, 16); + grub_memcpy ((void *) (VGA_ADDR + 32 * i), ascii_bitmaps + 16 * i, 16); } static void @@ -78,6 +90,7 @@ load_palette (void) 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))) { @@ -106,8 +119,10 @@ grub_qemu_init_cirrus (void) } grub_pci_iterate (find_card); +#endif - grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE); + grub_outb (GRUB_VGA_IO_MISC_COLOR, + GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_MISC_WRITE); load_font (); @@ -143,5 +158,5 @@ grub_qemu_init_cirrus (void) grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START); grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END); - grub_outb (0x20, 0x3c0); + grub_outb (0x20, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); } diff --git a/grub-core/term/i386/pc/vga_text.c b/grub-core/term/i386/pc/vga_text.c index 1816bfae2..9abffcc0a 100644 --- a/grub-core/term/i386/pc/vga_text.c +++ b/grub-core/term/i386/pc/vga_text.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include @@ -29,7 +29,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); static int grub_curr_x, grub_curr_y; +#ifdef __mips__ +#define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb00b8000) +#else #define VGA_TEXT_SCREEN ((grub_uint16_t *) 0xb8000) +#endif static void screen_write_char (int x, int y, short c) diff --git a/include/grub/mips/qemu_mips/kernel.h b/include/grub/mips/qemu_mips/kernel.h index c08405e83..66add4b2e 100644 --- a/include/grub/mips/qemu_mips/kernel.h +++ b/include/grub/mips/qemu_mips/kernel.h @@ -25,6 +25,7 @@ void EXPORT_FUNC (grub_reboot) (void); void EXPORT_FUNC (grub_halt) (void); +void grub_qemu_init_cirrus (void); #endif diff --git a/include/grub/vga.h b/include/grub/vga.h index bf4439599..58ec3ba15 100644 --- a/include/grub/vga.h +++ b/include/grub/vga.h @@ -19,7 +19,12 @@ #ifndef GRUB_VGA_HEADER #define GRUB_VGA_HEADER 1 +#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS #include +#else +#include +#define GRUB_MACHINE_PCI_IO_BASE 0xb4000000 +#endif enum { From 72b9ad936abf84dbcd4a55b31fe64d316d1bd62a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 02:49:04 +0200 Subject: [PATCH 268/673] fix declarations in pxe --- grub-core/net/drivers/i386/pc/pxe.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index aa10cbbfa..cd598ea72 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -260,15 +260,13 @@ grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), return 0; } -static grub_err_t +static void grub_pxe_close (const struct grub_net_card *dev __attribute__ ((unused))) { if (pxe_rm_entry) grub_pxe_call (GRUB_PXENV_UNDI_CLOSE, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, pxe_rm_entry); - - return GRUB_ERR_NONE; } static grub_err_t @@ -322,7 +320,6 @@ grub_pc_net_config_real (char **device, char **path) GRUB_MOD_INIT(pxe) { struct grub_pxe_bangpxe *pxenv; - struct grub_pxe_undi_open *ou; struct grub_pxe_undi_info *ui; unsigned i; From cf1337aa029a66e8936fa799dbf48d4feabf1f8f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 02:50:35 +0200 Subject: [PATCH 269/673] * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new grub_read_cmos prototype. --- ChangeLog | 5 +++++ grub-core/kern/i386/qemu/mmap.c | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index c2d386032..06b71a246 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-05 Vladimir Serbinenko + + * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new + grub_read_cmos prototype. + 2011-07-05 Vladimir Serbinenko VGA text support in qemu-mips diff --git a/grub-core/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c index 208f36b7e..2b0c7f6a7 100644 --- a/grub-core/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -41,8 +41,11 @@ static grub_uint64_t mem_size, above_4g; void grub_machine_mmap_init () { - mem_size = ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH)) << 24 - | ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW)) << 16; + grub_uint8_t high, low, b, c, d; + grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH, &high); + grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW, &low); + mem_size = ((grub_uint64_t) high) << 24 + | ((grub_uint64_t) low) << 16; if (mem_size > 0) { /* Don't ask... */ @@ -50,15 +53,19 @@ grub_machine_mmap_init () } else { + grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH, &high); + grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW, &low); mem_size - = ((((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH)) << 18) - | ((grub_uint64_t) (grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW)) << 10)) + = ((((grub_uint64_t) high) << 18) | (((grub_uint64_t) low) << 10)) + 1024 * 1024; } - above_4g = (((grub_uint64_t) grub_cmos_read (0x5b)) << 16) - | (((grub_uint64_t) grub_cmos_read (0x5c)) << 24) - | (((grub_uint64_t) grub_cmos_read (0x5d)) << 32); + grub_cmos_read (0x5b, &b); + grub_cmos_read (0x5c, &c); + grub_cmos_read (0x5d, &d); + above_4g = (((grub_uint64_t) b) << 16) + | (((grub_uint64_t) c) << 24) + | (((grub_uint64_t) d) << 32); } grub_err_t From b975df6348fdf7bb02d107dd4fff92965e5f9182 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 12:53:37 +0200 Subject: [PATCH 270/673] Send TFTP_ERROR on tftp premature close. Several cleanups --- grub-core/net/ethernet.c | 40 ++++++++++++ grub-core/net/ip.c | 46 +++++++++++++- grub-core/net/net.c | 1 + grub-core/net/tftp.c | 118 +++++++++++++++++++++++++++++++++++- include/grub/net.h | 34 +++-------- include/grub/net/device.h | 0 include/grub/net/ethernet.h | 41 ++++++------- include/grub/net/ip.h | 63 ++++++++++--------- include/grub/net/tftp.h | 68 --------------------- include/grub/net/udp.h | 4 +- 10 files changed, 262 insertions(+), 153 deletions(-) delete mode 100644 include/grub/net/device.h delete mode 100644 include/grub/net/tftp.h diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 3006c9d93..acd33bcf6 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #include #include #include @@ -8,6 +26,28 @@ #include #include +#define LLCADDRMASK 0x7f + +struct etherhdr +{ + grub_uint8_t dst[6]; + grub_uint8_t src[6]; + grub_uint16_t type; +} __attribute__ ((packed)); + +struct llchdr +{ + grub_uint8_t dsap; + grub_uint8_t ssap; + grub_uint8_t ctrl; +} __attribute__ ((packed)); + +struct snaphdr +{ + grub_uint8_t oui[3]; + grub_uint16_t type; +} __attribute__ ((packed)); + grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 8b06f7d11..642a67f18 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #include #include #include @@ -7,8 +25,32 @@ #include #include +struct iphdr { + grub_uint8_t verhdrlen; + grub_uint8_t service; + grub_uint16_t len; + grub_uint16_t ident; + grub_uint16_t frags; + grub_uint8_t ttl; + grub_uint8_t protocol; + grub_uint16_t chksum; + grub_uint32_t src; + grub_uint32_t dest; +} __attribute__ ((packed)) ; + +struct ip6hdr +{ + grub_uint8_t version:4, priority:4; + grub_uint8_t flow_lbl[3]; + grub_uint16_t payload_len; + grub_uint8_t nexthdr; + grub_uint8_t hop_limit; + grub_uint8_t saddr[16]; + grub_uint8_t daddr[16]; +} __attribute__ ((packed)); + grub_uint16_t -ipchksum (void *ipv, int len) +grub_net_ip_chksum (void *ipv, int len) { grub_uint16_t *ip = (grub_uint16_t *) ipv; grub_uint32_t sum = 0; @@ -48,7 +90,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, iph->dest = target->ipv4; iph->chksum = 0; - iph->chksum = ipchksum ((void *) nb->data, sizeof (*iph)); + iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph)); /* Determine link layer target address via ARP. */ err = grub_net_arp_resolve (inf, target, &ll_target_addr); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index a3b76cae0..0d664d9b5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 6ffe27669..be1534021 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -1,5 +1,22 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #include -#include #include #include #include @@ -11,6 +28,74 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* IP port for the MTFTP server used for Intel's PXE */ +enum + { + MTFTP_SERVER_PORT = 75, + MTFTP_CLIENT_PORT = 76, + /* IP port for the TFTP server */ + TFTP_SERVER_PORT = 69 + }; + +enum + { + TFTP_DEFAULTSIZE_PACKET = 512, + TFTP_MAX_PACKET = 1432 + }; + +enum + { + TFTP_CODE_EOF = 1, + TFTP_CODE_MORE = 2, + TFTP_CODE_ERROR = 3, + TFTP_CODE_BOOT = 4, + TFTP_CODE_CFG = 5 + }; + +enum + { + TFTP_RRQ = 1, + TFTP_WRQ = 2, + TFTP_DATA = 3, + TFTP_ACK = 4, + TFTP_ERROR = 5, + TFTP_OACK = 6 + }; + +enum + { + TFTP_EUNDEF = 0, /* not defined */ + TFTP_ENOTFOUND = 1, /* file not found */ + TFTP_EACCESS = 2, /* access violation */ + TFTP_ENOSPACE = 3, /* disk full or allocation exceeded */ + TFTP_EBADOP = 4, /* illegal TFTP operation */ + TFTP_EBADID = 5, /* unknown transfer ID */ + TFTP_EEXISTS = 6, /* file already exists */ + TFTP_ENOUSER = 7 /* no such user */ + }; + +struct tftphdr { + grub_uint16_t opcode; + union { + grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; + struct { + grub_uint16_t block; + grub_int8_t download[TFTP_MAX_PACKET]; + } data; + struct { + grub_uint16_t block; + } ack; + struct { + grub_uint16_t errcode; + grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; + } err; + struct { + grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2]; + } oack; + } u; +} __attribute__ ((packed)) ; + + typedef struct tftp_data { grub_uint64_t file_size; @@ -40,7 +125,7 @@ tftp_receive (grub_net_socket_t sock __attribute__ ((unused)), switch (grub_be_to_cpu16 (tftph->opcode)) { case TFTP_OACK: - data->block_size = 512; + data->block_size = TFTP_DEFAULTSIZE_PACKET; data->have_oack = 1; for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { @@ -224,8 +309,35 @@ static grub_err_t tftp_close (struct grub_file *file) { tftp_data_t data = file->data; + if (data->sock) - grub_net_udp_close (data->sock); + { + char nbdata[512]; + grub_err_t err; + struct grub_net_buff nb_err; + struct tftphdr *tftph; + + nb_err.head = nbdata; + nb_err.end = nbdata + sizeof (nbdata); + + grub_netbuff_clear (&nb_err); + grub_netbuff_reserve (&nb_err, 512); + err = grub_netbuff_push (&nb_err, sizeof (tftph->opcode) + + sizeof (tftph->u.err.errcode) + + sizeof ("closed")); + if (!err) + { + tftph = (struct tftphdr *) nb_err.data; + tftph->opcode = grub_cpu_to_be16 (TFTP_ERROR); + tftph->u.err.errcode = grub_cpu_to_be16 (TFTP_EUNDEF); + grub_memcpy (tftph->u.err.errmsg, "closed", sizeof ("closed")); + + err = grub_net_send_udp_packet (data->sock, &nb_err); + } + if (err) + grub_print_error (); + grub_net_udp_close (data->sock); + } grub_free (data); return GRUB_ERR_NONE; } diff --git a/include/grub/net.h b/include/grub/net.h index 85fdef365..0ac0838cf 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011 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 @@ -82,6 +82,10 @@ typedef struct grub_net_packets grub_net_packet_t *last; } grub_net_packets_t; +#ifdef GRUB_MACHINE_EFI +#include +#endif + struct grub_net_card { struct grub_net_card *next; @@ -93,11 +97,13 @@ struct grub_net_card int opened; union { +#ifdef GRUB_MACHINE_EFI struct { struct grub_efi_simple_network *efi_net; - void *efi_handle; + grub_efi_handle_t efi_handle; }; +#endif void *data; int data_num; }; @@ -420,30 +426,6 @@ extern struct grub_net_network_level_interface *grub_net_network_level_interface #define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next) -grub_err_t grub_net_send_link_layer (struct grub_net_network_level_interface *inf, - struct grub_net_buff *nb, - grub_net_link_level_address_t *target); - -typedef int -(*grub_net_packet_handler_t) (struct grub_net_buff *nb, - struct grub_net_network_level_interface *inf); - -grub_err_t grub_net_recv_link_layer (struct grub_net_network_level_interface *inf, - grub_net_packet_handler_t handler); - - -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb, - const struct grub_net_card *card, - const grub_net_link_level_address_t *hwaddress); - -grub_err_t -grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *target, - struct grub_net_buff *nb); - -#define FOR_NET_NL_PACKETS(inf, var) FOR_PACKETS(inf->nl_pending, var) - void grub_net_poll_cards (unsigned time); diff --git a/include/grub/net/device.h b/include/grub/net/device.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index a841dc12c..a68aafd96 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -1,30 +1,26 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #ifndef GRUB_NET_ETHERNET_HEADER #define GRUB_NET_ETHERNET_HEADER 1 #include #include -#define LLCADDRMASK 0x7f - -struct etherhdr -{ - grub_uint8_t dst[6]; - grub_uint8_t src[6]; - grub_uint16_t type; -} __attribute__ ((packed)); - -struct llchdr -{ - grub_uint8_t dsap; - grub_uint8_t ssap; - grub_uint8_t ctrl; -} __attribute__ ((packed)); - -struct snaphdr -{ - grub_uint8_t oui[3]; - grub_uint16_t type; -} __attribute__ ((packed)); - /* IANA Ethertype */ enum { @@ -32,7 +28,6 @@ enum GRUB_NET_ETHERTYPE_ARP = 0x0806 }; - grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index cb8481a7d..9bed1e19c 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -1,35 +1,42 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #ifndef GRUB_NET_IP_HEADER #define GRUB_NET_IP_HEADER 1 #include +#include -struct iphdr { - grub_uint8_t verhdrlen; - grub_uint8_t service; - grub_uint16_t len; - grub_uint16_t ident; - grub_uint16_t frags; - grub_uint8_t ttl; - grub_uint8_t protocol; - grub_uint16_t chksum; - grub_uint32_t src; - grub_uint32_t dest; -} __attribute__ ((packed)) ; - -struct ip6hdr -{ - grub_uint8_t version:4, priority:4; - grub_uint8_t flow_lbl[3]; - grub_uint16_t payload_len; - grub_uint8_t nexthdr; - grub_uint8_t hop_limit; - grub_uint8_t saddr[16]; - grub_uint8_t daddr[16]; -} __attribute__ ((packed)); - -#define IP_UDP 0x11 /* UDP protocol */ +enum + { + IP_UDP = 0x11 /* UDP protocol */ + }; #define IP_BROADCAST 0xFFFFFFFF -grub_uint16_t ipchksum(void *ipv, int len); -void ipv4_ini(void); -void ipv4_fini(void); +grub_uint16_t grub_net_ip_chksum(void *ipv, int len); + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff *nb, + const struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress); + +grub_err_t +grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + struct grub_net_buff *nb); + #endif diff --git a/include/grub/net/tftp.h b/include/grub/net/tftp.h deleted file mode 100644 index 0d8cbd1de..000000000 --- a/include/grub/net/tftp.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef GRUB_NET_TFTP_HEADER -#define GRUB_NET_TFTP_HEADER 1 - -#include -#include -#include - -/* IP port for the MTFTP server used for Intel's PXE */ -#define MTFTP_SERVER_PORT 75 -#define MTFTP_CLIENT_PORT 76 - -#define TFTP_DEFAULTSIZE_PACKET 512 -#define TFTP_MAX_PACKET 1432 - -/* IP port for the TFTP server */ -#define TFTP_SERVER_PORT 69 - - -/* We define these based on what's in arpa/tftp.h. We just like our - * names better, cause they're clearer */ -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 -#define TFTP_OACK 6 - -#define TFTP_CODE_EOF 1 -#define TFTP_CODE_MORE 2 -#define TFTP_CODE_ERROR 3 -#define TFTP_CODE_BOOT 4 -#define TFTP_CODE_CFG 5 - -#define TFTP_EUNDEF 0 /* not defined */ -#define TFTP_ENOTFOUND 1 /* file not found */ -#define TFTP_EACCESS 2 /* access violation */ -#define TFTP_ENOSPACE 3 /* disk full or allocation exceeded */ -#define TFTP_EBADOP 4 /* illegal TFTP operation */ -#define TFTP_EBADID 5 /* unknown transfer ID */ -#define TFTP_EEXISTS 6 /* file already exists */ -#define TFTP_ENOUSER 7 /* no such user */ - - /* * own here because this is cleaner, and maps to the same data layout. - * */ - - -struct tftphdr { - grub_uint16_t opcode; - union { - grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; - struct { - grub_uint16_t block; - grub_int8_t download[TFTP_MAX_PACKET]; - } data; - struct { - grub_uint16_t block; - } ack; - struct { - grub_uint16_t errcode; - grub_int8_t errmsg[TFTP_DEFAULTSIZE_PACKET]; - } err; - struct { - grub_int8_t data[TFTP_DEFAULTSIZE_PACKET+2]; - } oack; - } u; -} __attribute__ ((packed)) ; - -#endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index 272612299..5aacf8abb 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -28,13 +28,11 @@ grub_net_udp_close (grub_net_socket_t sock) } grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket , struct grub_net_buff *nb); +grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb); grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf); -#define FOR_NET_UDP_PACKETS(inf, var) FOR_PACKETS(inf->udp_pending, var) - #endif From 1c3fcdee151a95730444352b2fb5774bfdd75ce6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 13:13:45 +0200 Subject: [PATCH 271/673] buffer network files. Fix incorrect net_fini_hw and unregister calls --- grub-core/net/net.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 0d664d9b5..1f2e2b7d4 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -32,6 +32,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -709,15 +710,36 @@ grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)) } static grub_err_t -grub_net_fs_open (struct grub_file *file, const char *name) +grub_net_fs_open (struct grub_file *file_out, const char *name) { + grub_err_t err; + struct grub_file *file, *bufio; + + file = grub_malloc (sizeof (*file)); + if (!file) + return grub_errno; + + grub_memcpy (file, file_out, sizeof (struct grub_file)); file->device->net->packs.first = NULL; file->device->net->packs.last = NULL; file->device->net->name = grub_strdup (name); if (!file->device->net->name) return grub_errno; - return file->device->net->protocol->open (file, name); + err = file->device->net->protocol->open (file, name); + if (err) + return err; + bufio = grub_bufio_open (file, 32768); + if (! bufio) + { + file->device->net->protocol->close (file); + grub_free (file->device->net->name); + grub_free (file); + return grub_errno; + } + + grub_memcpy (file_out, bufio, sizeof (struct grub_file)); + return GRUB_ERR_NONE; } static grub_err_t @@ -1430,8 +1452,6 @@ GRUB_MOD_INIT(net) fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw, grub_net_restore_hw, GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); - grub_net_fini_hw (0); - grub_loader_unregister_preboot_hook (fini_hnd); } GRUB_MOD_FINI(net) @@ -1446,5 +1466,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; + grub_net_fini_hw (0); grub_loader_unregister_preboot_hook (fini_hnd); } From 228ccedb5e7870931b628da5f1f758be65dac623 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 13:37:33 +0200 Subject: [PATCH 272/673] poll cards when idle --- grub-core/kern/term.c | 4 ++++ grub-core/net/net.c | 11 +++++++++++ include/grub/kernel.h | 3 +++ 3 files changed, 18 insertions(+) diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 7b3593161..d7c65dd82 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -29,6 +29,7 @@ struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; void (*grub_term_poll_usb) (void) = NULL; +void (*grub_net_poll_cards_idle) (void) = NULL; /* Put a Unicode character. */ static void @@ -91,6 +92,9 @@ grub_checkkey (void) if (grub_term_poll_usb) grub_term_poll_usb (); + if (grub_net_poll_cards_idle) + grub_net_poll_cards_idle (); + FOR_ACTIVE_TERM_INPUTS(term) { pending_key = term->getkey (term); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1f2e2b7d4..bee4f8321 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -33,6 +33,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -809,6 +810,14 @@ grub_net_poll_cards (unsigned time) } } +static void +grub_net_poll_cards_idle_real (void) +{ + struct grub_net_card *card; + FOR_NET_CARDS (card) + receive_packets (card); +} + /* Read from the packets list*/ static grub_ssize_t grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) @@ -1452,6 +1461,7 @@ GRUB_MOD_INIT(net) fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw, grub_net_restore_hw, GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; } GRUB_MOD_FINI(net) @@ -1468,4 +1478,5 @@ GRUB_MOD_FINI(net) grub_net_open = NULL; grub_net_fini_hw (0); grub_loader_unregister_preboot_hook (fini_hnd); + grub_net_poll_cards_idle = grub_net_poll_cards_idle_real; } diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 6a5f91c3d..aef585668 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -90,6 +90,9 @@ grub_machine_get_bootlocation (char **device, char **path); /* Register all the exported symbols. This is automatically generated. */ void grub_register_exported_symbols (void); +extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void); + + #if ! defined (ASM_FILE) extern char grub_prefix[]; #endif From 138eeb3625b22b9b5b286813088d8edca09ff2af Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 13:52:35 +0200 Subject: [PATCH 273/673] Move bootp into a separate file --- grub-core/Makefile.core.def | 1 + grub-core/net/net.c | 514 +----------------------------------- include/grub/net.h | 16 ++ 3 files changed, 24 insertions(+), 507 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index d1e1d30e4..7bceaa98f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1579,6 +1579,7 @@ module = { module = { name = net; common = net/net.c; + common = net/bootp.c; common = net/ip.c; common = net/udp.c; common = net/ethernet.c; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index bee4f8321..bc16fbde5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -16,10 +16,8 @@ * along with GRUB. If not, see . */ -#include #include #include -#include #include #include #include @@ -28,16 +26,14 @@ #include #include #include -#include #include -#include #include #include #include GRUB_MOD_LICENSE ("GPLv3+"); -static char *default_server; +char *grub_net_default_server; struct grub_net_route { @@ -59,17 +55,6 @@ struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static struct grub_fs grub_net_fs; -static inline void -grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) -{ - inter->card->num_ifaces--; - *inter->prev = inter->next; - if (inter->next) - inter->next->prev = inter->prev; - inter->next = 0; - inter->prev = 0; -} - void grub_net_card_unregister (struct grub_net_card *card) { @@ -644,7 +629,7 @@ grub_net_open_real (const char *name) { protname = "tftp"; protnamelen = sizeof ("tftp") - 1; - server = default_server; + server = grub_net_default_server; } else { @@ -659,7 +644,7 @@ grub_net_open_real (const char *name) else { protnamelen = grub_strlen (name); - server = default_server; + server = grub_net_default_server; protname = name; } } @@ -911,483 +896,6 @@ grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len) return grub_net_fs_read_real (file, buf, len); } -static char * -grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), - const char *val __attribute__ ((unused))) -{ - return NULL; -} - -static void -set_env_limn_ro (const char *intername, const char *suffix, - char *value, grub_size_t len) -{ - char c; - char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_") - + grub_strlen (suffix)]; - grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix); - c = value[len]; - value[len] = 0; - grub_env_set (varname, value); - value[len] = c; - grub_register_variable_hook (varname, 0, grub_env_write_readonly); -} - -static void -parse_dhcp_vendor (const char *name, void *vend, int limit) -{ - grub_uint8_t *ptr, *ptr0; - - ptr = ptr0 = vend; - - if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 - || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 - || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 - || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) - return; - ptr = ptr + sizeof (grub_uint32_t); - while (ptr - ptr0 < limit) - { - grub_uint8_t tagtype; - grub_uint8_t taglength; - - tagtype = *ptr++; - - /* Pad tag. */ - if (tagtype == 0) - continue; - - /* End tag. */ - if (tagtype == 0xff) - return; - - taglength = *ptr++; - - switch (tagtype) - { - case 12: - set_env_limn_ro (name, "hostname", (char *) ptr, taglength); - break; - - case 15: - set_env_limn_ro (name, "domain", (char *) ptr, taglength); - break; - - case 17: - set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); - break; - - case 18: - set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); - break; - - /* If you need any other options please contact GRUB - developpement team. */ - } - - ptr += taglength; - } -} - -#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) - -struct grub_net_network_level_interface * -grub_net_configure_by_dhcp_ack (const char *name, - struct grub_net_card *card, - grub_net_interface_flags_t flags, - const struct grub_net_bootp_packet *bp, - grub_size_t size, - int is_def, char **device, char **path) -{ - grub_net_network_level_address_t addr; - grub_net_link_level_address_t hwaddr; - struct grub_net_network_level_interface *inter; - - addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - addr.ipv4 = bp->your_ip; - - if (device) - *device = 0; - if (path) - *path = 0; - - grub_memcpy (hwaddr.mac, bp->mac_addr, - bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len - : sizeof (hwaddr.mac)); - hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - - inter = grub_net_add_addr (name, card, addr, hwaddr, flags); - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - char rname[grub_strlen (name) + sizeof ("_gw")]; - - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = bp->gateway_ip; - grub_snprintf (rname, sizeof (rname), "%s_gw", name); - grub_net_add_route_gw (rname, target, gw); - } - { - grub_net_network_level_netaddress_t target; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->gateway_ip; - target.ipv4.masksize = 32; - grub_net_add_route (name, target, inter); - } - - if (size > OFFSET_OF (boot_file, bp)) - set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, - sizeof (bp->boot_file)); - if (is_def) - default_server = 0; - if (size > OFFSET_OF (server_name, bp) - && bp->server_name[0]) - { - set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, - sizeof (bp->server_name)); - if (is_def && !default_server) - { - default_server = grub_strdup (bp->server_name); - grub_print_error (); - } - if (device && !*device) - { - *device = grub_xasprintf ("tftp,%s", bp->server_name); - grub_print_error (); - } - } - if (is_def && !default_server) - { - default_server = grub_xasprintf ("%d.%d.%d.%d", - ((grub_uint8_t *) &bp->server_ip)[0], - ((grub_uint8_t *) &bp->server_ip)[1], - ((grub_uint8_t *) &bp->server_ip)[2], - ((grub_uint8_t *) &bp->server_ip)[3]); - grub_print_error (); - } - - if (device && !*device) - { - *device = grub_xasprintf ("tftp,%d.%d.%d.%d", - ((grub_uint8_t *) &bp->server_ip)[0], - ((grub_uint8_t *) &bp->server_ip)[1], - ((grub_uint8_t *) &bp->server_ip)[2], - ((grub_uint8_t *) &bp->server_ip)[3]); - grub_print_error (); - } - if (size > OFFSET_OF (boot_file, bp) && path) - { - *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); - grub_print_error (); - if (*path) - { - char *slash; - slash = grub_strrchr (*path, '/'); - if (slash) - *slash = 0; - else - **path = 0; - } - } - if (size > OFFSET_OF (vendor, bp)) - parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); - - inter->dhcp_ack = grub_malloc (size); - if (inter->dhcp_ack) - { - grub_memcpy (inter->dhcp_ack, bp, size); - inter->dhcp_acklen = size; - } - else - grub_errno = GRUB_ERR_NONE; - - return inter; -} - -void -grub_net_process_dhcp (struct grub_net_buff *nb, - struct grub_net_card *card) -{ - char *name; - struct grub_net_network_level_interface *inf; - - name = grub_xasprintf ("%s:dhcp", card->name); - if (!name) - { - grub_print_error (); - return; - } - grub_net_configure_by_dhcp_ack (name, card, - 0, (const struct grub_net_bootp_packet *) nb->data, - (nb->tail - nb->data), 0, 0, 0); - grub_free (name); - if (grub_errno) - grub_print_error (); - else - { - FOR_NET_NETWORK_LEVEL_INTERFACES(inf) - if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0 - && grub_memcmp (inf->name + grub_strlen (card->name), - ":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0) - { - grub_net_network_level_interface_unregister (inf); - break; - } - } -} - -static char -hexdigit (grub_uint8_t val) -{ - if (val < 10) - return val + '0'; - return val + 'a' - 10; -} - -static grub_err_t -grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -{ - struct grub_net_network_level_interface *inter; - int num; - grub_uint8_t *ptr; - grub_uint8_t taglength; - - if (argc < 4) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); - - FOR_NET_NETWORK_LEVEL_INTERFACES (inter) - if (grub_strcmp (inter->name, args[1]) == 0) - break; - - if (!inter) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("unrecognised interface %s"), args[1]); - - if (!inter->dhcp_ack) - return grub_error (GRUB_ERR_IO, N_("no DHCP info found")); - - if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack)) - return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); - - num = grub_strtoul (args[2], 0, 0); - if (grub_errno) - return grub_errno; - - ptr = inter->dhcp_ack->vendor; - - if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 - || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 - || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 - || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) - return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); - ptr = ptr + sizeof (grub_uint32_t); - while (1) - { - grub_uint8_t tagtype; - - if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen) - return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); - - tagtype = *ptr++; - - /* Pad tag. */ - if (tagtype == 0) - continue; - - /* End tag. */ - if (tagtype == 0xff) - return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); - - taglength = *ptr++; - - if (tagtype == num) - break; - ptr += taglength; - } - - if (grub_strcmp (args[3], "string") == 0) - { - char *val = grub_malloc (taglength + 1); - if (!val) - return grub_errno; - grub_memcpy (val, ptr, taglength); - val[taglength] = 0; - if (args[0][0] == '-' && args[0][1] == 0) - grub_printf ("%s\n", val); - else - return grub_env_set (args[0], val); - return GRUB_ERR_NONE; - } - - if (grub_strcmp (args[3], "number") == 0) - { - grub_uint64_t val = 0; - int i; - for (i = 0; i < taglength; i++) - val = (val << 8) | ptr[i]; - if (args[0][0] == '-' && args[0][1] == 0) - grub_printf ("%llu\n", (unsigned long long) val); - else - { - char valn[64]; - grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val); - return grub_env_set (args[0], valn); - } - return GRUB_ERR_NONE; - } - - if (grub_strcmp (args[3], "hex") == 0) - { - char *val = grub_malloc (2 * taglength + 1); - int i; - if (!val) - return grub_errno; - for (i = 0; i < taglength; i++) - { - val[2 * i] = hexdigit (ptr[i] >> 4); - val[2 * i + 1] = hexdigit (ptr[i] & 0xf); - } - val[2 * taglength] = 0; - if (args[0][0] == '-' && args[0][1] == 0) - grub_printf ("%s\n", val); - else - return grub_env_set (args[0], val); - return GRUB_ERR_NONE; - } - - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "unrecognised format specification %s", args[3]); -} - -static grub_err_t -grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -{ - struct grub_net_card *card; - struct grub_net_network_level_interface *ifaces; - grub_size_t ncards = 0; - unsigned j = 0; - int interval; - grub_err_t err; - - FOR_NET_CARDS (card) - { - if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) - continue; - ncards++; - } - - ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); - if (!ifaces) - return grub_errno; - - j = 0; - FOR_NET_CARDS (card) - { - if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) - continue; - ifaces[j].card = card; - ifaces[j].next = &ifaces[j+1]; - if (j) - ifaces[j].prev = &ifaces[j-1].next; - ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); - card->num_ifaces++; - if (!ifaces[j].name) - { - unsigned i; - for (i = 0; i < j; i++) - grub_free (ifaces[i].name); - grub_free (ifaces); - return grub_errno; - } - ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV; - grub_memcpy (&ifaces[j].hwaddress, &card->default_address, - sizeof (ifaces[j].hwaddress)); - j++; - } - ifaces[ncards - 1].next = grub_net_network_level_interfaces; - if (grub_net_network_level_interfaces) - grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next; - grub_net_network_level_interfaces = &ifaces[0]; - ifaces[0].prev = &grub_net_network_level_interfaces; - for (interval = 200; interval < 10000; interval *= 2) - { - int done = 0; - for (j = 0; j < ncards; j++) - { - struct grub_net_bootp_packet *pack; - struct grub_datetime date; - grub_int32_t t; - struct grub_net_buff *nb; - struct udphdr *udph; - grub_net_network_level_address_t target; - - if (!ifaces[j].prev) - continue; - nb = grub_netbuff_alloc (sizeof (*pack)); - if (!nb) - return grub_errno; - err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); - if (err) - return err; - err = grub_netbuff_push (nb, sizeof (*pack) + 64); - if (err) - return err; - pack = (void *) nb->data; - done = 1; - grub_memset (pack, 0, sizeof (*pack) + 64); - pack->opcode = 1; - pack->hw_type = 1; - pack->hw_len = 6; - err = grub_get_datetime (&date); - if (err || !grub_datetime2unixtime (&date, &t)) - { - grub_errno = GRUB_ERR_NONE; - t = 0; - } - pack->ident = grub_cpu_to_be32 (t); - pack->seconds = 0;//grub_cpu_to_be16 (t); - - grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); - - grub_netbuff_push (nb, sizeof (*udph)); - - udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (68); - udph->dst = grub_cpu_to_be16 (67); - udph->chksum = 0; - udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4 = 0xffffffff; - - err = grub_net_send_ip_packet (&ifaces[j], &target, nb); - if (err) - return err; - } - if (!done) - break; - grub_net_poll_cards (interval); - } - - err = GRUB_ERR_NONE; - for (j = 0; j < ncards; j++) - { - if (!ifaces[j].prev) - continue; - grub_error_push (); - grub_net_network_level_interface_unregister (&ifaces[j]); - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", - ifaces[j].card->name); - } - - return err; -} - static struct grub_fs grub_net_fs = { .name = "netfs", @@ -1423,8 +931,8 @@ grub_net_restore_hw (void) static void *fini_hnd; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; -static grub_command_t cmd_lsroutes, cmd_lscards, cmd_getdhcp, cmd_bootp; -static grub_command_t cmd_dhcp, cmd_lsaddr; +static grub_command_t cmd_lsroutes, cmd_lscards; +static grub_command_t cmd_lsaddr; GRUB_MOD_INIT(net) { @@ -1446,15 +954,7 @@ GRUB_MOD_INIT(net) "", N_("list network cards")); cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs, "", N_("list network addresses")); - cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, - "[CARD]", - N_("perform a bootp autoconfiguration")); - cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, - "[CARD]", - N_("perform a bootp autoconfiguration")); - cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, - N_("VAR INTERFACE NUMBER DESCRIPTION"), - N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); + grub_bootp_init (); grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; @@ -1466,6 +966,7 @@ GRUB_MOD_INIT(net) GRUB_MOD_FINI(net) { + grub_bootp_fini (); grub_unregister_command (cmd_addaddr); grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); @@ -1473,7 +974,6 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_lsaddr); - grub_unregister_command (cmd_getdhcp); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; grub_net_fini_hw (0); diff --git a/include/grub/net.h b/include/grub/net.h index 0ac0838cf..92e637d89 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -429,4 +429,20 @@ extern struct grub_net_network_level_interface *grub_net_network_level_interface void grub_net_poll_cards (unsigned time); +void grub_bootp_init (void); +void grub_bootp_fini (void); + +static inline void +grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) +{ + inter->card->num_ifaces--; + *inter->prev = inter->next; + if (inter->next) + inter->next->prev = inter->prev; + inter->next = 0; + inter->prev = 0; +} + +extern char *grub_net_default_server; + #endif /* ! GRUB_NET_HEADER */ From 6cf88dfd7aa8091e7dfe48c5a1e6e722b48c8a37 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 15:02:19 +0200 Subject: [PATCH 274/673] add missing file --- grub-core/net/bootp.c | 527 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 527 insertions(+) create mode 100644 grub-core/net/bootp.c diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c new file mode 100644 index 000000000..a1aaf402f --- /dev/null +++ b/grub-core/net/bootp.c @@ -0,0 +1,527 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static char * +grub_env_write_readonly (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + return NULL; +} + +static void +set_env_limn_ro (const char *intername, const char *suffix, + char *value, grub_size_t len) +{ + char c; + char varname[sizeof ("net_") + grub_strlen (intername) + sizeof ("_") + + grub_strlen (suffix)]; + grub_snprintf (varname, sizeof (varname), "net_%s_%s", intername, suffix); + c = value[len]; + value[len] = 0; + grub_env_set (varname, value); + value[len] = c; + grub_register_variable_hook (varname, 0, grub_env_write_readonly); +} + +static void +parse_dhcp_vendor (const char *name, void *vend, int limit) +{ + grub_uint8_t *ptr, *ptr0; + + ptr = ptr0 = vend; + + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) + return; + ptr = ptr + sizeof (grub_uint32_t); + while (ptr - ptr0 < limit) + { + grub_uint8_t tagtype; + grub_uint8_t taglength; + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return; + + taglength = *ptr++; + + switch (tagtype) + { + case 12: + set_env_limn_ro (name, "hostname", (char *) ptr, taglength); + break; + + case 15: + set_env_limn_ro (name, "domain", (char *) ptr, taglength); + break; + + case 17: + set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); + break; + + case 18: + set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); + break; + + /* If you need any other options please contact GRUB + developpement team. */ + } + + ptr += taglength; + } +} + +#define OFFSET_OF(x, y) ((grub_uint8_t *)((y)->x) - (grub_uint8_t *)(y)) + +struct grub_net_network_level_interface * +grub_net_configure_by_dhcp_ack (const char *name, + struct grub_net_card *card, + grub_net_interface_flags_t flags, + const struct grub_net_bootp_packet *bp, + grub_size_t size, + int is_def, char **device, char **path) +{ + grub_net_network_level_address_t addr; + grub_net_link_level_address_t hwaddr; + struct grub_net_network_level_interface *inter; + + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + addr.ipv4 = bp->your_ip; + + if (device) + *device = 0; + if (path) + *path = 0; + + grub_memcpy (hwaddr.mac, bp->mac_addr, + bp->hw_len < sizeof (hwaddr.mac) ? bp->hw_len + : sizeof (hwaddr.mac)); + hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + + inter = grub_net_add_addr (name, card, addr, hwaddr, flags); + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof ("_gw")]; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s_gw", name); + grub_net_add_route_gw (rname, target, gw); + } + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->gateway_ip; + target.ipv4.masksize = 32; + grub_net_add_route (name, target, inter); + } + + if (size > OFFSET_OF (boot_file, bp)) + set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, + sizeof (bp->boot_file)); + if (is_def) + grub_net_default_server = 0; + if (size > OFFSET_OF (server_name, bp) + && bp->server_name[0]) + { + set_env_limn_ro (name, "dhcp_server_name", (char *) bp->server_name, + sizeof (bp->server_name)); + if (is_def && !grub_net_default_server) + { + grub_net_default_server = grub_strdup (bp->server_name); + grub_print_error (); + } + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%s", bp->server_name); + grub_print_error (); + } + } + if (is_def && !grub_net_default_server) + { + grub_net_default_server = grub_xasprintf ("%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_print_error (); + } + + if (device && !*device) + { + *device = grub_xasprintf ("tftp,%d.%d.%d.%d", + ((grub_uint8_t *) &bp->server_ip)[0], + ((grub_uint8_t *) &bp->server_ip)[1], + ((grub_uint8_t *) &bp->server_ip)[2], + ((grub_uint8_t *) &bp->server_ip)[3]); + grub_print_error (); + } + if (size > OFFSET_OF (boot_file, bp) && path) + { + *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); + grub_print_error (); + if (*path) + { + char *slash; + slash = grub_strrchr (*path, '/'); + if (slash) + *slash = 0; + else + **path = 0; + } + } + if (size > OFFSET_OF (vendor, bp)) + parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp)); + + inter->dhcp_ack = grub_malloc (size); + if (inter->dhcp_ack) + { + grub_memcpy (inter->dhcp_ack, bp, size); + inter->dhcp_acklen = size; + } + else + grub_errno = GRUB_ERR_NONE; + + return inter; +} + +void +grub_net_process_dhcp (struct grub_net_buff *nb, + struct grub_net_card *card) +{ + char *name; + struct grub_net_network_level_interface *inf; + + name = grub_xasprintf ("%s:dhcp", card->name); + if (!name) + { + grub_print_error (); + return; + } + grub_net_configure_by_dhcp_ack (name, card, + 0, (const struct grub_net_bootp_packet *) nb->data, + (nb->tail - nb->data), 0, 0, 0); + grub_free (name); + if (grub_errno) + grub_print_error (); + else + { + FOR_NET_NETWORK_LEVEL_INTERFACES(inf) + if (grub_memcmp (inf->name, card->name, grub_strlen (card->name)) == 0 + && grub_memcmp (inf->name + grub_strlen (card->name), + ":dhcp_tmp", sizeof (":dhcp_tmp") - 1) == 0) + { + grub_net_network_level_interface_unregister (inf); + break; + } + } +} + +static char +hexdigit (grub_uint8_t val) +{ + if (val < 10) + return val + '0'; + return val + 'a' - 10; +} + +static grub_err_t +grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_network_level_interface *inter; + int num; + grub_uint8_t *ptr; + grub_uint8_t taglength; + + if (argc < 4) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inter) + if (grub_strcmp (inter->name, args[1]) == 0) + break; + + if (!inter) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unrecognised interface %s"), args[1]); + + if (!inter->dhcp_ack) + return grub_error (GRUB_ERR_IO, N_("no DHCP info found")); + + if (inter->dhcp_acklen <= OFFSET_OF (vendor, inter->dhcp_ack)) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + + num = grub_strtoul (args[2], 0, 0); + if (grub_errno) + return grub_errno; + + ptr = inter->dhcp_ack->vendor; + + if (ptr[0] != GRUB_NET_BOOTP_RFC1048_MAGIC_0 + || ptr[1] != GRUB_NET_BOOTP_RFC1048_MAGIC_1 + || ptr[2] != GRUB_NET_BOOTP_RFC1048_MAGIC_2 + || ptr[3] != GRUB_NET_BOOTP_RFC1048_MAGIC_3) + return grub_error (GRUB_ERR_IO, N_("no DHCP options found")); + ptr = ptr + sizeof (grub_uint32_t); + while (1) + { + grub_uint8_t tagtype; + + if (ptr >= ((grub_uint8_t *) inter->dhcp_ack) + inter->dhcp_acklen) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + tagtype = *ptr++; + + /* Pad tag. */ + if (tagtype == 0) + continue; + + /* End tag. */ + if (tagtype == 0xff) + return grub_error (GRUB_ERR_IO, N_("no DHCP option %d found"), num); + + taglength = *ptr++; + + if (tagtype == num) + break; + ptr += taglength; + } + + if (grub_strcmp (args[3], "string") == 0) + { + char *val = grub_malloc (taglength + 1); + if (!val) + return grub_errno; + grub_memcpy (val, ptr, taglength); + val[taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "number") == 0) + { + grub_uint64_t val = 0; + int i; + for (i = 0; i < taglength; i++) + val = (val << 8) | ptr[i]; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%llu\n", (unsigned long long) val); + else + { + char valn[64]; + grub_printf (valn, sizeof (valn), "%lld\n", (unsigned long long) val); + return grub_env_set (args[0], valn); + } + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[3], "hex") == 0) + { + char *val = grub_malloc (2 * taglength + 1); + int i; + if (!val) + return grub_errno; + for (i = 0; i < taglength; i++) + { + val[2 * i] = hexdigit (ptr[i] >> 4); + val[2 * i + 1] = hexdigit (ptr[i] & 0xf); + } + val[2 * taglength] = 0; + if (args[0][0] == '-' && args[0][1] == 0) + grub_printf ("%s\n", val); + else + return grub_env_set (args[0], val); + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "unrecognised format specification %s", args[3]); +} + +static grub_err_t +grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_interface *ifaces; + grub_size_t ncards = 0; + unsigned j = 0; + int interval; + grub_err_t err; + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ncards++; + } + + ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); + if (!ifaces) + return grub_errno; + + j = 0; + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ifaces[j].card = card; + ifaces[j].next = &ifaces[j+1]; + if (j) + ifaces[j].prev = &ifaces[j-1].next; + ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name); + card->num_ifaces++; + if (!ifaces[j].name) + { + unsigned i; + for (i = 0; i < j; i++) + grub_free (ifaces[i].name); + grub_free (ifaces); + return grub_errno; + } + ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV; + grub_memcpy (&ifaces[j].hwaddress, &card->default_address, + sizeof (ifaces[j].hwaddress)); + j++; + } + ifaces[ncards - 1].next = grub_net_network_level_interfaces; + if (grub_net_network_level_interfaces) + grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next; + grub_net_network_level_interfaces = &ifaces[0]; + ifaces[0].prev = &grub_net_network_level_interfaces; + for (interval = 200; interval < 10000; interval *= 2) + { + int done = 0; + for (j = 0; j < ncards; j++) + { + struct grub_net_bootp_packet *pack; + struct grub_datetime date; + grub_int32_t t; + struct grub_net_buff *nb; + struct udphdr *udph; + grub_net_network_level_address_t target; + + if (!ifaces[j].prev) + continue; + nb = grub_netbuff_alloc (sizeof (*pack)); + if (!nb) + return grub_errno; + err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); + if (err) + return err; + err = grub_netbuff_push (nb, sizeof (*pack) + 64); + if (err) + return err; + pack = (void *) nb->data; + done = 1; + grub_memset (pack, 0, sizeof (*pack) + 64); + pack->opcode = 1; + pack->hw_type = 1; + pack->hw_len = 6; + err = grub_get_datetime (&date); + if (err || !grub_datetime2unixtime (&date, &t)) + { + grub_errno = GRUB_ERR_NONE; + t = 0; + } + pack->ident = grub_cpu_to_be32 (t); + pack->seconds = 0;//grub_cpu_to_be16 (t); + + grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); + + grub_netbuff_push (nb, sizeof (*udph)); + + udph = (struct udphdr *) nb->data; + udph->src = grub_cpu_to_be16 (68); + udph->dst = grub_cpu_to_be16 (67); + udph->chksum = 0; + udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4 = 0xffffffff; + + err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + if (err) + return err; + } + if (!done) + break; + grub_net_poll_cards (interval); + } + + err = GRUB_ERR_NONE; + for (j = 0; j < ncards; j++) + { + if (!ifaces[j].prev) + continue; + grub_error_push (); + grub_net_network_level_interface_unregister (&ifaces[j]); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", + ifaces[j].card->name); + } + + return err; +} + +static grub_command_t cmd_dhcp, cmd_getdhcp, cmd_bootp; + +void +grub_bootp_init (void) +{ + cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); + cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, + "[CARD]", + N_("perform a bootp autoconfiguration")); + cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, + N_("VAR INTERFACE NUMBER DESCRIPTION"), + N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); +} + +void +grub_bootp_fini (void) +{ + grub_unregister_command (cmd_getdhcp); + grub_unregister_command (cmd_dhcp); + grub_unregister_command (cmd_bootp); +} From c97dbbf2f28c7d3026e9109790167b646d76ac5e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:40:24 +0200 Subject: [PATCH 275/673] Fix a memory leak --- grub-core/disk/ieee1275/ofdisk.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index 0a935d5c2..7868b14b1 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -243,14 +243,24 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) grub_dprintf ("disk", "Opening `%s'.\n", devpath); if (grub_ieee1275_finddevice (devpath, &dev)) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); + { + grub_free (devpath); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "can't read device properties"); + } if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop), &actual)) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); + { + grub_free (devpath); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); + } if (grub_strcmp (prop, "block")) - return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); + { + grub_free (devpath); + return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); + } /* XXX: There is no property to read the number of blocks. There should be a property `#blocks', but it is not there. Perhaps it From c2aa00f059ab09bd427703c874d8ff7936ba3d39 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:40:36 +0200 Subject: [PATCH 276/673] Fix a memory leak --- grub-core/kern/dl.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 5f214e378..1841bf1f5 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -688,11 +688,9 @@ grub_dl_load_file (const char *filename) grub_file_close (file); mod = grub_dl_load_core (core, size); + grub_free (core); if (! mod) - { - grub_free (core); - return 0; - } + return 0; mod->ref_count--; return mod; From f872d4744e66dde8cccbc9a189ac39e432851e92 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:40:56 +0200 Subject: [PATCH 277/673] Fix compilation error --- grub-core/kern/ieee1275/openfw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 2cecd8c7f..4e705a4d8 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -23,7 +23,6 @@ #include #include #include -#include enum grub_ieee1275_parse_type { From e1a0e1b42841f02481f8051cccf9669aa5a231a4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:41:19 +0200 Subject: [PATCH 278/673] Fix the usage of unsupported %zx --- grub-core/kern/mm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index d54f3f240..ee4d58d81 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -515,7 +515,7 @@ grub_debug_malloc (const char *file, int line, grub_size_t size) void *ptr; if (grub_mm_debug) - grub_printf ("%s:%d: malloc (0x%zx) = ", file, line, size); + grub_printf ("%s:%d: malloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size); ptr = grub_malloc (size); if (grub_mm_debug) grub_printf ("%p\n", ptr); @@ -528,7 +528,7 @@ grub_debug_zalloc (const char *file, int line, grub_size_t size) void *ptr; if (grub_mm_debug) - grub_printf ("%s:%d: zalloc (0x%zx) = ", file, line, size); + grub_printf ("%s:%d: zalloc (0x%" PRIxGRUB_SIZE ") = ", file, line, size); ptr = grub_zalloc (size); if (grub_mm_debug) grub_printf ("%p\n", ptr); @@ -547,7 +547,7 @@ void * grub_debug_realloc (const char *file, int line, void *ptr, grub_size_t size) { if (grub_mm_debug) - grub_printf ("%s:%d: realloc (%p, 0x%zx) = ", file, line, ptr, size); + grub_printf ("%s:%d: realloc (%p, 0x%" PRIxGRUB_SIZE ") = ", file, line, ptr, size); ptr = grub_realloc (ptr, size); if (grub_mm_debug) grub_printf ("%p\n", ptr); @@ -561,8 +561,8 @@ grub_debug_memalign (const char *file, int line, grub_size_t align, void *ptr; if (grub_mm_debug) - grub_printf ("%s:%d: memalign (0x%zx, 0x%zx) = ", - file, line, align, size); + grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE + ") = ", file, line, align, size); ptr = grub_memalign (align, size); if (grub_mm_debug) grub_printf ("%p\n", ptr); From c3bf5267b016238d09455c843d425e7a9ce30e83 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 17:41:49 +0200 Subject: [PATCH 279/673] Fix a memory leak --- grub-core/net/bootp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index a1aaf402f..84bdc04d7 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -444,13 +444,22 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), continue; nb = grub_netbuff_alloc (sizeof (*pack)); if (!nb) - return grub_errno; + { + grub_netbuff_free (nb); + return grub_errno; + } err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128); if (err) - return err; + { + grub_netbuff_free (nb); + return err; + } err = grub_netbuff_push (nb, sizeof (*pack) + 64); if (err) - return err; + { + grub_netbuff_free (nb); + return err; + } pack = (void *) nb->data; done = 1; grub_memset (pack, 0, sizeof (*pack) + 64); @@ -480,6 +489,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), target.ipv4 = 0xffffffff; err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + grub_netbuff_free (nb); if (err) return err; } @@ -491,6 +501,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), err = GRUB_ERR_NONE; for (j = 0; j < ncards; j++) { + grub_free (ifaces[j].name); if (!ifaces[j].prev) continue; grub_error_push (); @@ -499,6 +510,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), ifaces[j].card->name); } + grub_free (ifaces); return err; } From d1831ca48a8ee052599f129c36e346336fae6b17 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 18:21:07 +0200 Subject: [PATCH 280/673] Limit idle polling frequency --- grub-core/net/drivers/ieee1275/ofnet.c | 1 + grub-core/net/net.c | 10 +++++++++- include/grub/net.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index cc29d0987..20d45ee3d 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -253,6 +253,7 @@ grub_ofnet_findcards (void) card->flags = 0; shortname = find_alias (alias->path); card->name = grub_xasprintf ("ofnet_%s", shortname ? : alias->path); + card->idle_poll_delay_ms = 1; grub_free (shortname); card->driver = &ofdriver; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index bc16fbde5..641aebd64 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -768,6 +768,7 @@ receive_packets (struct grub_net_card *card) if (!nb) { grub_print_error (); + card->last_poll = grub_get_time_ms (); return; } @@ -775,6 +776,7 @@ receive_packets (struct grub_net_card *card) if (actual < 0) { grub_netbuff_free (nb); + card->last_poll = grub_get_time_ms (); break; } grub_net_recv_ethernet_packet (nb, card); @@ -800,7 +802,13 @@ grub_net_poll_cards_idle_real (void) { struct grub_net_card *card; FOR_NET_CARDS (card) - receive_packets (card); + { + grub_uint64_t ctime = grub_get_time_ms (); + + if (ctime < card->last_poll + || ctime >= card->last_poll + card->idle_poll_delay_ms) + receive_packets (card); + } } /* Read from the packets list*/ diff --git a/include/grub/net.h b/include/grub/net.h index 92e637d89..45d08f3f5 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -95,6 +95,8 @@ struct grub_net_card grub_net_card_flags_t flags; int num_ifaces; int opened; + unsigned idle_poll_delay_ms; + grub_uint64_t last_poll; union { #ifdef GRUB_MACHINE_EFI From 697ffdc55b6fcb150e19ad5f746142edbcf5e372 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 18:21:24 +0200 Subject: [PATCH 281/673] Fix a memory leak --- grub-core/net/net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 641aebd64..0f8a60413 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -725,6 +725,7 @@ grub_net_fs_open (struct grub_file *file_out, const char *name) } grub_memcpy (file_out, bufio, sizeof (struct grub_file)); + grub_free (bufio); return GRUB_ERR_NONE; } From 1c358e5948c43ac7684c2067c9aa035dd3493778 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 6 Jul 2011 22:15:58 +0200 Subject: [PATCH 282/673] * po/POTFILES.in: Regenerate. --- ChangeLog | 4 + po/POTFILES.in | 342 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 328 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 110a980f0..e6aace254 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-06 Vladimir Serbinenko + + * po/POTFILES.in: Regenerate. + 2011-07-06 Vladimir Serbinenko Unify sparc init with other ieee1275. diff --git a/po/POTFILES.in b/po/POTFILES.in index 8329fdf0a..2bf4aa10c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,5 +1,22 @@ -# List of files which contain translatable strings. +grub-core/boot/decompressor/minilib.c +grub-core/boot/decompressor/none.c +grub-core/boot/decompressor/xz.c +grub-core/bus/bonito.c +grub-core/bus/cs5536.c +grub-core/bus/emu/pci.c +grub-core/bus/pci.c +grub-core/bus/usb/emu/usb.c +grub-core/bus/usb/ohci.c +grub-core/bus/usb/serial/common.c +grub-core/bus/usb/serial/ftdi.c +grub-core/bus/usb/serial/pl2303.c +grub-core/bus/usb/uhci.c +grub-core/bus/usb/usb.c +grub-core/bus/usb/usbhub.c +grub-core/bus/usb/usbtrans.c grub-core/commands/acpi.c +grub-core/commands/acpihalt.c +grub-core/commands/arc/lsdev.c grub-core/commands/blocklist.c grub-core/commands/boot.c grub-core/commands/cat.c @@ -7,33 +24,41 @@ grub-core/commands/cmp.c grub-core/commands/configfile.c grub-core/commands/date.c grub-core/commands/echo.c +grub-core/commands/efi/acpi.c grub-core/commands/efi/fixvideo.c grub-core/commands/efi/loadbios.c +grub-core/commands/efi/lsefimmap.c +grub-core/commands/efi/lsefisystab.c +grub-core/commands/efi/lssal.c +grub-core/commands/extcmd.c grub-core/commands/gptsync.c grub-core/commands/halt.c grub-core/commands/hashsum.c grub-core/commands/hdparm.c grub-core/commands/help.c grub-core/commands/hexdump.c +grub-core/commands/i386/cmostest.c grub-core/commands/i386/cpuid.c +grub-core/commands/i386/pc/acpi.c grub-core/commands/i386/pc/drivemap.c grub-core/commands/i386/pc/halt.c grub-core/commands/i386/pc/lsapm.c grub-core/commands/i386/pc/play.c -grub-core/commands/i386/pc/pxecmd.c +grub-core/commands/i386/pc/sendkey.c grub-core/commands/ieee1275/suspend.c grub-core/commands/iorw.c grub-core/commands/keylayouts.c grub-core/commands/keystatus.c grub-core/commands/legacycfg.c grub-core/commands/loadenv.c -grub-core/commands/ls.c grub-core/commands/lsacpi.c +grub-core/commands/ls.c grub-core/commands/lsmmap.c grub-core/commands/lspci.c grub-core/commands/memrw.c grub-core/commands/menuentry.c grub-core/commands/minicmd.c +grub-core/commands/mips/loongson/lsspd.c grub-core/commands/parttool.c grub-core/commands/password.c grub-core/commands/password_pbkdf2.c @@ -51,67 +76,348 @@ grub-core/commands/sleep.c grub-core/commands/terminal.c grub-core/commands/test.c grub-core/commands/testload.c +grub-core/commands/time.c grub-core/commands/true.c grub-core/commands/usbtest.c grub-core/commands/videoinfo.c grub-core/commands/videotest.c +grub-core/commands/wildcard.c grub-core/commands/xnu_uuid.c - +grub-core/disk/ahci.c +grub-core/disk/arc/arcdisk.c +grub-core/disk/ata.c +grub-core/disk/dmraid_nvidia.c +grub-core/disk/efi/efidisk.c +grub-core/disk/host.c +grub-core/disk/i386/pc/biosdisk.c +grub-core/disk/ieee1275/nand.c +grub-core/disk/ieee1275/ofdisk.c grub-core/disk/loopback.c - +grub-core/disk/lvm.c +grub-core/disk/mdraid1x_linux.c +grub-core/disk/mdraid_linux.c +grub-core/disk/memdisk.c +grub-core/disk/pata.c +grub-core/disk/raid5_recover.c +grub-core/disk/raid6_recover.c +grub-core/disk/raid.c +grub-core/disk/scsi.c +grub-core/disk/usbms.c +grub-core/efiemu/i386/coredetect.c +grub-core/efiemu/i386/loadcore32.c +grub-core/efiemu/i386/loadcore64.c +grub-core/efiemu/i386/nocfgtables.c +grub-core/efiemu/i386/pc/cfgtables.c +grub-core/efiemu/loadcore32.c +grub-core/efiemu/loadcore64.c +grub-core/efiemu/loadcore.c +grub-core/efiemu/loadcore_common.c grub-core/efiemu/main.c - +grub-core/efiemu/mm.c +grub-core/efiemu/pnvram.c +grub-core/efiemu/prepare32.c +grub-core/efiemu/prepare64.c +grub-core/efiemu/prepare.c +grub-core/efiemu/runtime/efiemu.c +grub-core/efiemu/symbols.c +grub-core/font/font.c grub-core/font/font_cmd.c - +grub-core/fs/affs.c +grub-core/fs/afs_be.c +grub-core/fs/afs.c +grub-core/fs/befs_be.c +grub-core/fs/befs.c +grub-core/fs/btrfs.c +grub-core/fs/cpio.c +grub-core/fs/ext2.c +grub-core/fs/fat.c +grub-core/fs/fshelp.c +grub-core/fs/hfs.c +grub-core/fs/hfsplus.c +grub-core/fs/iso9660.c +grub-core/fs/jfs.c +grub-core/fs/minix2.c +grub-core/fs/minix3.c +grub-core/fs/minix.c +grub-core/fs/nilfs2.c +grub-core/fs/ntfs.c +grub-core/fs/ntfscomp.c +grub-core/fs/reiserfs.c +grub-core/fs/romfs.c +grub-core/fs/sfs.c +grub-core/fs/squash4.c +grub-core/fs/tar.c +grub-core/fs/udf.c +grub-core/fs/ufs2.c +grub-core/fs/ufs.c +grub-core/fs/xfs.c +grub-core/fs/zfs/zfs.c +grub-core/fs/zfs/zfs_fletcher.c +grub-core/fs/zfs/zfsinfo.c +grub-core/fs/zfs/zfs_lzjb.c +grub-core/fs/zfs/zfs_sha256.c +grub-core/gentrigtables.c grub-core/gettext/gettext.c - +grub-core/gfxmenu/font.c +grub-core/gfxmenu/gfxmenu.c +grub-core/gfxmenu/gui_box.c +grub-core/gfxmenu/gui_canvas.c +grub-core/gfxmenu/gui_circular_progress.c +grub-core/gfxmenu/gui_image.c +grub-core/gfxmenu/gui_label.c +grub-core/gfxmenu/gui_list.c grub-core/gfxmenu/gui_progress_bar.c - +grub-core/gfxmenu/gui_string_util.c +grub-core/gfxmenu/gui_util.c +grub-core/gfxmenu/icon_manager.c +grub-core/gfxmenu/model.c +grub-core/gfxmenu/theme_loader.c +grub-core/gfxmenu/view.c +grub-core/gfxmenu/widget-box.c grub-core/hello/hello.c - +grub-core/hook/datehook.c +grub-core/io/bufio.c +grub-core/io/gzio.c +grub-core/io/xzio.c +grub-core/kern/command.c grub-core/kern/corecmd.c +grub-core/kern/device.c +grub-core/kern/disk.c +grub-core/kern/dl.c +grub-core/kern/efi/efi.c +grub-core/kern/efi/init.c +grub-core/kern/efi/mm.c +grub-core/kern/elf.c +grub-core/kern/emu/cache.c +grub-core/kern/emu/console.c +grub-core/kern/emu/full.c +grub-core/kern/emu/getroot.c grub-core/kern/emu/hostdisk.c +grub-core/kern/emu/hostfs.c +grub-core/kern/emu/lite.c +grub-core/kern/emu/main.c grub-core/kern/emu/misc.c +grub-core/kern/emu/mm.c +grub-core/kern/emu/time.c +grub-core/kern/env.c grub-core/kern/err.c - +grub-core/kern/file.c +grub-core/kern/fs.c +grub-core/kern/generic/millisleep.c +grub-core/kern/generic/rtc_get_time_ms.c +grub-core/kern/i386/coreboot/init.c +grub-core/kern/i386/coreboot/mmap.c +grub-core/kern/i386/dl.c +grub-core/kern/i386/efi/init.c +grub-core/kern/i386/multiboot_mmap.c +grub-core/kern/i386/pc/init.c +grub-core/kern/i386/pc/mmap.c +grub-core/kern/i386/pit.c +grub-core/kern/i386/qemu/mmap.c +grub-core/kern/i386/tsc.c +grub-core/kern/ia64/dl.c +grub-core/kern/ia64/dl_helper.c +grub-core/kern/ia64/efi/init.c +grub-core/kern/ieee1275/cmain.c +grub-core/kern/ieee1275/ieee1275.c +grub-core/kern/ieee1275/init.c +grub-core/kern/ieee1275/mmap.c +grub-core/kern/ieee1275/openfw.c +grub-core/kern/list.c +grub-core/kern/main.c +grub-core/kern/mips/arc/init.c +grub-core/kern/mips/dl.c +grub-core/kern/mips/init.c +grub-core/kern/mips/loongson/init.c +grub-core/kern/mips/qemu_mips/init.c +grub-core/kern/misc.c +grub-core/kern/mm.c +grub-core/kern/parser.c +grub-core/kern/partition.c +grub-core/kern/powerpc/dl.c +grub-core/kern/rescue_parser.c +grub-core/kern/rescue_reader.c +grub-core/kern/sparc64/dl.c +grub-core/kern/sparc64/ieee1275/ieee1275.c +grub-core/kern/term.c +grub-core/kern/time.c +grub-core/kern/vga_init.c +grub-core/kern/x86_64/dl.c +grub-core/lib/arc/datetime.c grub-core/lib/arg.c - +grub-core/lib/cmdline.c +grub-core/lib/cmos_datetime.c +grub-core/lib/crc.c +grub-core/lib/crypto.c +grub-core/lib/efi/datetime.c +grub-core/lib/efi/halt.c +grub-core/lib/efi/relocator.c +grub-core/lib/emu/halt.c +grub-core/lib/envblk.c +grub-core/lib/hexdump.c +grub-core/lib/i386/halt.c +grub-core/lib/i386/pc/biosnum.c +grub-core/lib/i386/pc/vesa_modes_table.c +grub-core/lib/i386/relocator.c +grub-core/lib/ieee1275/cmos.c +grub-core/lib/ieee1275/datetime.c +grub-core/lib/ieee1275/halt.c +grub-core/lib/ieee1275/relocator.c +grub-core/lib/legacy_parse.c +grub-core/lib/LzFind.c +grub-core/lib/LzmaDec.c +grub-core/lib/LzmaEnc.c +grub-core/lib/mips/relocator.c +grub-core/lib/pbkdf2.c +grub-core/lib/powerpc/relocator.c +grub-core/lib/reed_solomon.c +grub-core/lib/relocator.c +grub-core/lib/xzembed/xz_dec_bcj.c +grub-core/lib/xzembed/xz_dec_lzma2.c +grub-core/lib/xzembed/xz_dec_stream.c +grub-core/loader/aout.c grub-core/loader/efi/appleloader.c grub-core/loader/efi/chainloader.c +grub-core/loader/i386/bsd32.c +grub-core/loader/i386/bsd64.c grub-core/loader/i386/bsd.c +grub-core/loader/i386/bsd_pagetable.c +grub-core/loader/i386/bsdXX.c +grub-core/loader/i386/coreboot/chainloader.c grub-core/loader/i386/linux.c +grub-core/loader/i386/multiboot_mbi.c grub-core/loader/i386/pc/chainloader.c +grub-core/loader/i386/pc/freedos.c grub-core/loader/i386/pc/linux.c grub-core/loader/i386/pc/ntldr.c grub-core/loader/i386/xnu.c +grub-core/loader/ia64/efi/linux.c +grub-core/loader/macho32.c +grub-core/loader/macho64.c +grub-core/loader/macho.c +grub-core/loader/machoXX.c grub-core/loader/mips/linux.c grub-core/loader/multiboot.c +grub-core/loader/multiboot_elfxx.c +grub-core/loader/multiboot_mbi2.c grub-core/loader/powerpc/ieee1275/linux.c grub-core/loader/sparc64/ieee1275/linux.c grub-core/loader/xnu.c - +grub-core/loader/xnu_resume.c +grub-core/mmap/efi/mmap.c +grub-core/mmap/i386/mmap.c +grub-core/mmap/i386/pc/mmap.c +grub-core/mmap/i386/uppermem.c +grub-core/mmap/mips/uppermem.c grub-core/mmap/mmap.c - +grub-core/net/arp.c +grub-core/net/bootp.c +grub-core/net/drivers/efi/efinet.c +grub-core/net/drivers/emu/emunet.c +grub-core/net/drivers/i386/pc/pxe.c +grub-core/net/drivers/ieee1275/ofnet.c +grub-core/net/ethernet.c +grub-core/net/ip.c +grub-core/net/netbuff.c +grub-core/net/net.c +grub-core/net/tftp.c +grub-core/net/udp.c grub-core/normal/auth.c +grub-core/normal/autofs.c +grub-core/normal/charset.c grub-core/normal/cmdline.c grub-core/normal/color.c +grub-core/normal/completion.c grub-core/normal/context.c +grub-core/normal/crypto.c +grub-core/normal/datetime.c grub-core/normal/dyncmd.c grub-core/normal/main.c grub-core/normal/menu.c grub-core/normal/menu_entry.c grub-core/normal/menu_text.c grub-core/normal/misc.c - +grub-core/normal/term.c +grub-core/partmap/acorn.c +grub-core/partmap/amiga.c +grub-core/partmap/apple.c +grub-core/partmap/bsdlabel.c +grub-core/partmap/dvh.c +grub-core/partmap/gpt.c +grub-core/partmap/msdos.c +grub-core/partmap/sun.c +grub-core/partmap/sunpc.c +grub-core/parttool/msdospart.c +grub-core/script/argv.c +grub-core/script/execute.c +grub-core/script/function.c +grub-core/script/lexer.c grub-core/script/main.c - +grub-core/script/script.c +grub-core/term/arc/console.c +grub-core/term/at_keyboard.c +grub-core/term/efi/console.c grub-core/term/gfxterm.c +grub-core/term/i386/pc/console.c +grub-core/term/i386/pc/vga_text.c +grub-core/term/i386/vga_common.c +grub-core/term/ieee1275/ofconsole.c +grub-core/term/ns8250.c grub-core/term/serial.c grub-core/term/terminfo.c - +grub-core/term/tparm.c +grub-core/term/usb_keyboard.c +grub-core/tests/example_functional_test.c +grub-core/tests/lib/functional_test.c +grub-core/tests/lib/test.c grub-core/tests/test_blockarg.c - +grub-core/video/bitmap.c +grub-core/video/bitmap_scale.c +grub-core/video/bochs.c +grub-core/video/cirrus.c +grub-core/video/colors.c +grub-core/video/efi_gop.c +grub-core/video/efi_uga.c +grub-core/video/emu/sdl.c +grub-core/video/fb/fbblit.c +grub-core/video/fb/fbfill.c +grub-core/video/fb/fbutil.c +grub-core/video/fb/video_fb.c +grub-core/video/i386/pc/vbe.c +grub-core/video/i386/pc/vga.c +grub-core/video/ieee1275.c +grub-core/video/readers/jpeg.c +grub-core/video/readers/png.c +grub-core/video/readers/tga.c +grub-core/video/sis315_init.c +grub-core/video/sis315pro.c +grub-core/video/sm712.c +grub-core/video/sm712_init.c +grub-core/video/video.c +tests/example_unit_test.c +tests/lib/unit_test.c +util/bin2h.c +util/deviceiter.c +util/devicemap.c util/grub-editenv.c util/grub-fstest.c +util/grub-macho2img.c +util/grub-menulst2cfg.c +util/grub-mkdevicemap.c +util/grub-mkfont.c util/grub-mkimage.c +util/grub-mkimagexx.c +util/grub-mklayout.c +util/grub-mkpasswd-pbkdf2.c +util/grub-mkrelpath.c +util/grub-pe2elf.c +util/grub-probe.c +util/grub-script-check.c util/grub-setup.c +util/ieee1275/devicemap.c +util/ieee1275/grub-ofpathname.c +util/ieee1275/ofpath.c +util/lvm.c +util/misc.c +util/raid.c +util/resolve.c From 0044d1db2e43943112aac3f3482e97d66584e645 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 7 Jul 2011 21:46:25 +0200 Subject: [PATCH 283/673] Simplify disk opening --- grub-core/disk/arc/arcdisk.c | 6 +++++- grub-core/disk/ata.c | 3 +-- grub-core/disk/efi/efidisk.c | 3 +-- grub-core/disk/host.c | 3 +-- grub-core/disk/i386/pc/biosdisk.c | 3 +-- grub-core/disk/ieee1275/nand.c | 3 +-- grub-core/disk/ieee1275/ofdisk.c | 3 +-- grub-core/disk/loopback.c | 3 +-- grub-core/disk/lvm.c | 6 ++---- grub-core/disk/memdisk.c | 3 +-- grub-core/disk/raid.c | 4 ++-- grub-core/disk/scsi.c | 3 +-- grub-core/kern/disk.c | 28 +++++++++------------------- grub-core/kern/emu/hostdisk.c | 3 +-- include/grub/disk.h | 4 +--- 15 files changed, 29 insertions(+), 49 deletions(-) diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index 7dff30931..170bf521d 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -79,7 +79,8 @@ arcdisk_hash_add (char *devpath) static int -grub_arcdisk_iterate (int (*hook_in) (const char *name)) +grub_arcdisk_iterate (int (*hook_in) (const char *name), + grub_disk_pull_t pull) { auto int hook (const char *name, const struct grub_arc_component *comp); int hook (const char *name, const struct grub_arc_component *comp) @@ -90,6 +91,9 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name)) return 0; return hook_in (name); } + if (pull != GRUB_DISK_PULL_NONE) + return 0; + return grub_arc_iterate_devs (hook, 1); } diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 9a09ee158..8add7f4de 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -412,8 +412,7 @@ grub_ata_iterate (int (*hook_in) (const char *name), } static grub_err_t -grub_ata_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_ata_open (const char *name, grub_disk_t disk) { unsigned id, bus; struct grub_ata *ata; diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 4ae1d7bb9..85969cc1d 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -454,8 +454,7 @@ get_device (struct grub_efidisk_data *devices, int num) } static grub_err_t -grub_efidisk_open (const char *name, struct grub_disk *disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_efidisk_open (const char *name, struct grub_disk *disk) { int num; struct grub_efidisk_data *d = 0; diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index 5376cc6ce..5ee0d2e56 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -39,8 +39,7 @@ grub_host_iterate (int (*hook) (const char *name), } static grub_err_t -grub_host_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_host_open (const char *name, grub_disk_t disk) { if (grub_strcmp (name, "host")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a host disk"); diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 1198d4305..e152b9d89 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -328,8 +328,7 @@ grub_biosdisk_iterate (int (*hook) (const char *name), } static grub_err_t -grub_biosdisk_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_biosdisk_open (const char *name, grub_disk_t disk) { grub_uint64_t total_sectors = 0; int drive; diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index 4be5b5641..94d62bc4f 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -58,8 +58,7 @@ grub_nand_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf); static grub_err_t -grub_nand_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_nand_open (const char *name, grub_disk_t disk) { grub_ieee1275_ihandle_t dev_ihandle = 0; struct grub_nand_data *data = 0; diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index 7b7db3a08..2cd43d80a 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -233,8 +233,7 @@ compute_dev_path (const char *name) } static grub_err_t -grub_ofdisk_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_ofdisk_open (const char *name, grub_disk_t disk) { grub_ieee1275_phandle_t dev; char *devpath; diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index 21345af57..dca83b7c6 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -148,8 +148,7 @@ grub_loopback_iterate (int (*hook) (const char *name), } static grub_err_t -grub_loopback_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_loopback_open (const char *name, grub_disk_t disk) { struct grub_loopback *dev; diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 9e304c001..06e9f6d6a 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -181,8 +181,7 @@ find_lv (const char *name) static const char *scan_for = NULL; static grub_err_t -grub_lvm_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull) +grub_lvm_open (const char *name, grub_disk_t disk) { struct grub_lvm_lv *lv = NULL; int explicit = 0; @@ -192,8 +191,7 @@ grub_lvm_open (const char *name, grub_disk_t disk, lv = find_lv (name); - if (! lv && !scan_depth && - pull == (explicit ? GRUB_DISK_PULL_RESCAN : GRUB_DISK_PULL_RESCAN_UNTYPED)) + if (! lv && !scan_depth && explicit) { scan_for = name; scan_depth++; diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 775234055..ed570c6a0 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -40,8 +40,7 @@ grub_memdisk_iterate (int (*hook) (const char *name), } static grub_err_t -grub_memdisk_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_memdisk_open (const char *name, grub_disk_t disk) { if (grub_strcmp (name, "memdisk")) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk"); diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index a7d36bfb2..5d8326daf 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -257,7 +257,7 @@ find_array (const char *name) } static grub_err_t -grub_raid_open (const char *name, grub_disk_t disk, grub_disk_pull_t pull) +grub_raid_open (const char *name, grub_disk_t disk) { struct grub_raid_array *array; unsigned n; @@ -268,7 +268,7 @@ grub_raid_open (const char *name, grub_disk_t disk, grub_disk_pull_t pull) array = find_array (name); - if (! array && pull == GRUB_DISK_PULL_RESCAN) + if (! array) { scan_devices (name); if (grub_errno) diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 5ab5177e9..610cc4dc5 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -371,8 +371,7 @@ grub_scsi_iterate (int (*hook) (const char *name), } static grub_err_t -grub_scsi_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_scsi_open (const char *name, grub_disk_t disk) { grub_scsi_dev_t p; grub_scsi_t scsi; diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 022157434..5584030bd 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -206,13 +206,9 @@ grub_disk_dev_iterate (int (*hook) (const char *name)) grub_disk_pull_t pull; for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) - { - if (pull == GRUB_DISK_PULL_RESCAN_UNTYPED) - continue; - for (p = grub_disk_dev_list; p; p = p->next) - if (p->iterate && (p->iterate) (hook, pull)) - return 1; - } + for (p = grub_disk_dev_list; p; p = p->next) + if (p->iterate && (p->iterate) (hook, pull)) + return 1; return 0; } @@ -243,7 +239,6 @@ grub_disk_open (const char *name) grub_disk_dev_t dev; char *raw = (char *) name; grub_uint64_t current_time; - grub_disk_pull_t pull; grub_dprintf ("disk", "Opening `%s'...\n", name); @@ -270,19 +265,14 @@ grub_disk_open (const char *name) if (! disk->name) goto fail; - for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) + for (dev = grub_disk_dev_list; dev; dev = dev->next) { - for (dev = grub_disk_dev_list; dev; dev = dev->next) - { - if ((dev->open) (raw, disk, pull) == GRUB_ERR_NONE) - break; - else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) - grub_errno = GRUB_ERR_NONE; - else - goto fail; - } - if (dev) + if ((dev->open) (raw, disk) == GRUB_ERR_NONE) break; + else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + grub_errno = GRUB_ERR_NONE; + else + goto fail; } if (! dev) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index a2f9ce084..59d7a4a2c 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -227,8 +227,7 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), } static grub_err_t -grub_util_biosdisk_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_util_biosdisk_open (const char *name, grub_disk_t disk) { int drive; struct stat st; diff --git a/include/grub/disk.h b/include/grub/disk.h index efa27a4d2..2b6d02972 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -56,7 +56,6 @@ typedef enum GRUB_DISK_PULL_NONE, GRUB_DISK_PULL_REMOVABLE, GRUB_DISK_PULL_RESCAN, - GRUB_DISK_PULL_RESCAN_UNTYPED, GRUB_DISK_PULL_MAX } grub_disk_pull_t; @@ -74,8 +73,7 @@ struct grub_disk_dev grub_disk_pull_t pull); /* Open the device named NAME, and set up DISK. */ - grub_err_t (*open) (const char *name, struct grub_disk *disk, - grub_disk_pull_t pull); + grub_err_t (*open) (const char *name, struct grub_disk *disk); /* Close the disk DISK. */ void (*close) (struct grub_disk *disk); From cd8fe79a594a644773493ac339a4a1ebf73dd527 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 03:59:05 +0200 Subject: [PATCH 284/673] Fix compilation on GNU/Linux. * grub-core/kern/emu/getroot.c (grub_util_pull_device) [!FreeBSD]: Disable geli. (grub_util_get_grub_dev) [!FreeBSD]: Likewise. (grub_util_pull_device) [HAVE_DEVICE_MAPPER]: Fix const and func name. * grub-core/disk/cryptodisk.c (grub_cryptodisk_open): Fix proto. --- ChangeLog | 10 ++++++++++ grub-core/disk/cryptodisk.c | 3 +-- grub-core/kern/emu/getroot.c | 9 ++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b587dae2a..4bef20b13 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-07-07 Vladimir Serbinenko + + Fix compilation on GNU/Linux. + + * grub-core/kern/emu/getroot.c (grub_util_pull_device) [!FreeBSD]: + Disable geli. + (grub_util_get_grub_dev) [!FreeBSD]: Likewise. + (grub_util_pull_device) [HAVE_DEVICE_MAPPER]: Fix const and func name. + * grub-core/disk/cryptodisk.c (grub_cryptodisk_open): Fix proto. + 2011-07-07 Vladimir Serbinenko 2011-07-07 Michael Gorven 2011-07-07 Clemens Fruhwirth diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 1a5e8164b..2852b65c4 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -413,8 +413,7 @@ grub_cryptodisk_iterate (int (*hook) (const char *name), } static grub_err_t -grub_cryptodisk_open (const char *name, grub_disk_t disk, - grub_disk_pull_t pull __attribute__ ((unused))) +grub_cryptodisk_open (const char *name, grub_disk_t disk) { grub_cryptodisk_t dev; diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index 380c5a7d1..9986fc5fc 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -975,6 +975,7 @@ grub_util_pull_device (const char *os_dev) switch (ab) { case GRUB_DEV_ABSTRACTION_GELI: +#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) { char *whole; struct gmesh mesh; @@ -1035,8 +1036,8 @@ grub_util_pull_device (const char *os_dev) grub_free (grdev); } - } +#endif break; case GRUB_DEV_ABSTRACTION_LVM: @@ -1065,14 +1066,14 @@ grub_util_pull_device (const char *os_dev) grub_util_pull_device (subdev); } } - if (ab == GRUB_DEV_ABSTRACTION_CRYPTO && lastsubdev) + if (ab == GRUB_DEV_ABSTRACTION_LUKS && lastsubdev) { char *grdev = grub_util_get_grub_dev (lastsubdev); dm_tree_free (tree); if (grdev) { grub_err_t err; - err = grub_luks_cheat_mount (grdev, os_dev); + err = grub_cryptodisk_cheat_mount (grdev, os_dev); if (err) grub_util_error ("Can't mount crypto: %s", grub_errmsg); } @@ -1141,6 +1142,7 @@ grub_util_get_grub_dev (const char *os_dev) break; case GRUB_DEV_ABSTRACTION_GELI: +#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) { char *whole; struct gmesh mesh; @@ -1187,6 +1189,7 @@ grub_util_get_grub_dev (const char *os_dev) } } } +#endif break; case GRUB_DEV_ABSTRACTION_RAID: From def9832af6b454f077c01100155c6a787b0b5f4d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 04:06:02 +0200 Subject: [PATCH 285/673] * po/POTFILES.in: Regenerate. --- ChangeLog | 4 ++ po/POTFILES.in | 117 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4bef20b13..e86b3a4f1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-08 Vladimir Serbinenko + + * po/POTFILES.in: Regenerate. + 2011-07-07 Vladimir Serbinenko Fix compilation on GNU/Linux. diff --git a/po/POTFILES.in b/po/POTFILES.in index 2bf4aa10c..83cb48b2c 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -83,16 +83,20 @@ grub-core/commands/videoinfo.c grub-core/commands/videotest.c grub-core/commands/wildcard.c grub-core/commands/xnu_uuid.c +grub-core/disk/AFSplitter.c grub-core/disk/ahci.c grub-core/disk/arc/arcdisk.c grub-core/disk/ata.c +grub-core/disk/cryptodisk.c grub-core/disk/dmraid_nvidia.c grub-core/disk/efi/efidisk.c +grub-core/disk/geli.c grub-core/disk/host.c grub-core/disk/i386/pc/biosdisk.c grub-core/disk/ieee1275/nand.c grub-core/disk/ieee1275/ofdisk.c grub-core/disk/loopback.c +grub-core/disk/luks.c grub-core/disk/lvm.c grub-core/disk/mdraid1x_linux.c grub-core/disk/mdraid_linux.c @@ -174,6 +178,59 @@ grub-core/gfxmenu/model.c grub-core/gfxmenu/theme_loader.c grub-core/gfxmenu/view.c grub-core/gfxmenu/widget-box.c +grub-core/gnulib/alloca.c +grub-core/gnulib/argp-ba.c +grub-core/gnulib/argp-eexst.c +grub-core/gnulib/argp-fmtstream.c +grub-core/gnulib/argp-fs-xinl.c +grub-core/gnulib/argp-help.c +grub-core/gnulib/argp-parse.c +grub-core/gnulib/argp-pin.c +grub-core/gnulib/argp-pv.c +grub-core/gnulib/argp-pvh.c +grub-core/gnulib/argp-xinl.c +grub-core/gnulib/asnprintf.c +grub-core/gnulib/basename-lgpl.c +grub-core/gnulib/btowc.c +grub-core/gnulib/dirname-lgpl.c +grub-core/gnulib/error.c +grub-core/gnulib/fnmatch.c +grub-core/gnulib/fnmatch_loop.c +grub-core/gnulib/getdelim.c +grub-core/gnulib/getline.c +grub-core/gnulib/getopt1.c +grub-core/gnulib/getopt.c +grub-core/gnulib/localcharset.c +grub-core/gnulib/malloc.c +grub-core/gnulib/mbrtowc.c +grub-core/gnulib/mbsinit.c +grub-core/gnulib/mbsrtowcs.c +grub-core/gnulib/mbsrtowcs-state.c +grub-core/gnulib/memchr.c +grub-core/gnulib/mempcpy.c +grub-core/gnulib/nl_langinfo.c +grub-core/gnulib/printf-args.c +grub-core/gnulib/printf-parse.c +grub-core/gnulib/progname.c +grub-core/gnulib/rawmemchr.c +grub-core/gnulib/realloc.c +grub-core/gnulib/regcomp.c +grub-core/gnulib/regex.c +grub-core/gnulib/regexec.c +grub-core/gnulib/regex_internal.c +grub-core/gnulib/sleep.c +grub-core/gnulib/stdio-write.c +grub-core/gnulib/strcasecmp.c +grub-core/gnulib/strchrnul.c +grub-core/gnulib/strerror.c +grub-core/gnulib/stripslash.c +grub-core/gnulib/strncasecmp.c +grub-core/gnulib/strndup.c +grub-core/gnulib/strnlen1.c +grub-core/gnulib/strnlen.c +grub-core/gnulib/vasnprintf.c +grub-core/gnulib/vsnprintf.c +grub-core/gnulib/wcrtomb.c grub-core/hello/hello.c grub-core/hook/datehook.c grub-core/io/bufio.c @@ -198,6 +255,7 @@ grub-core/kern/emu/lite.c grub-core/kern/emu/main.c grub-core/kern/emu/misc.c grub-core/kern/emu/mm.c +grub-core/kern/emu/raid.c grub-core/kern/emu/time.c grub-core/kern/env.c grub-core/kern/err.c @@ -264,6 +322,63 @@ grub-core/lib/ieee1275/datetime.c grub-core/lib/ieee1275/halt.c grub-core/lib/ieee1275/relocator.c grub-core/lib/legacy_parse.c +grub-core/lib/libgcrypt/cipher/ac.c +grub-core/lib/libgcrypt/cipher/arcfour.c +grub-core/lib/libgcrypt/cipher/blowfish.c +grub-core/lib/libgcrypt/cipher/camellia.c +grub-core/lib/libgcrypt/cipher/camellia-glue.c +grub-core/lib/libgcrypt/cipher/cast5.c +grub-core/lib/libgcrypt/cipher/cipher.c +grub-core/lib/libgcrypt/cipher/crc.c +grub-core/lib/libgcrypt/cipher/des.c +grub-core/lib/libgcrypt/cipher/dsa.c +grub-core/lib/libgcrypt/cipher/ecc.c +grub-core/lib/libgcrypt/cipher/elgamal.c +grub-core/lib/libgcrypt/cipher/hash-common.c +grub-core/lib/libgcrypt/cipher/hmac-tests.c +grub-core/lib/libgcrypt/cipher/md4.c +grub-core/lib/libgcrypt/cipher/md5.c +grub-core/lib/libgcrypt/cipher/md.c +grub-core/lib/libgcrypt/cipher/primegen.c +grub-core/lib/libgcrypt/cipher/pubkey.c +grub-core/lib/libgcrypt/cipher/rfc2268.c +grub-core/lib/libgcrypt/cipher/rijndael.c +grub-core/lib/libgcrypt/cipher/rmd160.c +grub-core/lib/libgcrypt/cipher/rsa.c +grub-core/lib/libgcrypt/cipher/seed.c +grub-core/lib/libgcrypt/cipher/serpent.c +grub-core/lib/libgcrypt/cipher/sha1.c +grub-core/lib/libgcrypt/cipher/sha256.c +grub-core/lib/libgcrypt/cipher/sha512.c +grub-core/lib/libgcrypt/cipher/tiger.c +grub-core/lib/libgcrypt/cipher/twofish.c +grub-core/lib/libgcrypt/cipher/whirlpool.c +grub-core/lib/libgcrypt-grub/cipher/arcfour.c +grub-core/lib/libgcrypt-grub/cipher/blowfish.c +grub-core/lib/libgcrypt-grub/cipher/camellia.c +grub-core/lib/libgcrypt-grub/cipher/camellia-glue.c +grub-core/lib/libgcrypt-grub/cipher/cast5.c +grub-core/lib/libgcrypt-grub/cipher/crc.c +grub-core/lib/libgcrypt-grub/cipher/des.c +grub-core/lib/libgcrypt-grub/cipher/dsa.c +grub-core/lib/libgcrypt-grub/cipher/ecc.c +grub-core/lib/libgcrypt-grub/cipher/elgamal.c +grub-core/lib/libgcrypt-grub/cipher/init.c +grub-core/lib/libgcrypt-grub/cipher/md4.c +grub-core/lib/libgcrypt-grub/cipher/md5.c +grub-core/lib/libgcrypt-grub/cipher/primegen.c +grub-core/lib/libgcrypt-grub/cipher/rfc2268.c +grub-core/lib/libgcrypt-grub/cipher/rijndael.c +grub-core/lib/libgcrypt-grub/cipher/rmd160.c +grub-core/lib/libgcrypt-grub/cipher/rsa.c +grub-core/lib/libgcrypt-grub/cipher/seed.c +grub-core/lib/libgcrypt-grub/cipher/serpent.c +grub-core/lib/libgcrypt-grub/cipher/sha1.c +grub-core/lib/libgcrypt-grub/cipher/sha256.c +grub-core/lib/libgcrypt-grub/cipher/sha512.c +grub-core/lib/libgcrypt-grub/cipher/tiger.c +grub-core/lib/libgcrypt-grub/cipher/twofish.c +grub-core/lib/libgcrypt-grub/cipher/whirlpool.c grub-core/lib/LzFind.c grub-core/lib/LzmaDec.c grub-core/lib/LzmaEnc.c @@ -371,6 +486,7 @@ grub-core/tests/example_functional_test.c grub-core/tests/lib/functional_test.c grub-core/tests/lib/test.c grub-core/tests/test_blockarg.c +grub-core/unidata.c grub-core/video/bitmap.c grub-core/video/bitmap_scale.c grub-core/video/bochs.c @@ -419,5 +535,4 @@ util/ieee1275/grub-ofpathname.c util/ieee1275/ofpath.c util/lvm.c util/misc.c -util/raid.c util/resolve.c From 4db34616962a6350cc94c07b8eddb18f66aae0f6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 04:07:15 +0200 Subject: [PATCH 286/673] Priority queue implementation --- grub-core/Makefile.core.def | 5 + grub-core/lib/priority_queue.c | 246 +++++++++++++++++++++++++++++++++ include/grub/priority_queue.h | 36 +++++ 3 files changed, 287 insertions(+) create mode 100644 grub-core/lib/priority_queue.c create mode 100644 include/grub/priority_queue.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7200bd3e9..a31d9963c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1667,6 +1667,11 @@ module = { enable = videomodules; }; +module = { + name = priority_queue; + common = lib/priority_queue.c; +}; + module = { name = time; common = commands/time.c; diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c new file mode 100644 index 000000000..5b02ef381 --- /dev/null +++ b/grub-core/lib/priority_queue.c @@ -0,0 +1,246 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#ifndef TEST +#include +#include +#else +#include +#include +#include + +#include + +using namespace std; + +typedef size_t grub_size_t; +typedef int (*grub_comparator_t) (const void *a, const void *b); +typedef unsigned char grub_uint8_t; +#define grub_malloc malloc +#define grub_memcpy memcpy +#define grub_realloc realloc +#define grub_free free + +typedef enum + { + GRUB_ERR_NONE, + grub_errno + } grub_err_t; +#endif + +struct grub_priority_queue +{ + grub_size_t elsize; + grub_size_t allocated; + grub_size_t used; + grub_comparator_t cmp; + void *els; +}; + +#ifdef TEST +typedef struct grub_priority_queue *grub_priority_queue_t; +#endif + +static inline void * +element (struct grub_priority_queue *pq, grub_size_t k) +{ + return ((grub_uint8_t *) pq->els) + k * pq->elsize; +} + +static inline void +swap (struct grub_priority_queue *pq, grub_size_t m, grub_size_t n) +{ + grub_uint8_t *p1, *p2; + grub_size_t l; + p1 = (grub_uint8_t *) element (pq, m); + p2 = (grub_uint8_t *) element (pq, n); + for (l = pq->elsize; l; l--, p1++, p2++) + { + grub_uint8_t t; + t = *p1; + *p1 = *p2; + *p2 = t; + } +} + +static inline grub_size_t +parent (grub_size_t v) +{ + return (v - 1) / 2; +} + +static inline grub_size_t +left_child (grub_size_t v) +{ + return 2 * v + 1; +} + +static inline grub_size_t +right_child (grub_size_t v) +{ + return 2 * v + 2; +} + +void * +grub_priority_queue_top (grub_priority_queue_t pq) +{ + if (!pq->used) + return 0; + return element (pq, 0); +} + +grub_priority_queue_t +grub_priority_queue_new (grub_size_t elsize, + grub_comparator_t cmp) +{ + struct grub_priority_queue *ret; + void *els; + els = grub_malloc (elsize * 8); + if (!els) + return 0; + ret = (struct grub_priority_queue *) grub_malloc (sizeof (*ret)); + if (!ret) + { + grub_free (els); + return 0; + } + ret->elsize = elsize; + ret->allocated = 8; + ret->used = 0; + ret->cmp = cmp; + ret->els = els; + return ret; +} + +/* Heap property: pq->cmp (element (pq, p), element (pq, parent (p))) <= 0. */ +grub_err_t +grub_priority_queue_push (grub_priority_queue_t pq, void *el) +{ + grub_size_t p; + if (pq->used == pq->allocated) + { + void *els; + els = grub_realloc (pq->els, pq->elsize * 2 * pq->allocated); + if (!els) + return grub_errno; + pq->allocated *= 2; + pq->els = els; + } + pq->used++; + grub_memcpy (element (pq, pq->used - 1), el, pq->elsize); + for (p = pq->used - 1; p; p = parent (p)) + { + if (pq->cmp (element (pq, p), element (pq, parent (p))) <= 0) + break; + swap (pq, p, parent (p)); + } + + return GRUB_ERR_NONE; +} + +void +grub_priority_queue_pop (grub_priority_queue_t pq) +{ + grub_size_t p; + + swap (pq, 0, pq->used - 1); + pq->used--; + for (p = 0; left_child (p) < pq->used; ) + { + grub_size_t c; + if (pq->cmp (element (pq, left_child (p)), element (pq, p)) <= 0 + && (right_child (p) >= pq->used + || pq->cmp (element (pq, right_child (p)), element (pq, p)) <= 0)) + break; + if (right_child (p) >= pq->used + || pq->cmp (element (pq, left_child (p)), + element (pq, right_child (p))) > 0) + c = left_child (p); + else + c = right_child (p); + swap (pq, p, c); + p = c; + } +} + +#ifdef TEST + +static int +compar (const void *a_, const void *b_) +{ + int a = *(int *) a_; + int b = *(int *) b_; + if (a < b) + return -1; + if (a > b) + return +1; + return 0; +} + +int +main (void) +{ + priority_queue pq; + grub_priority_queue_t pq2; + int counter; + int s = 0; + pq2 = grub_priority_queue_new (sizeof (int), compar); + if (!pq2) + return 1; + srand (1); + + for (counter = 0; counter < 1000000; counter++) + { + int op = rand () % 10; + if (s && *(int *) grub_priority_queue_top (pq2) != pq.top ()) + { + printf ("Error at %d\n", counter); + return 2; + } + if (op < 3 && s) + { + grub_priority_queue_pop (pq2); + pq.pop (); + s--; + } + else + { + int v = rand (); + int e; + pq.push (v); + e = grub_priority_queue_push (pq2, &v); + if (e) + return 3; + s++; + } + } + while (s) + { + if (*(int *) grub_priority_queue_top (pq2) != pq.top ()) + { + printf ("Error at the end. %d elements remaining.\n", s); + return 4; + } + grub_priority_queue_pop (pq2); + pq.pop (); + s--; + } + printf ("All tests passed successfully\n"); + return 0; +} +#endif diff --git a/include/grub/priority_queue.h b/include/grub/priority_queue.h new file mode 100644 index 000000000..335ea9a39 --- /dev/null +++ b/include/grub/priority_queue.h @@ -0,0 +1,36 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#ifndef GRUB_PRIORITY_QUEUE_HEADER +#define GRUB_PRIORITY_QUEUE_HEADER 1 + +#include +#include + +struct grub_priority_queue; +typedef struct grub_priority_queue *grub_priority_queue_t; +typedef int (*grub_comparator_t) (const void *a, const void *b); + +grub_priority_queue_t grub_priority_queue_new (grub_size_t elsize, + grub_comparator_t cmp); +void grub_priority_queue_destroy (grub_priority_queue_t pq); +void *grub_priority_queue_top (grub_priority_queue_t pq); +void grub_priority_queue_pop (grub_priority_queue_t pq); +grub_err_t grub_priority_queue_push (grub_priority_queue_t pq, void *el); + +#endif From 2e418de6460421240d5109b115b937694e6ba96e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 13:33:12 +0200 Subject: [PATCH 287/673] Remove getroot.c from core on emu platform. * grub-core/Makefile.core.def (kernel): Remove kern/emu/getroot.c and kern/emu/raid.c. * grub-core/kern/emu/main.c (main): Don't try to guess root device. It's useless. * grub-core/kern/emu/misc.c (get_win32_path): Moved from here... * util/getroot.c (get_win32_path): ... here. * grub-core/kern/emu/misc.c (fini_libzfs): Moved from here... * util/getroot.c (fini_libzfs): ... here. * grub-core/kern/emu/misc.c (grub_get_libzfs_handle): Moved from here... * util/getroot.c (grub_get_libzfs_handle): ... here. * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): Moved from here... * util/getroot.c (grub_find_zpool_from_dir): ... here. * grub-core/kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Moved from here... * util/getroot.c (grub_make_system_path_relative_to_its_root): ... here. * grub-core/kern/emu/getroot.c: Moved from here ... * util/getroot.c: ... here. All users updated. * grub-core/kern/emu/raid.c: Moved from here ... * util/raid.c: ... here. All users updated. --- ChangeLog | 25 +++ Makefile.util.def | 4 +- grub-core/Makefile.core.def | 2 - grub-core/kern/emu/main.c | 21 +- grub-core/kern/emu/misc.c | 267 ------------------------- {grub-core/kern/emu => util}/getroot.c | 259 ++++++++++++++++++++++++ {grub-core/kern/emu => util}/raid.c | 0 7 files changed, 289 insertions(+), 289 deletions(-) rename {grub-core/kern/emu => util}/getroot.c (84%) rename {grub-core/kern/emu => util}/raid.c (100%) diff --git a/ChangeLog b/ChangeLog index e86b3a4f1..33c5b0b92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2011-07-08 Vladimir Serbinenko + + Remove getroot.c from core on emu platform. + + * grub-core/Makefile.core.def (kernel): Remove kern/emu/getroot.c and + kern/emu/raid.c. + * grub-core/kern/emu/main.c (main): Don't try to guess root device. It's + useless. + * grub-core/kern/emu/misc.c (get_win32_path): Moved from here... + * util/getroot.c (get_win32_path): ... here. + * grub-core/kern/emu/misc.c (fini_libzfs): Moved from here... + * util/getroot.c (fini_libzfs): ... here. + * grub-core/kern/emu/misc.c (grub_get_libzfs_handle): Moved from here... + * util/getroot.c (grub_get_libzfs_handle): ... here. + * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): + Moved from here... + * util/getroot.c (grub_find_zpool_from_dir): ... here. + * grub-core/kern/emu/misc.c + (grub_make_system_path_relative_to_its_root): Moved from here... + * util/getroot.c (grub_make_system_path_relative_to_its_root): ... here. + * grub-core/kern/emu/getroot.c: Moved from here ... + * util/getroot.c: ... here. All users updated. + * grub-core/kern/emu/raid.c: Moved from here ... + * util/raid.c: ... here. All users updated. + 2011-07-08 Vladimir Serbinenko * po/POTFILES.in: Regenerate. diff --git a/Makefile.util.def b/Makefile.util.def index 18dd2fef8..c87020493 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -9,8 +9,8 @@ library = { common = grub-core/kern/command.c; common = grub-core/kern/device.c; common = grub-core/kern/disk.c; - common = grub-core/kern/emu/getroot.c; - common = grub-core/kern/emu/raid.c; + common = util/getroot.c; + common = util/raid.c; common = grub-core/kern/emu/hostdisk.c; common = grub-core/kern/emu/misc.c; common = grub-core/kern/emu/mm.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7200bd3e9..0924602f3 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -195,8 +195,6 @@ kernel = { emu = gnulib/error.c; emu = kern/emu/cache_s.S; emu = kern/emu/console.c; - emu = kern/emu/getroot.c; - emu = kern/emu/raid.c; emu = kern/emu/hostdisk.c; emu = kern/emu/hostfs.c; emu = kern/emu/main.c; diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 2092d03cb..9a58acd9e 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -111,7 +111,7 @@ usage (int status) "\n" "GRUB emulator.\n" "\n" - " -r, --root-device=DEV use DEV as the root device [default=guessed]\n" + " -r, --root-device=DEV use DEV as the root device [default=host]\n" " -m, --device-map=FILE use FILE as the device map [default=%s]\n" " -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n" " -v, --verbose print verbose messages\n" @@ -204,24 +204,9 @@ main (int argc, char *argv[]) /* Make sure that there is a root device. */ if (! root_dev) - { - char *device_name = grub_guess_root_device (dir); - if (! device_name) - grub_util_error ("cannot find a device for %s", dir); + root_dev = grub_strdup ("host"); - root_dev = grub_util_get_grub_dev (device_name); - if (! root_dev) - { - grub_util_info ("guessing the root device failed, because of `%s'", - grub_errmsg); - grub_util_error ("cannot guess the root device. Specify the option `--root-device'"); - } - } - - if (strcmp (root_dev, "host") == 0) - dir = xstrdup (dir); - else - dir = grub_make_system_path_relative_to_its_root (dir); + dir = xstrdup (dir); /* Start GRUB! */ if (setjmp (main_env) == 0) diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 44c40b010..737f5f1a9 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -46,14 +46,6 @@ # include #endif -#ifdef HAVE_LIBZFS -# include -#endif - -#ifdef HAVE_LIBNVPAIR -# include -#endif - #ifdef HAVE_SYS_PARAM_H # include #endif @@ -242,265 +234,6 @@ canonicalize_file_name (const char *path) return ret; } -#ifdef __CYGWIN__ -/* Convert POSIX path to Win32 path, - remove drive letter, replace backslashes. */ -static char * -get_win32_path (const char *path) -{ - char winpath[PATH_MAX]; - if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, path, winpath, sizeof(winpath))) - grub_util_error ("cygwin_conv_path() failed"); - - int len = strlen (winpath); - int offs = (len > 2 && winpath[1] == ':' ? 2 : 0); - - int i; - for (i = offs; i < len; i++) - if (winpath[i] == '\\') - winpath[i] = '/'; - return xstrdup (winpath + offs); -} -#endif - -#ifdef HAVE_LIBZFS -static libzfs_handle_t *__libzfs_handle; - -static void -fini_libzfs (void) -{ - libzfs_fini (__libzfs_handle); -} - -libzfs_handle_t * -grub_get_libzfs_handle (void) -{ - if (! __libzfs_handle) - { - __libzfs_handle = libzfs_init (); - - if (__libzfs_handle) - atexit (fini_libzfs); - } - - return __libzfs_handle; -} -#endif /* HAVE_LIBZFS */ - -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) -/* ZFS has similar problems to those of btrfs (see above). */ -void -grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) -{ - char *slash; - - *poolname = *poolfs = NULL; - -#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME) - /* FreeBSD and GNU/kFreeBSD. */ - { - struct statfs mnt; - - if (statfs (dir, &mnt) != 0) - return; - - if (strcmp (mnt.f_fstypename, "zfs") != 0) - return; - - *poolname = xstrdup (mnt.f_mntfromname); - } -#elif defined(HAVE_GETEXTMNTENT) - /* Solaris. */ - { - struct stat st; - struct extmnttab mnt; - - if (stat (dir, &st) != 0) - return; - - FILE *mnttab = fopen ("/etc/mnttab", "r"); - if (! mnttab) - return; - - while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0) - { - if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev - && !strcmp (mnt.mnt_fstype, "zfs")) - { - *poolname = xstrdup (mnt.mnt_special); - break; - } - } - - fclose (mnttab); - } -#endif - - if (! *poolname) - return; - - slash = strchr (*poolname, '/'); - if (slash) - { - *slash = '\0'; - *poolfs = xstrdup (slash + 1); - } - else - *poolfs = xstrdup (""); -} -#endif - -/* This function never prints trailing slashes (so that its output - can be appended a slash unconditionally). */ -char * -grub_make_system_path_relative_to_its_root (const char *path) -{ - struct stat st; - char *p, *buf, *buf2, *buf3, *ret; - uintptr_t offset = 0; - dev_t num; - size_t len; - -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - char *poolfs = NULL; -#endif - - /* canonicalize. */ - p = canonicalize_file_name (path); - if (p == NULL) - grub_util_error ("failed to get canonical path of %s", path); - -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */ - { - char *dummy; - grub_find_zpool_from_dir (p, &dummy, &poolfs); - } -#endif - - len = strlen (p) + 1; - buf = xstrdup (p); - free (p); - - if (stat (buf, &st) < 0) - grub_util_error ("cannot stat %s: %s", buf, strerror (errno)); - - buf2 = xstrdup (buf); - num = st.st_dev; - - /* This loop sets offset to the number of chars of the root - directory we're inspecting. */ - while (1) - { - p = strrchr (buf, '/'); - if (p == NULL) - /* This should never happen. */ - grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)"); - if (p != buf) - *p = 0; - else - *++p = 0; - - if (stat (buf, &st) < 0) - grub_util_error ("cannot stat %s: %s", buf, strerror (errno)); - - /* buf is another filesystem; we found it. */ - if (st.st_dev != num) - { - /* offset == 0 means path given is the mount point. - This works around special-casing of "/" in Un*x. This function never - prints trailing slashes (so that its output can be appended a slash - unconditionally). Each slash in is considered a preceding slash, and - therefore the root directory is an empty string. */ - if (offset == 0) - { - free (buf); -#ifdef __linux__ - { - char *bind; - grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); - if (bind && bind[0] && bind[1]) - { - buf3 = bind; - goto parsedir; - } - grub_free (bind); - } -#endif - free (buf2); -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - if (poolfs) - return xasprintf ("/%s/@", poolfs); -#endif - return xstrdup (""); - } - else - break; - } - - offset = p - buf; - /* offset == 1 means root directory. */ - if (offset == 1) - { - /* Include leading slash. */ - offset = 0; - break; - } - } - free (buf); - buf3 = xstrdup (buf2 + offset); - buf2[offset] = 0; -#ifdef __linux__ - { - char *bind; - grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); - if (bind && bind[0] && bind[1]) - { - char *temp = buf3; - buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3); - grub_free (temp); - } - grub_free (bind); - } -#endif - - free (buf2); - -#ifdef __CYGWIN__ - if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16)) - { - /* Reached some mount point not below /cygdrive. - GRUB does not know Cygwin's emulated mounts, - convert to Win32 path. */ - grub_util_info ("Cygwin path = %s\n", buf3); - char * temp = get_win32_path (buf3); - free (buf3); - buf3 = temp; - } -#endif - - parsedir: - /* Remove trailing slashes, return empty string if root directory. */ - len = strlen (buf3); - while (len > 0 && buf3[len - 1] == '/') - { - buf3[len - 1] = '\0'; - len--; - } - -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - if (poolfs) - { - ret = xasprintf ("/%s/@%s", poolfs, buf3); - free (buf3); - } - else -#endif - ret = buf3; - - return ret; -} - #ifdef HAVE_DEVICE_MAPPER static void device_mapper_null_log (int level __attribute__ ((unused)), const char *file __attribute__ ((unused)), diff --git a/grub-core/kern/emu/getroot.c b/util/getroot.c similarity index 84% rename from grub-core/kern/emu/getroot.c rename to util/getroot.c index 9986fc5fc..71064583f 100644 --- a/grub-core/kern/emu/getroot.c +++ b/util/getroot.c @@ -1330,3 +1330,262 @@ grub_util_check_char_device (const char *blk_dev) else return 0; } + +#ifdef __CYGWIN__ +/* Convert POSIX path to Win32 path, + remove drive letter, replace backslashes. */ +static char * +get_win32_path (const char *path) +{ + char winpath[PATH_MAX]; + if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, path, winpath, sizeof(winpath))) + grub_util_error ("cygwin_conv_path() failed"); + + int len = strlen (winpath); + int offs = (len > 2 && winpath[1] == ':' ? 2 : 0); + + int i; + for (i = offs; i < len; i++) + if (winpath[i] == '\\') + winpath[i] = '/'; + return xstrdup (winpath + offs); +} +#endif + +#ifdef HAVE_LIBZFS +static libzfs_handle_t *__libzfs_handle; + +static void +fini_libzfs (void) +{ + libzfs_fini (__libzfs_handle); +} + +libzfs_handle_t * +grub_get_libzfs_handle (void) +{ + if (! __libzfs_handle) + { + __libzfs_handle = libzfs_init (); + + if (__libzfs_handle) + atexit (fini_libzfs); + } + + return __libzfs_handle; +} +#endif /* HAVE_LIBZFS */ + +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) +/* ZFS has similar problems to those of btrfs (see above). */ +void +grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) +{ + char *slash; + + *poolname = *poolfs = NULL; + +#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME) + /* FreeBSD and GNU/kFreeBSD. */ + { + struct statfs mnt; + + if (statfs (dir, &mnt) != 0) + return; + + if (strcmp (mnt.f_fstypename, "zfs") != 0) + return; + + *poolname = xstrdup (mnt.f_mntfromname); + } +#elif defined(HAVE_GETEXTMNTENT) + /* Solaris. */ + { + struct stat st; + struct extmnttab mnt; + + if (stat (dir, &st) != 0) + return; + + FILE *mnttab = fopen ("/etc/mnttab", "r"); + if (! mnttab) + return; + + while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0) + { + if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev + && !strcmp (mnt.mnt_fstype, "zfs")) + { + *poolname = xstrdup (mnt.mnt_special); + break; + } + } + + fclose (mnttab); + } +#endif + + if (! *poolname) + return; + + slash = strchr (*poolname, '/'); + if (slash) + { + *slash = '\0'; + *poolfs = xstrdup (slash + 1); + } + else + *poolfs = xstrdup (""); +} +#endif + +/* This function never prints trailing slashes (so that its output + can be appended a slash unconditionally). */ +char * +grub_make_system_path_relative_to_its_root (const char *path) +{ + struct stat st; + char *p, *buf, *buf2, *buf3, *ret; + uintptr_t offset = 0; + dev_t num; + size_t len; + +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + char *poolfs = NULL; +#endif + + /* canonicalize. */ + p = canonicalize_file_name (path); + if (p == NULL) + grub_util_error ("failed to get canonical path of %s", path); + +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */ + { + char *dummy; + grub_find_zpool_from_dir (p, &dummy, &poolfs); + } +#endif + + len = strlen (p) + 1; + buf = xstrdup (p); + free (p); + + if (stat (buf, &st) < 0) + grub_util_error ("cannot stat %s: %s", buf, strerror (errno)); + + buf2 = xstrdup (buf); + num = st.st_dev; + + /* This loop sets offset to the number of chars of the root + directory we're inspecting. */ + while (1) + { + p = strrchr (buf, '/'); + if (p == NULL) + /* This should never happen. */ + grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)"); + if (p != buf) + *p = 0; + else + *++p = 0; + + if (stat (buf, &st) < 0) + grub_util_error ("cannot stat %s: %s", buf, strerror (errno)); + + /* buf is another filesystem; we found it. */ + if (st.st_dev != num) + { + /* offset == 0 means path given is the mount point. + This works around special-casing of "/" in Un*x. This function never + prints trailing slashes (so that its output can be appended a slash + unconditionally). Each slash in is considered a preceding slash, and + therefore the root directory is an empty string. */ + if (offset == 0) + { + free (buf); +#ifdef __linux__ + { + char *bind; + grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); + if (bind && bind[0] && bind[1]) + { + buf3 = bind; + goto parsedir; + } + grub_free (bind); + } +#endif + free (buf2); +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + if (poolfs) + return xasprintf ("/%s/@", poolfs); +#endif + return xstrdup (""); + } + else + break; + } + + offset = p - buf; + /* offset == 1 means root directory. */ + if (offset == 1) + { + /* Include leading slash. */ + offset = 0; + break; + } + } + free (buf); + buf3 = xstrdup (buf2 + offset); + buf2[offset] = 0; +#ifdef __linux__ + { + char *bind; + grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); + if (bind && bind[0] && bind[1]) + { + char *temp = buf3; + buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3); + grub_free (temp); + } + grub_free (bind); + } +#endif + + free (buf2); + +#ifdef __CYGWIN__ + if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16)) + { + /* Reached some mount point not below /cygdrive. + GRUB does not know Cygwin's emulated mounts, + convert to Win32 path. */ + grub_util_info ("Cygwin path = %s\n", buf3); + char * temp = get_win32_path (buf3); + free (buf3); + buf3 = temp; + } +#endif + + parsedir: + /* Remove trailing slashes, return empty string if root directory. */ + len = strlen (buf3); + while (len > 0 && buf3[len - 1] == '/') + { + buf3[len - 1] = '\0'; + len--; + } + +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + if (poolfs) + { + ret = xasprintf ("/%s/@%s", poolfs, buf3); + free (buf3); + } + else +#endif + ret = buf3; + + return ret; +} diff --git a/grub-core/kern/emu/raid.c b/util/raid.c similarity index 100% rename from grub-core/kern/emu/raid.c rename to util/raid.c From 1367c143dd181a84e459c3444ed08fc9ee683e12 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 14:41:52 +0200 Subject: [PATCH 288/673] several cleanups. Ping reply support --- grub-core/Makefile.core.def | 1 + grub-core/net/bootp.c | 3 +- grub-core/net/icmp.c | 107 ++++++++++++++++++++++++++++++++++++ grub-core/net/ip.c | 28 +++++++--- grub-core/net/tftp.c | 4 +- grub-core/net/udp.c | 107 ++++++++++++++++++++++++++++-------- include/grub/net.h | 38 +------------ include/grub/net/arp.h | 18 ++++++ include/grub/net/ip.h | 24 ++++++-- include/grub/net/udp.h | 21 +++---- 10 files changed, 263 insertions(+), 88 deletions(-) create mode 100644 grub-core/net/icmp.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2d96d6739..9bc893595 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1597,6 +1597,7 @@ module = { common = net/bootp.c; common = net/ip.c; common = net/udp.c; + common = net/icmp.c; common = net/ethernet.c; common = net/arp.c; common = net/netbuff.c; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 84bdc04d7..1428c2a07 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -488,7 +488,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; target.ipv4 = 0xffffffff; - err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + err = grub_net_send_ip_packet (&ifaces[j], &target, nb, + GRUB_NET_IP_UDP); grub_netbuff_free (nb); if (err) return err; diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c new file mode 100644 index 000000000..8ea020107 --- /dev/null +++ b/grub-core/net/icmp.c @@ -0,0 +1,107 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#include +#include +#include + +struct icmp_header +{ + grub_uint8_t type; + grub_uint8_t code; + grub_uint16_t checksum; +}; + +struct ping_header +{ + grub_uint16_t id; + grub_uint16_t seq; +}; + +enum + { + ICMP_ECHO_REPLY = 0, + ICMP_ECHO = 8, + }; + +grub_err_t +grub_net_recv_icmp_packet (struct grub_net_buff * nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *src) +{ + struct icmp_header *icmph; + grub_err_t err; + grub_uint16_t checksum; + + icmph = (struct icmp_header *) nb->data; + + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "ICMP packet too small"); + + checksum = icmph->checksum; + icmph->checksum = 0; + if (checksum != grub_net_ip_chksum (nb->data, nb->tail - nb->data)) + return GRUB_ERR_NONE; + icmph->checksum = checksum; + + err = grub_netbuff_pull (nb, sizeof (*icmph)); + if (err) + return err; + + switch (icmph->type) + { + case ICMP_ECHO: + { + struct grub_net_buff *nb_reply; + struct icmp_header *icmphr; + if (icmph->code) + break; + nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512); + if (!nb_reply) + { + grub_netbuff_free (nb); + return grub_errno; + } + err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512); + if (err) + goto ping_fail; + err = grub_netbuff_push (nb_reply, nb->tail - nb->data); + if (err) + goto ping_fail; + grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data); + err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); + if (err) + goto ping_fail; + icmphr = (struct icmp_header *) nb_reply->data; + icmphr->type = ICMP_ECHO_REPLY; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_chksum ((void *) nb_reply->data, + nb_reply->tail - nb_reply->data); + err = grub_net_send_ip_packet (inf, src, nb_reply, GRUB_NET_IP_ICMP); + + ping_fail: + grub_netbuff_free (nb); + grub_netbuff_free (nb_reply); + return err; + } + }; + + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 642a67f18..e2ba4adfb 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -50,18 +50,23 @@ struct ip6hdr } __attribute__ ((packed)); grub_uint16_t -grub_net_ip_chksum (void *ipv, int len) +grub_net_ip_chksum (void *ipv, grub_size_t len) { grub_uint16_t *ip = (grub_uint16_t *) ipv; grub_uint32_t sum = 0; - len >>= 1; - while (len--) + for (; len >= 2; len -= 2) { sum += grub_be_to_cpu16 (*(ip++)); if (sum > 0xFFFF) sum -= 0xFFFF; } + if (len) + { + sum += *((grub_uint8_t *) ip) << 8; + if (sum > 0xFFFF) + sum -= 0xFFFF; + } return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); } @@ -69,7 +74,8 @@ grub_net_ip_chksum (void *ipv, int len) grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, const grub_net_network_level_address_t * target, - struct grub_net_buff * nb) + struct grub_net_buff * nb, + grub_net_ip_protocol_t proto) { struct iphdr *iph; static int id = 0x2400; @@ -85,7 +91,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, iph->ident = grub_cpu_to_be16 (++id); iph->frags = 0; iph->ttl = 0xff; - iph->protocol = 0x11; + iph->protocol = proto; iph->src = inf->address.ipv4; iph->dest = target->ipv4; @@ -108,6 +114,7 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; struct grub_net_network_level_interface *inf = NULL; + grub_net_network_level_address_t source; err = grub_netbuff_pull (nb, sizeof (*iph)); if (err) @@ -117,7 +124,7 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, { struct udphdr *udph; udph = (struct udphdr *) nb->data; - if (iph->protocol == IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) + if (iph->protocol == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) { FOR_NET_NETWORK_LEVEL_INTERFACES (inf) if (inf->card == card @@ -146,10 +153,15 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, } } + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + source.ipv4 = iph->src; + switch (iph->protocol) { - case IP_UDP: - return grub_net_recv_udp_packet (nb, inf); + case GRUB_NET_IP_UDP: + return grub_net_recv_udp_packet (nb, inf, &source); + case GRUB_NET_IP_ICMP: + return grub_net_recv_icmp_packet (nb, inf, &source); default: grub_netbuff_free (nb); break; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index be1534021..13c4971f9 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -102,11 +102,11 @@ typedef struct tftp_data grub_uint64_t block; grub_uint32_t block_size; int have_oack; - grub_net_socket_t sock; + grub_net_udp_socket_t sock; } *tftp_data_t; static grub_err_t -tftp_receive (grub_net_socket_t sock __attribute__ ((unused)), +tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), struct grub_net_buff *nb, void *f) { diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 47a67a967..15bc1f490 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -1,13 +1,66 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #include #include #include #include #include -grub_net_socket_t +struct grub_net_udp_socket +{ + struct grub_net_udp_socket *next; + + enum { GRUB_NET_SOCKET_START, + GRUB_NET_SOCKET_ESTABLISHED, + GRUB_NET_SOCKET_CLOSED } status; + int in_port; + int out_port; + grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, + void *recv); + void *recv_hook_data; + grub_net_network_level_address_t out_nla; + struct grub_net_network_level_interface *inf; +}; + +struct grub_net_udp_socket *udp_sockets; + +#define FOR_UDP_SOCKETS(var) for (var = udp_sockets; var; var = var->next) + +static inline void +udp_socket_register (grub_net_udp_socket_t sock) +{ + grub_list_push (GRUB_AS_LIST_P (&udp_sockets), + GRUB_AS_LIST (sock)); +} + +void +grub_net_udp_close (grub_net_udp_socket_t sock) +{ + grub_list_remove (GRUB_AS_LIST_P (&udp_sockets), + GRUB_AS_LIST (sock)); + grub_free (sock); +} + +grub_net_udp_socket_t grub_net_udp_open (char *server, grub_uint16_t out_port, - grub_err_t (*recv_hook) (grub_net_socket_t sock, + grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, void *data), void *recv_hook_data) @@ -16,12 +69,18 @@ grub_net_udp_open (char *server, grub_net_network_level_address_t addr; struct grub_net_network_level_interface *inf; grub_net_network_level_address_t gateway; - grub_net_socket_t socket; + grub_net_udp_socket_t socket; static int in_port = 25300; err = grub_net_resolve_address (server, &addr); if (err) return NULL; + + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "not a IPv4 address"); + return NULL; + } err = grub_net_route_address (addr, &gateway, &inf); if (err) @@ -31,21 +90,21 @@ grub_net_udp_open (char *server, if (socket == NULL) return NULL; - socket->x_out_port = out_port; - socket->x_inf = inf; - socket->x_out_nla = addr; - socket->x_in_port = in_port++; - socket->x_status = GRUB_NET_SOCKET_START; + socket->out_port = out_port; + socket->inf = inf; + socket->out_nla = addr; + socket->in_port = in_port++; + socket->status = GRUB_NET_SOCKET_START; socket->recv_hook = recv_hook; socket->recv_hook_data = recv_hook_data; - grub_net_socket_register (socket); + udp_socket_register (socket); return socket; } grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket, +grub_net_send_udp_packet (const grub_net_udp_socket_t socket, struct grub_net_buff *nb) { struct udphdr *udph; @@ -56,37 +115,41 @@ grub_net_send_udp_packet (const grub_net_socket_t socket, return err; udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (socket->x_in_port); - udph->dst = grub_cpu_to_be16 (socket->x_out_port); + udph->src = grub_cpu_to_be16 (socket->in_port); + udph->dst = grub_cpu_to_be16 (socket->out_port); /* No chechksum. */ udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - return grub_net_send_ip_packet (socket->x_inf, &(socket->x_out_nla), nb); + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb, + GRUB_NET_IP_UDP); } grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff * nb, - struct grub_net_network_level_interface * inf) +grub_net_recv_udp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source) { struct udphdr *udph; - grub_net_socket_t sock; + grub_net_udp_socket_t sock; grub_err_t err; udph = (struct udphdr *) nb->data; err = grub_netbuff_pull (nb, sizeof (*udph)); if (err) return err; - FOR_NET_SOCKETS (sock) + FOR_UDP_SOCKETS (sock) { - if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port - && inf == sock->x_inf && sock->recv_hook) + if (grub_be_to_cpu16 (udph->dst) == sock->in_port + && inf == sock->inf && sock->recv_hook + && source->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && source->ipv4 == sock->out_nla.ipv4) { - if (sock->x_status == GRUB_NET_SOCKET_START) + if (sock->status == GRUB_NET_SOCKET_START) { - sock->x_out_port = grub_be_to_cpu16 (udph->src); - sock->x_status = GRUB_NET_SOCKET_ESTABLISHED; + sock->out_port = grub_be_to_cpu16 (udph->src); + sock->status = GRUB_NET_SOCKET_ESTABLISHED; } /* App protocol remove its own reader. */ diff --git a/include/grub/net.h b/include/grub/net.h index 45d08f3f5..f6600690a 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -196,40 +196,6 @@ struct grub_net_app_protocol grub_err_t (*close) (struct grub_file *file); }; -struct grub_net_socket -{ - struct grub_net_socket *next; - - enum { GRUB_NET_SOCKET_START, - GRUB_NET_SOCKET_ESTABLISHED, - GRUB_NET_SOCKET_CLOSED } x_status; - int x_in_port; - int x_out_port; - grub_err_t (*recv_hook) (grub_net_socket_t sock, struct grub_net_buff *nb, - void *recv); - void *recv_hook_data; - grub_net_network_level_address_t x_out_nla; - struct grub_net_network_level_interface *x_inf; -}; - -extern struct grub_net_socket *grub_net_sockets; - -static inline void -grub_net_socket_register (grub_net_socket_t sock) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (sock)); -} - -static inline void -grub_net_socket_unregister (grub_net_socket_t sock) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (sock)); -} - -#define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next) - typedef struct grub_net { char *server; @@ -337,7 +303,7 @@ void grub_net_card_unregister (struct grub_net_card *card); #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) -#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next) +#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = (var ? var->next : 0); var; var = next, next = (var ? var->next : 0)) struct grub_net_session * @@ -426,7 +392,7 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) -#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next) +#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = (var ? var->next : 0); var; var = next, next = (var ? var->next : 0)) void grub_net_poll_cards (unsigned time); diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index c60ea333f..27a6719c4 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #ifndef GRUB_NET_ARP_HEADER #define GRUB_NET_ARP_HEADER 1 #include diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 9bed1e19c..a3c64c1cb 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -21,13 +21,15 @@ #include #include -enum +typedef enum grub_net_ip_protocol { - IP_UDP = 0x11 /* UDP protocol */ - }; -#define IP_BROADCAST 0xFFFFFFFF + GRUB_NET_IP_ICMP = 1, + GRUB_NET_IP_TCP = 6, + GRUB_NET_IP_UDP = 17 + } grub_net_ip_protocol_t; +#define GRUB_NET_IP_BROADCAST 0xFFFFFFFF -grub_uint16_t grub_net_ip_chksum(void *ipv, int len); +grub_uint16_t grub_net_ip_chksum(void *ipv, grub_size_t len); grub_err_t grub_net_recv_ip_packets (struct grub_net_buff *nb, @@ -37,6 +39,16 @@ grub_net_recv_ip_packets (struct grub_net_buff *nb, grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, - struct grub_net_buff *nb); + struct grub_net_buff *nb, + grub_net_ip_protocol_t proto); + +grub_err_t +grub_net_recv_icmp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *src); +grub_err_t +grub_net_recv_udp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *src); #endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index 5aacf8abb..8d978569d 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -11,28 +11,23 @@ struct udphdr grub_uint16_t chksum; } __attribute__ ((packed)); +struct grub_net_udp_socket; +typedef struct grub_net_udp_socket *grub_net_udp_socket_t; -grub_net_socket_t +grub_net_udp_socket_t grub_net_udp_open (char *server, grub_uint16_t out_port, - grub_err_t (*recv_hook) (grub_net_socket_t sock, + grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, void *data), void *recv_hook_data); -static inline void -grub_net_udp_close (grub_net_socket_t sock) -{ - grub_net_socket_unregister (sock); - grub_free (sock); -} +void +grub_net_udp_close (grub_net_udp_socket_t sock); grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb); - -grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff *nb, - struct grub_net_network_level_interface *inf); +grub_net_send_udp_packet (const grub_net_udp_socket_t socket, + struct grub_net_buff *nb); #endif From 5438143da6b709575b9467e6660cb3f383509695 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 15:43:34 +0200 Subject: [PATCH 289/673] improve robustness of IPv4 receiving code --- grub-core/net/ip.c | 86 +++++++++++++++++++++++++++++++++++++++------ grub-core/net/net.c | 6 ++++ 2 files changed, 81 insertions(+), 11 deletions(-) diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index e2ba4adfb..ee3ccd4d6 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -35,9 +35,16 @@ struct iphdr { grub_uint8_t protocol; grub_uint16_t chksum; grub_uint32_t src; - grub_uint32_t dest; + grub_uint32_t dest; } __attribute__ ((packed)) ; +enum +{ + DONT_FRAGMENT = 0x4000, + MORE_FRAGMENTS = 0x2000, + OFFSET_MASK = 0x1fff +}; + struct ip6hdr { grub_uint8_t version:4, priority:4; @@ -116,9 +123,61 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, struct grub_net_network_level_interface *inf = NULL; grub_net_network_level_address_t source; - err = grub_netbuff_pull (nb, sizeof (*iph)); + if ((iph->verhdrlen >> 4) != 4) + { + grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if ((iph->verhdrlen & 0xf) < 5) + { + grub_dprintf ("net", "IP header too short: %d\n", + (iph->verhdrlen & 0xf)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + err = grub_netbuff_pull (nb, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); if (err) - return err; + { + grub_netbuff_free (nb); + return err; + } + + /* Check size*/ + { + grub_size_t expected_size = grub_be_to_cpu16 (iph->len); + grub_size_t actual_size = (nb->tail - nb->data + + (iph->verhdrlen & 0xf) + * sizeof (grub_uint32_t)); + if (actual_size > expected_size) + { + err = grub_netbuff_unput (nb, actual_size - expected_size); + if (err) + { + grub_netbuff_free (nb); + return err; + } + } + if (actual_size < expected_size) + { + grub_dprintf ("net", "Cut IP packet actual: %" PRIuGRUB_SIZE + ", expected %" PRIuGRUB_SIZE "\n", actual_size, + expected_size); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + } + + /* Fragmented packet. Bad. */ + if (((grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS) != 0) + || (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) != 0) + { + /* FIXME. */ + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } /* DHCP needs special treatment since we don't know IP yet. */ { @@ -136,21 +195,26 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, return err; grub_net_process_dhcp (nb, inf->card); grub_netbuff_free (nb); + return GRUB_ERR_NONE; } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } } + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && inf->address.ipv4 == iph->dest + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + } + if (!inf) { - FOR_NET_NETWORK_LEVEL_INTERFACES (inf) - { - if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && inf->address.ipv4 == iph->dest - && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) - break; - } + grub_netbuff_free (nb); + return GRUB_ERR_NONE; } source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 0f8a60413..7bed078e3 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -781,6 +781,12 @@ receive_packets (struct grub_net_card *card) break; } grub_net_recv_ethernet_packet (nb, card); + if (grub_errno) + { + grub_dprintf ("net", "error receiving: %d: %s\n", grub_errno, + grub_errmsg); + grub_errno = GRUB_ERR_NONE; + } } grub_print_error (); } From 6a1af81a97eb146e1b99dcbb039d722dbfa605c4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 18:49:35 +0200 Subject: [PATCH 290/673] add mtu information --- grub-core/net/drivers/efi/efinet.c | 1 + grub-core/net/drivers/emu/emunet.c | 18 ++++++++++++++++++ grub-core/net/drivers/i386/pc/pxe.c | 1 + grub-core/net/drivers/ieee1275/ofnet.c | 18 ++++++++++-------- include/grub/net.h | 1 + 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 5c6aac608..0fc779966 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -136,6 +136,7 @@ grub_efinet_findcards (void) card->driver = &efidriver; card->flags = 0; card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + card->mtu = net->mode->max_packet_size; grub_memcpy (card->default_address.mac, net->mode->current_address, sizeof (card->default_address.mac)); diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index d1e49a2f4..96f773340 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -1,3 +1,20 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ #include #include @@ -52,6 +69,7 @@ static struct grub_net_card emucard = { .name = "emu0", .driver = &emudriver, + .mtu = 1500, .default_address = { .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, {.mac = {0, 1, 2, 3, 4, 5}} diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index cd598ea72..588673177 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -345,6 +345,7 @@ GRUB_MOD_INIT(pxe) if (i == sizeof (grub_pxe_card.default_address.mac)) grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr, sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.mtu = ui->mtu; grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 20d45ee3d..035a96220 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -28,7 +28,6 @@ struct grub_ofnetcard_data { char *path; grub_ieee1275_ihandle_t handle; - grub_uint32_t mtu; }; static grub_err_t @@ -85,7 +84,7 @@ get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) grub_netbuff_clear (nb); start_time = grub_get_time_ms (); do - rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual); + rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu, &actual); while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); if (actual) { @@ -228,12 +227,15 @@ grub_ofnet_findcards (void) grub_ieee1275_finddevice (ofdata->path, &devhandle); - if (grub_ieee1275_get_integer_property - (devhandle, "max-frame-size", &(ofdata->mtu), - sizeof (ofdata->mtu), 0)) - { - ofdata->mtu = 1500; - } + { + grub_uint32_t t; + if (grub_ieee1275_get_integer_property (devhandle, + "max-frame-size", &t, + sizeof (t), 0)) + card->mtu = 1500; + else + card->mtu = t; + } if (grub_ieee1275_get_property (devhandle, "mac-address", &(lla.mac), 6, 0) diff --git a/include/grub/net.h b/include/grub/net.h index f6600690a..f3c0489e2 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -97,6 +97,7 @@ struct grub_net_card int opened; unsigned idle_poll_delay_ms; grub_uint64_t last_poll; + grub_size_t mtu; union { #ifdef GRUB_MACHINE_EFI From e2955971a3cd4e22e523fcc2ec07c1f3029060de Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 8 Jul 2011 20:38:12 +0200 Subject: [PATCH 291/673] move packet allocation to recv code to allow bigger buffers --- grub-core/net/drivers/efi/efinet.c | 58 ++++++++++++++++++-------- grub-core/net/drivers/emu/emunet.c | 31 ++++++++++---- grub-core/net/drivers/i386/pc/pxe.c | 30 ++++++++----- grub-core/net/drivers/ieee1275/ofnet.c | 22 +++++++--- grub-core/net/ip.c | 3 ++ grub-core/net/net.c | 13 +----- include/grub/net.h | 3 +- 7 files changed, 105 insertions(+), 55 deletions(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 0fc779966..906a688dc 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -42,43 +42,65 @@ send_card_buffer (const struct grub_net_card *dev, return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev, - struct grub_net_buff *nb) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev) { grub_efi_simple_network_t *net = dev->efi_net; grub_err_t err; grub_efi_status_t st; - grub_efi_uintn_t bufsize = 1500; + grub_efi_uintn_t bufsize = 1536; + struct grub_net_buff *nb; - err = grub_netbuff_clear (nb); - if (err) - return -1; + nb = grub_netbuff_alloc (bufsize); + if (!nb) + return NULL; - err = grub_netbuff_put (nb, 1500); - if (err) - return -1; + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } st = efi_call_7 (net->receive, net, NULL, &bufsize, nb->data, NULL, NULL, NULL); if (st == GRUB_EFI_BUFFER_TOO_SMALL) { - err = grub_netbuff_put (nb, bufsize - 1500); - if (err) - return -1; + grub_netbuff_free (nb); + + bufsize = ALIGN_UP (bufsize, 32); + + nb = grub_netbuff_alloc (bufsize); + if (!nb) + return NULL; + + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } + st = efi_call_7 (net->receive, net, NULL, &bufsize, nb->data, NULL, NULL, NULL); } if (st != GRUB_EFI_SUCCESS) { - grub_netbuff_clear (nb); - return -1; + grub_netbuff_free (nb); + return NULL; } - err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize); + err = grub_netbuff_put (nb, bufsize); if (err) - return -1; + { + grub_netbuff_free (nb); + return NULL; + } - return bufsize; + return nb; } static struct grub_net_card_driver efidriver = diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index 96f773340..ff333d370 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -43,19 +43,34 @@ send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)), return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *pack) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev __attribute__ ((unused))) { ssize_t actual; + struct grub_net_buff *nb; - grub_netbuff_clear (pack); - actual = read (fd, pack->data, 1500); + nb = grub_netbuff_alloc (1536); + if (!nb) + return NULL; + + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } + + actual = read (fd, nb->data, 1536); if (actual < 0) - return -1; - grub_netbuff_put (pack, actual); + { + grub_netbuff_free (nb); + return NULL; + } + grub_netbuff_put (nb, actual); - return actual; + return nb; } static struct grub_net_card_driver emudriver = diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 588673177..6c5f2fdc4 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -164,14 +164,13 @@ grub_pxe_scan (void) return bangpxe; } -static grub_ssize_t -grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *buf) +static struct grub_net_buff * +grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused))) { struct grub_pxe_undi_isr *isr; static int in_progress = 0; char *ptr, *end; - int len; + struct grub_net_buff *buf; isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -183,7 +182,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS) { in_progress = 0; - return -1; + return NULL; } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; @@ -201,17 +200,27 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE) { in_progress = 0; - return -1; + return NULL; } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); } - grub_netbuff_put (buf, isr->frame_len); + buf = grub_netbuff_alloc (isr->frame_len); + if (!buf) + return NULL; + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (buf, 2); + if (!buf) + { + grub_netbuff_free (buf); + return NULL; + } ptr = buf->data; end = ptr + isr->frame_len; - len = isr->frame_len; + grub_netbuff_put (buf, isr->frame_len); grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); ptr += isr->buffer_len; while (ptr < end) @@ -222,7 +231,8 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) { in_progress = 1; - return -1; + grub_netbuff_free (buf); + return NULL; } grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); @@ -230,7 +240,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), } in_progress = 1; - return len; + return buf; } static grub_err_t diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 035a96220..9c0c84c65 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -73,25 +73,35 @@ send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev) { grub_ssize_t actual; int rc; struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; + struct grub_net_buff *nb; - grub_netbuff_clear (nb); + nb = grub_netbuff_alloc (dev->mtu + 64); + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } start_time = grub_get_time_ms (); do - rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu, &actual); + rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual); while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); if (actual) { grub_netbuff_put (nb, actual); - return actual; + return nb; } - return -1; + grub_netbuff_free (nb); + return NULL; } static struct grub_net_card_driver ofdriver = diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index ee3ccd4d6..eaecc9ea6 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -123,6 +123,9 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, struct grub_net_network_level_interface *inf = NULL; grub_net_network_level_address_t source; + if (((grub_addr_t) nb->data) & 3) + grub_fatal ("unaligned %p\n", nb->data); + if ((iph->verhdrlen >> 4) != 4) { grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 7bed078e3..ab0fbd3c5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -764,19 +764,10 @@ receive_packets (struct grub_net_card *card) /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; - grub_ssize_t actual; - nb = grub_netbuff_alloc (1500); + + nb = card->driver->recv (card); if (!nb) { - grub_print_error (); - card->last_poll = grub_get_time_ms (); - return; - } - - actual = card->driver->recv (card, nb); - if (actual < 0) - { - grub_netbuff_free (nb); card->last_poll = grub_get_time_ms (); break; } diff --git a/include/grub/net.h b/include/grub/net.h index f3c0489e2..83f260d63 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -64,8 +64,7 @@ struct grub_net_card_driver void (*close) (const struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, struct grub_net_buff *buf); - grub_ssize_t (*recv) (const struct grub_net_card *dev, - struct grub_net_buff *buf); + struct grub_net_buff * (*recv) (const struct grub_net_card *dev); }; typedef struct grub_net_packet From fecdbd6b17e438f2e2ebd1b56e5745c6046e4ad0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 9 Jul 2011 00:27:27 +0200 Subject: [PATCH 292/673] support ip fragmentation --- grub-core/lib/priority_queue.c | 7 + grub-core/net/arp.c | 4 +- grub-core/net/ethernet.c | 2 + grub-core/net/ip.c | 414 +++++++++++++++++++++++++++------ grub-core/net/netbuff.c | 3 +- grub-core/net/tftp.c | 20 +- grub-core/net/udp.c | 2 + include/grub/net.h | 4 + include/grub/net/netbuff.h | 16 +- 9 files changed, 374 insertions(+), 98 deletions(-) diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c index 5b02ef381..772b7b854 100644 --- a/grub-core/lib/priority_queue.c +++ b/grub-core/lib/priority_queue.c @@ -104,6 +104,13 @@ grub_priority_queue_top (grub_priority_queue_t pq) return element (pq, 0); } +void +grub_priority_queue_destroy (grub_priority_queue_t pq) +{ + grub_free (pq->els); + grub_free (pq); +} + grub_priority_queue_t grub_priority_queue_new (grub_size_t elsize, grub_comparator_t cmp) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index d726f2c3a..b45bd4c9f 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -38,7 +38,7 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, struct grub_net_buff nb; struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; - char *aux, arp_data[128]; + grub_uint8_t *aux, arp_data[128]; grub_err_t err; int i; @@ -74,7 +74,7 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, arp_header->hln = 6; arp_header->pln = 4; arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); - aux = (char *) arp_header + sizeof (*arp_header); + aux = (grub_uint8_t *) arp_header + sizeof (*arp_header); /* Sender hardware address. */ grub_memcpy (aux, &inf->hwaddress.mac, 6); diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index acd33bcf6..c368eda54 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -57,6 +57,8 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, struct etherhdr *eth; grub_err_t err; + COMPILE_TIME_ASSERT (sizeof (*eth) < GRUB_NET_MAX_LINK_HEADER_SIZE); + err = grub_netbuff_push (nb, sizeof (*eth)); if (err) return err; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index eaecc9ea6..9144eabc6 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include struct iphdr { grub_uint8_t verhdrlen; @@ -56,6 +58,39 @@ struct ip6hdr grub_uint8_t daddr[16]; } __attribute__ ((packed)); +static int +cmp (const void *a__, const void *b__) +{ + struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; + struct grub_net_buff *b_ = *(struct grub_net_buff **) b__; + struct iphdr *a = (struct iphdr *) a_->data; + struct iphdr *b = (struct iphdr *) b_->data; + /* We want the first elements to be on top. */ + if ((grub_be_to_cpu16 (a->frags) & OFFSET_MASK) + < (grub_be_to_cpu16 (b->frags) & OFFSET_MASK)) + return +1; + if ((grub_be_to_cpu16 (a->frags) & OFFSET_MASK) + > (grub_be_to_cpu16 (b->frags) & OFFSET_MASK)) + return -1; + return 0; +} + +struct reassemble +{ + struct reassemble *next; + grub_uint32_t source; + grub_uint32_t dest; + grub_uint16_t id; + grub_uint8_t proto; + grub_uint64_t last_time; + grub_priority_queue_t pq; + grub_uint8_t *asm_buffer; + grub_size_t total_len; + grub_size_t cur_ptr; +}; + +struct reassemble *reassembles; + grub_uint16_t grub_net_ip_chksum (void *ipv, grub_size_t len) { @@ -78,6 +113,72 @@ grub_net_ip_chksum (void *ipv, grub_size_t len) return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); } +static int id = 0x2400; + +static grub_err_t +send_fragmented (struct grub_net_network_level_interface * inf, + const grub_net_network_level_address_t * target, + struct grub_net_buff * nb, + grub_net_ip_protocol_t proto, + grub_net_link_level_address_t ll_target_addr) +{ + grub_size_t off = 0; + grub_size_t fraglen; + grub_err_t err; + + fraglen = (inf->card->mtu - sizeof (struct iphdr)) & ~7; + id++; + + while (nb->tail - nb->data) + { + grub_size_t len = fraglen; + struct grub_net_buff *nb2; + struct iphdr *iph; + + if ((grub_ssize_t) len > nb->tail - nb->data) + len = nb->tail - nb->data; + nb2 = grub_netbuff_alloc (fraglen + sizeof (struct iphdr) + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb2) + return grub_errno; + err = grub_netbuff_reserve (nb2, GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + return err; + err = grub_netbuff_put (nb2, sizeof (struct iphdr)); + if (err) + return err; + + iph = (struct iphdr *) nb2->data; + iph->verhdrlen = ((4 << 4) | 5); + iph->service = 0; + iph->len = grub_cpu_to_be16 (len + sizeof (struct iphdr)); + iph->ident = grub_cpu_to_be16 (id); + iph->frags = grub_cpu_to_be16 (off | (((grub_ssize_t) len + == nb->tail - nb->data) + ? 0 : MORE_FRAGMENTS)); + iph->ttl = 0xff; + iph->protocol = proto; + iph->src = inf->address.ipv4; + iph->dest = target->ipv4; + off += len / 8; + + iph->chksum = 0; + iph->chksum = grub_net_ip_chksum ((void *) nb2->data, sizeof (*iph)); + err = grub_netbuff_put (nb2, len); + if (err) + return err; + grub_memcpy (iph + 1, nb->data, len); + err = grub_netbuff_pull (nb, len); + if (err) + return err; + err = send_ethernet_packet (inf, nb2, ll_target_addr, + GRUB_NET_ETHERTYPE_IP); + if (err) + return err; + } + return GRUB_ERR_NONE; +} + grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, const grub_net_network_level_address_t * target, @@ -85,10 +186,19 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, grub_net_ip_protocol_t proto) { struct iphdr *iph; - static int id = 0x2400; grub_net_link_level_address_t ll_target_addr; grub_err_t err; + COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph)); + + /* Determine link layer target address via ARP. */ + err = grub_net_arp_resolve (inf, target, &ll_target_addr); + if (err) + return err; + + if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu) + return send_fragmented (inf, target, nb, proto, ll_target_addr); + grub_netbuff_push (nb, sizeof (*iph)); iph = (struct iphdr *) nb->data; @@ -105,88 +215,26 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, iph->chksum = 0; iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph)); - /* Determine link layer target address via ARP. */ - err = grub_net_arp_resolve (inf, target, &ll_target_addr); - if (err) - return err; return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP); } -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff * nb, - const struct grub_net_card * card, - const grub_net_link_level_address_t * hwaddress) +static grub_err_t +handle_dgram (struct grub_net_buff *nb, + const struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + grub_net_ip_protocol_t proto, grub_uint32_t src, + grub_uint32_t dst) { - struct iphdr *iph = (struct iphdr *) nb->data; - grub_err_t err; struct grub_net_network_level_interface *inf = NULL; + grub_err_t err; grub_net_network_level_address_t source; - if (((grub_addr_t) nb->data) & 3) - grub_fatal ("unaligned %p\n", nb->data); - - if ((iph->verhdrlen >> 4) != 4) - { - grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - - if ((iph->verhdrlen & 0xf) < 5) - { - grub_dprintf ("net", "IP header too short: %d\n", - (iph->verhdrlen & 0xf)); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - - err = grub_netbuff_pull (nb, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); - if (err) - { - grub_netbuff_free (nb); - return err; - } - - /* Check size*/ - { - grub_size_t expected_size = grub_be_to_cpu16 (iph->len); - grub_size_t actual_size = (nb->tail - nb->data - + (iph->verhdrlen & 0xf) - * sizeof (grub_uint32_t)); - if (actual_size > expected_size) - { - err = grub_netbuff_unput (nb, actual_size - expected_size); - if (err) - { - grub_netbuff_free (nb); - return err; - } - } - if (actual_size < expected_size) - { - grub_dprintf ("net", "Cut IP packet actual: %" PRIuGRUB_SIZE - ", expected %" PRIuGRUB_SIZE "\n", actual_size, - expected_size); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - } - - /* Fragmented packet. Bad. */ - if (((grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS) != 0) - || (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) != 0) - { - /* FIXME. */ - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - /* DHCP needs special treatment since we don't know IP yet. */ { struct udphdr *udph; udph = (struct udphdr *) nb->data; - if (iph->protocol == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) + if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) { FOR_NET_NETWORK_LEVEL_INTERFACES (inf) if (inf->card == card @@ -209,7 +257,7 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, { if (inf->card == card && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && inf->address.ipv4 == iph->dest + && inf->address.ipv4 == dst && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) break; } @@ -221,9 +269,9 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, } source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - source.ipv4 = iph->src; + source.ipv4 = src; - switch (iph->protocol) + switch (proto) { case GRUB_NET_IP_UDP: return grub_net_recv_udp_packet (nb, inf, &source); @@ -233,6 +281,224 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, grub_netbuff_free (nb); break; } + return GRUB_ERR_NONE; +} + +static void +free_rsm (struct reassemble *rsm) +{ + struct grub_net_buff **nb; + while ((nb = grub_priority_queue_top (rsm->pq))) + { + grub_netbuff_free (*nb); + grub_priority_queue_pop (rsm->pq); + } + grub_free (rsm->asm_buffer); + grub_priority_queue_destroy (rsm->pq); +} + +static void +free_old_fragments (void) +{ + struct reassemble *rsm, **prev; + grub_uint64_t limit_time = grub_get_time_ms () - 90000; + + for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev) + if (rsm->last_time < limit_time) + { + *prev = rsm->next; + free_rsm (rsm); + } +} + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff * nb, + const struct grub_net_card * card, + const grub_net_link_level_address_t * hwaddress) +{ + struct iphdr *iph = (struct iphdr *) nb->data; + grub_err_t err; + struct reassemble *rsm, **prev; + + if ((iph->verhdrlen >> 4) != 4) + { + grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if ((iph->verhdrlen & 0xf) < 5) + { + grub_dprintf ("net", "IP header too short: %d\n", + (iph->verhdrlen & 0xf)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if (nb->tail - nb->data < (grub_ssize_t) ((iph->verhdrlen & 0xf) + * sizeof (grub_uint32_t))) + { + grub_dprintf ("net", "IP packet too short: %d\n", + (iph->verhdrlen & 0xf)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + /* Check size. */ + { + grub_size_t expected_size = grub_be_to_cpu16 (iph->len); + grub_size_t actual_size = (nb->tail - nb->data); + if (actual_size > expected_size) + { + err = grub_netbuff_unput (nb, actual_size - expected_size); + if (err) + { + grub_netbuff_free (nb); + return err; + } + } + if (actual_size < expected_size) + { + grub_dprintf ("net", "Cut IP packet actual: %" PRIuGRUB_SIZE + ", expected %" PRIuGRUB_SIZE "\n", actual_size, + expected_size); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + } + + /* Unfragmented packet. Good. */ + if (((grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS) == 0) + && (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) == 0) + { + err = grub_netbuff_pull (nb, ((iph->verhdrlen & 0xf) + * sizeof (grub_uint32_t))); + if (err) + { + grub_netbuff_free (nb); + return err; + } + return handle_dgram (nb, card, hwaddress, iph->protocol, + iph->src, iph->dest); + } + + for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev) + if (rsm->source == iph->src && rsm->dest == iph->dest + && rsm->id == iph->ident && rsm->proto == iph->protocol) + break; + if (!rsm) + { + rsm = grub_malloc (sizeof (*rsm)); + if (!rsm) + return grub_errno; + rsm->source = iph->src; + rsm->dest = iph->dest; + rsm->id = iph->ident; + rsm->proto = iph->protocol; + rsm->next = reassembles; + reassembles = rsm; + prev = &reassembles; + rsm->pq = grub_priority_queue_new (sizeof (struct grub_net_buff **), cmp); + if (!rsm->pq) + { + grub_free (rsm); + return grub_errno; + } + rsm->asm_buffer = 0; + rsm->total_len = 0; + rsm->cur_ptr = 0; + } + + rsm->last_time = grub_get_time_ms (); + free_old_fragments (); + + err = grub_priority_queue_push (rsm->pq, &nb); + if (err) + return err; + + if (!(grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS)) + { + rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + + (nb->tail - nb->data)); + rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); + rsm->asm_buffer = grub_zalloc (rsm->total_len); + if (!rsm->asm_buffer) + { + *prev = rsm->next; + free_rsm (rsm); + return grub_errno; + } + } + if (!rsm->asm_buffer) + return GRUB_ERR_NONE; + + while (1) + { + struct grub_net_buff **nb_top_p, *nb_top; + grub_size_t copy; + grub_uint8_t *res; + grub_size_t res_len; + struct grub_net_buff *ret; + grub_net_ip_protocol_t proto; + grub_uint32_t src; + grub_uint32_t dst; + + nb_top_p = grub_priority_queue_top (rsm->pq); + if (!nb_top_p) + return GRUB_ERR_NONE; + nb_top = *nb_top_p; + grub_priority_queue_pop (rsm->pq); + iph = (struct iphdr *) nb_top->data; + err = grub_netbuff_pull (nb_top, ((iph->verhdrlen & 0xf) + * sizeof (grub_uint32_t))); + if (err) + { + grub_netbuff_free (nb_top); + return err; + } + if (rsm->cur_ptr < (grub_size_t) 8 * (grub_be_to_cpu16 (iph->frags) + & OFFSET_MASK)) + return GRUB_ERR_NONE; + + rsm->cur_ptr = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + + (nb_top->tail - nb_top->head)); + if ((grub_size_t) 8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + >= rsm->total_len) + { + grub_netbuff_free (nb_top); + continue; + } + copy = nb_top->tail - nb_top->data; + if (rsm->total_len - 8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + < copy) + copy = rsm->total_len - 8 * (grub_be_to_cpu16 (iph->frags) + & OFFSET_MASK); + grub_memcpy (&rsm->asm_buffer[8 * (grub_be_to_cpu16 (iph->frags) + & OFFSET_MASK)], + nb_top->data, copy); + + if ((grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS)) + continue; + + res = rsm->asm_buffer; + proto = rsm->proto; + src = rsm->source; + dst = rsm->dest; + + rsm->asm_buffer = 0; + res_len = rsm->total_len; + *prev = rsm->next; + free_rsm (rsm); + ret = grub_malloc (sizeof (*ret)); + if (!ret) + { + grub_free (res); + return grub_errno; + } + ret->data = ret->head = res; + ret->tail = ret->end = res + res_len; + return handle_dgram (ret, card, hwaddress, proto, src, dst); + } return GRUB_ERR_NONE; } diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index d20104ab0..cb6106fc7 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -21,7 +21,6 @@ #include #include - grub_err_t grub_netbuff_put (struct grub_net_buff *nb, grub_size_t len) { @@ -87,7 +86,7 @@ grub_netbuff_alloc (grub_size_t len) return NULL; nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); nb->head = nb->data = nb->tail = data; - nb->end = (char *) nb; + nb->end = (grub_uint8_t *) nb; return nb; } diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 13c4971f9..659e836c0 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -112,10 +112,10 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), { grub_file_t file = f; struct tftphdr *tftph = (void *) nb->data; - char nbdata[512]; + grub_uint8_t nbdata[512]; tftp_data_t data = file->data; grub_err_t err; - char *ptr; + grub_uint8_t *ptr; struct grub_net_buff nb_ack; nb_ack.head = nbdata; @@ -130,15 +130,11 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) - { - data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, - 0, 0); - } + data->file_size = grub_strtoul ((char *) ptr + sizeof ("tsize\0") + - 1, 0, 0); if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) - { - data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, - 0, 0); - } + data->block_size = grub_strtoul ((char *) ptr + sizeof ("blksize\0") + - 1, 0, 0); while (ptr < nb->tail && *ptr) ptr++; ptr++; @@ -210,7 +206,7 @@ tftp_open (struct grub_file *file, const char *filename) int i; int rrqlen; int hdrlen; - char open_data[1500]; + grub_uint8_t open_data[1500]; struct grub_net_buff nb; tftp_data_t data; grub_err_t err; @@ -312,7 +308,7 @@ tftp_close (struct grub_file *file) if (data->sock) { - char nbdata[512]; + grub_uint8_t nbdata[512]; grub_err_t err; struct grub_net_buff nb_err; struct tftphdr *tftph; diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 15bc1f490..0a43fe24f 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -110,6 +110,8 @@ grub_net_send_udp_packet (const grub_net_udp_socket_t socket, struct udphdr *udph; grub_err_t err; + COMPILE_TIME_ASSERT (GRUB_NET_UDP_HEADER_SIZE == sizeof (*udph)); + err = grub_netbuff_push (nb, sizeof (*udph)); if (err) return err; diff --git a/include/grub/net.h b/include/grub/net.h index 83f260d63..e7631b884 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -27,6 +27,10 @@ #include #include +#define GRUB_NET_MAX_LINK_HEADER_SIZE 64 +#define GRUB_NET_UDP_HEADER_SIZE 8 +#define GRUB_NET_OUR_IPV4_HEADER_SIZE 20 + typedef enum grub_link_level_protocol_id { GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h index 245e813c3..5fafd89f6 100644 --- a/include/grub/net/netbuff.h +++ b/include/grub/net/netbuff.h @@ -8,14 +8,14 @@ struct grub_net_buff { - /*Pointer to the start of the buffer*/ - char *head; - /*Pointer to the data */ - char *data; - /*Pointer to the tail */ - char *tail; - /*Pointer to the end of the buffer*/ - char *end; + /* Pointer to the start of the buffer. */ + grub_uint8_t *head; + /* Pointer to the data. */ + grub_uint8_t *data; + /* Pointer to the tail. */ + grub_uint8_t *tail; + /* Pointer to the end of the buffer. */ + grub_uint8_t *end; }; grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len); From 92bb3cfc1792b0fe0cc6888223f319dfd9384432 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 9 Jul 2011 01:28:47 +0200 Subject: [PATCH 293/673] Use priority queue to reassemble TFTP packets --- grub-core/lib/priority_queue.c | 2 +- grub-core/net/tftp.c | 187 +++++++++++++++++++++++---------- include/grub/priority_queue.h | 2 +- 3 files changed, 135 insertions(+), 56 deletions(-) diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c index 772b7b854..0cf258ecf 100644 --- a/grub-core/lib/priority_queue.c +++ b/grub-core/lib/priority_queue.c @@ -136,7 +136,7 @@ grub_priority_queue_new (grub_size_t elsize, /* Heap property: pq->cmp (element (pq, p), element (pq, parent (p))) <= 0. */ grub_err_t -grub_priority_queue_push (grub_priority_queue_t pq, void *el) +grub_priority_queue_push (grub_priority_queue_t pq, const void *el) { grub_size_t p; if (pq->used == pq->allocated) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 659e836c0..16616cfea 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -103,8 +105,49 @@ typedef struct tftp_data grub_uint32_t block_size; int have_oack; grub_net_udp_socket_t sock; + grub_priority_queue_t pq; } *tftp_data_t; +static int +cmp (const void *a__, const void *b__) +{ + struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; + struct grub_net_buff *b_ = *(struct grub_net_buff **) b__; + struct tftphdr *a = (struct tftphdr *) a_->data; + struct tftphdr *b = (struct tftphdr *) b_->data; + /* We want the first elements to be on top. */ + if (grub_be_to_cpu16 (a->u.data.block) < grub_be_to_cpu16 (b->u.data.block)) + return +1; + if (grub_be_to_cpu16 (a->u.data.block) > grub_be_to_cpu16 (b->u.data.block)) + return -1; + return 0; +} + +static grub_err_t +ack (grub_net_udp_socket_t sock, grub_uint16_t block) +{ + struct tftphdr *tftph_ack; + grub_uint8_t nbdata[512]; + struct grub_net_buff nb_ack; + grub_err_t err; + + nb_ack.head = nbdata; + nb_ack.end = nbdata + sizeof (nbdata); + grub_netbuff_clear (&nb_ack); + grub_netbuff_reserve (&nb_ack, 512); + err = grub_netbuff_push (&nb_ack, sizeof (tftph_ack->opcode) + + sizeof (tftph_ack->u.ack.block)); + if (err) + return err; + + tftph_ack = (struct tftphdr *) nb_ack.data; + tftph_ack->opcode = grub_cpu_to_be16 (TFTP_ACK); + tftph_ack->u.ack.block = block; + + err = grub_net_send_udp_packet (sock, &nb_ack); + return err; +} + static grub_err_t tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), struct grub_net_buff *nb, @@ -112,14 +155,12 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), { grub_file_t file = f; struct tftphdr *tftph = (void *) nb->data; - grub_uint8_t nbdata[512]; tftp_data_t data = file->data; grub_err_t err; grub_uint8_t *ptr; - struct grub_net_buff nb_ack; - nb_ack.head = nbdata; - nb_ack.end = nbdata + sizeof (nbdata); + if (nb->tail - nb->data < (grub_ssize_t) sizeof (tftph->opcode)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "TFTP packet too small"); tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) @@ -141,61 +182,89 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), } data->block = 0; grub_netbuff_free (nb); - break; - case TFTP_DATA: - err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block)); + err = ack (data->sock, 0); if (err) return err; - if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) - { - unsigned size = nb->tail - nb->data; - data->block++; - if (size < data->block_size) - { - file->device->net->eof = 1; - } - /* Prevent garbage in broken cards. */ - if (size > data->block_size) - { - err = grub_netbuff_unput (nb, size - data->block_size); - if (err) - return err; - } - /* If there is data, puts packet in socket list. */ - if ((nb->tail - nb->data) > 0) - grub_net_put_packet (&file->device->net->packs, nb); - else - grub_netbuff_free (nb); - } - else - { - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - break; + return GRUB_ERR_NONE; + case TFTP_DATA: + if (nb->tail - nb->data < (grub_ssize_t) (sizeof (tftph->opcode) + + sizeof (tftph->u.data.block))) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "TFTP packet too small"); + err = ack (data->sock, tftph->u.data.block); + if (err) + return err; + + err = grub_priority_queue_push (data->pq, &nb); + if (err) + return err; + + { + struct grub_net_buff **nb_top_p, *nb_top; + while (1) + { + nb_top_p = grub_priority_queue_top (data->pq); + if (!nb_top_p) + return GRUB_ERR_NONE; + nb_top = *nb_top_p; + tftph = (struct tftphdr *) nb_top->data; + grub_refresh (); + if (grub_be_to_cpu16 (tftph->u.data.block) >= data->block + 1) + break; + grub_priority_queue_pop (data->pq); + } + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + { + unsigned size; + + grub_priority_queue_pop (data->pq); + + err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (err) + return err; + size = nb_top->tail - nb_top->data; + + data->block++; + if (size < data->block_size) + { + file->device->net->eof = 1; + grub_net_udp_close (data->sock); + data->sock = NULL; + } + /* Prevent garbage in broken cards. Is it still necessary + given that IP implementation has been fixed? + */ + if (size > data->block_size) + { + err = grub_netbuff_unput (nb_top, size - data->block_size); + if (err) + return err; + } + /* If there is data, puts packet in socket list. */ + if ((nb_top->tail - nb_top->data) > 0) + grub_net_put_packet (&file->device->net->packs, nb_top); + else + grub_netbuff_free (nb); + } + } + return GRUB_ERR_NONE; case TFTP_ERROR: grub_netbuff_free (nb); return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); + default: + grub_netbuff_free (nb); + return GRUB_ERR_NONE; } - grub_netbuff_clear (&nb_ack); - grub_netbuff_reserve (&nb_ack, 512); - err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); - if (err) - return err; +} - tftph = (struct tftphdr *) nb_ack.data; - tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - tftph->u.ack.block = grub_cpu_to_be16 (data->block); +static void +destroy_pq (tftp_data_t data) +{ + struct grub_net_buff **nb_p; + while ((nb_p = grub_priority_queue_top (data->pq))) + grub_netbuff_free (*nb_p); - err = grub_net_send_udp_packet (data->sock, &nb_ack); - if (file->device->net->eof) - { - grub_net_udp_close (data->sock); - data->sock = NULL; - } - return err; + grub_priority_queue_destroy (data->pq); } static grub_err_t @@ -261,16 +330,25 @@ tftp_open (struct grub_file *file, const char *filename) file->not_easily_seekable = 1; file->data = data; + + data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp); + if (!data->pq) + return grub_errno; + data->sock = grub_net_udp_open (file->device->net->server, TFTP_SERVER_PORT, tftp_receive, file); if (!data->sock) - return grub_errno; + { + destroy_pq (data); + return grub_errno; + } err = grub_net_send_udp_packet (data->sock, &nb); if (err) { grub_net_udp_close (data->sock); + destroy_pq (data); return err; } @@ -278,8 +356,6 @@ tftp_open (struct grub_file *file, const char *filename) for (i = 0; i < 3; i++) { grub_net_poll_cards (100); - if (grub_errno) - return grub_errno; if (data->have_oack) break; /* Retry. */ @@ -287,6 +363,7 @@ tftp_open (struct grub_file *file, const char *filename) if (err) { grub_net_udp_close (data->sock); + destroy_pq (data); return err; } } @@ -294,6 +371,7 @@ tftp_open (struct grub_file *file, const char *filename) if (!data->have_oack) { grub_net_udp_close (data->sock); + destroy_pq (data); return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); } file->size = data->file_size; @@ -334,6 +412,7 @@ tftp_close (struct grub_file *file) grub_print_error (); grub_net_udp_close (data->sock); } + destroy_pq (data); grub_free (data); return GRUB_ERR_NONE; } diff --git a/include/grub/priority_queue.h b/include/grub/priority_queue.h index 335ea9a39..a5d98c8c9 100644 --- a/include/grub/priority_queue.h +++ b/include/grub/priority_queue.h @@ -31,6 +31,6 @@ grub_priority_queue_t grub_priority_queue_new (grub_size_t elsize, void grub_priority_queue_destroy (grub_priority_queue_t pq); void *grub_priority_queue_top (grub_priority_queue_t pq); void grub_priority_queue_pop (grub_priority_queue_t pq); -grub_err_t grub_priority_queue_push (grub_priority_queue_t pq, void *el); +grub_err_t grub_priority_queue_push (grub_priority_queue_t pq, const void *el); #endif From 3a7af37260e317bd555988d9e8a457d9d6767247 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 08:46:48 +0200 Subject: [PATCH 294/673] basic tcp implementation --- grub-core/Makefile.core.def | 1 + grub-core/net/bootp.c | 6 +- grub-core/net/ip.c | 37 ++- grub-core/net/net.c | 2 + grub-core/net/tcp.c | 637 ++++++++++++++++++++++++++++++++++++ grub-core/net/tftp.c | 19 +- grub-core/net/udp.c | 51 ++- include/grub/err.h | 1 + include/grub/net.h | 3 + include/grub/net/ip.h | 10 + include/grub/net/tcp.h | 44 +++ include/grub/net/udp.h | 18 + 12 files changed, 802 insertions(+), 27 deletions(-) create mode 100644 grub-core/net/tcp.c create mode 100644 include/grub/net/tcp.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 9bc893595..673092b4f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1597,6 +1597,7 @@ module = { common = net/bootp.c; common = net/ip.c; common = net/udp.c; + common = net/tcp.c; common = net/icmp.c; common = net/ethernet.c; common = net/arp.c; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 1428c2a07..b1db05147 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -473,7 +473,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), t = 0; } pack->ident = grub_cpu_to_be32 (t); - pack->seconds = 0;//grub_cpu_to_be16 (t); + pack->seconds = grub_cpu_to_be16 (t); grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); @@ -484,9 +484,11 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), udph->dst = grub_cpu_to_be16 (67); udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; target.ipv4 = 0xffffffff; + udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, + &ifaces[j].address, + &target); err = grub_net_send_ip_packet (&ifaces[j], &target, nb, GRUB_NET_IP_UDP); diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 9144eabc6..69579970f 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -100,13 +100,13 @@ grub_net_ip_chksum (void *ipv, grub_size_t len) for (; len >= 2; len -= 2) { sum += grub_be_to_cpu16 (*(ip++)); - if (sum > 0xFFFF) + if (sum >= 0xFFFF) sum -= 0xFFFF; } if (len) { sum += *((grub_uint8_t *) ip) << 8; - if (sum > 0xFFFF) + if (sum >= 0xFFFF) sum -= 0xFFFF; } @@ -229,6 +229,13 @@ handle_dgram (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf = NULL; grub_err_t err; grub_net_network_level_address_t source; + grub_net_network_level_address_t dest; + + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + source.ipv4 = src; + + dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + dest.ipv4 = dst; /* DHCP needs special treatment since we don't know IP yet. */ { @@ -241,6 +248,27 @@ handle_dgram (struct grub_net_buff *nb, && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) { + if (udph->chksum) + { + grub_uint16_t chk, expected; + chk = udph->chksum; + udph->chksum = 0; + expected = grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_UDP, + &source, + &dest); + if (expected != chk) + { + grub_dprintf ("net", "Invalid UDP checksum. " + "Expected %x, got %x\n", + grub_be_to_cpu16 (expected), + grub_be_to_cpu16 (chk)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + udph->chksum = chk; + } + err = grub_netbuff_pull (nb, sizeof (*udph)); if (err) return err; @@ -268,13 +296,12 @@ handle_dgram (struct grub_net_buff *nb, return GRUB_ERR_NONE; } - source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - source.ipv4 = src; - switch (proto) { case GRUB_NET_IP_UDP: return grub_net_recv_udp_packet (nb, inf, &source); + case GRUB_NET_IP_TCP: + return grub_net_recv_tcp_packet (nb, inf, &source); case GRUB_NET_IP_ICMP: return grub_net_recv_icmp_packet (nb, inf, &source); default: diff --git a/grub-core/net/net.c b/grub-core/net/net.c index ab0fbd3c5..0ff8d01ff 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -793,6 +793,7 @@ grub_net_poll_cards (unsigned time) while ((grub_get_time_ms () - start_time) < time) receive_packets (card); } + grub_net_tcp_retransmit (); } static void @@ -807,6 +808,7 @@ grub_net_poll_cards_idle_real (void) || ctime >= card->last_poll + card->idle_poll_delay_ms) receive_packets (card); } + grub_net_tcp_retransmit (); } /* Read from the packets list*/ diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c new file mode 100644 index 000000000..3bc3d5c9c --- /dev/null +++ b/grub-core/net/tcp.c @@ -0,0 +1,637 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#include +#include +#include +#include +#include +#include + +#define TCP_SYN_RETRANSMISSION_TIMEOUT 1000 +#define TCP_SYN_RETRANSMISSION_COUNT 3 +#define TCP_RETRANSMISSION_TIMEOUT 10000 +#define TCP_RETRANSMISSION_COUNT 5 + +struct unacked +{ + struct unacked *next; + struct grub_net_buff *nb; + grub_uint64_t last_try; + int try_count; +}; + +enum + { + TCP_FIN = 0x1, + TCP_SYN = 0x2, + TCP_ACK = 0x10 + }; + +struct grub_net_tcp_socket +{ + struct grub_net_tcp_socket *next; + + int established; + int i_closed; + int they_closed; + int in_port; + int out_port; + int errors; + grub_uint32_t my_start_seq; + grub_uint32_t my_cur_seq; + grub_uint32_t their_start_seq; + grub_uint32_t their_cur_seq; + grub_uint16_t my_window; + struct unacked *unack_first; + struct unacked *unack_last; + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, struct grub_net_buff *nb, + void *recv); + void (*error_hook) (grub_net_tcp_socket_t sock, void *recv); + void *hook_data; + grub_net_network_level_address_t out_nla; + struct grub_net_network_level_interface *inf; + grub_net_packets_t packs; + grub_priority_queue_t pq; +}; + +struct tcphdr +{ + grub_uint16_t src; + grub_uint16_t dst; + grub_uint32_t seqnr; + grub_uint32_t ack; + grub_uint16_t flags; + grub_uint16_t window; + grub_uint16_t checksum; + grub_uint16_t urgent; +} __attribute__ ((packed)); + +struct tcp_pseudohdr +{ + grub_uint32_t src; + grub_uint32_t dst; + grub_uint8_t zero; + grub_uint8_t proto; + grub_uint16_t tcp_length; +} __attribute__ ((packed)); + +struct grub_net_tcp_socket *tcp_sockets; + +#define FOR_TCP_SOCKETS(var) for (var = tcp_sockets; var; var = var->next) + +static inline void +tcp_socket_register (grub_net_tcp_socket_t sock) +{ + grub_list_push (GRUB_AS_LIST_P (&tcp_sockets), + GRUB_AS_LIST (sock)); +} + +static grub_err_t +tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket) +{ + grub_err_t err; + grub_uint8_t *nbd; + struct unacked *unack; + struct tcphdr *tcph; + grub_size_t size; + + tcph = (struct tcphdr *) nb->data; + + tcph->seqnr = grub_cpu_to_be32 (socket->my_cur_seq); + size = (nb->tail - nb->data - (grub_be_to_cpu16 (tcph->flags) >> 12) * 4); + if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + size++; + socket->my_cur_seq += size; + tcph->src = grub_cpu_to_be16 (socket->in_port); + tcph->dst = grub_cpu_to_be16 (socket->out_port); + tcph->checksum = 0; + tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, + &socket->inf->address, + &socket->out_nla); + nbd = nb->data; + if (size) + { + unack = grub_malloc (sizeof (*unack)); + if (!unack) + return grub_errno; + + unack->next = NULL; + unack->nb = nb; + unack->try_count = 1; + unack->last_try = grub_get_time_ms (); + if (!socket->unack_last) + socket->unack_first = socket->unack_last = unack; + else + socket->unack_last->next = unack; + } + + err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb, + GRUB_NET_IP_TCP); + if (err) + return err; + nb->data = nbd; + return GRUB_ERR_NONE; +} + +void +grub_net_tcp_close (grub_net_tcp_socket_t sock) +{ + struct grub_net_buff *nb_fin; + struct tcphdr *tcph_fin; + grub_err_t err; + + sock->i_closed = 1; + + nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin) + 128); + if (!nb_fin) + return; + err = grub_netbuff_reserve (nb_fin, 128); + if (err) + { + grub_netbuff_free (nb_fin); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + + err = grub_netbuff_put (nb_fin, sizeof (*tcph_fin)); + if (err) + { + grub_netbuff_free (nb_fin); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + tcph_fin = (void *) nb_fin->data; + tcph_fin->ack = grub_cpu_to_be32 (0); + tcph_fin->flags = grub_cpu_to_be16 ((5 << 12) | TCP_FIN); + tcph_fin->window = grub_cpu_to_be16 (0); + tcph_fin->urgent = 0; + err = tcp_send (nb_fin, sock); + if (err) + { + grub_netbuff_free (nb_fin); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + } + return; +} + +static void +ack (grub_net_tcp_socket_t sock) +{ + struct grub_net_buff *nb_ack; + struct tcphdr *tcph_ack; + grub_err_t err; + + nb_ack = grub_netbuff_alloc (sizeof (*tcph_ack) + 128); + if (!nb_ack) + return; + err = grub_netbuff_reserve (nb_ack, 128); + if (err) + { + grub_netbuff_free (nb_ack); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + + err = grub_netbuff_put (nb_ack, sizeof (*tcph_ack)); + if (err) + { + grub_netbuff_free (nb_ack); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + tcph_ack = (void *) nb_ack->data; + tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq); + tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_ACK); + tcph_ack->window = grub_cpu_to_be16 (sock->my_window); + tcph_ack->urgent = 0; + tcph_ack->src = grub_cpu_to_be16 (sock->in_port); + tcph_ack->dst = grub_cpu_to_be16 (sock->out_port); + err = tcp_send (nb_ack, sock); + if (err) + { + grub_dprintf ("net", "error acking socket\n"); + grub_errno = GRUB_ERR_NONE; + } +} + +static void +kill_socket (grub_net_tcp_socket_t sock) +{ + if (sock->error_hook) + sock->error_hook (sock, sock->hook_data); + grub_net_tcp_close (sock); +} + +void +grub_net_tcp_retransmit (void) +{ + grub_net_tcp_socket_t sock; + grub_uint64_t ctime = grub_get_time_ms (); + grub_uint64_t limit_time = ctime - TCP_RETRANSMISSION_TIMEOUT; + + FOR_TCP_SOCKETS (sock) + { + struct unacked *unack; + for (unack = sock->unack_first; unack; unack = unack->next) + { + grub_uint8_t *nbd; + grub_err_t err; + + if (unack->last_try > limit_time) + continue; + + if (unack->try_count > TCP_RETRANSMISSION_COUNT) + { + kill_socket (sock); + break; + } + unack->try_count++; + unack->last_try = ctime; + nbd = unack->nb->data; + err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla), unack->nb, + GRUB_NET_IP_TCP); + unack->nb->data = nbd; + if (err) + { + grub_dprintf ("net", "TCP retransmit failed: %s\n", grub_errmsg); + grub_errno = GRUB_ERR_NONE; + } + } + } +} + +grub_uint16_t +grub_net_ip_transport_checksum (struct grub_net_buff *nb, + grub_uint16_t proto, + const grub_net_network_level_address_t *src, + const grub_net_network_level_address_t *dst) +{ + struct tcp_pseudohdr ph; + grub_uint16_t a, b; + grub_uint32_t c; + + a = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) nb->data, + nb->tail - nb->data)); + + ph.src = src->ipv4; + ph.dst = dst->ipv4; + ph.zero = 0; + ph.tcp_length = grub_cpu_to_be16 (nb->tail - nb->data); + ph.proto = proto; + b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph))); + c = (grub_uint32_t) a + (grub_uint32_t) b; + if (c >= 0xffff) + c -= 0xffff; + return grub_cpu_to_be16 (~c); +} + +/* FIXME: overflow. */ +static int +cmp (const void *a__, const void *b__) +{ + struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; + struct grub_net_buff *b_ = *(struct grub_net_buff **) b__; + struct tcphdr *a = (struct tcphdr *) a_->data; + struct tcphdr *b = (struct tcphdr *) b_->data; + /* We want the first elements to be on top. */ + if (grub_be_to_cpu32 (a->seqnr) < grub_be_to_cpu32 (b->seqnr)) + return +1; + if (grub_be_to_cpu32 (a->seqnr) > grub_be_to_cpu32 (b->seqnr)) + return -1; + return 0; +} + +static void +destroy_pq (grub_net_tcp_socket_t sock) +{ + struct grub_net_buff **nb_p; + while ((nb_p = grub_priority_queue_top (sock->pq))) + grub_netbuff_free (*nb_p); + + grub_priority_queue_destroy (sock->pq); +} + +grub_net_tcp_socket_t +grub_net_tcp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data) +{ + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + grub_net_tcp_socket_t socket; + static grub_uint16_t in_port = 21550; + struct grub_net_buff *nb; + struct tcphdr *tcph; + int i; + grub_uint8_t *nbd; + + err = grub_net_resolve_address (server, &addr); + if (err) + return NULL; + + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "not a IPv4 address"); + return NULL; + } + + err = grub_net_route_address (addr, &gateway, &inf); + if (err) + return NULL; + + socket = grub_zalloc (sizeof (*socket)); + if (socket == NULL) + return NULL; + + socket->out_port = out_port; + socket->inf = inf; + socket->out_nla = addr; + socket->in_port = in_port++; + socket->recv_hook = recv_hook; + socket->error_hook = error_hook; + socket->hook_data = hook_data; + + nb = grub_netbuff_alloc (sizeof (*tcph) + 128); + if (!nb) + return NULL; + err = grub_netbuff_reserve (nb, 128); + if (err) + { + grub_netbuff_free (nb); + return NULL; + } + + err = grub_netbuff_put (nb, sizeof (*tcph)); + if (err) + { + grub_netbuff_free (nb); + return NULL; + } + socket->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp); + if (!socket->pq) + { + grub_netbuff_free (nb); + return NULL; + } + + tcph = (void *) nb->data; + socket->my_start_seq = grub_get_time_ms (); + socket->my_cur_seq = socket->my_start_seq + 1; + socket->my_window = 8192; + tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq); + tcph->ack = grub_cpu_to_be32 (0); + tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN); + tcph->window = grub_cpu_to_be16 (socket->my_window); + tcph->urgent = 0; + tcph->src = grub_cpu_to_be16 (socket->in_port); + tcph->dst = grub_cpu_to_be16 (socket->out_port); + tcph->checksum = 0; + tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, + &socket->inf->address, + &socket->out_nla); + + tcp_socket_register (socket); + + nbd = nb->data; + for (i = 0; i < TCP_SYN_RETRANSMISSION_COUNT; i++) + { + int j; + nb->data = nbd; + err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb, + GRUB_NET_IP_TCP); + if (err) + { + grub_list_remove (GRUB_AS_LIST_P (&tcp_sockets), + GRUB_AS_LIST (socket)); + grub_free (socket); + grub_netbuff_free (nb); + return NULL; + } + for (j = 0; (j < TCP_SYN_RETRANSMISSION_TIMEOUT / 10 + && !socket->established); j++) + grub_net_poll_cards (10); + if (socket->established) + break; + } + if (!socket->established) + { + grub_list_remove (GRUB_AS_LIST_P (&tcp_sockets), + GRUB_AS_LIST (socket)); + grub_free (socket); + grub_error (GRUB_ERR_NET_NO_ANSWER, "no answer"); + + grub_netbuff_free (nb); + destroy_pq (socket); + return NULL; + } + + grub_netbuff_free (nb); + return socket; +} + +grub_err_t +grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, + struct grub_net_buff *nb) +{ + struct tcphdr *tcph; + grub_err_t err; + + err = grub_netbuff_push (nb, sizeof (*tcph)); + if (err) + return err; + + tcph = (struct tcphdr *) nb->data; + tcph->ack = grub_cpu_to_be32 (0); + tcph->flags = grub_cpu_to_be16 ((5 << 12)); + tcph->window = grub_cpu_to_be16 (socket->my_window); + tcph->urgent = 0; + return tcp_send (nb, socket); +} + +grub_err_t +grub_net_recv_tcp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source) +{ + struct tcphdr *tcph; + grub_net_tcp_socket_t sock; + grub_err_t err; + + tcph = (struct tcphdr *) nb->data; + if ((grub_be_to_cpu16 (tcph->flags) >> 12) < 5) + { + grub_dprintf ("net", "TCP header too short: %u\n", + grub_be_to_cpu16 (tcph->flags) >> 12); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (nb->tail - nb->data < (grub_ssize_t) ((grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t))) + { + grub_dprintf ("net", "TCP packet too short: %" PRIuGRUB_SIZE "\n", + nb->tail - nb->data); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + FOR_TCP_SOCKETS (sock) + { + if (grub_be_to_cpu16 (tcph->dst) == sock->in_port + && grub_be_to_cpu16 (tcph->src) == sock->out_port + && inf == sock->inf + && source->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && source->ipv4 == sock->out_nla.ipv4) + { + if (tcph->checksum) + { + grub_uint16_t chk, expected; + chk = tcph->checksum; + tcph->checksum = 0; + expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, + &sock->out_nla, + &sock->inf->address); + if (expected != chk) + { + grub_dprintf ("net", "Invalid TCP checksum. " + "Expected %x, got %x\n", + grub_be_to_cpu16 (expected), + grub_be_to_cpu16 (chk)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + tcph->checksum = chk; + } + + if ((grub_be_to_cpu16 (tcph->flags) & TCP_SYN) + && (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) + && !sock->established) + { + sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr); + sock->their_cur_seq = sock->their_start_seq + 1; + sock->established = 1; + } + + if (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) + { + struct unacked *unack, *next; + grub_uint32_t acked = grub_be_to_cpu16 (tcph->ack); + for (unack = sock->unack_first; unack; unack = next) + { + grub_uint32_t seqnr; + next = unack->next; + seqnr = grub_be_to_cpu32 (((struct tcphdr *) unack->nb->data) + ->seqnr); + seqnr += (nb->tail - nb->data + - (grub_be_to_cpu16 (tcph->flags) >> 12) * 4); + if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + seqnr++; + + if (seqnr > acked) + break; + grub_netbuff_free (unack->nb); + grub_free (unack); + } + sock->unack_first = unack; + if (!sock->unack_last) + sock->unack_last = NULL; + } + + if (grub_be_to_cpu32 (tcph->seqnr) < sock->their_cur_seq) + { + ack (sock); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + err = grub_priority_queue_push (sock->pq, &nb); + if (err) + return err; + + { + struct grub_net_buff **nb_top_p, *nb_top; + while (1) + { + nb_top_p = grub_priority_queue_top (sock->pq); + if (!nb_top_p) + return GRUB_ERR_NONE; + nb_top = *nb_top_p; + tcph = (struct tcphdr *) nb_top->data; + if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq) + break; + grub_priority_queue_pop (sock->pq); + } + if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) + return GRUB_ERR_NONE; + while (1) + { + nb_top_p = grub_priority_queue_top (sock->pq); + if (!nb_top_p) + break; + nb_top = *nb_top_p; + tcph = (struct tcphdr *) nb_top->data; + + if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) + break; + grub_priority_queue_pop (sock->pq); + + err = grub_netbuff_pull (nb, (grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t)); + if (err) + return err; + + sock->their_cur_seq += (nb_top->tail - nb_top->data); + if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + { + sock->they_closed = 1; + sock->their_cur_seq++; + } + /* If there is data, puts packet in socket list. */ + if ((nb_top->tail - nb_top->data) > 0) + grub_net_put_packet (&sock->packs, nb_top); + else + grub_netbuff_free (nb); + } + ack (sock); + } + while (sock->packs.first) + { + nb = sock->packs.first->nb; + if (sock->recv_hook) + sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data); + grub_net_remove_packet (sock->packs.first); + } + + return GRUB_ERR_NONE; + } + } + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 16616cfea..bc8886442 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -207,7 +207,6 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), return GRUB_ERR_NONE; nb_top = *nb_top_p; tftph = (struct tftphdr *) nb_top->data; - grub_refresh (); if (grub_be_to_cpu16 (tftph->u.data.block) >= data->block + 1) break; grub_priority_queue_pop (data->pq); @@ -279,6 +278,7 @@ tftp_open (struct grub_file *file, const char *filename) struct grub_net_buff nb; tftp_data_t data; grub_err_t err; + grub_uint8_t *nbd; data = grub_zalloc (sizeof (*data)); if (!data) @@ -344,21 +344,11 @@ tftp_open (struct grub_file *file, const char *filename) return grub_errno; } - err = grub_net_send_udp_packet (data->sock, &nb); - if (err) - { - grub_net_udp_close (data->sock); - destroy_pq (data); - return err; - } - /* Receive OACK packet. */ + nbd = nb.data; for (i = 0; i < 3; i++) { - grub_net_poll_cards (100); - if (data->have_oack) - break; - /* Retry. */ + nb.data = nbd; err = grub_net_send_udp_packet (data->sock, &nb); if (err) { @@ -366,6 +356,9 @@ tftp_open (struct grub_file *file, const char *filename) destroy_pq (data); return err; } + grub_net_poll_cards (100); + if (data->have_oack) + break; } if (!data->have_oack) diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 0a43fe24f..e816547ac 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -120,10 +120,13 @@ grub_net_send_udp_packet (const grub_net_udp_socket_t socket, udph->src = grub_cpu_to_be16 (socket->in_port); udph->dst = grub_cpu_to_be16 (socket->out_port); - /* No chechksum. */ udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); + udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, + &socket->inf->address, + &socket->out_nla); + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb, GRUB_NET_IP_UDP); } @@ -136,26 +139,60 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb, struct udphdr *udph; grub_net_udp_socket_t sock; grub_err_t err; + udph = (struct udphdr *) nb->data; - err = grub_netbuff_pull (nb, sizeof (*udph)); - if (err) - return err; + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*udph)) + { + grub_dprintf ("net", "UDP packet too short: %" PRIuGRUB_SIZE "\n", + nb->tail - nb->data); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } FOR_UDP_SOCKETS (sock) { if (grub_be_to_cpu16 (udph->dst) == sock->in_port - && inf == sock->inf && sock->recv_hook + && inf == sock->inf && source->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && source->ipv4 == sock->out_nla.ipv4) + && source->ipv4 == sock->out_nla.ipv4 + && (sock->status == GRUB_NET_SOCKET_START + || grub_be_to_cpu16 (udph->src) == sock->out_port)) { + if (udph->chksum) + { + grub_uint16_t chk, expected; + chk = udph->chksum; + udph->chksum = 0; + expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, + &sock->out_nla, + &sock->inf->address); + if (expected != chk) + { + grub_dprintf ("net", "Invalid UDP checksum. " + "Expected %x, got %x\n", + grub_be_to_cpu16 (expected), + grub_be_to_cpu16 (chk)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + udph->chksum = chk; + } + if (sock->status == GRUB_NET_SOCKET_START) { sock->out_port = grub_be_to_cpu16 (udph->src); sock->status = GRUB_NET_SOCKET_ESTABLISHED; } + err = grub_netbuff_pull (nb, sizeof (*udph)); + if (err) + return err; + /* App protocol remove its own reader. */ - sock->recv_hook (sock, nb, sock->recv_hook_data); + if (sock->recv_hook) + sock->recv_hook (sock, nb, sock->recv_hook_data); + else + grub_netbuff_free (nb); return GRUB_ERR_NONE; } } diff --git a/include/grub/err.h b/include/grub/err.h index 40f39dd5d..e03378d70 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -59,6 +59,7 @@ typedef enum GRUB_ERR_NET_BAD_ADDRESS, GRUB_ERR_NET_ROUTE_LOOP, GRUB_ERR_NET_NO_ROUTE, + GRUB_ERR_NET_NO_ANSWER, GRUB_ERR_WAIT, GRUB_ERR_BUG } diff --git a/include/grub/net.h b/include/grub/net.h index e7631b884..d71edfd1e 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -415,6 +415,9 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter inter->prev = 0; } +void +grub_net_tcp_retransmit (void); + extern char *grub_net_default_server; #endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index a3c64c1cb..e385e5ac1 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -50,5 +50,15 @@ grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *src); +grub_err_t +grub_net_recv_tcp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source); + +grub_uint16_t +grub_net_ip_transport_checksum (struct grub_net_buff *nb, + grub_uint16_t proto, + const grub_net_network_level_address_t *src, + const grub_net_network_level_address_t *dst); #endif diff --git a/include/grub/net/tcp.h b/include/grub/net/tcp.h new file mode 100644 index 000000000..88cc6878e --- /dev/null +++ b/include/grub/net/tcp.h @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#ifndef GRUB_NET_TCP_HEADER +#define GRUB_NET_TCP_HEADER 1 +#include +#include + +struct grub_net_tcp_socket; +typedef struct grub_net_tcp_socket *grub_net_tcp_socket_t; + +grub_net_tcp_socket_t +grub_net_tcp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data); + +grub_err_t +grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, + struct grub_net_buff *nb); + +void +grub_net_tcp_close (grub_net_tcp_socket_t sock); + +#endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index 8d978569d..fca94ba47 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #ifndef GRUB_NET_UDP_HEADER #define GRUB_NET_UDP_HEADER 1 #include From 3a2e86033488dc0a20cfcca9a4fa228e28e17558 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 09:52:08 +0200 Subject: [PATCH 295/673] TCP improvements --- grub-core/net/tcp.c | 56 ++++++++++++++++++++++++++++++++------------- include/grub/err.h | 3 ++- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 3bc3d5c9c..8fbf0bdfa 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -40,6 +40,7 @@ enum { TCP_FIN = 0x1, TCP_SYN = 0x2, + TCP_RST = 0x4, TCP_ACK = 0x10 }; @@ -53,6 +54,7 @@ struct grub_net_tcp_socket int in_port; int out_port; int errors; + int reseted; grub_uint32_t my_start_seq; grub_uint32_t my_cur_seq; grub_uint32_t their_start_seq; @@ -146,6 +148,8 @@ tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket) if (err) return err; nb->data = nbd; + if (!size) + grub_netbuff_free (nb); return GRUB_ERR_NONE; } @@ -235,14 +239,6 @@ ack (grub_net_tcp_socket_t sock) } } -static void -kill_socket (grub_net_tcp_socket_t sock) -{ - if (sock->error_hook) - sock->error_hook (sock, sock->hook_data); - grub_net_tcp_close (sock); -} - void grub_net_tcp_retransmit (void) { @@ -263,7 +259,9 @@ grub_net_tcp_retransmit (void) if (unack->try_count > TCP_RETRANSMISSION_COUNT) { - kill_socket (sock); + if (sock->error_hook) + sock->error_hook (sock, sock->hook_data); + grub_net_tcp_close (sock); break; } unack->try_count++; @@ -435,9 +433,9 @@ grub_net_tcp_open (char *server, grub_netbuff_free (nb); return NULL; } - for (j = 0; (j < TCP_SYN_RETRANSMISSION_TIMEOUT / 10 + for (j = 0; (j < TCP_SYN_RETRANSMISSION_TIMEOUT / 50 && !socket->established); j++) - grub_net_poll_cards (10); + grub_net_poll_cards (50); if (socket->established) break; } @@ -445,11 +443,14 @@ grub_net_tcp_open (char *server, { grub_list_remove (GRUB_AS_LIST_P (&tcp_sockets), GRUB_AS_LIST (socket)); - grub_free (socket); - grub_error (GRUB_ERR_NET_NO_ANSWER, "no answer"); + if (socket->reseted) + grub_error (GRUB_ERR_NET_PORT_CLOSED, "port closed"); + else + grub_error (GRUB_ERR_NET_NO_ANSWER, "no answer"); grub_netbuff_free (nb); destroy_pq (socket); + grub_free (socket); return NULL; } @@ -539,10 +540,27 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, sock->established = 1; } + if (grub_be_to_cpu16 (tcph->flags) & TCP_RST) + { + struct unacked *unack, *next; + sock->reseted = 1; + for (unack = sock->unack_first; unack; unack = next) + { + next = unack->next; + grub_netbuff_free (unack->nb); + grub_free (unack); + } + + sock->unack_first = NULL; + sock->unack_last = NULL; + + return GRUB_ERR_NONE; + } + if (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) { struct unacked *unack, *next; - grub_uint32_t acked = grub_be_to_cpu16 (tcph->ack); + grub_uint32_t acked = grub_be_to_cpu32 (tcph->ack); for (unack = sock->unack_first; unack; unack = next) { grub_uint32_t seqnr; @@ -577,6 +595,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, { struct grub_net_buff **nb_top_p, *nb_top; + int do_ack = 0; while (1) { nb_top_p = grub_priority_queue_top (sock->pq); @@ -612,14 +631,19 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, { sock->they_closed = 1; sock->their_cur_seq++; + do_ack = 1; } /* If there is data, puts packet in socket list. */ if ((nb_top->tail - nb_top->data) > 0) - grub_net_put_packet (&sock->packs, nb_top); + { + grub_net_put_packet (&sock->packs, nb_top); + do_ack = 1; + } else grub_netbuff_free (nb); } - ack (sock); + if (do_ack) + ack (sock); } while (sock->packs.first) { diff --git a/include/grub/err.h b/include/grub/err.h index e03378d70..c91911644 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -61,7 +61,8 @@ typedef enum GRUB_ERR_NET_NO_ROUTE, GRUB_ERR_NET_NO_ANSWER, GRUB_ERR_WAIT, - GRUB_ERR_BUG + GRUB_ERR_BUG, + GRUB_ERR_NET_PORT_CLOSED } grub_err_t; From bfca152e5a5c4f077b27c806245ebb7e11c9dadd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 09:53:29 +0200 Subject: [PATCH 296/673] Fix a memory leak --- grub-core/net/tcp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 8fbf0bdfa..c64170edf 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -554,6 +554,8 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, sock->unack_first = NULL; sock->unack_last = NULL; + grub_netbuff_free (nb); + return GRUB_ERR_NONE; } From f4e6e2909bdca758733afb2009fe06d7a8a15448 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 11:26:34 +0200 Subject: [PATCH 297/673] TCP fragmentation --- grub-core/net/tcp.c | 46 +++++++++++++++++++++++++++++++++++++++--- include/grub/net/tcp.h | 3 ++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index c64170edf..489277678 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -41,7 +41,9 @@ enum TCP_FIN = 0x1, TCP_SYN = 0x2, TCP_RST = 0x4, - TCP_ACK = 0x10 + TCP_PUSH = 0x8, + TCP_ACK = 0x10, + TCP_URG = 0x20, }; struct grub_net_tcp_socket @@ -460,10 +462,48 @@ grub_net_tcp_open (char *server, grub_err_t grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, - struct grub_net_buff *nb) + struct grub_net_buff *nb, int push) { struct tcphdr *tcph; grub_err_t err; + grub_ssize_t fraglen; + fraglen = (socket->inf->card->mtu - GRUB_NET_OUR_IPV4_HEADER_SIZE + - sizeof (*tcph)); + + while (nb->tail - nb->data > fraglen) + { + struct grub_net_buff *nb2; + + nb2 = grub_netbuff_alloc (fraglen + sizeof (*tcph) + + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb2) + return grub_errno; + err = grub_netbuff_reserve (nb2, GRUB_NET_MAX_LINK_HEADER_SIZE + + GRUB_NET_OUR_IPV4_HEADER_SIZE); + if (err) + return err; + err = grub_netbuff_put (nb2, sizeof (*tcph)); + if (err) + return err; + + tcph = (struct tcphdr *) nb2->data; + tcph->ack = grub_cpu_to_be32 (0); + tcph->flags = grub_cpu_to_be16 ((5 << 12)); + tcph->window = grub_cpu_to_be16 (socket->my_window); + tcph->urgent = 0; + err = grub_netbuff_put (nb2, fraglen); + if (err) + return err; + grub_memcpy (tcph + 1, nb->data, fraglen); + err = grub_netbuff_pull (nb, fraglen); + if (err) + return err; + + err = tcp_send (nb2, socket); + if (err) + return err; + } err = grub_netbuff_push (nb, sizeof (*tcph)); if (err) @@ -471,7 +511,7 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, tcph = (struct tcphdr *) nb->data; tcph->ack = grub_cpu_to_be32 (0); - tcph->flags = grub_cpu_to_be16 ((5 << 12)); + tcph->flags = grub_cpu_to_be16 ((5 << 12) | (push ? TCP_PUSH : 0)); tcph->window = grub_cpu_to_be16 (socket->my_window); tcph->urgent = 0; return tcp_send (nb, socket); diff --git a/include/grub/net/tcp.h b/include/grub/net/tcp.h index 88cc6878e..cd05074f5 100644 --- a/include/grub/net/tcp.h +++ b/include/grub/net/tcp.h @@ -36,7 +36,8 @@ grub_net_tcp_open (char *server, grub_err_t grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, - struct grub_net_buff *nb); + struct grub_net_buff *nb, + int push); void grub_net_tcp_close (grub_net_tcp_socket_t sock); From 16a2bab03c78d1f727ab48fe9af47abe6bea7b22 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 15:32:43 +0200 Subject: [PATCH 298/673] * util/grub-install.in: Source grub-mkconfig_lib. --- ChangeLog | 4 ++++ util/grub-install.in | 2 ++ 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 33c5b0b92..96b48f2fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-10 Vladimir Serbinenko + + * util/grub-install.in: Source grub-mkconfig_lib. + 2011-07-08 Vladimir Serbinenko Remove getroot.c from core on emu platform. diff --git a/util/grub-install.in b/util/grub-install.in index 09894d0d0..711c9c7e2 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -59,6 +59,8 @@ update_nvram=yes removable=no efi_quiet= +. ${libdir}/@PACKAGE@/grub-mkconfig_lib + # Get GRUB_DISTRIBUTOR. if test -f "${sysconfdir}/default/grub" ; then . "${sysconfdir}/default/grub" From c4edd548324dd0c1bfdd5d8cc4566de25074fdb6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 15:33:57 +0200 Subject: [PATCH 299/673] * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Fix incorrect memory usage. --- ChangeLog | 5 +++++ grub-core/disk/efi/efidisk.c | 9 +++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 96b48f2fe..cf2354f6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-10 Vladimir Serbinenko + + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Fix + incorrect memory usage. + 2011-07-10 Vladimir Serbinenko * util/grub-install.in: Source grub-mkconfig_lib. diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 85969cc1d..0baeb8e4b 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -709,7 +709,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) { - grub_partition_t tpart = NULL; + char *partition_name = NULL; char *device_name; grub_efi_device_path_t *dup_dp, *dup_ldp; grub_efi_hard_drive_device_path_t hd; @@ -722,7 +722,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) if (grub_partition_get_start (part) == hd.partition_start && grub_partition_get_len (part) == hd.partition_size) { - tpart = part; + partition_name = grub_partition_get_name (part); return 1; } @@ -760,17 +760,14 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) } else { - char *partition_name; - grub_partition_iterate (parent, find_partition); - if (! tpart) + if (! partition_name) { grub_disk_close (parent); return 0; } - partition_name = grub_partition_get_name (tpart); device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); grub_free (partition_name); } From e4bcf6258cd128aa81257ca8dd217596f9cd5771 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 15:56:56 +0200 Subject: [PATCH 300/673] * po/POTFILES.in: Regenerate. --- ChangeLog | 4 + po/POTFILES.in | 1076 ++++++++++++++++++++++++------------------------ 2 files changed, 542 insertions(+), 538 deletions(-) diff --git a/ChangeLog b/ChangeLog index cf2354f6d..84167f226 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-10 Vladimir Serbinenko + + * po/POTFILES.in: Regenerate. + 2011-07-10 Vladimir Serbinenko * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Fix diff --git a/po/POTFILES.in b/po/POTFILES.in index 83cb48b2c..ebb0aadaa 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,538 +1,538 @@ -grub-core/boot/decompressor/minilib.c -grub-core/boot/decompressor/none.c -grub-core/boot/decompressor/xz.c -grub-core/bus/bonito.c -grub-core/bus/cs5536.c -grub-core/bus/emu/pci.c -grub-core/bus/pci.c -grub-core/bus/usb/emu/usb.c -grub-core/bus/usb/ohci.c -grub-core/bus/usb/serial/common.c -grub-core/bus/usb/serial/ftdi.c -grub-core/bus/usb/serial/pl2303.c -grub-core/bus/usb/uhci.c -grub-core/bus/usb/usb.c -grub-core/bus/usb/usbhub.c -grub-core/bus/usb/usbtrans.c -grub-core/commands/acpi.c -grub-core/commands/acpihalt.c -grub-core/commands/arc/lsdev.c -grub-core/commands/blocklist.c -grub-core/commands/boot.c -grub-core/commands/cat.c -grub-core/commands/cmp.c -grub-core/commands/configfile.c -grub-core/commands/date.c -grub-core/commands/echo.c -grub-core/commands/efi/acpi.c -grub-core/commands/efi/fixvideo.c -grub-core/commands/efi/loadbios.c -grub-core/commands/efi/lsefimmap.c -grub-core/commands/efi/lsefisystab.c -grub-core/commands/efi/lssal.c -grub-core/commands/extcmd.c -grub-core/commands/gptsync.c -grub-core/commands/halt.c -grub-core/commands/hashsum.c -grub-core/commands/hdparm.c -grub-core/commands/help.c -grub-core/commands/hexdump.c -grub-core/commands/i386/cmostest.c -grub-core/commands/i386/cpuid.c -grub-core/commands/i386/pc/acpi.c -grub-core/commands/i386/pc/drivemap.c -grub-core/commands/i386/pc/halt.c -grub-core/commands/i386/pc/lsapm.c -grub-core/commands/i386/pc/play.c -grub-core/commands/i386/pc/sendkey.c -grub-core/commands/ieee1275/suspend.c -grub-core/commands/iorw.c -grub-core/commands/keylayouts.c -grub-core/commands/keystatus.c -grub-core/commands/legacycfg.c -grub-core/commands/loadenv.c -grub-core/commands/lsacpi.c -grub-core/commands/ls.c -grub-core/commands/lsmmap.c -grub-core/commands/lspci.c -grub-core/commands/memrw.c -grub-core/commands/menuentry.c -grub-core/commands/minicmd.c -grub-core/commands/mips/loongson/lsspd.c -grub-core/commands/parttool.c -grub-core/commands/password.c -grub-core/commands/password_pbkdf2.c -grub-core/commands/probe.c -grub-core/commands/read.c -grub-core/commands/reboot.c -grub-core/commands/regexp.c -grub-core/commands/search.c -grub-core/commands/search_file.c -grub-core/commands/search_label.c -grub-core/commands/search_uuid.c -grub-core/commands/search_wrap.c -grub-core/commands/setpci.c -grub-core/commands/sleep.c -grub-core/commands/terminal.c -grub-core/commands/test.c -grub-core/commands/testload.c -grub-core/commands/time.c -grub-core/commands/true.c -grub-core/commands/usbtest.c -grub-core/commands/videoinfo.c -grub-core/commands/videotest.c -grub-core/commands/wildcard.c -grub-core/commands/xnu_uuid.c -grub-core/disk/AFSplitter.c -grub-core/disk/ahci.c -grub-core/disk/arc/arcdisk.c -grub-core/disk/ata.c -grub-core/disk/cryptodisk.c -grub-core/disk/dmraid_nvidia.c -grub-core/disk/efi/efidisk.c -grub-core/disk/geli.c -grub-core/disk/host.c -grub-core/disk/i386/pc/biosdisk.c -grub-core/disk/ieee1275/nand.c -grub-core/disk/ieee1275/ofdisk.c -grub-core/disk/loopback.c -grub-core/disk/luks.c -grub-core/disk/lvm.c -grub-core/disk/mdraid1x_linux.c -grub-core/disk/mdraid_linux.c -grub-core/disk/memdisk.c -grub-core/disk/pata.c -grub-core/disk/raid5_recover.c -grub-core/disk/raid6_recover.c -grub-core/disk/raid.c -grub-core/disk/scsi.c -grub-core/disk/usbms.c -grub-core/efiemu/i386/coredetect.c -grub-core/efiemu/i386/loadcore32.c -grub-core/efiemu/i386/loadcore64.c -grub-core/efiemu/i386/nocfgtables.c -grub-core/efiemu/i386/pc/cfgtables.c -grub-core/efiemu/loadcore32.c -grub-core/efiemu/loadcore64.c -grub-core/efiemu/loadcore.c -grub-core/efiemu/loadcore_common.c -grub-core/efiemu/main.c -grub-core/efiemu/mm.c -grub-core/efiemu/pnvram.c -grub-core/efiemu/prepare32.c -grub-core/efiemu/prepare64.c -grub-core/efiemu/prepare.c -grub-core/efiemu/runtime/efiemu.c -grub-core/efiemu/symbols.c -grub-core/font/font.c -grub-core/font/font_cmd.c -grub-core/fs/affs.c -grub-core/fs/afs_be.c -grub-core/fs/afs.c -grub-core/fs/befs_be.c -grub-core/fs/befs.c -grub-core/fs/btrfs.c -grub-core/fs/cpio.c -grub-core/fs/ext2.c -grub-core/fs/fat.c -grub-core/fs/fshelp.c -grub-core/fs/hfs.c -grub-core/fs/hfsplus.c -grub-core/fs/iso9660.c -grub-core/fs/jfs.c -grub-core/fs/minix2.c -grub-core/fs/minix3.c -grub-core/fs/minix.c -grub-core/fs/nilfs2.c -grub-core/fs/ntfs.c -grub-core/fs/ntfscomp.c -grub-core/fs/reiserfs.c -grub-core/fs/romfs.c -grub-core/fs/sfs.c -grub-core/fs/squash4.c -grub-core/fs/tar.c -grub-core/fs/udf.c -grub-core/fs/ufs2.c -grub-core/fs/ufs.c -grub-core/fs/xfs.c -grub-core/fs/zfs/zfs.c -grub-core/fs/zfs/zfs_fletcher.c -grub-core/fs/zfs/zfsinfo.c -grub-core/fs/zfs/zfs_lzjb.c -grub-core/fs/zfs/zfs_sha256.c -grub-core/gentrigtables.c -grub-core/gettext/gettext.c -grub-core/gfxmenu/font.c -grub-core/gfxmenu/gfxmenu.c -grub-core/gfxmenu/gui_box.c -grub-core/gfxmenu/gui_canvas.c -grub-core/gfxmenu/gui_circular_progress.c -grub-core/gfxmenu/gui_image.c -grub-core/gfxmenu/gui_label.c -grub-core/gfxmenu/gui_list.c -grub-core/gfxmenu/gui_progress_bar.c -grub-core/gfxmenu/gui_string_util.c -grub-core/gfxmenu/gui_util.c -grub-core/gfxmenu/icon_manager.c -grub-core/gfxmenu/model.c -grub-core/gfxmenu/theme_loader.c -grub-core/gfxmenu/view.c -grub-core/gfxmenu/widget-box.c -grub-core/gnulib/alloca.c -grub-core/gnulib/argp-ba.c -grub-core/gnulib/argp-eexst.c -grub-core/gnulib/argp-fmtstream.c -grub-core/gnulib/argp-fs-xinl.c -grub-core/gnulib/argp-help.c -grub-core/gnulib/argp-parse.c -grub-core/gnulib/argp-pin.c -grub-core/gnulib/argp-pv.c -grub-core/gnulib/argp-pvh.c -grub-core/gnulib/argp-xinl.c -grub-core/gnulib/asnprintf.c -grub-core/gnulib/basename-lgpl.c -grub-core/gnulib/btowc.c -grub-core/gnulib/dirname-lgpl.c -grub-core/gnulib/error.c -grub-core/gnulib/fnmatch.c -grub-core/gnulib/fnmatch_loop.c -grub-core/gnulib/getdelim.c -grub-core/gnulib/getline.c -grub-core/gnulib/getopt1.c -grub-core/gnulib/getopt.c -grub-core/gnulib/localcharset.c -grub-core/gnulib/malloc.c -grub-core/gnulib/mbrtowc.c -grub-core/gnulib/mbsinit.c -grub-core/gnulib/mbsrtowcs.c -grub-core/gnulib/mbsrtowcs-state.c -grub-core/gnulib/memchr.c -grub-core/gnulib/mempcpy.c -grub-core/gnulib/nl_langinfo.c -grub-core/gnulib/printf-args.c -grub-core/gnulib/printf-parse.c -grub-core/gnulib/progname.c -grub-core/gnulib/rawmemchr.c -grub-core/gnulib/realloc.c -grub-core/gnulib/regcomp.c -grub-core/gnulib/regex.c -grub-core/gnulib/regexec.c -grub-core/gnulib/regex_internal.c -grub-core/gnulib/sleep.c -grub-core/gnulib/stdio-write.c -grub-core/gnulib/strcasecmp.c -grub-core/gnulib/strchrnul.c -grub-core/gnulib/strerror.c -grub-core/gnulib/stripslash.c -grub-core/gnulib/strncasecmp.c -grub-core/gnulib/strndup.c -grub-core/gnulib/strnlen1.c -grub-core/gnulib/strnlen.c -grub-core/gnulib/vasnprintf.c -grub-core/gnulib/vsnprintf.c -grub-core/gnulib/wcrtomb.c -grub-core/hello/hello.c -grub-core/hook/datehook.c -grub-core/io/bufio.c -grub-core/io/gzio.c -grub-core/io/xzio.c -grub-core/kern/command.c -grub-core/kern/corecmd.c -grub-core/kern/device.c -grub-core/kern/disk.c -grub-core/kern/dl.c -grub-core/kern/efi/efi.c -grub-core/kern/efi/init.c -grub-core/kern/efi/mm.c -grub-core/kern/elf.c -grub-core/kern/emu/cache.c -grub-core/kern/emu/console.c -grub-core/kern/emu/full.c -grub-core/kern/emu/getroot.c -grub-core/kern/emu/hostdisk.c -grub-core/kern/emu/hostfs.c -grub-core/kern/emu/lite.c -grub-core/kern/emu/main.c -grub-core/kern/emu/misc.c -grub-core/kern/emu/mm.c -grub-core/kern/emu/raid.c -grub-core/kern/emu/time.c -grub-core/kern/env.c -grub-core/kern/err.c -grub-core/kern/file.c -grub-core/kern/fs.c -grub-core/kern/generic/millisleep.c -grub-core/kern/generic/rtc_get_time_ms.c -grub-core/kern/i386/coreboot/init.c -grub-core/kern/i386/coreboot/mmap.c -grub-core/kern/i386/dl.c -grub-core/kern/i386/efi/init.c -grub-core/kern/i386/multiboot_mmap.c -grub-core/kern/i386/pc/init.c -grub-core/kern/i386/pc/mmap.c -grub-core/kern/i386/pit.c -grub-core/kern/i386/qemu/mmap.c -grub-core/kern/i386/tsc.c -grub-core/kern/ia64/dl.c -grub-core/kern/ia64/dl_helper.c -grub-core/kern/ia64/efi/init.c -grub-core/kern/ieee1275/cmain.c -grub-core/kern/ieee1275/ieee1275.c -grub-core/kern/ieee1275/init.c -grub-core/kern/ieee1275/mmap.c -grub-core/kern/ieee1275/openfw.c -grub-core/kern/list.c -grub-core/kern/main.c -grub-core/kern/mips/arc/init.c -grub-core/kern/mips/dl.c -grub-core/kern/mips/init.c -grub-core/kern/mips/loongson/init.c -grub-core/kern/mips/qemu_mips/init.c -grub-core/kern/misc.c -grub-core/kern/mm.c -grub-core/kern/parser.c -grub-core/kern/partition.c -grub-core/kern/powerpc/dl.c -grub-core/kern/rescue_parser.c -grub-core/kern/rescue_reader.c -grub-core/kern/sparc64/dl.c -grub-core/kern/sparc64/ieee1275/ieee1275.c -grub-core/kern/term.c -grub-core/kern/time.c -grub-core/kern/vga_init.c -grub-core/kern/x86_64/dl.c -grub-core/lib/arc/datetime.c -grub-core/lib/arg.c -grub-core/lib/cmdline.c -grub-core/lib/cmos_datetime.c -grub-core/lib/crc.c -grub-core/lib/crypto.c -grub-core/lib/efi/datetime.c -grub-core/lib/efi/halt.c -grub-core/lib/efi/relocator.c -grub-core/lib/emu/halt.c -grub-core/lib/envblk.c -grub-core/lib/hexdump.c -grub-core/lib/i386/halt.c -grub-core/lib/i386/pc/biosnum.c -grub-core/lib/i386/pc/vesa_modes_table.c -grub-core/lib/i386/relocator.c -grub-core/lib/ieee1275/cmos.c -grub-core/lib/ieee1275/datetime.c -grub-core/lib/ieee1275/halt.c -grub-core/lib/ieee1275/relocator.c -grub-core/lib/legacy_parse.c -grub-core/lib/libgcrypt/cipher/ac.c -grub-core/lib/libgcrypt/cipher/arcfour.c -grub-core/lib/libgcrypt/cipher/blowfish.c -grub-core/lib/libgcrypt/cipher/camellia.c -grub-core/lib/libgcrypt/cipher/camellia-glue.c -grub-core/lib/libgcrypt/cipher/cast5.c -grub-core/lib/libgcrypt/cipher/cipher.c -grub-core/lib/libgcrypt/cipher/crc.c -grub-core/lib/libgcrypt/cipher/des.c -grub-core/lib/libgcrypt/cipher/dsa.c -grub-core/lib/libgcrypt/cipher/ecc.c -grub-core/lib/libgcrypt/cipher/elgamal.c -grub-core/lib/libgcrypt/cipher/hash-common.c -grub-core/lib/libgcrypt/cipher/hmac-tests.c -grub-core/lib/libgcrypt/cipher/md4.c -grub-core/lib/libgcrypt/cipher/md5.c -grub-core/lib/libgcrypt/cipher/md.c -grub-core/lib/libgcrypt/cipher/primegen.c -grub-core/lib/libgcrypt/cipher/pubkey.c -grub-core/lib/libgcrypt/cipher/rfc2268.c -grub-core/lib/libgcrypt/cipher/rijndael.c -grub-core/lib/libgcrypt/cipher/rmd160.c -grub-core/lib/libgcrypt/cipher/rsa.c -grub-core/lib/libgcrypt/cipher/seed.c -grub-core/lib/libgcrypt/cipher/serpent.c -grub-core/lib/libgcrypt/cipher/sha1.c -grub-core/lib/libgcrypt/cipher/sha256.c -grub-core/lib/libgcrypt/cipher/sha512.c -grub-core/lib/libgcrypt/cipher/tiger.c -grub-core/lib/libgcrypt/cipher/twofish.c -grub-core/lib/libgcrypt/cipher/whirlpool.c -grub-core/lib/libgcrypt-grub/cipher/arcfour.c -grub-core/lib/libgcrypt-grub/cipher/blowfish.c -grub-core/lib/libgcrypt-grub/cipher/camellia.c -grub-core/lib/libgcrypt-grub/cipher/camellia-glue.c -grub-core/lib/libgcrypt-grub/cipher/cast5.c -grub-core/lib/libgcrypt-grub/cipher/crc.c -grub-core/lib/libgcrypt-grub/cipher/des.c -grub-core/lib/libgcrypt-grub/cipher/dsa.c -grub-core/lib/libgcrypt-grub/cipher/ecc.c -grub-core/lib/libgcrypt-grub/cipher/elgamal.c -grub-core/lib/libgcrypt-grub/cipher/init.c -grub-core/lib/libgcrypt-grub/cipher/md4.c -grub-core/lib/libgcrypt-grub/cipher/md5.c -grub-core/lib/libgcrypt-grub/cipher/primegen.c -grub-core/lib/libgcrypt-grub/cipher/rfc2268.c -grub-core/lib/libgcrypt-grub/cipher/rijndael.c -grub-core/lib/libgcrypt-grub/cipher/rmd160.c -grub-core/lib/libgcrypt-grub/cipher/rsa.c -grub-core/lib/libgcrypt-grub/cipher/seed.c -grub-core/lib/libgcrypt-grub/cipher/serpent.c -grub-core/lib/libgcrypt-grub/cipher/sha1.c -grub-core/lib/libgcrypt-grub/cipher/sha256.c -grub-core/lib/libgcrypt-grub/cipher/sha512.c -grub-core/lib/libgcrypt-grub/cipher/tiger.c -grub-core/lib/libgcrypt-grub/cipher/twofish.c -grub-core/lib/libgcrypt-grub/cipher/whirlpool.c -grub-core/lib/LzFind.c -grub-core/lib/LzmaDec.c -grub-core/lib/LzmaEnc.c -grub-core/lib/mips/relocator.c -grub-core/lib/pbkdf2.c -grub-core/lib/powerpc/relocator.c -grub-core/lib/reed_solomon.c -grub-core/lib/relocator.c -grub-core/lib/xzembed/xz_dec_bcj.c -grub-core/lib/xzembed/xz_dec_lzma2.c -grub-core/lib/xzembed/xz_dec_stream.c -grub-core/loader/aout.c -grub-core/loader/efi/appleloader.c -grub-core/loader/efi/chainloader.c -grub-core/loader/i386/bsd32.c -grub-core/loader/i386/bsd64.c -grub-core/loader/i386/bsd.c -grub-core/loader/i386/bsd_pagetable.c -grub-core/loader/i386/bsdXX.c -grub-core/loader/i386/coreboot/chainloader.c -grub-core/loader/i386/linux.c -grub-core/loader/i386/multiboot_mbi.c -grub-core/loader/i386/pc/chainloader.c -grub-core/loader/i386/pc/freedos.c -grub-core/loader/i386/pc/linux.c -grub-core/loader/i386/pc/ntldr.c -grub-core/loader/i386/xnu.c -grub-core/loader/ia64/efi/linux.c -grub-core/loader/macho32.c -grub-core/loader/macho64.c -grub-core/loader/macho.c -grub-core/loader/machoXX.c -grub-core/loader/mips/linux.c -grub-core/loader/multiboot.c -grub-core/loader/multiboot_elfxx.c -grub-core/loader/multiboot_mbi2.c -grub-core/loader/powerpc/ieee1275/linux.c -grub-core/loader/sparc64/ieee1275/linux.c -grub-core/loader/xnu.c -grub-core/loader/xnu_resume.c -grub-core/mmap/efi/mmap.c -grub-core/mmap/i386/mmap.c -grub-core/mmap/i386/pc/mmap.c -grub-core/mmap/i386/uppermem.c -grub-core/mmap/mips/uppermem.c -grub-core/mmap/mmap.c -grub-core/net/arp.c -grub-core/net/bootp.c -grub-core/net/drivers/efi/efinet.c -grub-core/net/drivers/emu/emunet.c -grub-core/net/drivers/i386/pc/pxe.c -grub-core/net/drivers/ieee1275/ofnet.c -grub-core/net/ethernet.c -grub-core/net/ip.c -grub-core/net/netbuff.c -grub-core/net/net.c -grub-core/net/tftp.c -grub-core/net/udp.c -grub-core/normal/auth.c -grub-core/normal/autofs.c -grub-core/normal/charset.c -grub-core/normal/cmdline.c -grub-core/normal/color.c -grub-core/normal/completion.c -grub-core/normal/context.c -grub-core/normal/crypto.c -grub-core/normal/datetime.c -grub-core/normal/dyncmd.c -grub-core/normal/main.c -grub-core/normal/menu.c -grub-core/normal/menu_entry.c -grub-core/normal/menu_text.c -grub-core/normal/misc.c -grub-core/normal/term.c -grub-core/partmap/acorn.c -grub-core/partmap/amiga.c -grub-core/partmap/apple.c -grub-core/partmap/bsdlabel.c -grub-core/partmap/dvh.c -grub-core/partmap/gpt.c -grub-core/partmap/msdos.c -grub-core/partmap/sun.c -grub-core/partmap/sunpc.c -grub-core/parttool/msdospart.c -grub-core/script/argv.c -grub-core/script/execute.c -grub-core/script/function.c -grub-core/script/lexer.c -grub-core/script/main.c -grub-core/script/script.c -grub-core/term/arc/console.c -grub-core/term/at_keyboard.c -grub-core/term/efi/console.c -grub-core/term/gfxterm.c -grub-core/term/i386/pc/console.c -grub-core/term/i386/pc/vga_text.c -grub-core/term/i386/vga_common.c -grub-core/term/ieee1275/ofconsole.c -grub-core/term/ns8250.c -grub-core/term/serial.c -grub-core/term/terminfo.c -grub-core/term/tparm.c -grub-core/term/usb_keyboard.c -grub-core/tests/example_functional_test.c -grub-core/tests/lib/functional_test.c -grub-core/tests/lib/test.c -grub-core/tests/test_blockarg.c -grub-core/unidata.c -grub-core/video/bitmap.c -grub-core/video/bitmap_scale.c -grub-core/video/bochs.c -grub-core/video/cirrus.c -grub-core/video/colors.c -grub-core/video/efi_gop.c -grub-core/video/efi_uga.c -grub-core/video/emu/sdl.c -grub-core/video/fb/fbblit.c -grub-core/video/fb/fbfill.c -grub-core/video/fb/fbutil.c -grub-core/video/fb/video_fb.c -grub-core/video/i386/pc/vbe.c -grub-core/video/i386/pc/vga.c -grub-core/video/ieee1275.c -grub-core/video/readers/jpeg.c -grub-core/video/readers/png.c -grub-core/video/readers/tga.c -grub-core/video/sis315_init.c -grub-core/video/sis315pro.c -grub-core/video/sm712.c -grub-core/video/sm712_init.c -grub-core/video/video.c -tests/example_unit_test.c -tests/lib/unit_test.c -util/bin2h.c -util/deviceiter.c -util/devicemap.c -util/grub-editenv.c -util/grub-fstest.c -util/grub-macho2img.c -util/grub-menulst2cfg.c -util/grub-mkdevicemap.c -util/grub-mkfont.c -util/grub-mkimage.c -util/grub-mkimagexx.c -util/grub-mklayout.c -util/grub-mkpasswd-pbkdf2.c -util/grub-mkrelpath.c -util/grub-pe2elf.c -util/grub-probe.c -util/grub-script-check.c -util/grub-setup.c -util/ieee1275/devicemap.c -util/ieee1275/grub-ofpathname.c -util/ieee1275/ofpath.c -util/lvm.c -util/misc.c -util/resolve.c +./grub-core/boot/decompressor/minilib.c +./grub-core/boot/decompressor/none.c +./grub-core/boot/decompressor/xz.c +./grub-core/bus/bonito.c +./grub-core/bus/cs5536.c +./grub-core/bus/emu/pci.c +./grub-core/bus/pci.c +./grub-core/bus/usb/emu/usb.c +./grub-core/bus/usb/ohci.c +./grub-core/bus/usb/serial/common.c +./grub-core/bus/usb/serial/ftdi.c +./grub-core/bus/usb/serial/pl2303.c +./grub-core/bus/usb/uhci.c +./grub-core/bus/usb/usb.c +./grub-core/bus/usb/usbhub.c +./grub-core/bus/usb/usbtrans.c +./grub-core/commands/acpi.c +./grub-core/commands/acpihalt.c +./grub-core/commands/arc/lsdev.c +./grub-core/commands/blocklist.c +./grub-core/commands/boot.c +./grub-core/commands/cat.c +./grub-core/commands/cmp.c +./grub-core/commands/configfile.c +./grub-core/commands/date.c +./grub-core/commands/echo.c +./grub-core/commands/efi/acpi.c +./grub-core/commands/efi/fixvideo.c +./grub-core/commands/efi/loadbios.c +./grub-core/commands/efi/lsefimmap.c +./grub-core/commands/efi/lsefisystab.c +./grub-core/commands/efi/lssal.c +./grub-core/commands/extcmd.c +./grub-core/commands/gptsync.c +./grub-core/commands/halt.c +./grub-core/commands/hashsum.c +./grub-core/commands/hdparm.c +./grub-core/commands/help.c +./grub-core/commands/hexdump.c +./grub-core/commands/i386/cmostest.c +./grub-core/commands/i386/cpuid.c +./grub-core/commands/i386/pc/acpi.c +./grub-core/commands/i386/pc/drivemap.c +./grub-core/commands/i386/pc/halt.c +./grub-core/commands/i386/pc/lsapm.c +./grub-core/commands/i386/pc/play.c +./grub-core/commands/i386/pc/sendkey.c +./grub-core/commands/ieee1275/suspend.c +./grub-core/commands/iorw.c +./grub-core/commands/keylayouts.c +./grub-core/commands/keystatus.c +./grub-core/commands/legacycfg.c +./grub-core/commands/loadenv.c +./grub-core/commands/lsacpi.c +./grub-core/commands/ls.c +./grub-core/commands/lsmmap.c +./grub-core/commands/lspci.c +./grub-core/commands/memrw.c +./grub-core/commands/menuentry.c +./grub-core/commands/minicmd.c +./grub-core/commands/mips/loongson/lsspd.c +./grub-core/commands/parttool.c +./grub-core/commands/password.c +./grub-core/commands/password_pbkdf2.c +./grub-core/commands/probe.c +./grub-core/commands/read.c +./grub-core/commands/reboot.c +./grub-core/commands/regexp.c +./grub-core/commands/search.c +./grub-core/commands/search_file.c +./grub-core/commands/search_label.c +./grub-core/commands/search_uuid.c +./grub-core/commands/search_wrap.c +./grub-core/commands/setpci.c +./grub-core/commands/sleep.c +./grub-core/commands/terminal.c +./grub-core/commands/test.c +./grub-core/commands/testload.c +./grub-core/commands/time.c +./grub-core/commands/true.c +./grub-core/commands/usbtest.c +./grub-core/commands/videoinfo.c +./grub-core/commands/videotest.c +./grub-core/commands/wildcard.c +./grub-core/commands/xnu_uuid.c +./grub-core/disk/AFSplitter.c +./grub-core/disk/ahci.c +./grub-core/disk/arc/arcdisk.c +./grub-core/disk/ata.c +./grub-core/disk/cryptodisk.c +./grub-core/disk/dmraid_nvidia.c +./grub-core/disk/efi/efidisk.c +./grub-core/disk/geli.c +./grub-core/disk/host.c +./grub-core/disk/i386/pc/biosdisk.c +./grub-core/disk/ieee1275/nand.c +./grub-core/disk/ieee1275/ofdisk.c +./grub-core/disk/loopback.c +./grub-core/disk/luks.c +./grub-core/disk/lvm.c +./grub-core/disk/mdraid1x_linux.c +./grub-core/disk/mdraid_linux.c +./grub-core/disk/memdisk.c +./grub-core/disk/pata.c +./grub-core/disk/raid5_recover.c +./grub-core/disk/raid6_recover.c +./grub-core/disk/raid.c +./grub-core/disk/scsi.c +./grub-core/disk/usbms.c +./grub-core/efiemu/i386/coredetect.c +./grub-core/efiemu/i386/loadcore32.c +./grub-core/efiemu/i386/loadcore64.c +./grub-core/efiemu/i386/nocfgtables.c +./grub-core/efiemu/i386/pc/cfgtables.c +./grub-core/efiemu/loadcore32.c +./grub-core/efiemu/loadcore64.c +./grub-core/efiemu/loadcore.c +./grub-core/efiemu/loadcore_common.c +./grub-core/efiemu/main.c +./grub-core/efiemu/mm.c +./grub-core/efiemu/pnvram.c +./grub-core/efiemu/prepare32.c +./grub-core/efiemu/prepare64.c +./grub-core/efiemu/prepare.c +./grub-core/efiemu/runtime/efiemu.c +./grub-core/efiemu/symbols.c +./grub-core/font/font.c +./grub-core/font/font_cmd.c +./grub-core/fs/affs.c +./grub-core/fs/afs_be.c +./grub-core/fs/afs.c +./grub-core/fs/befs_be.c +./grub-core/fs/befs.c +./grub-core/fs/btrfs.c +./grub-core/fs/cpio.c +./grub-core/fs/ext2.c +./grub-core/fs/fat.c +./grub-core/fs/fshelp.c +./grub-core/fs/hfs.c +./grub-core/fs/hfsplus.c +./grub-core/fs/iso9660.c +./grub-core/fs/jfs.c +./grub-core/fs/minix2.c +./grub-core/fs/minix3.c +./grub-core/fs/minix.c +./grub-core/fs/nilfs2.c +./grub-core/fs/ntfs.c +./grub-core/fs/ntfscomp.c +./grub-core/fs/reiserfs.c +./grub-core/fs/romfs.c +./grub-core/fs/sfs.c +./grub-core/fs/squash4.c +./grub-core/fs/tar.c +./grub-core/fs/udf.c +./grub-core/fs/ufs2.c +./grub-core/fs/ufs.c +./grub-core/fs/xfs.c +./grub-core/fs/zfs/zfs.c +./grub-core/fs/zfs/zfs_fletcher.c +./grub-core/fs/zfs/zfsinfo.c +./grub-core/fs/zfs/zfs_lzjb.c +./grub-core/fs/zfs/zfs_sha256.c +./grub-core/gentrigtables.c +./grub-core/gettext/gettext.c +./grub-core/gfxmenu/font.c +./grub-core/gfxmenu/gfxmenu.c +./grub-core/gfxmenu/gui_box.c +./grub-core/gfxmenu/gui_canvas.c +./grub-core/gfxmenu/gui_circular_progress.c +./grub-core/gfxmenu/gui_image.c +./grub-core/gfxmenu/gui_label.c +./grub-core/gfxmenu/gui_list.c +./grub-core/gfxmenu/gui_progress_bar.c +./grub-core/gfxmenu/gui_string_util.c +./grub-core/gfxmenu/gui_util.c +./grub-core/gfxmenu/icon_manager.c +./grub-core/gfxmenu/model.c +./grub-core/gfxmenu/theme_loader.c +./grub-core/gfxmenu/view.c +./grub-core/gfxmenu/widget-box.c +./grub-core/gnulib/alloca.c +./grub-core/gnulib/argp-ba.c +./grub-core/gnulib/argp-eexst.c +./grub-core/gnulib/argp-fmtstream.c +./grub-core/gnulib/argp-fs-xinl.c +./grub-core/gnulib/argp-help.c +./grub-core/gnulib/argp-parse.c +./grub-core/gnulib/argp-pin.c +./grub-core/gnulib/argp-pv.c +./grub-core/gnulib/argp-pvh.c +./grub-core/gnulib/argp-xinl.c +./grub-core/gnulib/asnprintf.c +./grub-core/gnulib/basename-lgpl.c +./grub-core/gnulib/btowc.c +./grub-core/gnulib/dirname-lgpl.c +./grub-core/gnulib/error.c +./grub-core/gnulib/fnmatch.c +./grub-core/gnulib/fnmatch_loop.c +./grub-core/gnulib/getdelim.c +./grub-core/gnulib/getline.c +./grub-core/gnulib/getopt1.c +./grub-core/gnulib/getopt.c +./grub-core/gnulib/localcharset.c +./grub-core/gnulib/malloc.c +./grub-core/gnulib/mbrtowc.c +./grub-core/gnulib/mbsinit.c +./grub-core/gnulib/mbsrtowcs.c +./grub-core/gnulib/mbsrtowcs-state.c +./grub-core/gnulib/memchr.c +./grub-core/gnulib/mempcpy.c +./grub-core/gnulib/nl_langinfo.c +./grub-core/gnulib/printf-args.c +./grub-core/gnulib/printf-parse.c +./grub-core/gnulib/progname.c +./grub-core/gnulib/rawmemchr.c +./grub-core/gnulib/realloc.c +./grub-core/gnulib/regcomp.c +./grub-core/gnulib/regex.c +./grub-core/gnulib/regexec.c +./grub-core/gnulib/regex_internal.c +./grub-core/gnulib/sleep.c +./grub-core/gnulib/stdio-write.c +./grub-core/gnulib/strcasecmp.c +./grub-core/gnulib/strchrnul.c +./grub-core/gnulib/strerror.c +./grub-core/gnulib/stripslash.c +./grub-core/gnulib/strncasecmp.c +./grub-core/gnulib/strndup.c +./grub-core/gnulib/strnlen1.c +./grub-core/gnulib/strnlen.c +./grub-core/gnulib/vasnprintf.c +./grub-core/gnulib/vsnprintf.c +./grub-core/gnulib/wcrtomb.c +./grub-core/hello/hello.c +./grub-core/hook/datehook.c +./grub-core/io/bufio.c +./grub-core/io/gzio.c +./grub-core/io/xzio.c +./grub-core/kern/command.c +./grub-core/kern/corecmd.c +./grub-core/kern/device.c +./grub-core/kern/disk.c +./grub-core/kern/dl.c +./grub-core/kern/efi/efi.c +./grub-core/kern/efi/init.c +./grub-core/kern/efi/mm.c +./grub-core/kern/elf.c +./grub-core/kern/emu/cache.c +./grub-core/kern/emu/console.c +./grub-core/kern/emu/full.c +./grub-core/kern/emu/hostdisk.c +./grub-core/kern/emu/hostfs.c +./grub-core/kern/emu/lite.c +./grub-core/kern/emu/main.c +./grub-core/kern/emu/misc.c +./grub-core/kern/emu/mm.c +./grub-core/kern/emu/time.c +./grub-core/kern/env.c +./grub-core/kern/err.c +./grub-core/kern/file.c +./grub-core/kern/fs.c +./grub-core/kern/generic/millisleep.c +./grub-core/kern/generic/rtc_get_time_ms.c +./grub-core/kern/i386/coreboot/init.c +./grub-core/kern/i386/coreboot/mmap.c +./grub-core/kern/i386/dl.c +./grub-core/kern/i386/efi/init.c +./grub-core/kern/i386/multiboot_mmap.c +./grub-core/kern/i386/pc/init.c +./grub-core/kern/i386/pc/mmap.c +./grub-core/kern/i386/pit.c +./grub-core/kern/i386/qemu/mmap.c +./grub-core/kern/i386/tsc.c +./grub-core/kern/ia64/dl.c +./grub-core/kern/ia64/dl_helper.c +./grub-core/kern/ia64/efi/init.c +./grub-core/kern/ieee1275/cmain.c +./grub-core/kern/ieee1275/ieee1275.c +./grub-core/kern/ieee1275/init.c +./grub-core/kern/ieee1275/mmap.c +./grub-core/kern/ieee1275/openfw.c +./grub-core/kern/list.c +./grub-core/kern/main.c +./grub-core/kern/mips/arc/init.c +./grub-core/kern/mips/dl.c +./grub-core/kern/mips/init.c +./grub-core/kern/mips/loongson/init.c +./grub-core/kern/mips/qemu_mips/init.c +./grub-core/kern/misc.c +./grub-core/kern/mm.c +./grub-core/kern/parser.c +./grub-core/kern/partition.c +./grub-core/kern/powerpc/dl.c +./grub-core/kern/rescue_parser.c +./grub-core/kern/rescue_reader.c +./grub-core/kern/sparc64/dl.c +./grub-core/kern/sparc64/ieee1275/ieee1275.c +./grub-core/kern/term.c +./grub-core/kern/time.c +./grub-core/kern/vga_init.c +./grub-core/kern/x86_64/dl.c +./grub-core/lib/arc/datetime.c +./grub-core/lib/arg.c +./grub-core/lib/cmdline.c +./grub-core/lib/cmos_datetime.c +./grub-core/lib/crc.c +./grub-core/lib/crypto.c +./grub-core/lib/efi/datetime.c +./grub-core/lib/efi/halt.c +./grub-core/lib/efi/relocator.c +./grub-core/lib/emu/halt.c +./grub-core/lib/envblk.c +./grub-core/lib/hexdump.c +./grub-core/lib/i386/halt.c +./grub-core/lib/i386/pc/biosnum.c +./grub-core/lib/i386/pc/vesa_modes_table.c +./grub-core/lib/i386/relocator.c +./grub-core/lib/ieee1275/cmos.c +./grub-core/lib/ieee1275/datetime.c +./grub-core/lib/ieee1275/halt.c +./grub-core/lib/ieee1275/relocator.c +./grub-core/lib/legacy_parse.c +./grub-core/lib/libgcrypt/cipher/ac.c +./grub-core/lib/libgcrypt/cipher/arcfour.c +./grub-core/lib/libgcrypt/cipher/blowfish.c +./grub-core/lib/libgcrypt/cipher/camellia.c +./grub-core/lib/libgcrypt/cipher/camellia-glue.c +./grub-core/lib/libgcrypt/cipher/cast5.c +./grub-core/lib/libgcrypt/cipher/cipher.c +./grub-core/lib/libgcrypt/cipher/crc.c +./grub-core/lib/libgcrypt/cipher/des.c +./grub-core/lib/libgcrypt/cipher/dsa.c +./grub-core/lib/libgcrypt/cipher/ecc.c +./grub-core/lib/libgcrypt/cipher/elgamal.c +./grub-core/lib/libgcrypt/cipher/hash-common.c +./grub-core/lib/libgcrypt/cipher/hmac-tests.c +./grub-core/lib/libgcrypt/cipher/md4.c +./grub-core/lib/libgcrypt/cipher/md5.c +./grub-core/lib/libgcrypt/cipher/md.c +./grub-core/lib/libgcrypt/cipher/primegen.c +./grub-core/lib/libgcrypt/cipher/pubkey.c +./grub-core/lib/libgcrypt/cipher/rfc2268.c +./grub-core/lib/libgcrypt/cipher/rijndael.c +./grub-core/lib/libgcrypt/cipher/rmd160.c +./grub-core/lib/libgcrypt/cipher/rsa.c +./grub-core/lib/libgcrypt/cipher/seed.c +./grub-core/lib/libgcrypt/cipher/serpent.c +./grub-core/lib/libgcrypt/cipher/sha1.c +./grub-core/lib/libgcrypt/cipher/sha256.c +./grub-core/lib/libgcrypt/cipher/sha512.c +./grub-core/lib/libgcrypt/cipher/tiger.c +./grub-core/lib/libgcrypt/cipher/twofish.c +./grub-core/lib/libgcrypt/cipher/whirlpool.c +./grub-core/lib/libgcrypt-grub/cipher/arcfour.c +./grub-core/lib/libgcrypt-grub/cipher/blowfish.c +./grub-core/lib/libgcrypt-grub/cipher/camellia.c +./grub-core/lib/libgcrypt-grub/cipher/camellia-glue.c +./grub-core/lib/libgcrypt-grub/cipher/cast5.c +./grub-core/lib/libgcrypt-grub/cipher/crc.c +./grub-core/lib/libgcrypt-grub/cipher/des.c +./grub-core/lib/libgcrypt-grub/cipher/dsa.c +./grub-core/lib/libgcrypt-grub/cipher/ecc.c +./grub-core/lib/libgcrypt-grub/cipher/elgamal.c +./grub-core/lib/libgcrypt-grub/cipher/init.c +./grub-core/lib/libgcrypt-grub/cipher/md4.c +./grub-core/lib/libgcrypt-grub/cipher/md5.c +./grub-core/lib/libgcrypt-grub/cipher/primegen.c +./grub-core/lib/libgcrypt-grub/cipher/rfc2268.c +./grub-core/lib/libgcrypt-grub/cipher/rijndael.c +./grub-core/lib/libgcrypt-grub/cipher/rmd160.c +./grub-core/lib/libgcrypt-grub/cipher/rsa.c +./grub-core/lib/libgcrypt-grub/cipher/seed.c +./grub-core/lib/libgcrypt-grub/cipher/serpent.c +./grub-core/lib/libgcrypt-grub/cipher/sha1.c +./grub-core/lib/libgcrypt-grub/cipher/sha256.c +./grub-core/lib/libgcrypt-grub/cipher/sha512.c +./grub-core/lib/libgcrypt-grub/cipher/tiger.c +./grub-core/lib/libgcrypt-grub/cipher/twofish.c +./grub-core/lib/libgcrypt-grub/cipher/whirlpool.c +./grub-core/lib/LzFind.c +./grub-core/lib/LzmaDec.c +./grub-core/lib/LzmaEnc.c +./grub-core/lib/mips/relocator.c +./grub-core/lib/pbkdf2.c +./grub-core/lib/powerpc/relocator.c +./grub-core/lib/reed_solomon.c +./grub-core/lib/relocator.c +./grub-core/lib/xzembed/xz_dec_bcj.c +./grub-core/lib/xzembed/xz_dec_lzma2.c +./grub-core/lib/xzembed/xz_dec_stream.c +./grub-core/loader/aout.c +./grub-core/loader/efi/appleloader.c +./grub-core/loader/efi/chainloader.c +./grub-core/loader/i386/bsd32.c +./grub-core/loader/i386/bsd64.c +./grub-core/loader/i386/bsd.c +./grub-core/loader/i386/bsd_pagetable.c +./grub-core/loader/i386/bsdXX.c +./grub-core/loader/i386/coreboot/chainloader.c +./grub-core/loader/i386/linux.c +./grub-core/loader/i386/multiboot_mbi.c +./grub-core/loader/i386/pc/chainloader.c +./grub-core/loader/i386/pc/freedos.c +./grub-core/loader/i386/pc/linux.c +./grub-core/loader/i386/pc/ntldr.c +./grub-core/loader/i386/xnu.c +./grub-core/loader/ia64/efi/linux.c +./grub-core/loader/macho32.c +./grub-core/loader/macho64.c +./grub-core/loader/macho.c +./grub-core/loader/machoXX.c +./grub-core/loader/mips/linux.c +./grub-core/loader/multiboot.c +./grub-core/loader/multiboot_elfxx.c +./grub-core/loader/multiboot_mbi2.c +./grub-core/loader/powerpc/ieee1275/linux.c +./grub-core/loader/sparc64/ieee1275/linux.c +./grub-core/loader/xnu.c +./grub-core/loader/xnu_resume.c +./grub-core/mmap/efi/mmap.c +./grub-core/mmap/i386/mmap.c +./grub-core/mmap/i386/pc/mmap.c +./grub-core/mmap/i386/uppermem.c +./grub-core/mmap/mips/uppermem.c +./grub-core/mmap/mmap.c +./grub-core/net/arp.c +./grub-core/net/bootp.c +./grub-core/net/drivers/efi/efinet.c +./grub-core/net/drivers/emu/emunet.c +./grub-core/net/drivers/i386/pc/pxe.c +./grub-core/net/drivers/ieee1275/ofnet.c +./grub-core/net/ethernet.c +./grub-core/net/ip.c +./grub-core/net/netbuff.c +./grub-core/net/net.c +./grub-core/net/tftp.c +./grub-core/net/udp.c +./grub-core/normal/auth.c +./grub-core/normal/autofs.c +./grub-core/normal/charset.c +./grub-core/normal/cmdline.c +./grub-core/normal/color.c +./grub-core/normal/completion.c +./grub-core/normal/context.c +./grub-core/normal/crypto.c +./grub-core/normal/datetime.c +./grub-core/normal/dyncmd.c +./grub-core/normal/main.c +./grub-core/normal/menu.c +./grub-core/normal/menu_entry.c +./grub-core/normal/menu_text.c +./grub-core/normal/misc.c +./grub-core/normal/term.c +./grub-core/partmap/acorn.c +./grub-core/partmap/amiga.c +./grub-core/partmap/apple.c +./grub-core/partmap/bsdlabel.c +./grub-core/partmap/dvh.c +./grub-core/partmap/gpt.c +./grub-core/partmap/msdos.c +./grub-core/partmap/sun.c +./grub-core/partmap/sunpc.c +./grub-core/parttool/msdospart.c +./grub-core/script/argv.c +./grub-core/script/execute.c +./grub-core/script/function.c +./grub-core/script/lexer.c +./grub-core/script/main.c +./grub-core/script/script.c +./grub-core/term/arc/console.c +./grub-core/term/at_keyboard.c +./grub-core/term/efi/console.c +./grub-core/term/gfxterm.c +./grub-core/term/i386/pc/console.c +./grub-core/term/i386/pc/vga_text.c +./grub-core/term/i386/vga_common.c +./grub-core/term/ieee1275/ofconsole.c +./grub-core/term/ns8250.c +./grub-core/term/serial.c +./grub-core/term/terminfo.c +./grub-core/term/tparm.c +./grub-core/term/usb_keyboard.c +./grub-core/tests/example_functional_test.c +./grub-core/tests/lib/functional_test.c +./grub-core/tests/lib/test.c +./grub-core/tests/test_blockarg.c +./grub-core/unidata.c +./grub-core/video/bitmap.c +./grub-core/video/bitmap_scale.c +./grub-core/video/bochs.c +./grub-core/video/cirrus.c +./grub-core/video/colors.c +./grub-core/video/efi_gop.c +./grub-core/video/efi_uga.c +./grub-core/video/emu/sdl.c +./grub-core/video/fb/fbblit.c +./grub-core/video/fb/fbfill.c +./grub-core/video/fb/fbutil.c +./grub-core/video/fb/video_fb.c +./grub-core/video/i386/pc/vbe.c +./grub-core/video/i386/pc/vga.c +./grub-core/video/ieee1275.c +./grub-core/video/readers/jpeg.c +./grub-core/video/readers/png.c +./grub-core/video/readers/tga.c +./grub-core/video/sis315_init.c +./grub-core/video/sis315pro.c +./grub-core/video/sm712.c +./grub-core/video/sm712_init.c +./grub-core/video/video.c +./tests/example_unit_test.c +./tests/lib/unit_test.c +./util/bin2h.c +./util/deviceiter.c +./util/devicemap.c +./util/getroot.c +./util/grub-editenv.c +./util/grub-fstest.c +./util/grub-macho2img.c +./util/grub-menulst2cfg.c +./util/grub-mkdevicemap.c +./util/grub-mkfont.c +./util/grub-mkimage.c +./util/grub-mkimagexx.c +./util/grub-mklayout.c +./util/grub-mkpasswd-pbkdf2.c +./util/grub-mkrelpath.c +./util/grub-pe2elf.c +./util/grub-probe.c +./util/grub-script-check.c +./util/grub-setup.c +./util/ieee1275/devicemap.c +./util/ieee1275/grub-ofpathname.c +./util/ieee1275/ofpath.c +./util/lvm.c +./util/misc.c +./util/raid.c +./util/resolve.c From ca5572a9ad872fd26712d0fbae1ab63adc64787b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 16:06:31 +0200 Subject: [PATCH 301/673] * util/grub-install.in: Recognize ESP mounted at /boot/EFI. --- ChangeLog | 4 ++++ util/grub-install.in | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 84167f226..0b386157c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-10 Vladimir Serbinenko + + * util/grub-install.in: Recognize ESP mounted at /boot/EFI. + 2011-07-10 Vladimir Serbinenko * po/POTFILES.in: Regenerate. diff --git a/util/grub-install.in b/util/grub-install.in index 711c9c7e2..1e9e1a2fd 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -335,6 +335,12 @@ if [ x"$platform" = xefi ]; then if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}"`"; then efidir="${bootdir}/efi" fi + elif test -d "${bootdir}/EFI"; then + install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}/EFI"`" + # Is it a mount point? + if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}"`"; then + efidir="${bootdir}/EFI" + fi elif test -n "$rootdir" && test "x$rootdir" != "x/"; then # The EFI System Partition may have been given directly using # --root-directory. From c410299b05a5cc61f31ecf1b5be639ce94094637 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 10 Jul 2011 23:37:28 +0200 Subject: [PATCH 302/673] TCP listening support --- grub-core/net/tcp.c | 432 +++++++++++++++++++++++++++-------------- include/grub/net/tcp.h | 23 +++ 2 files changed, 308 insertions(+), 147 deletions(-) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 489277678..f6d864523 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -74,6 +74,19 @@ struct grub_net_tcp_socket grub_priority_queue_t pq; }; +struct grub_net_tcp_listen +{ + struct grub_net_tcp_listen *next; + + grub_uint16_t port; + const struct grub_net_network_level_interface *inf; + + grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen, + grub_net_tcp_socket_t sock, + void *data); + void *hook_data; +}; + struct tcphdr { grub_uint16_t src; @@ -95,9 +108,38 @@ struct tcp_pseudohdr grub_uint16_t tcp_length; } __attribute__ ((packed)); -struct grub_net_tcp_socket *tcp_sockets; +static struct grub_net_tcp_socket *tcp_sockets; +static struct grub_net_tcp_listen *tcp_listens; -#define FOR_TCP_SOCKETS(var) for (var = tcp_sockets; var; var = var->next) +#define FOR_TCP_SOCKETS(var) FOR_LIST_ELEMENTS (var, tcp_sockets) +#define FOR_TCP_LISTENS(var) FOR_LIST_ELEMENTS (var, tcp_listens) + +grub_net_tcp_listen_t +grub_net_tcp_listen (grub_uint16_t port, + const struct grub_net_network_level_interface *inf, + grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen, + grub_net_tcp_socket_t sock, + void *data), + void *hook_data) +{ + grub_net_tcp_listen_t ret; + ret = grub_malloc (sizeof (*ret)); + if (!ret) + return NULL; + ret->listen_hook = listen_hook; + ret->hook_data = hook_data; + ret->port = port; + ret->inf = inf; + grub_list_push (GRUB_AS_LIST_P (&tcp_listens), GRUB_AS_LIST (ret)); + return ret; +} + +void +grub_net_tcp_stop_listen (grub_net_tcp_listen_t listen) +{ + grub_list_remove (GRUB_AS_LIST_P (&tcp_listens), + GRUB_AS_LIST (listen)); +} static inline void tcp_socket_register (grub_net_tcp_socket_t sock) @@ -106,6 +148,25 @@ tcp_socket_register (grub_net_tcp_socket_t sock) GRUB_AS_LIST (sock)); } +static void +error (grub_net_tcp_socket_t sock) +{ + struct unacked *unack, *next; + + if (sock->established && sock->error_hook) + sock->error_hook (sock, sock->hook_data); + + for (unack = sock->unack_first; unack; unack = next) + { + next = unack->next; + grub_netbuff_free (unack->nb); + grub_free (unack); + } + + sock->unack_first = NULL; + sock->unack_last = NULL; +} + static grub_err_t tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket) { @@ -164,10 +225,13 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock) sock->i_closed = 1; - nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin) + 128); + nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin) + + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); if (!nb_fin) return; - err = grub_netbuff_reserve (nb_fin, 128); + err = grub_netbuff_reserve (nb_fin, GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); if (err) { grub_netbuff_free (nb_fin); @@ -261,9 +325,7 @@ grub_net_tcp_retransmit (void) if (unack->try_count > TCP_RETRANSMISSION_COUNT) { - if (sock->error_hook) - sock->error_hook (sock, sock->hook_data); - grub_net_tcp_close (sock); + error (sock); break; } unack->try_count++; @@ -332,6 +394,54 @@ destroy_pq (grub_net_tcp_socket_t sock) grub_priority_queue_destroy (sock->pq); } +grub_err_t +grub_net_tcp_accept (grub_net_tcp_socket_t sock, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data) +{ + struct grub_net_buff *nb_ack; + struct tcphdr *tcph; + grub_err_t err; + + sock->recv_hook = recv_hook; + sock->error_hook = error_hook; + sock->hook_data = hook_data; + nb_ack = grub_netbuff_alloc (sizeof (*tcph) + + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb_ack) + return grub_errno; + err = grub_netbuff_reserve (nb_ack, GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + { + grub_netbuff_free (nb_ack); + return err; + } + + err = grub_netbuff_put (nb_ack, sizeof (*tcph)); + if (err) + { + grub_netbuff_free (nb_ack); + return err; + } + tcph = (void *) nb_ack->data; + tcph->ack = grub_cpu_to_be32 (sock->their_cur_seq); + tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN | TCP_ACK); + tcph->window = grub_cpu_to_be16 (sock->my_window); + tcph->urgent = 0; + tcp_socket_register (sock); + err = tcp_send (nb_ack, sock); + if (err) + return err; + sock->my_cur_seq++; + return GRUB_ERR_NONE; +} + grub_net_tcp_socket_t grub_net_tcp_open (char *server, grub_uint16_t out_port, @@ -545,159 +655,187 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, FOR_TCP_SOCKETS (sock) { - if (grub_be_to_cpu16 (tcph->dst) == sock->in_port - && grub_be_to_cpu16 (tcph->src) == sock->out_port - && inf == sock->inf - && source->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && source->ipv4 == sock->out_nla.ipv4) + if (!(grub_be_to_cpu16 (tcph->dst) == sock->in_port + && grub_be_to_cpu16 (tcph->src) == sock->out_port + && inf == sock->inf + && source->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && source->ipv4 == sock->out_nla.ipv4)) + continue; + if (tcph->checksum) { - if (tcph->checksum) + grub_uint16_t chk, expected; + chk = tcph->checksum; + tcph->checksum = 0; + expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, + &sock->out_nla, + &sock->inf->address); + if (expected != chk) { - grub_uint16_t chk, expected; - chk = tcph->checksum; - tcph->checksum = 0; - expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, - &sock->out_nla, - &sock->inf->address); - if (expected != chk) - { - grub_dprintf ("net", "Invalid TCP checksum. " - "Expected %x, got %x\n", - grub_be_to_cpu16 (expected), - grub_be_to_cpu16 (chk)); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - tcph->checksum = chk; - } - - if ((grub_be_to_cpu16 (tcph->flags) & TCP_SYN) - && (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) - && !sock->established) - { - sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr); - sock->their_cur_seq = sock->their_start_seq + 1; - sock->established = 1; - } - - if (grub_be_to_cpu16 (tcph->flags) & TCP_RST) - { - struct unacked *unack, *next; - sock->reseted = 1; - for (unack = sock->unack_first; unack; unack = next) - { - next = unack->next; - grub_netbuff_free (unack->nb); - grub_free (unack); - } - - sock->unack_first = NULL; - sock->unack_last = NULL; - - grub_netbuff_free (nb); - - return GRUB_ERR_NONE; - } - - if (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) - { - struct unacked *unack, *next; - grub_uint32_t acked = grub_be_to_cpu32 (tcph->ack); - for (unack = sock->unack_first; unack; unack = next) - { - grub_uint32_t seqnr; - next = unack->next; - seqnr = grub_be_to_cpu32 (((struct tcphdr *) unack->nb->data) - ->seqnr); - seqnr += (nb->tail - nb->data - - (grub_be_to_cpu16 (tcph->flags) >> 12) * 4); - if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) - seqnr++; - - if (seqnr > acked) - break; - grub_netbuff_free (unack->nb); - grub_free (unack); - } - sock->unack_first = unack; - if (!sock->unack_last) - sock->unack_last = NULL; - } - - if (grub_be_to_cpu32 (tcph->seqnr) < sock->their_cur_seq) - { - ack (sock); + grub_dprintf ("net", "Invalid TCP checksum. " + "Expected %x, got %x\n", + grub_be_to_cpu16 (expected), + grub_be_to_cpu16 (chk)); grub_netbuff_free (nb); return GRUB_ERR_NONE; } + tcph->checksum = chk; + } - err = grub_priority_queue_push (sock->pq, &nb); - if (err) - return err; + if ((grub_be_to_cpu16 (tcph->flags) & TCP_SYN) + && (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) + && !sock->established) + { + sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr); + sock->their_cur_seq = sock->their_start_seq + 1; + sock->established = 1; + } - { - struct grub_net_buff **nb_top_p, *nb_top; - int do_ack = 0; - while (1) - { - nb_top_p = grub_priority_queue_top (sock->pq); - if (!nb_top_p) - return GRUB_ERR_NONE; - nb_top = *nb_top_p; - tcph = (struct tcphdr *) nb_top->data; - if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq) - break; - grub_priority_queue_pop (sock->pq); - } - if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) - return GRUB_ERR_NONE; - while (1) - { - nb_top_p = grub_priority_queue_top (sock->pq); - if (!nb_top_p) - break; - nb_top = *nb_top_p; - tcph = (struct tcphdr *) nb_top->data; + if (grub_be_to_cpu16 (tcph->flags) & TCP_RST) + { + sock->reseted = 1; - if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) - break; - grub_priority_queue_pop (sock->pq); + error (sock); - err = grub_netbuff_pull (nb, (grub_be_to_cpu16 (tcph->flags) - >> 12) * sizeof (grub_uint32_t)); - if (err) - return err; + grub_netbuff_free (nb); - sock->their_cur_seq += (nb_top->tail - nb_top->data); - if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) - { - sock->they_closed = 1; - sock->their_cur_seq++; - do_ack = 1; - } - /* If there is data, puts packet in socket list. */ - if ((nb_top->tail - nb_top->data) > 0) - { - grub_net_put_packet (&sock->packs, nb_top); - do_ack = 1; - } - else - grub_netbuff_free (nb); - } - if (do_ack) - ack (sock); - } - while (sock->packs.first) - { - nb = sock->packs.first->nb; - if (sock->recv_hook) - sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data); - grub_net_remove_packet (sock->packs.first); - } - return GRUB_ERR_NONE; } + + if (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) + { + struct unacked *unack, *next; + grub_uint32_t acked = grub_be_to_cpu32 (tcph->ack); + for (unack = sock->unack_first; unack; unack = next) + { + grub_uint32_t seqnr; + next = unack->next; + seqnr = grub_be_to_cpu32 (((struct tcphdr *) unack->nb->data) + ->seqnr); + seqnr += (nb->tail - nb->data + - (grub_be_to_cpu16 (tcph->flags) >> 12) * 4); + if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + seqnr++; + + if (seqnr > acked) + break; + grub_netbuff_free (unack->nb); + grub_free (unack); + } + sock->unack_first = unack; + if (!sock->unack_last) + sock->unack_last = NULL; + } + + if (grub_be_to_cpu32 (tcph->seqnr) < sock->their_cur_seq) + { + ack (sock); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + err = grub_priority_queue_push (sock->pq, &nb); + if (err) + return err; + + { + struct grub_net_buff **nb_top_p, *nb_top; + int do_ack = 0; + while (1) + { + nb_top_p = grub_priority_queue_top (sock->pq); + if (!nb_top_p) + return GRUB_ERR_NONE; + nb_top = *nb_top_p; + tcph = (struct tcphdr *) nb_top->data; + if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq) + break; + grub_priority_queue_pop (sock->pq); + } + if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) + return GRUB_ERR_NONE; + while (1) + { + nb_top_p = grub_priority_queue_top (sock->pq); + if (!nb_top_p) + break; + nb_top = *nb_top_p; + tcph = (struct tcphdr *) nb_top->data; + + if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) + break; + grub_priority_queue_pop (sock->pq); + + err = grub_netbuff_pull (nb, (grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t)); + if (err) + return err; + + sock->their_cur_seq += (nb_top->tail - nb_top->data); + if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + { + sock->they_closed = 1; + sock->their_cur_seq++; + do_ack = 1; + } + /* If there is data, puts packet in socket list. */ + if ((nb_top->tail - nb_top->data) > 0) + { + grub_net_put_packet (&sock->packs, nb_top); + do_ack = 1; + } + else + grub_netbuff_free (nb); + } + if (do_ack) + ack (sock); + } + while (sock->packs.first) + { + nb = sock->packs.first->nb; + if (sock->recv_hook) + sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data); + grub_net_remove_packet (sock->packs.first); + } + + return GRUB_ERR_NONE; } + if (grub_be_to_cpu16 (tcph->flags) & TCP_SYN) + { + grub_net_tcp_listen_t listen; + + FOR_TCP_LISTENS (listen) + { + if (!(grub_be_to_cpu16 (tcph->dst) == listen->port + && (inf == listen->inf || listen->inf == NULL))) + continue; + sock = grub_zalloc (sizeof (*sock)); + if (sock == NULL) + return grub_errno; + + sock->out_port = grub_be_to_cpu16 (tcph->src); + sock->in_port = grub_be_to_cpu16 (tcph->dst); + sock->inf = inf; + sock->out_nla = *source; + sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr); + sock->their_cur_seq = sock->their_start_seq + 1; + sock->my_cur_seq = sock->my_start_seq = grub_get_time_ms (); + sock->my_window = 8192; + + sock->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), + cmp); + if (!sock->pq) + { + grub_netbuff_free (nb); + return grub_errno; + } + + err = listen->listen_hook (listen, sock, listen->hook_data); + + grub_netbuff_free (nb); + return err; + + } + } grub_netbuff_free (nb); return GRUB_ERR_NONE; } diff --git a/include/grub/net/tcp.h b/include/grub/net/tcp.h index cd05074f5..0ac7819bc 100644 --- a/include/grub/net/tcp.h +++ b/include/grub/net/tcp.h @@ -24,6 +24,9 @@ struct grub_net_tcp_socket; typedef struct grub_net_tcp_socket *grub_net_tcp_socket_t; +struct grub_net_tcp_listen; +typedef struct grub_net_tcp_listen *grub_net_tcp_listen_t; + grub_net_tcp_socket_t grub_net_tcp_open (char *server, grub_uint16_t out_port, @@ -34,6 +37,17 @@ grub_net_tcp_open (char *server, void *data), void *hook_data); +grub_net_tcp_listen_t +grub_net_tcp_listen (grub_uint16_t port, + const struct grub_net_network_level_interface *inf, + grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen, + grub_net_tcp_socket_t sock, + void *data), + void *hook_data); + +void +grub_net_tcp_stop_listen (grub_net_tcp_listen_t listen); + grub_err_t grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, struct grub_net_buff *nb, @@ -42,4 +56,13 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, void grub_net_tcp_close (grub_net_tcp_socket_t sock); +grub_err_t +grub_net_tcp_accept (grub_net_tcp_socket_t sock, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data); + #endif From 4ebb4c616f98b0c9da54a5c38502a3c11acf0b25 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Jul 2011 03:47:10 +0200 Subject: [PATCH 303/673] Remove useless include in tftp --- grub-core/net/tftp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index bc8886442..7c58e640b 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -26,7 +26,6 @@ #include #include #include -#include GRUB_MOD_LICENSE ("GPLv3+"); From 440694e3d39beeb144dd600b76c5245f935bc22e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Jul 2011 03:48:10 +0200 Subject: [PATCH 304/673] Fix TCP retransmission --- grub-core/net/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index f6d864523..578a254f4 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -708,12 +708,14 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, for (unack = sock->unack_first; unack; unack = next) { grub_uint32_t seqnr; + struct tcphdr *unack_tcph; next = unack->next; seqnr = grub_be_to_cpu32 (((struct tcphdr *) unack->nb->data) ->seqnr); - seqnr += (nb->tail - nb->data - - (grub_be_to_cpu16 (tcph->flags) >> 12) * 4); - if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + unack_tcph = (struct tcphdr *) unack->nb->data; + seqnr += (unack->nb->tail - unack->nb->data + - (grub_be_to_cpu16 (unack_tcph->flags) >> 12) * 4); + if (grub_be_to_cpu16 (unack_tcph->flags) & TCP_FIN) seqnr++; if (seqnr > acked) From 80e722366d307f93c94ab54d4717d973887c87b9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Jul 2011 03:49:02 +0200 Subject: [PATCH 305/673] First attempt at http --- grub-core/Makefile.core.def | 5 + grub-core/net/http.c | 356 ++++++++++++++++++++++++++++++++++++ grub-core/net/tcp.c | 5 +- include/grub/err.h | 4 +- include/grub/misc.h | 14 ++ include/grub/net.h | 13 +- 6 files changed, 391 insertions(+), 6 deletions(-) create mode 100644 grub-core/net/http.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 673092b4f..f42b272ca 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1609,6 +1609,11 @@ module = { common = net/tftp.c; }; +module = { + name = http; + common = net/http.c; +}; + module = { name = ofnet; common = net/drivers/ieee1275/ofnet.c; diff --git a/grub-core/net/http.c b/grub-core/net/http.c new file mode 100644 index 000000000..b5de4c5c6 --- /dev/null +++ b/grub-core/net/http.c @@ -0,0 +1,356 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +enum + { + HTTP_PORT = 80 + }; + + +typedef struct http_data +{ + grub_uint64_t file_size; + grub_uint64_t position; + char *current_line; + grub_size_t current_line_len; + int headers_recv; + int first_line_recv; + grub_net_tcp_socket_t sock; +} *http_data_t; + +static grub_err_t +parse_line (http_data_t data, char *ptr, grub_size_t len) +{ + char *end = ptr + len; + while (end > ptr && *(end - 1) == '\r') + end--; + *end = 0; + if (ptr == end) + { + data->headers_recv = 1; + return GRUB_ERR_NONE; + } + + if (!data->first_line_recv) + { + int code; + if (grub_memcmp (ptr, "HTTP/1.1 ", sizeof ("HTTP/1.1 ") - 1) != 0) + return grub_error (GRUB_ERR_NET_INVALID_RESPONSE, + "unsupported HTTP response"); + ptr += sizeof ("HTTP/1.1 ") - 1; + code = grub_strtoul (ptr, &ptr, 10); + if (grub_errno) + return grub_errno; + switch (code) + { + case 200: + break; + default: + return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR, + "unsupported HTTP error %d: %s", + code, ptr); + } + data->first_line_recv = 1; + return GRUB_ERR_NONE; + } + if (grub_memcmp (ptr, "Content-Length: ", sizeof ("Content-Length: ") - 1) + == 0) + { + ptr += sizeof ("Content-Length: ") - 1; + data->file_size = grub_strtoull (ptr, &ptr, 10); + return GRUB_ERR_NONE; + } + return GRUB_ERR_NONE; +} + +static void +http_err (grub_net_tcp_socket_t sock __attribute__ ((unused)), + void *f) +{ + grub_file_t file = f; + http_data_t data = file->data; + + if (data->sock) + grub_net_tcp_close (data->sock); + grub_free (data); + if (data->current_line) + grub_free (data->current_line); + file->device->net->eof = 1; +} + +static grub_err_t +http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), + struct grub_net_buff *nb, + void *f) +{ + grub_file_t file = f; + http_data_t data = file->data; + char *ptr = (char *) nb->data; + grub_err_t err; + + if (!data->headers_recv && data->current_line) + { + int have_line = 1; + char *t; + ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); + if (ptr) + ptr++; + else + { + have_line = 0; + ptr = (char *) nb->tail; + } + t = grub_realloc (data->current_line, + data->current_line_len + (ptr - (char *) nb->data)); + if (!t) + { + grub_netbuff_free (nb); + grub_net_tcp_close (data->sock); + return grub_errno; + } + + data->current_line = t; + grub_memcpy (data->current_line + data->current_line_len, + nb->data, ptr - (char *) nb->data); + data->current_line_len += ptr - (char *) nb->data; + if (!have_line) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + err = parse_line (data, data->current_line, data->current_line_len); + grub_free (data->current_line); + data->current_line = 0; + data->current_line_len = 0; + if (err) + { + grub_net_tcp_close (data->sock); + grub_netbuff_free (nb); + return err; + } + } + + while (ptr < (char *) nb->tail && !data->headers_recv) + { + char *ptr2; + ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr); + if (!ptr2) + { + data->current_line = grub_malloc ((char *) nb->tail - ptr); + if (!data->current_line) + { + grub_netbuff_free (nb); + grub_net_tcp_close (data->sock); + return grub_errno; + } + data->current_line_len = (char *) nb->tail - ptr; + grub_memcpy (data->current_line, ptr, data->current_line_len); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + err = parse_line (data, ptr, ptr2 - ptr); + if (err) + { + grub_net_tcp_close (data->sock); + grub_netbuff_free (nb); + return err; + } + ptr = ptr2 + 1; + } + + if (((char *) nb->tail - ptr) > 0) + { + data->position += ((char *) nb->tail - ptr); + err = grub_netbuff_pull (nb, ptr - (char *) nb->data); + if (err) + { + grub_net_tcp_close (data->sock); + grub_netbuff_free (nb); + return err; + } + grub_net_put_packet (&file->device->net->packs, nb); + } + else + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} + +static grub_err_t +http_open (struct grub_file *file, const char *filename) +{ + struct grub_net_buff *nb; + http_data_t data; + grub_err_t err; + grub_uint8_t *ptr; + int i; + + data = grub_zalloc (sizeof (*data)); + if (!data) + return grub_errno; + + nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE + + sizeof ("GET ") - 1 + + grub_strlen (filename) + + sizeof (" HTTP/1.1\r\nHost: ") - 1 + + grub_strlen (file->device->net->server) + + sizeof ("\r\nUser-Agent: " PACKAGE_STRING + "\r\n\r\n") - 1); + if (!nb) + { + grub_free (data); + return grub_errno; + } + + grub_netbuff_reserve (nb, GRUB_NET_TCP_RESERVE_SIZE); + ptr = nb->tail; + err = grub_netbuff_put (nb, sizeof ("GET ") - 1); + if (err) + { + grub_free (data); + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, "GET ", sizeof ("GET ") - 1); + + ptr = nb->tail; + err = grub_netbuff_put (nb, grub_strlen (filename)); + if (err) + { + grub_free (data); + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, filename, grub_strlen (filename)); + + ptr = nb->tail; + err = grub_netbuff_put (nb, sizeof (" HTTP/1.1\r\nHost: ") - 1); + if (err) + { + grub_free (data); + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, " HTTP/1.1\r\nHost: ", + sizeof (" HTTP/1.1\r\nHost: ") - 1); + + ptr = nb->tail; + err = grub_netbuff_put (nb, grub_strlen (file->device->net->server)); + if (err) + { + grub_free (data); + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, file->device->net->server, + grub_strlen (file->device->net->server)); + + ptr = nb->tail; + err = grub_netbuff_put (nb, + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n") + - 1); + if (err) + { + grub_free (data); + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, "\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n", + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n") - 1); + + file->not_easily_seekable = 1; + file->data = data; + + data->sock = grub_net_tcp_open (file->device->net->server, + HTTP_PORT, http_receive, + http_err, + file); + if (!data->sock) + { + grub_free (data); + grub_netbuff_free (nb); + return grub_errno; + } + + // grub_net_poll_cards (5000); + + err = grub_net_send_tcp_packet (data->sock, nb, 1); + if (err) + { + grub_free (data); + grub_net_tcp_close (data->sock); + return err; + } + + for (i = 0; !data->headers_recv && i < 100; i++) + { + grub_net_tcp_retransmit (); + grub_net_poll_cards (300); + } + + if (!data->headers_recv) + { + grub_net_tcp_close (data->sock); + grub_free (data); + return grub_error (GRUB_ERR_TIMEOUT, "Time out opening http."); + } + file->size = data->file_size; + + return GRUB_ERR_NONE; +} + +static grub_err_t +http_close (struct grub_file *file) +{ + http_data_t data = file->data; + + if (data->sock) + grub_net_tcp_close (data->sock); + grub_free (data); + if (data->current_line) + grub_free (data->current_line); + return GRUB_ERR_NONE; +} + +static struct grub_net_app_protocol grub_http_protocol = + { + .name = "http", + .open = http_open, + .close = http_close + }; + +GRUB_MOD_INIT (http) +{ + grub_net_app_level_register (&grub_http_protocol); +} + +GRUB_MOD_FINI (http) +{ + grub_net_app_level_unregister (&grub_http_protocol); +} diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 578a254f4..25e8ab4ed 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -25,8 +25,8 @@ #define TCP_SYN_RETRANSMISSION_TIMEOUT 1000 #define TCP_SYN_RETRANSMISSION_COUNT 3 -#define TCP_RETRANSMISSION_TIMEOUT 10000 -#define TCP_RETRANSMISSION_COUNT 5 +#define TCP_RETRANSMISSION_TIMEOUT 1000 +#define TCP_RETRANSMISSION_COUNT 10 struct unacked { @@ -577,6 +577,7 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, struct tcphdr *tcph; grub_err_t err; grub_ssize_t fraglen; + COMPILE_TIME_ASSERT (sizeof (struct tcphdr) == GRUB_NET_TCP_HEADER_SIZE); fraglen = (socket->inf->card->mtu - GRUB_NET_OUR_IPV4_HEADER_SIZE - sizeof (*tcph)); diff --git a/include/grub/err.h b/include/grub/err.h index c91911644..f6610193c 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -62,7 +62,9 @@ typedef enum GRUB_ERR_NET_NO_ANSWER, GRUB_ERR_WAIT, GRUB_ERR_BUG, - GRUB_ERR_NET_PORT_CLOSED + GRUB_ERR_NET_PORT_CLOSED, + GRUB_ERR_NET_INVALID_RESPONSE, + GRUB_ERR_NET_UNKNOWN_ERROR } grub_err_t; diff --git a/include/grub/misc.h b/include/grub/misc.h index da4bd4a7e..e608ddfb8 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -302,6 +302,20 @@ void EXPORT_FUNC (__deregister_frame_info) (void); /* Inline functions. */ +static inline char * +grub_memchr (const void *p, int c, grub_size_t len) +{ + const char *s = p; + const char *e = s + len; + + for (; s < e; s++) + if (*s == c) + return (char *) s; + + return 0; +} + + static inline unsigned int grub_abs (int x) { diff --git a/include/grub/net.h b/include/grub/net.h index d71edfd1e..255784315 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -27,9 +27,16 @@ #include #include -#define GRUB_NET_MAX_LINK_HEADER_SIZE 64 -#define GRUB_NET_UDP_HEADER_SIZE 8 -#define GRUB_NET_OUR_IPV4_HEADER_SIZE 20 +enum + { + GRUB_NET_MAX_LINK_HEADER_SIZE = 64, + GRUB_NET_UDP_HEADER_SIZE = 8, + GRUB_NET_TCP_HEADER_SIZE = 20, + GRUB_NET_OUR_IPV4_HEADER_SIZE = 20, + GRUB_NET_TCP_RESERVE_SIZE = GRUB_NET_TCP_HEADER_SIZE + + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE + }; typedef enum grub_link_level_protocol_id { From bf66054fb3969fffed65b0fa6dea535ae368a0f8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Jul 2011 16:44:40 +0200 Subject: [PATCH 306/673] * grub-core/kern/mips/cache_flush.S [GRUB_MACHINE_MIPS_LOONGSON]: Flush all four ways. --- ChangeLog | 5 +++++ grub-core/kern/mips/cache_flush.S | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index e4ca1a6c3..55f097965 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-23 Vladimir Serbinenko + + * grub-core/kern/mips/cache_flush.S [GRUB_MACHINE_MIPS_LOONGSON]: Flush + all four ways. + 2011-07-21 Colin Watson Preferred resolution detection for VBE. diff --git a/grub-core/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S index a352fd8ba..c03c337b5 100644 --- a/grub-core/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -9,6 +9,13 @@ subu $t1, $t3, $t2 1: cache 1, 0($t0) + /* All four ways. */ +#ifdef GRUB_MACHINE_MIPS_LOONGSON + cache 1, 1($t0) + cache 1, 2($t0) + cache 1, 3($t0) +#endif + addiu $t1, $t1, -0x4 bne $t1, $zero, 1b addiu $t0, $t0, 0x4 From a1167439107cc51d864452c7249c994f6b5b2ce1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Jul 2011 17:14:38 +0200 Subject: [PATCH 307/673] * include/grub/mips/kernel.h: Fix define conflict. --- ChangeLog | 4 ++++ include/grub/mips/kernel.h | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 55f097965..15e7344f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-23 Vladimir Serbinenko + + * include/grub/mips/kernel.h: Fix define conflict. + 2011-07-23 Vladimir Serbinenko * grub-core/kern/mips/cache_flush.S [GRUB_MACHINE_MIPS_LOONGSON]: Flush diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h index d82d0a97d..d351f17cb 100644 --- a/include/grub/mips/kernel.h +++ b/include/grub/mips/kernel.h @@ -16,8 +16,8 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_KERNEL_MACHINE_HEADER -#define GRUB_KERNEL_MACHINE_HEADER 1 +#ifndef GRUB_KERNEL_CPU_HEADER +#define GRUB_KERNEL_CPU_HEADER 1 #include From 6be1c01fd721bbea8353e0c0ad547a2c0056640c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Jul 2011 17:18:31 +0200 Subject: [PATCH 308/673] * include/grub/video.h: add missing EXPORT_FUND on grub_video_edid_checksum and grub_video_edid_preferred_mode. --- ChangeLog | 5 +++++ include/grub/video.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 15e7344f2..71c33569f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-23 Vladimir Serbinenko + + * include/grub/video.h: add missing EXPORT_FUND on + grub_video_edid_checksum and grub_video_edid_preferred_mode. + 2011-07-23 Vladimir Serbinenko * include/grub/mips/kernel.h: Fix define conflict. diff --git a/include/grub/video.h b/include/grub/video.h index b2adff11d..e30589a3d 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -486,8 +486,8 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); -grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); -grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info, +grub_err_t EXPORT_FUNC (grub_video_edid_checksum) (struct grub_video_edid_info *edid_info); +grub_err_t EXPORT_FUNC (grub_video_edid_preferred_mode) (struct grub_video_edid_info *edid_info, unsigned int *width, unsigned int *height); From 583168a216e477bfbf6039ddc331d5827833ec08 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 23 Jul 2011 18:18:14 +0200 Subject: [PATCH 309/673] * grub-core/disk/pata.c (grub_pata_readwrite): Add missing wait. --- ChangeLog | 4 ++++ grub-core/disk/pata.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 71c33569f..2eb0c0fcd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-23 Vladimir Serbinenko + + * grub-core/disk/pata.c (grub_pata_readwrite): Add missing wait. + 2011-07-23 Vladimir Serbinenko * include/grub/video.h: add missing EXPORT_FUND on diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index ff6f77366..c54fe91ab 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -177,6 +177,10 @@ grub_pata_readwrite (struct grub_ata *disk, /* Start command. */ grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd); + /* Wait for !BSY. */ + if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA)) + return grub_errno; + /* Check status. */ grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS); grub_dprintf ("pata", "status=0x%x\n", sts); From b70e4cb08d055181585c9b1d3e7a0366e90d17f5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Jul 2011 07:48:19 +0200 Subject: [PATCH 310/673] * grub-core/normal/menu.c (grub_menu_execute_entry): Fix NULL dereference. --- ChangeLog | 5 +++++ grub-core/normal/menu.c | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2eb0c0fcd..5069e5651 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-23 Vladimir Serbinenko + + * grub-core/normal/menu.c (grub_menu_execute_entry): Fix NULL + dereference. + 2011-07-23 Vladimir Serbinenko * grub-core/disk/pata.c (grub_pata_readwrite): Add missing wait. diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index 5844cb2f0..2c127794b 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -232,7 +232,8 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) grub_env_export ("chosen"); grub_free (buf); } - for (ptr = def; *ptr; ptr++) + + for (ptr = def; ptr && *ptr; ptr++) { if (ptr[0] == '>' && ptr[1] == '>') { @@ -242,10 +243,12 @@ grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot) if (ptr[0] == '>') break; } - if (ptr[0] && ptr[1]) + + if (ptr && ptr[0] && ptr[1]) grub_env_set ("default", ptr + 1); else grub_env_unset ("default"); + grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args); if (errs_before != grub_err_printed_errors) From c77069f5ae4107323bf71c8c9d8505048acae740 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Jul 2011 07:57:29 +0200 Subject: [PATCH 311/673] * util/grub-mkrescue.in: Add missing quotes. --- ChangeLog | 6 +++++- util/grub-mkrescue.in | 14 +++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5069e5651..570de50e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ -2011-07-23 Vladimir Serbinenko +2011-07-25 Vladimir Serbinenko + + * util/grub-mkrescue.in: Add missing quotes. + +2011-07-25 Vladimir Serbinenko * grub-core/normal/menu.c (grub_menu_execute_entry): Fix NULL dereference. diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index f054c43a9..4c96dd42b 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -31,15 +31,15 @@ pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst self=`basename $0` -multiboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-multiboot -coreboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-coreboot -qemu_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-qemu -pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc -efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi -efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi +multiboot_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-multiboot" +coreboot_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-coreboot" +qemu_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-qemu" +pc_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc" +efi32_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi" +efi64_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi" rom_directory= override_dir= -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" xorriso=xorriso From 922275976579ecd9ebaa88eba3fb5e8933e9c93f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Jul 2011 08:06:20 +0200 Subject: [PATCH 312/673] * util/grub-install.in: Don't use uhci outside of x86. --- ChangeLog | 4 ++++ util/grub-install.in | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 570de50e1..32dfada58 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-07-25 Vladimir Serbinenko + + * util/grub-install.in: Don't use uhci outside of x86. + 2011-07-25 Vladimir Serbinenko * util/grub-mkrescue.in: Add missing quotes. diff --git a/util/grub-install.in b/util/grub-install.in index 1e9e1a2fd..3d2420b91 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -504,7 +504,11 @@ if [ "x$disk_module" = xata ]; then fi if [ "x$disk_module" = xnative ]; then - disk_module="pata ahci ohci uhci usbms" + disk_module="pata ahci ohci" + if [ "x$target_cpu" = "xi386" ] || [ "x$target_cpu" = "xx86_64" ]; then + disk_module="$disk_module uhci" + fi + disk_module="$disk_module usbms" fi # The order in this list is critical. Be careful when modifying it. From 6795300e7f230ac552c984ef051f0ae79f318bcf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Jul 2011 08:14:34 +0200 Subject: [PATCH 313/673] Support ATA disks with 4K sectors. * include/grub/ata.h (grub_ata): New member log_sector_size. * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size. (grub_ata_identify): Read sector size. (grub_ata_readwrite): Use log_sector_size rather than hardcoded value. --- ChangeLog | 9 +++++++++ grub-core/disk/ata.c | 23 ++++++++++++++++++++--- include/grub/ata.h | 1 + 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 32dfada58..5c4e20c28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-07-25 Vladimir Serbinenko + + Support ATA disks with non-4K sectors. + + * include/grub/ata.h (grub_ata): New member log_sector_size. + * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size. + (grub_ata_identify): Read sector size. + (grub_ata_readwrite): Use log_sector_size rather than hardcoded value. + 2011-07-25 Vladimir Serbinenko * util/grub-install.in: Don't use uhci outside of x86. diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 8add7f4de..330635f57 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -57,6 +57,7 @@ grub_ata_dumpinfo (struct grub_ata *dev, char *info) { grub_dprintf ("ata", "Addressing: %d\n", dev->addr); grub_dprintf ("ata", "Sectors: %lld\n", (unsigned long long) dev->size); + grub_dprintf ("ata", "Sector size: %u\n", 1U << dev->log_sector_size); } } @@ -170,6 +171,21 @@ grub_ata_identify (struct grub_ata *dev) else dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100])); + if (info16[106] & (1 << 12)) + { + grub_uint32_t secsize; + secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117])); + if (secsize & (secsize - 1) || !secsize + || secsize > 1048576) + secsize = 256; + for (dev->log_sector_size = 0; + (1U << dev->log_sector_size) < secsize; + dev->log_sector_size++); + dev->log_sector_size++; + } + else + dev->log_sector_size = 9; + /* Read CHS information. */ dev->cylinders = info16[1]; dev->heads = info16[3]; @@ -314,7 +330,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_ata_setaddress (ata, &parms, sector, batch, addressing); parms.taskfile.cmd = (! rw ? cmd : cmd_write); parms.buffer = buf; - parms.size = batch * GRUB_DISK_SECTOR_SIZE; + parms.size = batch << ata->log_sector_size; parms.write = rw; if (ata->dma) parms.dma = 1; @@ -322,9 +338,9 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, err = ata->dev->readwrite (ata, &parms, 0); if (err) return err; - if (parms.size != batch * GRUB_DISK_SECTOR_SIZE) + if (parms.size != batch << ata->log_sector_size) return grub_error (GRUB_ERR_READ_ERROR, "incomplete read"); - buf += GRUB_DISK_SECTOR_SIZE * batch; + buf += batch << ata->log_sector_size; sector += batch; nsectors += batch; } @@ -433,6 +449,7 @@ grub_ata_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); disk->total_sectors = ata->size; + disk->log_sector_size = ata->log_sector_size; disk->id = grub_make_scsi_id (id, bus, 0); diff --git a/include/grub/ata.h b/include/grub/ata.h index 6938b6a42..1a19f27aa 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -170,6 +170,7 @@ struct grub_ata /* Sector count. */ grub_uint64_t size; + grub_uint32_t log_sector_size; /* CHS maximums. */ grub_uint16_t cylinders; From 41aa28ea2a7c90c14016a122ae604c95aa4a8697 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 25 Jul 2011 08:19:30 +0200 Subject: [PATCH 314/673] New script grub-mkstandalone. * Makefile.util.def (grub-mkstandalone): New script. * docs/man/grub-mkstandalone.h2m: New file. * util/grub-mkstandalone.in: Likewise. --- ChangeLog | 10 +- Makefile.util.def | 6 ++ docs/man/grub-mkstandalone.h2m | 4 + util/grub-mkstandalone.in | 189 +++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 docs/man/grub-mkstandalone.h2m create mode 100644 util/grub-mkstandalone.in diff --git a/ChangeLog b/ChangeLog index 5c4e20c28..2593d598b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,14 @@ 2011-07-25 Vladimir Serbinenko - Support ATA disks with non-4K sectors. + New script grub-mkstandalone. + + * Makefile.util.def (grub-mkstandalone): New script. + * docs/man/grub-mkstandalone.h2m: New file. + * util/grub-mkstandalone.in: Likewise. + +2011-07-25 Vladimir Serbinenko + + Support ATA disks with 4K sectors. * include/grub/ata.h (grub_ata): New member log_sector_size. * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size. diff --git a/Makefile.util.def b/Makefile.util.def index c87020493..d86cb9761 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -412,6 +412,12 @@ script = { enable = powerpc_ieee1275; }; +script = { + mansection = 1; + name = grub-mkstandalone; + common = util/grub-mkstandalone.in; +}; + script = { mansection = 8; installdir = sbin; diff --git a/docs/man/grub-mkstandalone.h2m b/docs/man/grub-mkstandalone.h2m new file mode 100644 index 000000000..c77313978 --- /dev/null +++ b/docs/man/grub-mkstandalone.h2m @@ -0,0 +1,4 @@ +[NAME] +grub-mkstandalone \- make a memdisk-based GRUB image +[SEE ALSO] +.BR grub-mkimage (1) diff --git a/util/grub-mkstandalone.in b/util/grub-mkstandalone.in new file mode 100644 index 000000000..aaff99051 --- /dev/null +++ b/util/grub-mkstandalone.in @@ -0,0 +1,189 @@ +#! /bin/sh +set -e + +# Make GRUB rescue image +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 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 . + +# Initialize some variables. +transform="@program_transform_name@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libdir=@libdir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" + +self=`basename $0` + +source_dirrectory= +compression=auto +format= +grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +source= + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + +# Check the arguments. +while test $# -gt 0 +do + option=$1 + shift + + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" + exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift ;; + --modules=*) + modules=`echo "$option" | sed 's/--modules=//'` ;; + + -o | --output) + output_image=`argument $option "$@"`; shift ;; + --output=*) + output_image=`echo "$option" | sed 's/--output=//'` ;; + + --directory | -d) + source_directory=`argument $option "$@"`; shift ;; + --directory=*) + source_directory=`echo "$option" | sed 's/--rom-directory=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift ;; + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + + --compression | -C) + compression=`argument $option "$@"`; shift ;; + --compression=*) + compression=`echo "${option}/" | sed 's/--xorriso=//'` ;; + + --format | -O) + format=`argument $option "$@"`; shift ;; + --format=*) + format=`echo "${option}/" | sed 's/--xorriso=//'` ;; + + *) + source="${source} ${option} $@"; break ;; + esac +done + +if [ "x${output_image}" = x ] ; then + echo "output file must be given" >&2 + usage + exit 1 +fi + +if [ "x${format}" = x ] ; then + echo "format must be given" >&2 + usage + exit 1 +fi + +if [ "x$source_directory" = x ] ; then + cpu="`echo $format | awk -F - '{ print $1; }'`" + platform="`echo $format | awk -F - '{ print $2; }'`" + case "$platform" in + yeeloong | fuloong) + platform=loongson ;; + esac + case "$cpu-$platform" in + mips-loongson) + cpu=mipsel ;; + esac + source_directory="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/$cpu-$platform" +fi + +set $grub_mkimage dummy +if test -f "$1"; then + : +else + echo "$1: Not found." 1>&2 + exit 1 +fi + +memdisk_dir="`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 +mkdir -p "${memdisk_dir}"/boot/grub + +for file in "${source_directory}/"*.mod "${source_directory}/"efiemu32.o "${source_directory}/"efiemu64.o; do + if test -f "$file"; then + cp -f "$file" "${memdisk_dir}"/boot/grub/ + fi +done +for file in ${pkglib_DATA}; do + if test -f "${source_directory}/${file}"; then + cp -f "${source_directory}/${file}" "${memdisk_dir}"/boot/grub/ + fi +done + +mkdir -p "${memdisk_dir}"/boot/grub/locale +for file in "${source_directory}"/po/*.mo; do + if test -f "$file"; then + cp -f "$file" "${memdisk_dir}"/boot/grub/locale/ + fi +done + +for file in $source; do + cp -f "$file" "${memdisk_dir}"/"$file"; +done + +memdisk_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 + +(cd "${memdisk_dir}"; tar -cf - * $source) > "${memdisk_img}" +rm -rf "${memdisk_dir}" +$grub_mkimage -O "${format}" -C "$compression" -d "${source_directory}" -m "${memdisk_img}" -o "$output_image" --prefix='(memdisk)/boot/grub' memdisk tar $modules +rm -rf "${memdisk_img}" + +exit 0 From 303b6246a3a44d51cf9263b754efbfe0e5f4272a Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 26 Jul 2011 11:59:47 +0100 Subject: [PATCH 315/673] * util/grub-install.in: Don't source grub-mkconfig_lib until after processing arguments (otherwise help2man fails when GRUB has not yet been installed). --- ChangeLog | 6 ++++++ util/grub-install.in | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2593d598b..fa33902ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-07-26 Colin Watson + + * util/grub-install.in: Don't source grub-mkconfig_lib until after + processing arguments (otherwise help2man fails when GRUB has not yet + been installed). + 2011-07-25 Vladimir Serbinenko New script grub-mkstandalone. diff --git a/util/grub-install.in b/util/grub-install.in index 3d2420b91..f9e1510d1 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -59,8 +59,6 @@ update_nvram=yes removable=no efi_quiet= -. ${libdir}/@PACKAGE@/grub-mkconfig_lib - # Get GRUB_DISTRIBUTOR. if test -f "${sysconfdir}/default/grub" ; then . "${sysconfdir}/default/grub" @@ -265,6 +263,8 @@ do esac done +. ${libdir}/@PACKAGE@/grub-mkconfig_lib + if test "x$install_device" = x && ([ "${target_cpu}-${platform}" = "i386-pc" ] \ || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then echo "install_device not specified." 1>&2 From 20168fcafeed3d87f437914a09e35a926c009faa Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 26 Jul 2011 16:19:47 +0100 Subject: [PATCH 316/673] * configure.ac: The Loongson port requires grub-mkfont due to its use of -DUSE_ASCII_FAILBACK. Raise an error if it is not going to be built. --- ChangeLog | 6 ++++++ configure.ac | 3 +++ 2 files changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index fa33902ab..19e034dc0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-07-26 Colin Watson + + * configure.ac: The Loongson port requires grub-mkfont due to its + use of -DUSE_ASCII_FAILBACK. Raise an error if it is not going to + be built. + 2011-07-26 Colin Watson * util/grub-install.in: Don't source grub-mkconfig_lib until after diff --git a/configure.ac b/configure.ac index f674a90aa..e6d726548 100644 --- a/configure.ac +++ b/configure.ac @@ -866,6 +866,9 @@ enable_grub_mkfont=yes else enable_grub_mkfont=no fi +if test x"$enable_grub_mkfont" = xno && test "x$platform" = xloongson; then + AC_MSG_ERROR([loongson port needs grub-mkfont]) +fi AC_SUBST([enable_grub_mkfont]) AC_SUBST([freetype_cflags]) AC_SUBST([freetype_libs]) From 66816d85565bc362b07ce0c623c3379d6b21119e Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 3 Aug 2011 13:30:46 +0200 Subject: [PATCH 317/673] 2011-08-03 Robert Millan * include/grub/zfs/zap_leaf.h (typedef union zap_leaf_chunk): Mark la_array as packed. Reported by: Zachary Bedell --- ChangeLog | 6 ++++++ include/grub/zfs/zap_leaf.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 19e034dc0..184b0d763 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-08-03 Robert Millan + + * include/grub/zfs/zap_leaf.h (typedef union zap_leaf_chunk): Mark + la_array as packed. + Reported by: Zachary Bedell + 2011-07-26 Colin Watson * configure.ac: The Loongson port requires grub-mkfont due to its diff --git a/include/grub/zfs/zap_leaf.h b/include/grub/zfs/zap_leaf.h index 1ef654054..5adfdc290 100644 --- a/include/grub/zfs/zap_leaf.h +++ b/include/grub/zfs/zap_leaf.h @@ -90,7 +90,7 @@ typedef union zap_leaf_chunk { { grub_uint8_t la_array[ZAP_LEAF_ARRAY_BYTES]; grub_uint64_t la_array64; - }; + } __attribute__ ((packed)); grub_uint16_t la_next; /* next blk or CHAIN_END */ } l_array; struct zap_leaf_free { From 6dc212f953b2ff19245a125a938e35b8b0f929ba Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 10 Aug 2011 22:24:02 +0200 Subject: [PATCH 318/673] 2011-08-10 Robert Millan Detect LSI MegaRAID SAS (`mfi') devices on GNU/kFreeBSD. * util/deviceiter.c [__FreeBSD_kernel__] (get_mfi_disk_name): New function. [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for mfi (/dev/mfid[0-9]+) devices using get_mfi_disk_name(). --- ChangeLog | 9 +++++++++ util/deviceiter.c | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/ChangeLog b/ChangeLog index 184b0d763..039621768 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-08-10 Robert Millan + + Detect LSI MegaRAID SAS (`mfi') devices on GNU/kFreeBSD. + + * util/deviceiter.c [__FreeBSD_kernel__] (get_mfi_disk_name): New + function. + [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for mfi + (/dev/mfid[0-9]+) devices using get_mfi_disk_name(). + 2011-08-03 Robert Millan * include/grub/zfs/zap_leaf.h (typedef union zap_leaf_chunk): Mark diff --git a/util/deviceiter.c b/util/deviceiter.c index 2a8acec0e..208dcfdde 100644 --- a/util/deviceiter.c +++ b/util/deviceiter.c @@ -298,6 +298,12 @@ get_ataraid_disk_name (char *name, int unit) { sprintf (name, "/dev/ar%d", unit); } + +static void +get_mfi_disk_name (char *name, int unit) +{ + sprintf (name, "/dev/mfid%d", unit); +} #endif #ifdef __linux__ @@ -661,6 +667,19 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), goto out; } } + + /* LSI MegaRAID SAS. */ + for (i = 0; i < 32; i++) + { + char name[20]; + + get_mfi_disk_name (name, i); + if (check_device_readable_unique (name)) + { + if (hook (name, 0)) + goto out; + } + } #endif #ifdef __linux__ From 1f1a380be9ba10bf904240106b3bbb274c11e65a Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 14 Aug 2011 11:39:31 +0200 Subject: [PATCH 319/673] Import minilzo library for LZO decompression support. * grub-core/lib/minilzo/lzoconf.h: New file. * grub-core/lib/minilzo/lzodefs.h: Likewise. * grub-core/lib/minilzo/minilzo.c: Likewise. * grub-core/lib/minilzo/minilzo.h: Likewise. * include/grub/types.h (GRUB_UCHAR_MAX): New define. (GRUB_USHRT_MAX): Likewise. (GRUB_UINT_MAX): Likewise. * grub-core/lib/posix_wrap/limits.h (USHRT_MAX): New define. (UINT_MAX): Likewise. (CHAR_BIT): Likewise. * grub-core/lib/posix_wrap/sys/types.h (ULONG_MAX): Moved to grub-core/lib/posix_wrap/limits.h (UCHAR_MAX): Likewise. --- ChangeLog.lzo | 18 + grub-core/lib/minilzo/lzoconf.h | 446 +++ grub-core/lib/minilzo/lzodefs.h | 1852 +++++++++++ grub-core/lib/minilzo/minilzo.c | 4562 ++++++++++++++++++++++++++ grub-core/lib/minilzo/minilzo.h | 109 + grub-core/lib/posix_wrap/limits.h | 31 + grub-core/lib/posix_wrap/sys/types.h | 3 - include/grub/types.h | 4 + 8 files changed, 7022 insertions(+), 3 deletions(-) create mode 100644 ChangeLog.lzo create mode 100644 grub-core/lib/minilzo/lzoconf.h create mode 100644 grub-core/lib/minilzo/lzodefs.h create mode 100644 grub-core/lib/minilzo/minilzo.c create mode 100644 grub-core/lib/minilzo/minilzo.h diff --git a/ChangeLog.lzo b/ChangeLog.lzo new file mode 100644 index 000000000..6f5191db2 --- /dev/null +++ b/ChangeLog.lzo @@ -0,0 +1,18 @@ +2011-08-14 Szymon Janc + + Import minilzo library for LZO decompression support. + + * grub-core/lib/minilzo/lzoconf.h: New file. + * grub-core/lib/minilzo/lzodefs.h: Likewise. + * grub-core/lib/minilzo/minilzo.c: Likewise. + * grub-core/lib/minilzo/minilzo.h: Likewise. + * include/grub/types.h (GRUB_UCHAR_MAX): New define. + (GRUB_USHRT_MAX): Likewise. + (GRUB_UINT_MAX): Likewise. + * grub-core/lib/posix_wrap/limits.h (USHRT_MAX): New define. + (UINT_MAX): Likewise. + (CHAR_BIT): Likewise. + * grub-core/lib/posix_wrap/sys/types.h (ULONG_MAX): Moved to + grub-core/lib/posix_wrap/limits.h + (UCHAR_MAX): Likewise. + diff --git a/grub-core/lib/minilzo/lzoconf.h b/grub-core/lib/minilzo/lzoconf.h new file mode 100644 index 000000000..1d0fe14fc --- /dev/null +++ b/grub-core/lib/minilzo/lzoconf.h @@ -0,0 +1,446 @@ +/* lzoconf.h -- configuration of the LZO data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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 2 of + the License, or (at your option) any later version. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H_INCLUDED +#define __LZOCONF_H_INCLUDED 1 + +#define LZO_VERSION 0x2050 +#define LZO_VERSION_STRING "2.05" +#define LZO_VERSION_DATE "Apr 23 2011" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include +#include + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* get OS and architecture defines */ +#ifndef __LZODEFS_H_INCLUDED +#include "lzodefs.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// some core defines +************************************************************************/ + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) ((c) + 0U) +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER 1 +# elif defined(__CHECKER__) +# define __LZO_CHECKER 1 +# elif defined(__INSURE__) +# define __LZO_CHECKER 1 +# elif defined(__PURIFY__) +# define __LZO_CHECKER 1 +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* lzo_uint should match size_t */ +#if !defined(LZO_UINT_MAX) +# if defined(LZO_ABI_LLP64) /* WIN64 */ +# if defined(LZO_OS_WIN64) + typedef unsigned __int64 lzo_uint; + typedef __int64 lzo_int; +# else + typedef unsigned long long lzo_uint; + typedef long long lzo_int; +# endif +# define LZO_UINT_MAX 0xffffffffffffffffull +# define LZO_INT_MAX 9223372036854775807LL +# define LZO_INT_MIN (-1LL - LZO_INT_MAX) +# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */ + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +/* Integral types with 32 bits or more. */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* Integral types with exactly 64 bits. */ +#if !defined(LZO_UINT64_MAX) +# if (LZO_UINT_MAX >= LZO_0xffffffffL) +# if ((((LZO_UINT_MAX) >> 31) >> 31) == 3) +# define lzo_uint64 lzo_uint +# define lzo_int64 lzo_int +# define LZO_UINT64_MAX LZO_UINT_MAX +# define LZO_INT64_MAX LZO_INT_MAX +# define LZO_INT64_MIN LZO_INT_MIN +# endif +# elif (ULONG_MAX >= LZO_0xffffffffL) +# if ((((ULONG_MAX) >> 31) >> 31) == 3) + typedef unsigned long lzo_uint64; + typedef long lzo_int64; +# define LZO_UINT64_MAX ULONG_MAX +# define LZO_INT64_MAX LONG_MAX +# define LZO_INT64_MIN LONG_MIN +# endif +# endif +#endif + +/* The larger type of lzo_uint and lzo_uint32. */ +#if (LZO_UINT_MAX >= LZO_UINT32_MAX) +# define lzo_xint lzo_uint +#else +# define lzo_xint lzo_uint32 +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL /*empty*/ +# elif defined(LZO_HAVE_MM_HUGE_PTR) +# define __LZO_MMODEL_HUGE 1 +# define __LZO_MMODEL __huge +# else +# define __LZO_MMODEL /*empty*/ +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#if defined(LZO_UINT64_MAX) +#define lzo_uint64p lzo_uint64 __LZO_MMODEL * +#define lzo_int64p lzo_int64 __LZO_MMODEL * +#endif +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_xintp lzo_xint __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * +/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ +#define lzo_byte unsigned char __LZO_MMODEL + +typedef int lzo_bool; + + +/*********************************************************************** +// function types +************************************************************************/ + +/* name mangling */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# define __LZO_CDECL __lzo_cdecl +#endif + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 /*empty*/ +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 /*empty*/ +#endif + +/* __cdecl calling convention for public C and assembly functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL +#endif + +/* function types */ +typedef int +(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + +typedef int +(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + + +/* Callback interface. Currently only the progress indicator ("nprogress") + * is used, but this may change in a future release. */ + +struct lzo_callback_t; +typedef struct lzo_callback_t lzo_callback_t; +#define lzo_callback_p lzo_callback_t __LZO_MMODEL * + +/* malloc & free function types */ +typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) + (lzo_callback_p self, lzo_uint items, lzo_uint size); +typedef void (__LZO_CDECL *lzo_free_func_t) + (lzo_callback_p self, lzo_voidp ptr); + +/* a progress indicator callback function */ +typedef void (__LZO_CDECL *lzo_progress_func_t) + (lzo_callback_p, lzo_uint, lzo_uint, int); + +struct lzo_callback_t +{ + /* custom allocators (set to 0 to disable) */ + lzo_alloc_func_t nalloc; /* [not used right now] */ + lzo_free_func_t nfree; /* [not used right now] */ + + /* a progress indicator callback function (set to 0 to disable) */ + lzo_progress_func_t nprogress; + + /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress + * callbacks points back to this struct, so you are free to store + * some extra info in the following variables. */ + lzo_voidp user1; + lzo_xint user2; + lzo_xint user3; +}; + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) +#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ +#define LZO_E_INVALID_ARGUMENT (-10) + + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) +#endif + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_callback_t)) +LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) + lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memset(lzo_voidp buf, int c, lzo_uint len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) + lzo_adler32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(lzo_uint32) + lzo_crc32(lzo_uint32 c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(const lzo_uint32p) + lzo_get_crc32_table(void); + +/* misc. */ +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint u; lzo_uint32 u32; unsigned long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of 'size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); +#define LZO_PTR_ALIGN_UP(p,size) \ + ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size))) + + +/*********************************************************************** +// deprecated macros - only for backward compatibility with LZO v1.xx +************************************************************************/ + +#if defined(LZO_CFG_COMPAT) + +#define __LZOCONF_H 1 + +#if defined(LZO_ARCH_I086) +# define __LZO_i386 1 +#elif defined(LZO_ARCH_I386) +# define __LZO_i386 1 +#endif + +#if defined(LZO_OS_DOS16) +# define __LZO_DOS 1 +# define __LZO_DOS16 1 +#elif defined(LZO_OS_DOS32) +# define __LZO_DOS 1 +#elif defined(LZO_OS_WIN16) +# define __LZO_WIN 1 +# define __LZO_WIN16 1 +#elif defined(LZO_OS_WIN32) +# define __LZO_WIN 1 +#endif + +#define __LZO_CMODEL /*empty*/ +#define __LZO_DMODEL /*empty*/ +#define __LZO_ENTRY __LZO_CDECL +#define LZO_EXTERN_CDECL LZO_EXTERN +#define LZO_ALIGN LZO_PTR_ALIGN_UP + +#define lzo_compress_asm_t lzo_compress_t +#define lzo_decompress_asm_t lzo_decompress_t + +#endif /* LZO_CFG_COMPAT */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 et: */ diff --git a/grub-core/lib/minilzo/lzodefs.h b/grub-core/lib/minilzo/lzodefs.h new file mode 100644 index 000000000..0e40e332a --- /dev/null +++ b/grub-core/lib/minilzo/lzodefs.h @@ -0,0 +1,1852 @@ +/* lzodefs.h -- architecture, OS and compiler specific defines + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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 2 of + the License, or (at your option) any later version. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__) +# else +# define LZO_CC_CLANG_CLANG 0x010000L +# endif +# define LZO_CC_CLANG LZO_CC_CLANG_GNUC +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_inline __inline__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline /*empty*/ +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# if 0 && defined(__cplusplus) +# define LZO_UNCONST_CAST(t,e) (const_cast (e)) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e)))))) +# else +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if (LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif /* already included */ + +/* vim:set ts=4 et: */ diff --git a/grub-core/lib/minilzo/minilzo.c b/grub-core/lib/minilzo/minilzo.c new file mode 100644 index 000000000..25a1f68b3 --- /dev/null +++ b/grub-core/lib/minilzo/minilzo.c @@ -0,0 +1,4562 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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 2 of + the License, or (at your option) any later version. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO 1 + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif +#include +#include +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__clang__) && defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG_CLANG (__clang_major__ * 0x10000L + __clang_minor__ * 0x100 + __clang_patchlevel__) +# else +# define LZO_CC_CLANG_CLANG 0x010000L +# endif +# define LZO_CC_CLANG LZO_CC_CLANG_GNUC +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if (LZO_ARCH_ARM_THUMB) && !(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086PM) && !(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_inline __inline__ +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline /*empty*/ +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 900) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# if 0 && defined(__cplusplus) +# define LZO_UNCONST_CAST(t,e) (const_cast (e)) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((lzo_uintptr_t) ((const void *) (e)))))) +# else +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((char *) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if (LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2050) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H 1 +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H 1 + +#if !defined(__LZO_IN_MINILZO) +#if (LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +# define ACC_LIBC_FREESTANDING 1 +# define ACC_OS_FREESTANDING 1 +#endif +#if (LZO_CFG_NO_UNALIGNED) +# define ACC_CFG_NO_UNALIGNED 1 +#endif +#if (LZO_ARCH_GENERIC) +# define ACC_ARCH_GENERIC 1 +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# define ACC_ABI_NEUTRAL_ENDIAN 1 +#endif +#if (LZO_HAVE_CONFIG_H) +# define ACC_CONFIG_NO_HEADER 1 +#endif +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) +# include LZO_CFG_EXTRA_CONFIG_HEADER +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#include "lzo/lzoconf.h" +#endif + +#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED) +# error "version mismatch" +#endif + +#if (LZO_CC_BORLANDC && LZO_ARCH_I086) +# pragma option -h +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +# pragma warning(disable: 4514 4710 4711) +#endif + +#if (LZO_CC_SUNPROC) +#if !defined(__cplusplus) +# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) +# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) +# pragma error_messages(off,E_STATEMENT_NOT_REACHED) +#endif +#endif + +#if (__LZO_MMODEL_HUGE) && !(LZO_HAVE_MM_HUGE_PTR) +# error "this should not happen - check defines for __huge" +#endif + +#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING) +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define ACC_WANT_ACC_INCD_H 1 +# define ACC_WANT_ACC_INCE_H 1 +# define ACC_WANT_ACC_INCI_H 1 +#elif 1 +# include +#else +# define ACC_WANT_ACC_INCD_H 1 +#endif + +#if (LZO_ARCH_I086) +# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT +# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0]) +# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1]) +# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o))) +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16) +# define __LZO_UINTPTR_T_IS_POINTER 1 + typedef char* lzo_uintptr_t; +# define lzo_uintptr_t lzo_uintptr_t +# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t size_t +# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long +# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned int +# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long long +# else +# define lzo_uintptr_t size_t +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include +#endif + +#if (LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memcmp +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memcpy +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memmove +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#elif !(__LZO_MMODEL_HUGE) +# undef lzo_memset +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if (LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(__lzo_inline) +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +# define __lzo_forceinline /*empty*/ +#endif +#if !defined(__lzo_noinline) +# define __lzo_noinline /*empty*/ +#endif + +#if (LZO_CFG_PGO) +# undef __acc_likely +# undef __acc_unlikely +# undef __lzo_likely +# undef __lzo_unlikely +# define __acc_likely(e) (e) +# define __acc_unlikely(e) (e) +# define __lzo_likely(e) (e) +# define __lzo_unlikely(e) (e) +#endif + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386 || LZO_ARCH_POWERPC) +# if (LZO_SIZEOF_SHORT == 2) +# define LZO_UNALIGNED_OK_2 1 +# endif +# if (LZO_SIZEOF_INT == 4) +# define LZO_UNALIGNED_OK_4 1 +# endif +#endif +#if 1 && (LZO_ARCH_AMD64) +# if defined(LZO_UINT64_MAX) +# define LZO_UNALIGNED_OK_8 1 +# endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +# undef LZO_UNALIGNED_OK_8 +#endif + +#undef UA_GET16 +#undef UA_SET16 +#undef UA_COPY16 +#undef UA_GET32 +#undef UA_SET32 +#undef UA_COPY32 +#undef UA_GET64 +#undef UA_SET64 +#undef UA_COPY64 +#if defined(LZO_UNALIGNED_OK_2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(unsigned short) == 2) +# if 1 && defined(ACC_UA_COPY16) +# define UA_GET16 ACC_UA_GET16 +# define UA_SET16 ACC_UA_SET16 +# define UA_COPY16 ACC_UA_COPY16 +# else +# define UA_GET16(p) (* (__lzo_ua_volatile const lzo_ushortp) (__lzo_ua_volatile const lzo_voidp) (p)) +# define UA_SET16(p,v) ((* (__lzo_ua_volatile lzo_ushortp) (__lzo_ua_volatile lzo_voidp) (p)) = (unsigned short) (v)) +# define UA_COPY16(d,s) UA_SET16(d, UA_GET16(s)) +# endif +#endif +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +# if 1 && defined(ACC_UA_COPY32) +# define UA_GET32 ACC_UA_GET32 +# define UA_SET32 ACC_UA_SET32 +# define UA_COPY32 ACC_UA_COPY32 +# else +# define UA_GET32(p) (* (__lzo_ua_volatile const lzo_uint32p) (__lzo_ua_volatile const lzo_voidp) (p)) +# define UA_SET32(p,v) ((* (__lzo_ua_volatile lzo_uint32p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint32) (v)) +# define UA_COPY32(d,s) UA_SET32(d, UA_GET32(s)) +# endif +#endif +#if defined(LZO_UNALIGNED_OK_8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64) == 8) +# if 1 && defined(ACC_UA_COPY64) +# define UA_GET64 ACC_UA_GET64 +# define UA_SET64 ACC_UA_SET64 +# define UA_COPY64 ACC_UA_COPY64 +# else +# define UA_GET64(p) (* (__lzo_ua_volatile const lzo_uint64p) (__lzo_ua_volatile const lzo_voidp) (p)) +# define UA_SET64(p,v) ((* (__lzo_ua_volatile lzo_uint64p) (__lzo_ua_volatile lzo_voidp) (p)) = (lzo_uint64) (v)) +# define UA_COPY64(d,s) UA_SET64(d, UA_GET64(s)) +# endif +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(lzo_uintptr_t) +# if (__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# else +# define lzo_uintptr_t acc_uintptr_t +# ifdef __ACC_INTPTR_T_IS_POINTER +# define __LZO_UINTPTR_T_IS_POINTER 1 +# endif +# endif +#endif + +#if (LZO_ARCH_I086) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0) +#elif (LZO_MM_PVP) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0) +#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0) +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; +#if defined(LZO_UINT64_MAX) + lzo_int64 a_lzo_int64; + lzo_uint64 a_lzo_uint64; +#endif + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#ifndef LZO_DETERMINISTIC +#define LZO_DETERMINISTIC 1 +#endif + +#ifndef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 1 +#if 0 && (LZO_ARCH_I086) +# undef LZO_DICT_USE_PTR +# define LZO_DICT_USE_PTR 0 +#endif +#endif + +#if (LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) + p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr)); +#elif (LZO_MM_PVP) + p = (lzo_uintptr_t) (ptr); + p = (p << 3) | (p >> 61); +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if defined(__LZO_UINTPTR_T_IS_POINTER) + size_t n = (size_t) ptr; + n = (((n + size - 1) / size) * size) - n; +#else + lzo_uintptr_t p, n; + p = __lzo_ptr_linear(ptr); + n = (((p + size - 1) / size) * size) - p; +#endif + + assert(size > 0); + assert((long)n >= 0); + assert(n <= size); + return (unsigned)n; +} + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_UTIL) + +/* If you use the LZO library in a product, I would appreciate that you + * keep this copyright string in the executable of your product. + */ + +static const char __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO Copyright (C) 1996-2011 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ +#if (LZO_OS_DOS16 && LZO_CC_TURBOC) + return (lzo_voidp) __lzo_copyright; +#else + return (const lzo_bytep) __lzo_copyright; +#endif +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) + const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2; + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) + lzo_hbyte_p p = (lzo_hbyte_p) s; + if __lzo_likely(len > 0) do + *p++ = (unsigned char) c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, c, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_INIT) + +#if !defined(__LZO_IN_MINILZO) + +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32) + ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4) +#if defined(LZO_UINT64_MAX) + ACCCHK_ASSERT(sizeof(lzo_uint64) == 8) + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int64) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint64) +#endif + +#if !defined(__LZO_UINTPTR_T_IS_POINTER) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32)) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint)) + ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint)) + +#endif +#undef ACCCHK_ASSERT + +#if 0 +#define WANT_lzo_bitops_clz32 1 +#define WANT_lzo_bitops_clz64 1 +#endif +#define WANT_lzo_bitops_ctz32 1 +#define WANT_lzo_bitops_ctz64 1 + +#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#include +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0 +#pragma intrinsic(_BitScanReverse) +static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanReverse(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz32 lzo_bitops_clz32 +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0 +#pragma intrinsic(_BitScanReverse64) +static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanReverse64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz64 lzo_bitops_clz64 +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#pragma intrinsic(_BitScanForward) +static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanForward(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz32 lzo_bitops_ctz32 +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#pragma intrinsic(_BitScanForward64) +static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanForward64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz64 lzo_bitops_ctz64 +#endif + +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || LZO_CC_LLVM) +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) +#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v)) +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v)) +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v)) +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32) +#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v)) +#endif +#endif + +#if 0 +#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) +#else +static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) +{ + return (lzo_voidp) ((lzo_bytep) ptr + off); +} +#endif + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + union { + lzo_xint a[2]; unsigned char b[2*LZO_MAX(8,sizeof(lzo_xint))]; +#if defined(LZO_UNALIGNED_OK_8) + lzo_uint64 c[2]; +#endif + unsigned short x[2]; lzo_uint32 y[2]; lzo_uint z[2]; + } u; + lzo_voidp p; + + u.a[0] = u.a[1] = 0; + p = u2p(&u, 0); + r &= ((* (lzo_bytep) p) == 0); +#if !defined(LZO_CFG_NO_CONFIG_CHECK) +#if defined(LZO_ABI_BIG_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif +#if defined(LZO_ABI_LITTLE_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[0] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif +#if defined(LZO_UNALIGNED_OK_2) + u.a[0] = u.a[1] = 0; + u.b[0] = 1; u.b[sizeof(unsigned short) + 1] = 2; + p = u2p(&u, 1); + r &= ((* (lzo_ushortp) p) == 0); +#endif +#if defined(LZO_UNALIGNED_OK_4) + u.a[0] = u.a[1] = 0; + u.b[0] = 3; u.b[sizeof(lzo_uint32) + 1] = 4; + p = u2p(&u, 1); + r &= ((* (lzo_uint32p) p) == 0); +#endif +#if defined(LZO_UNALIGNED_OK_8) + u.c[0] = u.c[1] = 0; + u.b[0] = 5; u.b[sizeof(lzo_uint64) + 1] = 6; + p = u2p(&u, 1); + r &= ((* (lzo_uint64p) p) == 0); +#endif +#if defined(lzo_bitops_clz32) + { unsigned i; lzo_uint32 v = 1; + for (i = 0; i < 31; i++, v <<= 1) + r &= lzo_bitops_clz32(v) == 31 - i; + } +#endif +#if defined(lzo_bitops_clz64) + { unsigned i; lzo_uint64 v = 1; + for (i = 0; i < 63; i++, v <<= 1) + r &= lzo_bitops_clz64(v) == 63 - i; + } +#endif +#if defined(lzo_bitops_ctz32) + { unsigned i; lzo_uint32 v = 1; + for (i = 0; i < 31; i++, v <<= 1) + r &= lzo_bitops_ctz32(v) == i; + } +#endif +#if defined(lzo_bitops_ctz64) + { unsigned i; lzo_uint64 v = 1; + for (i = 0; i < 63; i++, v <<= 1) + r &= lzo_bitops_ctz64(v) == i; + } +#endif +#endif + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT +#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef ACCCHK_ASSERT + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#endif + +#define LZO1X 1 +#define LZO_EOF_CODE 1 +#define M2_MAX_OFFSET 0x0800 + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#if 1 && defined(UA_GET32) +#undef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 0 +#undef lzo_dict_t +#define lzo_dict_t unsigned short +#endif + +#define LZO_NEED_DICT_H 1 +#ifndef D_BITS +#define D_BITS 14 +#endif +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) +#if 1 +#define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS))) +#else +#define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS))) +#endif + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H 1 + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X 1 +#endif + +#if !defined(__LZO_IN_MINILZO) +#include "lzo/lzo1x.h" +#endif + +#ifndef LZO_EOF_CODE +#define LZO_EOF_CODE 1 +#endif +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 6 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 6 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +#if (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_LLVM) +static void __attribute__((__unused__)) +#else +static void +#endif +DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if (LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_dict_t) pd(p, in)) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if (LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if (LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR) + +#ifndef DO_COMPRESS +#define DO_COMPRESS lzo1x_1_compress +#endif + +#if 1 && defined(DO_COMPRESS) && !defined(do_compress) +# define do_compress LZO_CPP_ECONCAT2(DO_COMPRESS,_core) +#endif + +#if defined(UA_GET64) +# define WANT_lzo_bitops_ctz64 1 +#elif defined(UA_GET32) +# define WANT_lzo_bitops_ctz32 1 +#endif + +#if (defined(_WIN32) || defined(_WIN64)) && ((LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#include +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) && 0 +#pragma intrinsic(_BitScanReverse) +static __lzo_inline unsigned lzo_bitops_clz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanReverse(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz32 lzo_bitops_clz32 +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) && 0 +#pragma intrinsic(_BitScanReverse64) +static __lzo_inline unsigned lzo_bitops_clz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanReverse64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_clz64 lzo_bitops_clz64 +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#pragma intrinsic(_BitScanForward) +static __lzo_inline unsigned lzo_bitops_ctz32(lzo_uint32 v) +{ + unsigned long r; + (void) _BitScanForward(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz32 lzo_bitops_ctz32 +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#pragma intrinsic(_BitScanForward64) +static __lzo_inline unsigned lzo_bitops_ctz64(lzo_uint64 v) +{ + unsigned long r; + (void) _BitScanForward64(&r, v); + return (unsigned) r; +} +#define lzo_bitops_ctz64 lzo_bitops_ctz64 +#endif + +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC && (__INTEL_COMPILER >= 1000)) || LZO_CC_LLVM) +#if !defined(lzo_bitops_clz32) && defined(WANT_lzo_bitops_clz32) +#define lzo_bitops_clz32(v) ((unsigned) __builtin_clz(v)) +#endif +#if !defined(lzo_bitops_clz64) && defined(WANT_lzo_bitops_clz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_clz64(v) ((unsigned) __builtin_clzll(v)) +#endif +#if !defined(lzo_bitops_ctz32) && defined(WANT_lzo_bitops_ctz32) +#define lzo_bitops_ctz32(v) ((unsigned) __builtin_ctz(v)) +#endif +#if !defined(lzo_bitops_ctz64) && defined(WANT_lzo_bitops_ctz64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_ctz64(v) ((unsigned) __builtin_ctzll(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount32) +#define lzo_bitops_popcount32(v) ((unsigned) __builtin_popcount(v)) +#endif +#if !defined(lzo_bitops_popcount32) && defined(WANT_lzo_bitops_popcount64) && defined(LZO_UINT64_MAX) +#define lzo_bitops_popcount64(v) ((unsigned) __builtin_popcountll(v)) +#endif +#endif + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_uint ti, lzo_voidp wrkmem) +{ + register const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - 20; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip - ti; + + ip += ti < 4 ? 4 - ti : 0; + for (;;) + { + const lzo_bytep m_pos; +#if !(LZO_DETERMINISTIC) + LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); + lzo_uint m_len; + lzo_uint dindex; +next: + if __lzo_unlikely(ip >= ip_end) + break; + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if defined(UA_GET32) + if (UA_GET32(m_pos) != UA_GET32(ip)) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) +#endif + { +literal: + UPDATE_I(dict,0,dindex,ip,in); + ip += 1 + ((ip - ii) >> 5); + continue; + } + UPDATE_I(dict,0,dindex,ip,in); +#else + lzo_uint m_off; + lzo_uint m_len; + { + lzo_uint32 dv; + lzo_uint dindex; +literal: + ip += 1 + ((ip - ii) >> 5); +next: + if __lzo_unlikely(ip >= ip_end) + break; + dv = UA_GET32(ip); + dindex = DINDEX(dv,ip); + GINDEX(m_off,m_pos,in+dict,dindex,in); + UPDATE_I(dict,0,dindex,ip,in); + if __lzo_unlikely(dv != UA_GET32(m_pos)) + goto literal; + } +#endif + + { + register lzo_uint t = pd(ip,ii); + if (t != 0) + { + if (t <= 3) + { + op[-2] |= LZO_BYTE(t); +#if defined(UA_COPY32) + UA_COPY32(op, ii); + op += t; +#else + { do *op++ = *ii++; while (--t > 0); } +#endif + } +#if defined(UA_COPY32) || defined(UA_COPY64) + else if (t <= 16) + { + *op++ = LZO_BYTE(t - 3); +#if defined(UA_COPY64) + UA_COPY64(op, ii); + UA_COPY64(op+8, ii+8); +#else + UA_COPY32(op, ii); + UA_COPY32(op+4, ii+4); + UA_COPY32(op+8, ii+8); + UA_COPY32(op+12, ii+12); +#endif + op += t; + } +#endif + else + { + if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + *op++ = 0; + while __lzo_unlikely(tt > 255) + { + tt -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } +#if defined(UA_COPY32) || defined(UA_COPY64) + do { +#if defined(UA_COPY64) + UA_COPY64(op, ii); + UA_COPY64(op+8, ii+8); +#else + UA_COPY32(op, ii); + UA_COPY32(op+4, ii+4); + UA_COPY32(op+8, ii+8); + UA_COPY32(op+12, ii+12); +#endif + op += 16; ii += 16; t -= 16; + } while (t >= 16); if (t > 0) +#endif + { do *op++ = *ii++; while (--t > 0); } + } + } + } + m_len = 4; + { +#if defined(UA_GET64) + lzo_uint64 v; + v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 8; + v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz64) + m_len += lzo_bitops_ctz64(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#elif defined(UA_GET32) + lzo_uint32 v; + v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 4; + v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz32) + m_len += lzo_bitops_ctz32(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#else + if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { + do { + m_len += 1; + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (ip[m_len] == m_pos[m_len]); + } +#endif + } +m_len_done: + m_off = pd(ip,m_pos); + ip += m_len; + ii = ip; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= M3_MAX_LEN) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= M3_MAX_LEN; + *op++ = M3_MARKER | 0; + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + else + { + m_off -= 0x4000; + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + goto next; + } + + *out_len = pd(op, out); + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + const lzo_bytep ip = in; + lzo_bytep op = out; + lzo_uint l = in_len; + lzo_uint t = 0; + + while (l > 20) + { + lzo_uint ll = l; + lzo_uintptr_t ll_end; +#if 0 || (LZO_DETERMINISTIC) + ll = LZO_MIN(ll, 49152); +#endif + ll_end = (lzo_uintptr_t)ip + ll; + if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) + break; +#if (LZO_DETERMINISTIC) + lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); +#endif + t = do_compress(ip,ll,op,out_len,t,wrkmem); + ip += ll; + op += *out_len; + l -= ll; + } + t += l; + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; +#if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400)) + + * (volatile unsigned char *) op++ = 0; +#else + *op++ = 0; +#endif + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + t += 3; + if (t >= 8) do + { + UA_COPY64(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY32(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY64(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN 1 +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + t += 3; + if (t >= 8) do + { + UA_COPY64(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY32(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY32(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) && !defined(LZO_UNALIGNED_OK_8) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_8) && defined(LZO_UNALIGNED_OK_4) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY64(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY32(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ + diff --git a/grub-core/lib/minilzo/minilzo.h b/grub-core/lib/minilzo/minilzo.h new file mode 100644 index 000000000..74fefa9fe --- /dev/null +++ b/grub-core/lib/minilzo/minilzo.h @@ -0,0 +1,109 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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 2 of + the License, or (at your option) any later version. + + The LZO library 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 the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H 1 + +#define MINILZO_VERSION 0x2050 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h index e69de29bb..fe8523e68 100644 --- a/grub-core/lib/posix_wrap/limits.h +++ b/grub-core/lib/posix_wrap/limits.h @@ -0,0 +1,31 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 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 . + */ + +#ifndef GRUB_POSIX_LIMITS_H +#define GRUB_POSIX_LIMITS_H + +#include + +#define UCHAR_MAX GRUB_UCHAR_MAX +#define USHRT_MAX GRUB_USHRT_MAX +#define UINT_MAX GRUB_UINT_MAX +#define ULONG_MAX GRUB_ULONG_MAX + +#define CHAR_BIT 8 + +#endif diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h index 69e49509e..0c58d6c44 100644 --- a/grub-core/lib/posix_wrap/sys/types.h +++ b/grub-core/lib/posix_wrap/sys/types.h @@ -24,9 +24,6 @@ typedef grub_size_t size_t; typedef enum { false = 0, true = 1 } bool; -#define ULONG_MAX GRUB_ULONG_MAX -#define UCHAR_MAX 0xff - typedef grub_uint8_t uint8_t; typedef grub_uint16_t uint16_t; typedef grub_uint32_t uint32_t; diff --git a/include/grub/types.h b/include/grub/types.h index 4fd7a3a4b..32d255d40 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -116,6 +116,10 @@ typedef grub_int32_t grub_ssize_t; # define PRIuGRUB_SIZE "u" #endif +#define GRUB_UCHAR_MAX 0xFF +#define GRUB_USHRT_MAX 65535 +#define GRUB_UINT_MAX 4294967295U + #if GRUB_CPU_SIZEOF_LONG == 8 # define GRUB_ULONG_MAX 18446744073709551615UL # define GRUB_LONG_MAX 9223372036854775807L From b2d7e331e2b5cb9899a13e5e105e96d2632da995 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 14 Aug 2011 11:41:19 +0200 Subject: [PATCH 320/673] Add helper functions for easier unaligned memory access. * include/grub/types.h (grub_get_unaligned16): New function. (grub_get_unaligned32): Likewise. (grub_get_unaligned64): Likewise. --- ChangeLog.lzo | 8 ++++++++ include/grub/types.h | 27 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/ChangeLog.lzo b/ChangeLog.lzo index 6f5191db2..701715747 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,11 @@ +2001-08-14 Szymon Janc + + Add helper functions for easier unaligned memory access. + + * include/grub/types.h (grub_get_unaligned16): New function. + (grub_get_unaligned32): Likewise. + (grub_get_unaligned64): Likewise. + 2011-08-14 Szymon Janc Import minilzo library for LZO decompression support. diff --git a/include/grub/types.h b/include/grub/types.h index 32d255d40..f057dd3d3 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -222,4 +222,31 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x)) #endif /* ! WORDS_BIGENDIAN */ +static inline grub_uint16_t grub_get_unaligned16(void *ptr) +{ + struct + { + grub_uint16_t d; + } __attribute__((packed)) *dd = ptr; + return dd->d; +} + +static inline grub_uint32_t grub_get_unaligned32(void *ptr) +{ + struct + { + grub_uint32_t d; + } __attribute__((packed)) *dd = ptr; + return dd->d; +} + +static inline grub_uint64_t grub_get_unaligned64(void *ptr) +{ + struct + { + grub_uint64_t d; + } __attribute__((packed)) *dd = ptr; + return dd->d; +} + #endif /* ! GRUB_TYPES_HEADER */ From b6085f323611098c84177e90701809b6a8c5dcaf Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 14 Aug 2011 11:42:53 +0200 Subject: [PATCH 321/673] * grub-core/fs/btrfs.c: Some code style fixes. --- ChangeLog.lzo | 4 + grub-core/fs/btrfs.c | 187 +++++++++++++++++++++---------------------- 2 files changed, 94 insertions(+), 97 deletions(-) diff --git a/ChangeLog.lzo b/ChangeLog.lzo index 701715747..0a9d852a4 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,7 @@ +2011-08-14 Szymon Janc + + * grub-core/fs/btrfs.c: Some code style fixes. + 2001-08-14 Szymon Janc Add helper functions for easier unaligned memory access. diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 6470c9819..1336c8f02 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -41,7 +41,7 @@ struct grub_btrfs_device } __attribute__ ((packed)); struct grub_btrfs_superblock -{ +{ grub_btrfs_checksum_t checksum; grub_btrfs_uuid_t uuid; grub_uint8_t dummy[0x10]; @@ -160,7 +160,8 @@ struct grub_btrfs_leaf_descriptor { unsigned depth; unsigned allocated; - struct { + struct + { grub_disk_addr_t addr; unsigned iter; unsigned maxiter; @@ -179,7 +180,7 @@ struct grub_btrfs_time { grub_int64_t sec; grub_uint32_t nanosec; -} __attribute__ ((aligned(4))); +} __attribute__ ((aligned (4))); struct grub_btrfs_inode { @@ -219,8 +220,8 @@ struct grub_btrfs_extent_data #define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100 static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2, - 256 * 1048576 * 2, - 1048576ULL * 1048576ULL * 2 }; + 256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2 +}; static grub_err_t grub_btrfs_read_logical (struct grub_btrfs_data *data, @@ -283,7 +284,7 @@ free_iterator (struct grub_btrfs_leaf_descriptor *desc) } static grub_err_t -save_ref (struct grub_btrfs_leaf_descriptor *desc, +save_ref (struct grub_btrfs_leaf_descriptor *desc, grub_disk_addr_t addr, unsigned i, unsigned m, int l) { desc->depth++; @@ -307,7 +308,7 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc, static int next (struct grub_btrfs_data *data, struct grub_btrfs_leaf_descriptor *desc, - grub_disk_addr_t *outaddr, grub_size_t *outsize, + grub_disk_addr_t * outaddr, grub_size_t * outsize, struct grub_btrfs_key *key_out) { grub_err_t err; @@ -316,8 +317,8 @@ next (struct grub_btrfs_data *data, for (; desc->depth > 0; desc->depth--) { desc->data[desc->depth - 1].iter++; - if (desc->data[desc->depth - 1].iter - < desc->data[desc->depth - 1].maxiter) + if (desc->data[desc->depth - 1].iter < + desc->data[desc->depth - 1].maxiter) break; } if (desc->depth == 0) @@ -330,17 +331,17 @@ next (struct grub_btrfs_data *data, err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter * sizeof (node) + sizeof (struct btrfs_header) - + desc->data[desc->depth - 1].addr, &node, - sizeof (node)); + + desc->data[desc->depth - 1].addr, + &node, sizeof (node)); if (err) return -err; - err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), &head, - sizeof (head)); + err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), + &head, sizeof (head)); if (err) return -err; - save_ref (desc, grub_le_to_cpu64 (node.addr), 0, + save_ref (desc, grub_le_to_cpu64 (node.addr), 0, grub_le_to_cpu32 (head.nitems), !head.level); } err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter @@ -354,15 +355,15 @@ next (struct grub_btrfs_data *data, *outaddr = desc->data[desc->depth - 1].addr + sizeof (struct btrfs_header) + grub_le_to_cpu32 (leaf.offset); *key_out = leaf.key; - return 1; + return 1; } static grub_err_t lower_bound (struct grub_btrfs_data *data, - const struct grub_btrfs_key *key_in, + const struct grub_btrfs_key *key_in, struct grub_btrfs_key *key_out, grub_disk_addr_t root, - grub_disk_addr_t *outaddr, grub_size_t *outsize, + grub_disk_addr_t * outaddr, grub_size_t * outsize, struct grub_btrfs_leaf_descriptor *desc) { grub_disk_addr_t addr = root; @@ -410,8 +411,9 @@ lower_bound (struct grub_btrfs_data *data, grub_dprintf ("btrfs", "internal node (depth %d) %" PRIxGRUB_UINT64_T " %x %" PRIxGRUB_UINT64_T "\n", depth, - node.key.object_id, node.key.type, node.key.offset); - + node.key.object_id, node.key.type, + node.key.offset); + if (key_cmp (&node.key, key_in) == 0) { err = GRUB_ERR_NONE; @@ -433,7 +435,7 @@ lower_bound (struct grub_btrfs_data *data, err = GRUB_ERR_NONE; if (desc) err = save_ref (desc, addr - sizeof (head), i - 1, - grub_le_to_cpu32 (head.nitems), 0); + grub_le_to_cpu32 (head.nitems), 0); if (err) return err; addr = grub_le_to_cpu64 (node_last.addr); @@ -457,7 +459,7 @@ lower_bound (struct grub_btrfs_data *data, &leaf, sizeof (leaf)); if (err) return err; - + grub_dprintf ("btrfs", "leaf (depth %d) %" PRIxGRUB_UINT64_T " %x %" PRIxGRUB_UINT64_T "\n", depth, @@ -465,31 +467,31 @@ lower_bound (struct grub_btrfs_data *data, if (key_cmp (&leaf.key, key_in) == 0) { - grub_memcpy (key_out, &leaf.key, sizeof(*key_out)); + grub_memcpy (key_out, &leaf.key, sizeof (*key_out)); *outsize = grub_le_to_cpu32 (leaf.size); *outaddr = addr + grub_le_to_cpu32 (leaf.offset); if (desc) return save_ref (desc, addr - sizeof (head), i, grub_le_to_cpu32 (head.nitems), 1); - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; } - + if (key_cmp (&leaf.key, key_in) > 0) break; - + have_last = 1; leaf_last = leaf; } if (have_last) { - grub_memcpy (key_out, &leaf_last.key, sizeof(*key_out)); + grub_memcpy (key_out, &leaf_last.key, sizeof (*key_out)); *outsize = grub_le_to_cpu32 (leaf_last.size); *outaddr = addr + grub_le_to_cpu32 (leaf_last.offset); if (desc) return save_ref (desc, addr - sizeof (head), i - 1, grub_le_to_cpu32 (head.nitems), 1); - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; } *outsize = 0; *outaddr = 0; @@ -503,8 +505,7 @@ lower_bound (struct grub_btrfs_data *data, } static grub_device_t -find_device (struct grub_btrfs_data *data, grub_uint64_t id, - int do_rescan) +find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) { grub_device_t dev_found = NULL; auto int hook (const char *name); @@ -540,7 +541,7 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, grub_device_close (dev); return 0; } - + dev_found = dev; return 1; } @@ -579,17 +580,16 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, } static grub_err_t -grub_btrfs_read_logical (struct grub_btrfs_data *data, - grub_disk_addr_t addr, +grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, void *buf, grub_size_t size) { while (size > 0) { grub_uint8_t *ptr; struct grub_btrfs_key *key; - struct grub_btrfs_chunk_item *chunk; + struct grub_btrfs_chunk_item *chunk; grub_uint64_t csize; - grub_err_t err = 0; + grub_err_t err = 0; struct grub_btrfs_key key_out; int challoc = 0; grub_device_t dev; @@ -601,20 +601,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, addr); for (ptr = data->sblock.bootstrap_mapping; ptr < data->sblock.bootstrap_mapping - + sizeof (data->sblock.bootstrap_mapping) - - sizeof (struct grub_btrfs_key); - ) + + sizeof (data->sblock.bootstrap_mapping) + - sizeof (struct grub_btrfs_key);) { key = (struct grub_btrfs_key *) ptr; if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK) break; chunk = (struct grub_btrfs_chunk_item *) (key + 1); - grub_dprintf ("btrfs", "%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n", + grub_dprintf ("btrfs", + "%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n", grub_le_to_cpu64 (key->offset), grub_le_to_cpu64 (chunk->size)); if (grub_le_to_cpu64 (key->offset) <= addr - && addr < grub_le_to_cpu64 (key->offset) - + grub_le_to_cpu64 (chunk->size)) + && addr < + grub_le_to_cpu64 (key->offset) + grub_le_to_cpu64 (chunk->size)) goto chunk_found; ptr += sizeof (*key) + sizeof (*chunk) + sizeof (struct grub_btrfs_chunk_stripe) @@ -704,11 +704,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, middle = grub_divmod64 (off, grub_le_to_cpu64 (chunk->stripe_length), &low); - + high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes), &stripen); - stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) - * high; + stripe_offset = + low + grub_le_to_cpu64 (chunk->stripe_length) * high; csize = grub_le_to_cpu64 (chunk->stripe_length) - low; break; } @@ -719,7 +719,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, middle = grub_divmod64 (off, grub_le_to_cpu64 (chunk->stripe_length), &low); - + high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nsubstripes), &stripen); @@ -759,7 +759,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, paddr = stripe->offset + stripe_offset; grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T - "+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %" + "+0x%" PRIxGRUB_UINT64_T + " (%d stripes (%d substripes) of %" PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T " maps to 0x%" PRIxGRUB_UINT64_T "\n", grub_le_to_cpu64 (key->offset), @@ -769,7 +770,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_le_to_cpu64 (chunk->stripe_length), stripen, stripe->offset); grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T - " for laddr 0x%" PRIxGRUB_UINT64_T"\n", paddr, + " for laddr 0x%" PRIxGRUB_UINT64_T "\n", paddr, addr); dev = find_device (data, stripe->device_id, j); @@ -815,7 +816,7 @@ grub_btrfs_mount (grub_device_t dev) } data = grub_zalloc (sizeof (*data)); - if (! data) + if (!data) return NULL; err = read_sblock (dev->disk, &data->sblock); @@ -866,8 +867,7 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data, key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM; key_in.offset = 0; - err = lower_bound (data, &key_in, &key_out, tree, - &elemaddr, &elemsize, NULL); + err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, NULL); if (err) return err; if (num != key_out.object_id @@ -917,19 +917,17 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, if (!data->extent) return grub_errno; - err = grub_btrfs_read_logical (data, elemaddr, - data->extent, elemsize); + err = grub_btrfs_read_logical (data, elemaddr, data->extent, + elemsize); if (err) return err; - data->extend = data->extstart - + grub_le_to_cpu64 (data->extent->size); + data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size); if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR - && (char *) &data->extent + elemsize - >= (char *) &data->extent->filled - + sizeof (data->extent->filled)) - data->extend = data->extstart - + grub_le_to_cpu64 (data->extent->filled); + && (char *) &data->extent + elemsize >= + (char *) &data->extent->filled + sizeof (data->extent->filled)) + data->extend = + data->extstart + grub_le_to_cpu64 (data->extent->filled); grub_dprintf ("btrfs", "extent 0x%" PRIxGRUB_UINT64_T "+0x%" PRIxGRUB_UINT64_T " (0x%" @@ -966,8 +964,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, if (data->extent->encoding) { - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "encoding not supported"); + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "encoding not supported"); return -1; } @@ -1008,8 +1005,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, grub_free (tmp); return -1; } - if (grub_zlib_decompress (tmp, zsize, extoff - + grub_le_to_cpu64 (data->extent->offset), + if (grub_zlib_decompress (tmp, zsize, extoff + + grub_le_to_cpu64 (data->extent->offset), buf, csize) != (grub_ssize_t) csize) { grub_free (tmp); @@ -1021,14 +1018,13 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (data->extent->laddr) + grub_le_to_cpu64 (data->extent->offset) - + extoff, - buf, csize); + + extoff, buf, csize); if (err) return -1; break; default: grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported extent type 0x%x", data->extent->type); + "unsupported extent type 0x%x", data->extent->type); return -1; } buf += csize; @@ -1041,7 +1037,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, static grub_err_t find_path (struct grub_btrfs_data *data, const char *path, struct grub_btrfs_key *key, - grub_uint64_t *tree, grub_uint8_t *type) + grub_uint64_t * tree, grub_uint8_t * type) { const char *slash = path; grub_err_t err; @@ -1096,9 +1092,9 @@ find_path (struct grub_btrfs_data *data, key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen)); - - err = lower_bound (data, key, &key_out, *tree, - &elemaddr, &elemsize, NULL); + + err = lower_bound (data, key, &key_out, *tree, &elemaddr, &elemsize, + NULL); if (err) { grub_free (direl); @@ -1140,7 +1136,7 @@ find_path (struct grub_btrfs_data *data, for (cdirel = direl; (grub_uint8_t *) cdirel - (grub_uint8_t *) direl - < (grub_ssize_t) elemsize; + < (grub_ssize_t) elemsize; cdirel = (void *) ((grub_uint8_t *) (direl + 1) + grub_le_to_cpu16 (cdirel->n) + grub_le_to_cpu16 (cdirel->m))) @@ -1174,7 +1170,7 @@ find_path (struct grub_btrfs_data *data, return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); } - + err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id, *tree); if (err) @@ -1205,7 +1201,7 @@ find_path (struct grub_btrfs_data *data, grub_free (tmp); return grub_errno; } - grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path, + grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path, grub_strlen (path) + 1); grub_free (path_alloc); grub_free (origpath); @@ -1247,8 +1243,7 @@ find_path (struct grub_btrfs_data *data, grub_free (origpath); return err; } - err = grub_btrfs_read_logical (data, elemaddr, - &ri, sizeof (ri)); + err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri)); if (err) { grub_free (direl); @@ -1279,7 +1274,7 @@ find_path (struct grub_btrfs_data *data, grub_free (path_alloc); grub_free (origpath); grub_free (direl); - return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x", + return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x", cdirel->key.type); } } @@ -1290,8 +1285,8 @@ find_path (struct grub_btrfs_data *data, static grub_err_t grub_btrfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + int (*hook) (const char *filename, + const struct grub_dirhook_info * info)) { struct grub_btrfs_data *data = grub_btrfs_mount (device); struct grub_btrfs_key key_in, key_out; @@ -1312,10 +1307,9 @@ grub_btrfs_dir (grub_device_t device, const char *path, if (err) return err; if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); - err = lower_bound (data, &key_in, &key_out, tree, - &elemaddr, &elemsize, &desc); + err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, &desc); if (err) return err; if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM @@ -1355,7 +1349,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, for (cdirel = direl; (grub_uint8_t *) cdirel - (grub_uint8_t *) direl - < (grub_ssize_t) elemsize; + < (grub_ssize_t) elemsize; cdirel = (void *) ((grub_uint8_t *) (direl + 1) + grub_le_to_cpu16 (cdirel->n) + grub_le_to_cpu16 (cdirel->m))) @@ -1384,7 +1378,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, } while (r > 0); - out: +out: grub_free (direl); free_iterator (&desc); @@ -1456,7 +1450,7 @@ grub_btrfs_uuid (grub_device_t device, char **uuid) *uuid = NULL; data = grub_btrfs_mount (device); - if (! data) + if (!data) return grub_errno; *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", @@ -1482,7 +1476,7 @@ grub_btrfs_label (grub_device_t device, char **label) *label = NULL; data = grub_btrfs_mount (device); - if (! data) + if (!data) return grub_errno; *label = grub_strndup (data->sblock.label, sizeof (data->sblock.label)); @@ -1492,26 +1486,25 @@ grub_btrfs_label (grub_device_t device, char **label) return grub_errno; } -static struct grub_fs grub_btrfs_fs = - { - .name = "btrfs", - .dir = grub_btrfs_dir, - .open = grub_btrfs_open, - .read = grub_btrfs_read, - .close = grub_btrfs_close, - .uuid = grub_btrfs_uuid, - .label = grub_btrfs_label, +static struct grub_fs grub_btrfs_fs = { + .name = "btrfs", + .dir = grub_btrfs_dir, + .open = grub_btrfs_open, + .read = grub_btrfs_read, + .close = grub_btrfs_close, + .uuid = grub_btrfs_uuid, + .label = grub_btrfs_label, #ifdef GRUB_UTIL - .reserved_first_sector = 1, + .reserved_first_sector = 1, #endif - }; +}; -GRUB_MOD_INIT(btrfs) +GRUB_MOD_INIT (btrfs) { grub_fs_register (&grub_btrfs_fs); } -GRUB_MOD_FINI(btrfs) +GRUB_MOD_FINI (btrfs) { grub_fs_unregister (&grub_btrfs_fs); } From 095f077e6db33fefb9c9eae6fcbb47b2bef577f8 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 14 Aug 2011 11:46:05 +0200 Subject: [PATCH 322/673] Add support for LZO compression in btrfs. * Makefile.util.def (libgrubmods.a): Add minilzo.c and add required flags to cflags in cppflags. * Makefile.core.def (btrfs): Likewise. * grub-core/fs/btrfs.c: Include minilzo.h. (grub_btrfs_superblock): Add sectorsize, nodesize, leafsize, stripsize and dummy5 field. (GRUB_BTRFS_COMPRESSION_LZO): New define. (grub_btrfs_extent_read): Add support for LZO compression type. --- ChangeLog.lzo | 13 ++++ Makefile.util.def | 3 + grub-core/Makefile.core.def | 3 + grub-core/fs/btrfs.c | 136 ++++++++++++++++++++++++++++++++---- 4 files changed, 143 insertions(+), 12 deletions(-) diff --git a/ChangeLog.lzo b/ChangeLog.lzo index 0a9d852a4..c89255389 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,16 @@ +2011-08-14 Szymon Janc + + Add support for LZO compression in btrfs. + + * Makefile.util.def (libgrubmods.a): Add minilzo.c and add required flags + to cflags in cppflags. + * Makefile.core.def (btrfs): Likewise. + * grub-core/fs/btrfs.c: Include minilzo.h. + (grub_btrfs_superblock): Add sectorsize, nodesize, leafsize, stripsize and + dummy5 field. + (GRUB_BTRFS_COMPRESSION_LZO): New define. + (grub_btrfs_extent_read): Add support for LZO compression type. + 2011-08-14 Szymon Janc * grub-core/fs/btrfs.c: Some code style fixes. diff --git a/Makefile.util.def b/Makefile.util.def index d86cb9761..3628e48f6 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -33,6 +33,8 @@ library = { library = { name = libgrubmods.a; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(top_srcdir)/grub-core/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; common_nodist = grub_script.tab.c; common_nodist = grub_script.yy.c; @@ -107,6 +109,7 @@ library = { common = grub-core/script/argv.c; common = grub-core/io/gzio.c; common = grub-core/kern/ia64/dl_helper.c; + common = grub-core/lib/minilzo/minilzo.c; }; program = { diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 0924602f3..1ff179c67 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -979,6 +979,9 @@ module = { name = btrfs; common = fs/btrfs.c; common = lib/crc.c; + common = lib/minilzo/minilzo.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; }; module = { diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 1336c8f02..1d24da3e3 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -26,6 +26,7 @@ #include #include #include +#include "minilzo.h" GRUB_MOD_LICENSE ("GPLv3+"); @@ -51,10 +52,15 @@ struct grub_btrfs_superblock grub_uint64_t chunk_tree; grub_uint8_t dummy2[0x20]; grub_uint64_t root_dir_objectid; - grub_uint8_t dummy3[0x41]; + grub_uint8_t dummy3[0x8]; + grub_uint32_t sectorsize; + grub_uint32_t nodesize; + grub_uint32_t leafsize; + grub_uint32_t stripsize; + grub_uint8_t dummy4[0x29]; struct grub_btrfs_device this_device; char label[0x100]; - grub_uint8_t dummy4[0x100]; + grub_uint8_t dummy5[0x100]; grub_uint8_t bootstrap_mapping[0x800]; } __attribute__ ((packed)); @@ -216,6 +222,7 @@ struct grub_btrfs_extent_data #define GRUB_BTRFS_COMPRESSION_NONE 0 #define GRUB_BTRFS_COMPRESSION_ZLIB 1 +#define GRUB_BTRFS_COMPRESSION_LZO 2 #define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100 @@ -954,7 +961,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, } if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE - && data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB) + && data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB + && data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO) { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "compression type 0x%x not supported", @@ -980,6 +988,42 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, != (grub_ssize_t) csize) return -1; } + else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) + { + grub_uint32_t total_size, chunk_size; + unsigned char *obuf; + unsigned char *ibuf = (unsigned char *) data->extent->inl; + lzo_uint ocnt = extoff + csize; + int ret; + + obuf = grub_malloc (extoff + csize); + if (!obuf) + return -1; + + total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (total_size); + + chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (chunk_size); + + /* Can we have multiple chunks in inline extent? */ + if (chunk_size + (sizeof (grub_uint32_t) * 2) != total_size) + { + grub_free (obuf); + return -1; + } + + ret = lzo1x_decompress_safe (ibuf, chunk_size, obuf, &ocnt, NULL); + + if (ret != LZO_E_OK) + { + grub_free (obuf); + return -1; + } + + grub_memcpy (buf, obuf + extoff, ocnt - extoff); + grub_free (obuf); + } else grub_memcpy (buf, data->extent->inl + extoff, csize); break; @@ -989,9 +1033,10 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, grub_memset (buf, 0, csize); break; } - if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB) + + if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE) { - char *tmp; + void *tmp; grub_uint64_t zsize; zsize = grub_le_to_cpu64 (data->extent->compressed_size); tmp = grub_malloc (zsize); @@ -1005,16 +1050,83 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, grub_free (tmp); return -1; } - if (grub_zlib_decompress (tmp, zsize, extoff + - grub_le_to_cpu64 (data->extent->offset), - buf, csize) != (grub_ssize_t) csize) + + if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB) { + grub_ssize_t ret; + + ret = grub_zlib_decompress (tmp, zsize, extoff + + grub_le_to_cpu64 (data->extent->offset), + buf, csize); + grub_free (tmp); - return -1; + + if (ret != (grub_ssize_t) csize) + return -1; + + break; } - grub_free (tmp); - break; - } + else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) + { + grub_uint32_t total_size, chunk_size, usize = 0; + grub_size_t off = extoff; + unsigned char *chunk, *ibuf = tmp; + char *obuf = buf; + /* XXX Is this correct size from sblock? */ + grub_uint32_t udata_size = grub_le_to_cpu32 (data->sblock.sectorsize); + + chunk = grub_malloc (udata_size); + if (!chunk) + { + grub_free (tmp); + return -1; + } + + /* XXX Use this for some sanity checks while decompressing. */ + total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (total_size); + + chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (chunk_size); + + /* Jump to first chunk with requested data. */ + while (off >= udata_size) + { + chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (chunk_size); + ibuf += chunk_size; + off -= udata_size; + } + + while (usize < csize) + { + chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + lzo_uint csize2 = udata_size; + int diff; + + ibuf += sizeof (chunk_size); + + if (lzo1x_decompress_safe (ibuf, chunk_size, chunk, &csize2, NULL) != LZO_E_OK) + { + grub_free (tmp); + grub_free (chunk); + return -1; + } + + diff = grub_min (csize2 - off, csize - usize); + + grub_memcpy (obuf, chunk + off, diff); + obuf += diff; + ibuf += chunk_size; + usize += diff; + off = 0; + } + + grub_free (tmp); + grub_free (chunk); + break; + } + } err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (data->extent->laddr) + grub_le_to_cpu64 (data->extent->offset) From 5f60ccac6f0c1a4236a964bed630c95ab67331cb Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 15 Aug 2011 23:21:29 +0100 Subject: [PATCH 323/673] * util/grub-probe.c: Remove duplicate #include. --- ChangeLog | 4 ++++ util/grub-probe.c | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 039621768..b4ec6f677 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-08-15 Colin Watson + + * util/grub-probe.c: Remove duplicate #include. + 2011-08-10 Robert Millan Detect LSI MegaRAID SAS (`mfi') devices on GNU/kFreeBSD. diff --git a/util/grub-probe.c b/util/grub-probe.c index 7c0a75123..3f519bcb4 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include From 828bc390d82e119133877f67ddd1eb3795fb8afc Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Mon, 15 Aug 2011 23:30:11 +0100 Subject: [PATCH 324/673] * util/grub-probe.c (probe): Canonicalise the path argument, fixing use of "/path/.." as in grub-install for EFI as well as handling symlinks correctly. Fixes Debian bug #637768. --- ChangeLog | 8 ++++++++ util/grub-probe.c | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b4ec6f677..f3c2cf690 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-08-15 Mario Limonciello +2011-08-15 Colin Watson + + * util/grub-probe.c (probe): Canonicalise the path argument, fixing + use of "/path/.." as in grub-install for EFI as well as handling + symlinks correctly. + Fixes Debian bug #637768. + 2011-08-15 Colin Watson * util/grub-probe.c: Remove duplicate #include. diff --git a/util/grub-probe.c b/util/grub-probe.c index 3f519bcb4..ae58c89f3 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -180,7 +180,10 @@ probe (const char *path, char *device_name) #endif } else - device_name = grub_guess_root_device (path); + { + grub_path = canonicalize_file_name (path); + device_name = grub_guess_root_device (grub_path); + } if (! device_name) grub_util_error ("cannot find a device for %s (is /dev mounted?)", path); From b1257f653367e8d21b625276f53f086d68fab0b3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Aug 2011 16:11:10 +0200 Subject: [PATCH 325/673] Don't accept text modes on EFI when booting Linux. * grub-core/loader/i386/linux.c (ACCEPTS_PURE_TEXT): New define. (grub_linux_boot) [!ACCEPTS_PURE_TEXT]: Restrict to graphics modes. --- ChangeLog | 7 +++++++ grub-core/loader/i386/linux.c | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f3c2cf690..fc1ea8713 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-08-16 Vladimir Serbinenko + + Don't accept text modes on EFI when booting Linux. + + * grub-core/loader/i386/linux.c (ACCEPTS_PURE_TEXT): New define. + (grub_linux_boot) [!ACCEPTS_PURE_TEXT]: Restrict to graphics modes. + 2011-08-15 Mario Limonciello 2011-08-15 Colin Watson diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 9e3d482ab..5356d7ace 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -45,15 +45,18 @@ GRUB_MOD_LICENSE ("GPLv3+"); #include #define HAS_VGA_TEXT 0 #define DEFAULT_VIDEO_MODE "auto" +#define ACCEPTS_PURE_TEXT 0 #elif defined (GRUB_MACHINE_IEEE1275) #include #define HAS_VGA_TEXT 0 #define DEFAULT_VIDEO_MODE "text" +#define ACCEPTS_PURE_TEXT 1 #else #include #include #define HAS_VGA_TEXT 1 #define DEFAULT_VIDEO_MODE "text" +#define ACCEPTS_PURE_TEXT 1 #endif #define GRUB_LINUX_CL_OFFSET 0x1000 @@ -483,12 +486,22 @@ grub_linux_boot (void) tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); if (! tmp) return grub_errno; +#if ACCEPTS_PURE_TEXT err = grub_video_set_mode (tmp, 0, 0); +#else + err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); +#endif grub_free (tmp); } else - err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0); - + { +#if ACCEPTS_PURE_TEXT + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0); +#else + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); +#endif + } if (err) { grub_print_error (); From 5c144cc8b2cd13b88a0cd214cfa8ee8207aad1c0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Aug 2011 16:19:06 +0200 Subject: [PATCH 326/673] * util/grub-setup.c (main): Add missing gcry initialisation. --- ChangeLog | 4 ++++ util/grub-setup.c | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index fc1ea8713..7acaf320c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-08-16 Vladimir Serbinenko + + * util/grub-setup.c (main): Add missing gcry initialisation. + 2011-08-16 Vladimir Serbinenko Don't accept text modes on EFI when booting Linux. diff --git a/util/grub-setup.c b/util/grub-setup.c index 8482e11c9..2505c03a4 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -893,6 +893,7 @@ main (int argc, char *argv[]) /* Initialize all modules. */ grub_init_all (); + grub_gcry_init_all (); grub_lvm_fini (); grub_mdraid09_fini (); From 43526629e58ac5d5eec0c7b6454bb96d750d197b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Aug 2011 23:10:38 +0200 Subject: [PATCH 327/673] * grub-core/fs/jfs.c (grub_jfs_read_file): New parameter ino. All users updated. (grub_jfs_lookup_symlink): Use correct starting inode. --- ChangeLog | 6 ++++++ grub-core/fs/jfs.c | 15 ++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7acaf320c..c414d79e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-08-16 Vladimir Serbinenko + + * grub-core/fs/jfs.c (grub_jfs_read_file): New parameter ino. + All users updated. + (grub_jfs_lookup_symlink): Use correct starting inode. + 2011-08-16 Vladimir Serbinenko * util/grub-setup.c (main): Add missing gcry initialisation. diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 36ec5fd25..ebc2c688a 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -614,7 +614,8 @@ grub_jfs_read_file (struct grub_jfs_data *data, /* Find the file with the pathname PATH on the filesystem described by DATA. */ static grub_err_t -grub_jfs_find_file (struct grub_jfs_data *data, const char *path) +grub_jfs_find_file (struct grub_jfs_data *data, const char *path, + grub_uint32_t start_ino) { char fpath[grub_strlen (path)]; char *name = fpath; @@ -623,7 +624,7 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path) grub_strncpy (fpath, path, grub_strlen (path) + 1); - if (grub_jfs_read_inode (data, GRUB_JFS_AGGR_INODE, &data->currinode)) + if (grub_jfs_read_inode (data, start_ino, &data->currinode)) return grub_errno; /* Skip the first slashes. */ @@ -724,11 +725,7 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) if (symlink[0] == '/') ino = 2; - /* Now load in the old inode. */ - if (grub_jfs_read_inode (data, ino, &data->currinode)) - return grub_errno; - - grub_jfs_find_file (data, symlink); + grub_jfs_find_file (data, symlink, ino); if (grub_errno) grub_error (grub_errno, "cannot follow symlink `%s'", symlink); @@ -750,7 +747,7 @@ grub_jfs_dir (grub_device_t device, const char *path, if (!data) goto fail; - if (grub_jfs_find_file (data, path)) + if (grub_jfs_find_file (data, path, GRUB_JFS_AGGR_INODE)) goto fail; diro = grub_jfs_opendir (data, &data->currinode); @@ -801,7 +798,7 @@ grub_jfs_open (struct grub_file *file, const char *name) if (!data) goto fail; - grub_jfs_find_file (data, name); + grub_jfs_find_file (data, name, GRUB_JFS_AGGR_INODE); if (grub_errno) goto fail; From 2bba8cfd55fb65fe92d47c9b14d6953940128a5e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Aug 2011 23:12:20 +0200 Subject: [PATCH 328/673] * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_iterate): Skip with non-zero pull. --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index c414d79e7..946dcbd80 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-16 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_iterate): Skip with + non-zero pull. + 2011-08-16 Vladimir Serbinenko * grub-core/fs/jfs.c (grub_jfs_read_file): New parameter ino. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index d1f76b28c..000ef2f79 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -217,6 +217,9 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), { unsigned i; + if (pull != GRUB_DISK_PULL_NONE) + return 0; + for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) if (map[i].drive && hook (map[i].drive)) return 1; From d6beefcfc9d3451fe262b6d57ccc215db8ce5681 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 17 Aug 2011 19:40:25 +0200 Subject: [PATCH 329/673] Add initial support for lzop files decompression. * grub-core/Makefile.core.def (lzopio): New module. * grub-core/io/lzopio.c: New file. * include/grub/file.h (grub_file_filter_id): New compression filter GRUB_FILE_FILTER_LZOPIO. --- ChangeLog.lzo | 9 + grub-core/Makefile.core.def | 8 + grub-core/io/lzopio.c | 527 ++++++++++++++++++++++++++++++++++++ include/grub/file.h | 1 + 4 files changed, 545 insertions(+) create mode 100644 grub-core/io/lzopio.c diff --git a/ChangeLog.lzo b/ChangeLog.lzo index c89255389..782c6b60d 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,12 @@ +2011-08-17 Szymon Janc + + Add initial support for lzop files decompression. + + * grub-core/Makefile.core.def (lzopio): New module. + * grub-core/io/lzopio.c: New file. + * include/grub/file.h (grub_file_filter_id): New compression filter + GRUB_FILE_FILTER_LZOPIO. + 2011-08-14 Szymon Janc Add support for LZO compression in btrfs. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 1ff179c67..67959d861 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1651,6 +1651,14 @@ module = { cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; }; +module = { + name = lzopio; + common = io/lzopio.c; + common = lib/minilzo/minilzo.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; +}; + module = { name = testload; common = commands/testload.c; diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c new file mode 100644 index 000000000..4ccc41a16 --- /dev/null +++ b/grub-core/io/lzopio.c @@ -0,0 +1,527 @@ +/* lzopio.c - decompression support for lzop */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include + +#include "minilzo.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define LZOP_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" +#define LZOP_MAGIC_SIZE 9 +#define CHECK_SIZE 4 +#define NEW_LZO_LIB 0x0940 +#define MIN_HEADER_SIZE 0 +#define MAX_HEADER_SIZE 0 + +/* Header flags - copied from conf.h of LZOP source code. */ +#define F_ADLER32_D 0x00000001L +#define F_ADLER32_C 0x00000002L +#define F_STDIN 0x00000004L +#define F_STDOUT 0x00000008L +#define F_NAME_DEFAULT 0x00000010L +#define F_DOSISH 0x00000020L +#define F_H_EXTRA_FIELD 0x00000040L +#define F_H_GMTDIFF 0x00000080L +#define F_CRC32_D 0x00000100L +#define F_CRC32_C 0x00000200L +#define F_MULTIPART 0x00000400L +#define F_H_FILTER 0x00000800L +#define F_H_CRC32 0x00001000L +#define F_H_PATH 0x00002000L +#define F_MASK 0x00003FFFL + +struct block_header +{ + grub_uint32_t usize; + grub_uint32_t csize; + grub_uint32_t ucheck; + grub_uint32_t ccheck; + unsigned char *cdata; + unsigned char *udata; +}; + +struct grub_lzopio +{ + grub_file_t file; + int ucheck; /* XXX Use gcry to validate checks. */ + int ccheck; + grub_off_t saved_off; /* Rounded down to block boundary. */ + grub_off_t start_block_off; + struct block_header block; +}; + +typedef struct grub_lzopio *grub_lzopio_t; +static struct grub_fs grub_lzopio_fs; + +/* Some helper functions. Memory allocated by those function is free either + * on next read_block_header() or on close() so no risk of leaks. This makes + * those function simpler. */ + +/* Read block header from file, after successful exit file points to + * beginning of block data. */ +static int +read_block_header (struct grub_lzopio *lzopio) +{ + /* Free cached block data if any. */ + grub_free (lzopio->block.udata); + grub_free (lzopio->block.cdata); + lzopio->block.udata = NULL; + lzopio->block.cdata = NULL; + + if (grub_file_read (lzopio->file, &lzopio->block.usize, + sizeof (lzopio->block.usize)) != + sizeof (lzopio->block.usize)) + return -1; + + lzopio->block.usize = grub_be_to_cpu32 (lzopio->block.usize); + + /* Last block has uncompressed data size == 0 and no other fields. */ + if (lzopio->block.usize == 0) + { + if (grub_file_tell (lzopio->file) == grub_file_size (lzopio->file)) + return 0; + else + return -1; + } + + /* Read compressed data block size. */ + if (grub_file_read (lzopio->file, &lzopio->block.csize, + sizeof (lzopio->block.csize)) != + sizeof (lzopio->block.csize)) + return -1; + + lzopio->block.csize = grub_be_to_cpu32 (lzopio->block.csize); + + /* XXX Handle incompressible data case here rather than in uncompress_block. + * This will allow to handle switch of ccheck/ucheck easier and also + * make uncompress_block() a bit simpler. */ + + /* Read data checks. */ + if (lzopio->ucheck) + { + if (grub_file_read (lzopio->file, &lzopio->block.ucheck, + sizeof (lzopio->block.ucheck)) != + sizeof (lzopio->block.ucheck)) + return -1; + } + + if (lzopio->ccheck) + { + if (grub_file_read (lzopio->file, &lzopio->block.ccheck, + sizeof (lzopio->block.ccheck)) != + sizeof (lzopio->block.ccheck)) + return -1; + } + return 0; +} + +/* Read block data into memory. File must be set to beginning of block data. + * Can't be called on last block. */ +static int +read_block_data (struct grub_lzopio *lzopio) +{ + lzopio->block.cdata = grub_malloc (lzopio->block.csize); + if (!lzopio->block.cdata) + return -1; + + if (grub_file_read (lzopio->file, lzopio->block.cdata, lzopio->block.csize) + != (grub_ssize_t) lzopio->block.csize) + return -1; + + if (lzopio->ccheck) + { + /* XXX Validate data checksum here. */ + } + + return 0; +} + +/* Read block data, uncompressed and also store it in memory. */ +/* XXX Investigate possibility of in-place decompression to reduce memory + * footprint. */ +static int +uncompress_block (struct grub_lzopio *lzopio) +{ + lzo_uint usize = lzopio->block.usize; + + if (read_block_data (lzopio) < 0) + return -1; + + if (lzopio->block.usize > lzopio->block.csize) + { + lzopio->block.udata = grub_malloc (lzopio->block.usize); + if (!lzopio->block.udata) + return -1; + + if (lzo1x_decompress_safe (lzopio->block.cdata, lzopio->block.csize, + lzopio->block.udata, &usize, + NULL) != LZO_E_OK) + return -1; + + if (lzopio->ucheck) + { + /* XXX Validate data checksum here. */ + } + + /* Compressed data can be free now. */ + grub_free (lzopio->block.cdata); + lzopio->block.cdata = NULL; + } + /* Incompressible block of data. */ + else if (lzopio->block.usize == lzopio->block.csize) + { + lzopio->block.udata = lzopio->block.cdata; + lzopio->block.cdata = NULL; + } + else + { + return -1; + } + + return 0; +} + +/* Jump to next block and read its header. */ +static int +jump_block (struct grub_lzopio *lzopio) +{ + /* only jump if block was not decompressed (and read from disk) */ + if (!lzopio->block.udata) + { + grub_off_t off = grub_file_tell (lzopio->file) + lzopio->block.csize; + + if (grub_file_seek (lzopio->file, off) == ((grub_off_t) - 1)) + return -1; + } + + lzopio->saved_off += lzopio->block.usize; + + return read_block_header (lzopio); +} + +static int +calculate_uncompressed_size (grub_file_t file) +{ + grub_lzopio_t lzopio = file->data; + grub_off_t usize_total = 0; + + if (read_block_header (lzopio) < 0) + return 0; + + /* FIXME: Don't do this for not easily seekable files. */ + while (lzopio->block.usize != 0) + { + usize_total += lzopio->block.usize; + + if (jump_block (lzopio) < 0) + return 0; + } + + file->size = usize_total; + + return 1; +} + +/* XXX Do something with this function, it is insane now:) */ +static int +test_header (grub_file_t file) +{ + grub_lzopio_t lzopio = file->data; + unsigned char magic[LZOP_MAGIC_SIZE]; + grub_uint16_t lzopver, ver, ver_ext; + grub_uint8_t method, level, name_len; + grub_uint32_t flags, mode, filter, mtime_lo, mtime_hi, checksum; + unsigned char *name = NULL; + + if (grub_file_read (lzopio->file, magic, sizeof (magic)) != sizeof (magic)) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found"); + return 0; + } + + if (grub_memcmp (magic, LZOP_MAGIC, LZOP_MAGIC_SIZE) != 0) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found"); + return 0; + } + + /* LZOP version. */ + if (grub_file_read (lzopio->file, &lzopver, sizeof (lzopver)) != + sizeof (lzopver)) + goto CORRUPTED; + + /* LZO lib version. */ + if (grub_file_read (lzopio->file, &ver, sizeof (ver)) != sizeof (ver)) + goto CORRUPTED; + + ver = grub_be_to_cpu16 (ver); + + if (ver >= NEW_LZO_LIB) + { + /* Read version of lib needed to extract data. */ + if (grub_file_read (lzopio->file, &ver_ext, sizeof (ver_ext)) != + sizeof (ver_ext)) + goto CORRUPTED; + + /* Too new version, should upgrade minilzo? */ + if (grub_be_to_cpu16 (ver_ext) > MINILZO_VERSION) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "unsupported LZO version"); + return 0; + } + } + + if (grub_file_read (lzopio->file, &method, sizeof (method)) != + sizeof (method)) + goto CORRUPTED; + + if (ver >= NEW_LZO_LIB) + { + if (grub_file_read (lzopio->file, &level, sizeof (level)) != + sizeof (level)) + goto CORRUPTED; + } + + if (grub_file_read (lzopio->file, &flags, sizeof (flags)) != sizeof (flags)) + goto CORRUPTED; + + flags = grub_be_to_cpu32 (flags); + + if (flags & F_CRC32_D) + lzopio->ucheck = 1; + else if (flags & F_ADLER32_D) + lzopio->ucheck = 2; + + if (flags & F_CRC32_C) + lzopio->ccheck = 1; + else if (flags & F_ADLER32_C) + lzopio->ccheck = 2; + + if (flags & F_H_FILTER) + { + if (grub_file_read (lzopio->file, &filter, sizeof (filter)) != + sizeof (filter)) + goto CORRUPTED; + } + + if (grub_file_read (lzopio->file, &mode, sizeof (mode)) != sizeof (mode)) + goto CORRUPTED; + + if (grub_file_read (lzopio->file, &mtime_lo, sizeof (mtime_lo)) != + sizeof (mtime_lo)) + goto CORRUPTED; + + if (ver >= NEW_LZO_LIB) + { + if (grub_file_read (lzopio->file, &mtime_hi, sizeof (mtime_hi)) != + sizeof (mtime_hi)) + goto CORRUPTED; + } + + if (grub_file_read (lzopio->file, &name_len, sizeof (name_len)) != + sizeof (name_len)) + goto CORRUPTED; + + if (name_len != 0) + { + name = grub_malloc (name_len); + if (!name) + return 0; + + if (grub_file_read (lzopio->file, name, name_len) != name_len) + { + grub_free (name); + goto CORRUPTED; + } + } + + if (grub_file_read (lzopio->file, &checksum, sizeof (checksum)) != + sizeof (checksum)) + { + grub_free (name); + goto CORRUPTED; + } + + grub_free (name); + + /* XXX Validate header checksum here. */ + if (checksum == checksum) + { + lzopio->start_block_off = grub_file_tell (lzopio->file); + + if (calculate_uncompressed_size (file) < 0) + goto CORRUPTED; + + lzopio->saved_off = 0; + + /* Get back to start block. */ + grub_file_seek (lzopio->file, lzopio->start_block_off); + + /* Read first block - grub_lzopio_read() expects valid block. */ + if (read_block_header (lzopio) < 0) + goto CORRUPTED; + + return 1; + } + +CORRUPTED: + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "lzop file corrupted"); + return 0; +} + +static grub_file_t +grub_lzopio_open (grub_file_t io) +{ + grub_file_t file; + grub_lzopio_t lzopio; + + file = (grub_file_t) grub_zalloc (sizeof (*file)); + if (!file) + return 0; + + lzopio = grub_zalloc (sizeof (*lzopio)); + if (!lzopio) + { + grub_free (file); + return 0; + } + + lzopio->file = io; + + file->device = io->device; + file->offset = 0; + file->data = lzopio; + file->read_hook = 0; + file->fs = &grub_lzopio_fs; + file->size = GRUB_FILE_SIZE_UNKNOWN; + file->not_easily_seekable = 1; + + if (grub_file_tell (lzopio->file) != 0) + grub_file_seek (lzopio->file, 0); + + if (!test_header (file)) + { + grub_errno = GRUB_ERR_NONE; + grub_file_seek (io, 0); + grub_free (lzopio); + grub_free (file); + + return io; + } + + return file; +} + +static grub_ssize_t +grub_lzopio_read (grub_file_t file, char *buf, grub_size_t len) +{ + grub_lzopio_t lzopio = file->data; + grub_ssize_t ret = 0; + + /* Backward seek before last read block. */ + if (lzopio->saved_off > grub_file_tell (file)) + { + lzopio->saved_off = 0; + grub_file_seek (lzopio->file, lzopio->start_block_off); + + if (read_block_header (lzopio) < 0) + goto CORRUPTED; + } + + /* Forward to first block with requested data. */ + while (lzopio->saved_off + lzopio->block.usize <= grub_file_tell (file)) + { + /* EOF, could be possible files with unknown size. */ + if (lzopio->block.usize == 0) + return 0; + + if (jump_block (lzopio) < 0) + goto CORRUPTED; + } + + while (len != 0 && lzopio->block.usize != 0) + { + grub_off_t off = grub_file_tell (file) - lzopio->saved_off; + long to_copy; + + /* Block not decompressed yet. */ + if (!lzopio->block.udata && uncompress_block (lzopio) < 0) + goto CORRUPTED; + + /* Copy requested data into buffer. */ + to_copy = grub_min (lzopio->block.usize - off, len); + grub_memcpy (buf, lzopio->block.udata + off, to_copy); + + len -= to_copy; + buf += to_copy; + ret += to_copy; + + /* Read to next block if needed. */ + if (len > 0 && read_block_header (lzopio) < 0) + goto CORRUPTED; + } + + return ret; + +CORRUPTED: + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "lzop file corrupted"); + return -1; +} + +/* Release everything, including the underlying file object. */ +static grub_err_t +grub_lzopio_close (grub_file_t file) +{ + grub_lzopio_t lzopio = file->data; + + grub_file_close (lzopio->file); + grub_free (lzopio->block.cdata); + grub_free (lzopio->block.udata); + grub_free (lzopio); + + /* Device must not be closed twice. */ + file->device = 0; + return grub_errno; +} + +static struct grub_fs grub_lzopio_fs = { + .name = "lzopio", + .dir = 0, + .open = 0, + .read = grub_lzopio_read, + .close = grub_lzopio_close, + .label = 0, + .next = 0 +}; + +GRUB_MOD_INIT (lzopio) +{ + grub_file_filter_register (GRUB_FILE_FILTER_LZOPIO, grub_lzopio_open); +} + +GRUB_MOD_FINI (lzopio) +{ + grub_file_filter_unregister (GRUB_FILE_FILTER_LZOPIO); +} diff --git a/include/grub/file.h b/include/grub/file.h index 3adb1706f..8fe87e6b4 100644 --- a/include/grub/file.h +++ b/include/grub/file.h @@ -56,6 +56,7 @@ typedef enum grub_file_filter_id { GRUB_FILE_FILTER_GZIO, GRUB_FILE_FILTER_XZIO, + GRUB_FILE_FILTER_LZOPIO, GRUB_FILE_FILTER_MAX, GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO, GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_XZIO, From 055e2b8b4f31be61160384d202c2f90422a723c2 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 19 Aug 2011 17:24:18 +0200 Subject: [PATCH 330/673] * configure.ac: Fixed typo in --enable-cache-stats description. --- ChangeLog.cacheinfo | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog.cacheinfo b/ChangeLog.cacheinfo index a26271cca..7e24e1083 100644 --- a/ChangeLog.cacheinfo +++ b/ChangeLog.cacheinfo @@ -1,3 +1,7 @@ +2011-08-19 Szymon Janc + + * configure.ac: Fixed typo in --enable-cache-stats description. + 2010-10-05 Szymon Janc Make enable of disk cache statistics code configurable. diff --git a/configure.ac b/configure.ac index 5f7846d41..224c9c9de 100644 --- a/configure.ac +++ b/configure.ac @@ -719,7 +719,7 @@ AC_ARG_ENABLE([mm-debug], AC_ARG_ENABLE([cache-stats], AS_HELP_STRING([--enable-cache-stats], - [enable disk cache statistics collection])]) + [enable disk cache statistics collection])) if test x$enable_cache_stats = xyes; then DISK_CACHE_STATS=1 From fb739ccd7923fb3d11d825d744faaf1cdf884d73 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 19 Aug 2011 20:06:42 +0200 Subject: [PATCH 331/673] * Makefile.am (AUTOMAKE_OPTIONS): = Added -Wno-portability flag. * grub-core/Makefile.am: Likewise. --- ChangeLog | 5 +++++ Makefile.am | 2 +- grub-core/Makefile.am | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 946dcbd80..17e2643b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-19 Szymon Janc + + * Makefile.am (AUTOMAKE_OPTIONS): = Added -Wno-portability flag. + * grub-core/Makefile.am: Likewise. + 2011-08-16 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_iterate): Skip with diff --git a/Makefile.am b/Makefile.am index 9301c91a5..c5f486e0d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -AUTOMAKE_OPTIONS = subdir-objects +AUTOMAKE_OPTIONS = subdir-objects -Wno-portability DEPDIR = .deps-util SUBDIRS = grub-core/gnulib . grub-core po docs util/bash-completion.d diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 3a085eb2c..f30014635 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -1,4 +1,4 @@ -AUTOMAKE_OPTIONS = subdir-objects +AUTOMAKE_OPTIONS = subdir-objects -Wno-portability DEPDIR=.deps-core From 14a2562cf7e8bb2d6f8d13b297d8e3b07308d945 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 19 Aug 2011 22:46:11 +0200 Subject: [PATCH 332/673] Rename Fuloong into Fuloong 2F. Add new ID for Fuloong2E. * grub-core/Makefile.core.def (fwstart_fuloong): Rename fwstart_fuloong into fwstart_fuloong2f. Use boot/mips/loongson/fuloong2f.S. * grub-core/boot/mips/loongson/fuloong.S: Rename to ... * grub-core/boot/mips/loongson/fuloong2f.S: ... this. (FULOONG): Rename to ... (FULOONG2F): ... this. All users updated. * grub-core/boot/mips/startup_raw.S (machtype_fuloong_str): Rename to (machtype_fuloong2f_str): ... this. (machtype_fuloong2e_str): New string. Check for machtype_fuloong2e_str. * grub-core/loader/mips/linux.c (loongson_machtypes) [GRUB_MACHINE_MIPS_LOONGSON]: Add GRUB_ARCH_MACHINE_FULOONG2E. * grub-core/term/serial.c (loongson_defserial) [GRUB_MACHINE_MIPS_LOONGSON]: New array. (grub_serial_register) [GRUB_MACHINE_MIPS_LOONGSON]: Use loongson_defserial. * include/grub/mips/loongson/kernel.h (GRUB_ARCH_MACHINE_FULOONG): Rename to ... (GRUB_ARCH_MACHINE_FULOONG2F): ... this. (GRUB_ARCH_MACHINE_FULOONG2E): New const. * util/grub-mkimage.c (image_target_desc): Rename IMAGE_FULOONG_FLASH to IMAGE_FULOONG2F_FLASH. All users updated. (image_targets): Rename images. * util/grub-mkstandalone.in: Accept fuloong2f and fuloong2e. --- ChangeLog | 29 +++++++++++++++++++ grub-core/Makefile.core.def | 4 +-- .../mips/loongson/{fuloong.S => fuloong2f.S} | 2 +- grub-core/boot/mips/loongson/fwstart.S | 26 ++++++++--------- grub-core/boot/mips/startup_raw.S | 14 +++++---- grub-core/bus/cs5536.c | 2 +- grub-core/kern/mips/loongson/init.c | 4 ++- grub-core/kern/mips/startup.S | 2 +- grub-core/loader/mips/linux.c | 3 +- grub-core/term/serial.c | 13 +++++++-- include/grub/mips/loongson/kernel.h | 3 +- util/grub-mkimage.c | 17 ++++++----- util/grub-mkstandalone.in | 2 +- 13 files changed, 82 insertions(+), 39 deletions(-) rename grub-core/boot/mips/loongson/{fuloong.S => fuloong2f.S} (51%) diff --git a/ChangeLog b/ChangeLog index 21975a2d3..fdc89b5a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2011-08-19 Vladimir Serbinenko + + Rename Fuloong into Fuloong 2F. Add new ID for Fuloong2E. + + * grub-core/Makefile.core.def (fwstart_fuloong): Rename fwstart_fuloong + into fwstart_fuloong2f. Use boot/mips/loongson/fuloong2f.S. + * grub-core/boot/mips/loongson/fuloong.S: Rename to ... + * grub-core/boot/mips/loongson/fuloong2f.S: ... this. + (FULOONG): Rename to ... + (FULOONG2F): ... this. All users updated. + * grub-core/boot/mips/startup_raw.S (machtype_fuloong_str): Rename to + (machtype_fuloong2f_str): ... this. + (machtype_fuloong2e_str): New string. + Check for machtype_fuloong2e_str. + * grub-core/loader/mips/linux.c (loongson_machtypes) + [GRUB_MACHINE_MIPS_LOONGSON]: Add GRUB_ARCH_MACHINE_FULOONG2E. + * grub-core/term/serial.c (loongson_defserial) + [GRUB_MACHINE_MIPS_LOONGSON]: New array. + (grub_serial_register) [GRUB_MACHINE_MIPS_LOONGSON]: Use + loongson_defserial. + * include/grub/mips/loongson/kernel.h (GRUB_ARCH_MACHINE_FULOONG): + Rename to ... + (GRUB_ARCH_MACHINE_FULOONG2F): ... this. + (GRUB_ARCH_MACHINE_FULOONG2E): New const. + * util/grub-mkimage.c (image_target_desc): Rename IMAGE_FULOONG_FLASH + to IMAGE_FULOONG2F_FLASH. All users updated. + (image_targets): Rename images. + * util/grub-mkstandalone.in: Accept fuloong2f and fuloong2e. + 2011-08-19 Szymon Janc Make enable of disk cache statistics code configurable. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index de57d2f0c..f129e98db 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -363,8 +363,8 @@ image = { }; image = { - name = fwstart_fuloong; - mips_loongson = boot/mips/loongson/fuloong.S; + name = fwstart_fuloong2f; + mips_loongson = boot/mips/loongson/fuloong2f.S; objcopyflags = '-O binary'; ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; enable = mips_loongson; diff --git a/grub-core/boot/mips/loongson/fuloong.S b/grub-core/boot/mips/loongson/fuloong2f.S similarity index 51% rename from grub-core/boot/mips/loongson/fuloong.S rename to grub-core/boot/mips/loongson/fuloong2f.S index 5df0d54c1..a88c81efe 100644 --- a/grub-core/boot/mips/loongson/fuloong.S +++ b/grub-core/boot/mips/loongson/fuloong2f.S @@ -1,2 +1,2 @@ -#define FULOONG 1 +#define FULOONG2F 1 #include "fwstart.S" diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index 38e87ad72..7ed5d30ae 100644 --- a/grub-core/boot/mips/loongson/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -26,7 +26,7 @@ #include #include -#ifdef FULOONG +#ifdef FULOONG2F #define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2 #define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200 #else @@ -43,10 +43,10 @@ start: _start: __start: - /* Put serial init as soon as possible. But on Fuloong serial is past - Geode, so on Fuloong we need Geode first. + /* Put serial init as soon as possible. But on Fuloong2f serial is past + Geode, so on Fuloong2f we need Geode first. */ -#ifndef FULOONG +#ifndef FULOONG2F bal serial_hw_init nop #endif @@ -72,7 +72,7 @@ retry_cs5536: bnel $t2, $t3, 1b sll $t4, $t4, 1 -#ifndef FULOONG +#ifndef FULOONG2F bal message addiu $a0, $a0, %lo(cs5536_found) bal printhex @@ -95,7 +95,7 @@ retry_cs5536: bal gpio_init nop -#ifdef FULOONG +#ifdef FULOONG2F bal serial_hw_init nop #endif @@ -130,7 +130,7 @@ retry_cs5536: sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0) sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) - /* Yeeloong and Fuloong have only one memory slot. */ + /* Yeeloong and Fuloong2f have only one memory slot. */ /* Output first byte on serial for debugging. */ ori $a1, $zero, GRUB_SMB_RAM_START_ADDR bal read_spd @@ -252,7 +252,7 @@ gpio_init: /* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2. */ serial_hw_init: move $t2, $ra -#ifdef FULOONG +#ifdef FULOONG2F lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO) addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO) lui $a1, %hi (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 \ @@ -471,7 +471,7 @@ regdump: .quad 0x0100020200010101 /* 4 */ .quad 0x0a04030603050203 /* 6 */ .quad 0x0f0e040000010a0b /* 7 */ -#ifdef FULOONG +#ifdef FULOONG2F .quad 0x0000000100000001 /* 8 */ #else .quad 0x0000010200000102 /* 8 */ @@ -482,7 +482,7 @@ regdump: .quad 0x002a3c0615000000 /* c */ .quad 0x002a002a002a002a /* d */ .quad 0x002a002a002a002a /* e */ -#ifdef FULOONG +#ifdef FULOONG2F .quad 0x00b40020005b0004 /* f */ #else .quad 0x00b40020006d0004 /* f */ @@ -503,7 +503,7 @@ regdump: /* Dump of GPIO connections. FIXME: Remove useless and macroify. */ gpio_dump: -#ifdef FULOONG +#ifdef FULOONG2F .long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000 .long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000 .long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000 @@ -740,8 +740,8 @@ continue: lui $t0, %hi(cached_continue - 0x20000000) addiu $t0, $t0, %lo(cached_continue - 0x20000000) jr $t0 -#ifdef FULOONG - addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG) +#ifdef FULOONG2F + addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG2F) #else addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG) #endif diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index 4ecff5efd..aefd387b6 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -109,7 +109,7 @@ argcont: DO_PARSE (memsizestr, $s4) DO_PARSE (highmemsizestr, $s5) DO_CHECKT1 (pmon_yeeloong_verstr, GRUB_ARCH_MACHINE_YEELOONG) - DO_CHECKT1 (pmon_fuloong_verstr, GRUB_ARCH_MACHINE_FULOONG) + DO_CHECKT1 (pmon_fuloong2f_verstr, GRUB_ARCH_MACHINE_FULOONG2F) 2: b argcont addiu $t0, $t0, 4 @@ -155,11 +155,12 @@ memsizestr: .asciiz "memsize=" highmemsizestr: .asciiz "highmemsize=" machtype_yeeloong_str1: .asciiz "machtype=8.9" machtype_yeeloong_str2: .asciiz "machtype=lemote-yeeloong-" -machtype_fuloong_str: .asciiz "machtype=lemote-fuloong-" +machtype_fuloong2f_str: .asciiz "machtype=lemote-fuloong-2f" +machtype_fuloong2e_str: .asciiz "machtype=lemote-fuloong-2e" pmon_yeeloong_str: .asciiz "PMON_VER=LM8" -pmon_fuloong_str: .asciiz "PMON_VER=LM6" +pmon_fuloong2f_str: .asciiz "PMON_VER=LM6" pmon_yeeloong_verstr: .asciiz "Version=LM8" -pmon_fuloong_verstr: .asciiz "Version=LM6" +pmon_fuloong2f_verstr: .asciiz "Version=LM6" .p2align 2 argdone: @@ -173,8 +174,9 @@ argdone: DO_CHECKA1 (machtype_yeeloong_str1, GRUB_ARCH_MACHINE_YEELOONG) DO_CHECKA1 (machtype_yeeloong_str2, GRUB_ARCH_MACHINE_YEELOONG) DO_CHECKA1 (pmon_yeeloong_str, GRUB_ARCH_MACHINE_YEELOONG) - DO_CHECKA1 (machtype_fuloong_str, GRUB_ARCH_MACHINE_FULOONG) - DO_CHECKA1 (pmon_fuloong_str, GRUB_ARCH_MACHINE_FULOONG) + DO_CHECKA1 (machtype_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F) + DO_CHECKA1 (machtype_fuloong2e_str, GRUB_ARCH_MACHINE_FULOONG2E) + DO_CHECKA1 (pmon_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F) addiu $a0, $a0, -1 b argdone addiu $a1, $a1, 4 diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 58ffeb60a..1aae7852e 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -281,7 +281,7 @@ grub_cs5536_init_geode (grub_pci_device_t dev) | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1); break; - case GRUB_ARCH_MACHINE_FULOONG: + case GRUB_ARCH_MACHINE_FULOONG2F: grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO, GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 | GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1 diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index bcef391b9..0e4948beb 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -213,7 +213,9 @@ grub_halt (void) { switch (grub_arch_machine) { - case GRUB_ARCH_MACHINE_FULOONG: + case GRUB_ARCH_MACHINE_FULOONG2E: + break; + case GRUB_ARCH_MACHINE_FULOONG2F: { grub_pci_device_t dev; grub_port_t p; diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 6220a8c33..da6450237 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -61,7 +61,7 @@ VARIABLE (grub_arch_highmemsize) .long 0 #ifdef GRUB_MACHINE_MIPS_LOONGSON VARIABLE (grub_arch_machine) - .long GRUB_ARCH_MACHINE_FULOONG + .long GRUB_ARCH_MACHINE_FULOONG2F #endif cont: /* Save our base. */ diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 64c4a0531..2b4875983 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -41,7 +41,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); const char loongson_machtypes[][60] = { [GRUB_ARCH_MACHINE_YEELOONG] = "machtype=lemote-yeeloong-2f-8.9inches", - [GRUB_ARCH_MACHINE_FULOONG] = "machtype=lemote-fuloong-2f-unknown" + [GRUB_ARCH_MACHINE_FULOONG2F] = "machtype=lemote-fuloong-2f-unknown", + [GRUB_ARCH_MACHINE_FULOONG2E] = "machtype=lemote-fuloong-2e-unknown" }; #endif diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index 0381349a4..b724a945a 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -239,6 +239,15 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args) return GRUB_ERR_NONE; } +#ifdef GRUB_MACHINE_MIPS_LOONGSON +const char loongson_defserial[][6] = + { + [GRUB_ARCH_MACHINE_YEELOONG] = "com0", + [GRUB_ARCH_MACHINE_FULOONG2F] = "com2", + [GRUB_ARCH_MACHINE_FULOONG2E] = "com1" + }; +#endif + grub_err_t grub_serial_register (struct grub_serial_port *port) { @@ -301,9 +310,7 @@ grub_serial_register (struct grub_serial_port *port) port->term_out = out; grub_terminfo_output_register (out, "vt100"); #ifdef GRUB_MACHINE_MIPS_LOONGSON - if (grub_strcmp (port->name, - (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG) - ? "com0" : "com2") == 0) + if (grub_strcmp (port->name, loongson_defserial[grub_arch_machine]) == 0) { grub_term_register_input_active ("serial_*", in); grub_term_register_output_active ("serial_*", out); diff --git a/include/grub/mips/loongson/kernel.h b/include/grub/mips/loongson/kernel.h index 612221ed2..ba94e4331 100644 --- a/include/grub/mips/loongson/kernel.h +++ b/include/grub/mips/loongson/kernel.h @@ -23,7 +23,8 @@ #include #define GRUB_ARCH_MACHINE_YEELOONG 0 -#define GRUB_ARCH_MACHINE_FULOONG 1 +#define GRUB_ARCH_MACHINE_FULOONG2F 1 +#define GRUB_ARCH_MACHINE_FULOONG2E 2 #ifndef ASM_FILE diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index b05507242..420690923 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -67,7 +67,7 @@ struct image_target_desc IMAGE_I386_PC, IMAGE_EFI, IMAGE_COREBOOT, IMAGE_SPARC64_AOUT, IMAGE_SPARC64_RAW, IMAGE_I386_IEEE1275, IMAGE_LOONGSON_ELF, IMAGE_QEMU, IMAGE_PPC, IMAGE_YEELOONG_FLASH, - IMAGE_FULOONG_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC, + IMAGE_FULOONG2F_FLASH, IMAGE_I386_PC_PXE, IMAGE_MIPS_ARC, IMAGE_QEMU_MIPS_FLASH } id; enum @@ -298,10 +298,10 @@ struct image_target_desc image_targets[] = }, { .dirname = "mipsel-loongson", - .names = { "mipsel-fuloong-flash", NULL }, + .names = { "mipsel-fuloong2f-flash", NULL }, .voidp_sizeof = 4, .bigendian = 0, - .id = IMAGE_FULOONG_FLASH, + .id = IMAGE_FULOONG2F_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .prefix = GRUB_KERNEL_MIPS_LOONGSON_PREFIX, .prefix_end = GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END, @@ -321,6 +321,7 @@ struct image_target_desc image_targets[] = { .dirname = "mipsel-loongson", .names = { "mipsel-loongson-elf", "mipsel-yeeloong-elf", + "mipsel-fuloong2f-elf", "mipsel-fuloong2e-elf", "mipsel-fuloong-elf", NULL }, .voidp_sizeof = 4, .bigendian = 0, @@ -1362,7 +1363,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], } break; case IMAGE_YEELOONG_FLASH: - case IMAGE_FULOONG_FLASH: + case IMAGE_FULOONG2F_FLASH: { char *rom_img; size_t rom_size; @@ -1381,7 +1382,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* None yet. */ - const grub_uint8_t fuloong_fwstart_good_hash[512 / 8] = + const grub_uint8_t fuloong2f_fwstart_good_hash[512 / 8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -1393,10 +1394,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], }; const grub_uint8_t *fwstart_good_hash; - if (image_target->id == IMAGE_FULOONG_FLASH) + if (image_target->id == IMAGE_FULOONG2F_FLASH) { - fwstart_good_hash = fuloong_fwstart_good_hash; - boot_path = grub_util_get_path (dir, "fwstart_fuloong.img"); + fwstart_good_hash = fuloong2f_fwstart_good_hash; + boot_path = grub_util_get_path (dir, "fwstart_fuloong2f.img"); } else { diff --git a/util/grub-mkstandalone.in b/util/grub-mkstandalone.in index aaff99051..e140ecc82 100644 --- a/util/grub-mkstandalone.in +++ b/util/grub-mkstandalone.in @@ -136,7 +136,7 @@ if [ "x$source_directory" = x ] ; then cpu="`echo $format | awk -F - '{ print $1; }'`" platform="`echo $format | awk -F - '{ print $2; }'`" case "$platform" in - yeeloong | fuloong) + yeeloong | fuloong | fuloong2f | fuloong2e) platform=loongson ;; esac case "$cpu-$platform" in From 9594c6897ec93b27066244a71005f262dab91f82 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 19 Aug 2011 22:49:48 +0200 Subject: [PATCH 333/673] * configure.ac: Don't impose march=loongson2f on loongson platform. (It can still be specified in TARGET_CFLAGS) --- ChangeLog | 5 +++++ configure.ac | 17 ----------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index fdc89b5a2..c2f501c00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-19 Vladimir Serbinenko + + * configure.ac: Don't impose march=loongson2f on loongson platform. (It + can still be specified in TARGET_CFLAGS) + 2011-08-19 Vladimir Serbinenko Rename Fuloong into Fuloong 2F. Add new ID for Fuloong2E. diff --git a/configure.ac b/configure.ac index 224c9c9de..9cfbd2340 100644 --- a/configure.ac +++ b/configure.ac @@ -412,23 +412,6 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" fi -if test "${target_cpu}-${platform}" = mipsel-loongson; then - AC_CACHE_CHECK([whether -march=loongson2f works], [grub_cv_cc_march_loongson2f], [ - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -march=loongson2f" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_march_loongson2f=yes], - [grub_cv_cc_march_loongson2f=no]) - CFLAGS="$SAVE_CFLAGS" - ]) - - if test "x$grub_cv_cc_march_loongson2f" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -march=loongson2f" - else - TARGET_CFLAGS="$TARGET_CFLAGS -march=mips3" - fi -fi - grub_apple_target_cc if test x$grub_cv_apple_target_cc = xyes ; then TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1" From 1227c1339017349e6d011fe4bc927ff394141272 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 19 Aug 2011 22:56:49 +0200 Subject: [PATCH 334/673] Fix PCI iterating on functions >= 4. * grub-core/bus/pci.c (grub_pci_iterate): Remove useless ghost skipping. * include/grub/mips/loongson/pci.h (GRUB_LOONGSON_OHCI_GHOST_FUNCTION): Removed. (GRUB_LOONGSON_EHCI_GHOST_FUNCTION): Likewise. (grub_pci_read): Fix bitmask. (grub_pci_read_word): Likewise. (grub_pci_read_byte): Likewise. (grub_pci_write): Likewise. (grub_pci_write_word): Likewise. (grub_pci_write_byte): Likewise. --- ChangeLog | 15 +++++++++++++++ grub-core/bus/pci.c | 10 ---------- include/grub/mips/loongson/pci.h | 14 ++++++-------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index c2f501c00..cfd46dad7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-08-19 Vladimir Serbinenko + + Fix PCI iterating on functions >= 4. + + * grub-core/bus/pci.c (grub_pci_iterate): Remove useless ghost skipping. + * include/grub/mips/loongson/pci.h (GRUB_LOONGSON_OHCI_GHOST_FUNCTION): + Removed. + (GRUB_LOONGSON_EHCI_GHOST_FUNCTION): Likewise. + (grub_pci_read): Fix bitmask. + (grub_pci_read_word): Likewise. + (grub_pci_read_byte): Likewise. + (grub_pci_write): Likewise. + (grub_pci_write_word): Likewise. + (grub_pci_write_byte): Likewise. + 2011-08-19 Vladimir Serbinenko * configure.ac: Don't impose march=loongson2f on loongson platform. (It diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index 51006a20e..f007ec33a 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -115,16 +115,6 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) continue; } -#ifdef GRUB_MACHINE_MIPS_LOONGSON - /* Skip ghosts. */ - if (id == GRUB_LOONGSON_OHCI_PCIID - && dev.function == GRUB_LOONGSON_OHCI_GHOST_FUNCTION) - continue; - if (id == GRUB_LOONGSON_EHCI_PCIID - && dev.function == GRUB_LOONGSON_EHCI_GHOST_FUNCTION) - continue; -#endif - if (hook (dev, id)) return; diff --git a/include/grub/mips/loongson/pci.h b/include/grub/mips/loongson/pci.h index 3f828c2f8..57c7dd1fc 100644 --- a/include/grub/mips/loongson/pci.h +++ b/include/grub/mips/loongson/pci.h @@ -26,8 +26,6 @@ #define GRUB_LOONGSON_OHCI_PCIID 0x00351033 #define GRUB_LOONGSON_EHCI_PCIID 0x00e01033 -#define GRUB_LOONGSON_OHCI_GHOST_FUNCTION 4 -#define GRUB_LOONGSON_EHCI_GHOST_FUNCTION 5 #define GRUB_PCI_NUM_BUS 1 #define GRUB_PCI_NUM_DEVICES 16 @@ -66,7 +64,7 @@ grub_pci_read (grub_pci_address_t addr) { GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); return *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE - | (addr & 0x03ff)); + | (addr & 0x07ff)); } static inline grub_uint16_t @@ -74,7 +72,7 @@ grub_pci_read_word (grub_pci_address_t addr) { GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); return *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE - | (addr & 0x03ff)); + | (addr & 0x07ff)); } static inline grub_uint8_t @@ -82,7 +80,7 @@ grub_pci_read_byte (grub_pci_address_t addr) { GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); return *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE - | (addr & 0x03ff)); + | (addr & 0x07ff)); } static inline void @@ -90,7 +88,7 @@ grub_pci_write (grub_pci_address_t addr, grub_uint32_t data) { GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE - | (addr & 0x03ff)) = data; + | (addr & 0x07ff)) = data; } static inline void @@ -98,7 +96,7 @@ grub_pci_write_word (grub_pci_address_t addr, grub_uint16_t data) { GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE - | (addr & 0x03ff)) = data; + | (addr & 0x07ff)) = data; } static inline void @@ -106,7 +104,7 @@ grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data) { GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE - | (addr & 0x03ff)) = data; + | (addr & 0x07ff)) = data; } volatile void * From 84beb0eeb95ef792fd1bab516324e62f0fb50b09 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 19 Aug 2011 22:59:24 +0200 Subject: [PATCH 335/673] * grub-core/kern/misc.c (grub_vprintf): Fix a bug on malloc failure. --- ChangeLog | 4 ++++ grub-core/kern/misc.c | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index cfd46dad7..5e45756c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-08-19 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vprintf): Fix a bug on malloc failure. + 2011-08-19 Vladimir Serbinenko Fix PCI iterating on functions >= 4. diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index a3dfabf82..ebf80f100 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -210,6 +210,7 @@ grub_vprintf (const char *fmt, va_list args) buf[PREALLOC_SIZE - 2] = '.'; buf[PREALLOC_SIZE - 1] = '.'; buf[PREALLOC_SIZE] = 0; + curbuf = buf; } else s = grub_vsnprintf_real (curbuf, s, fmt, ap2); From 0d1fd0113ba001d6fd379274e34ff7c3782ee347 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 19 Aug 2011 23:04:18 +0200 Subject: [PATCH 336/673] * include/grub/mips/loongson.h (GRUB_CPU_LOONGSON_COP0_PRID): New define. * grub-core/kern/mips/loongson/init.c (grub_machine_init): Check that PRID matches the detected subplatform and reset the subplatform if it doesn't. --- ChangeLog | 8 ++++++++ grub-core/kern/mips/loongson/init.c | 17 +++++++++++++++++ include/grub/mips/loongson.h | 1 + 3 files changed, 26 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5e45756c8..23283d924 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-08-19 Vladimir Serbinenko + + * include/grub/mips/loongson.h (GRUB_CPU_LOONGSON_COP0_PRID): New + define. + * grub-core/kern/mips/loongson/init.c (grub_machine_init): Check + that PRID matches the detected subplatform and reset the subplatform + if it doesn't. + 2011-08-19 Vladimir Serbinenko * grub-core/kern/misc.c (grub_vprintf): Fix a bug on malloc failure. diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 0e4948beb..7df0ec876 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -123,6 +123,23 @@ void grub_machine_init (void) { grub_addr_t modend; + grub_uint32_t prid; + + asm volatile ("mfc0 %0, " GRUB_CPU_LOONGSON_COP0_PRID : "=r" (prid)); + + switch (prid) + { + /* Loongson 2E. */ + case 0x6302: + grub_arch_machine = GRUB_ARCH_MACHINE_FULOONG2E; + break; + /* Loongson 2F. */ + case 0x6303: + if (grub_arch_machine != GRUB_ARCH_MACHINE_FULOONG2F + && grub_arch_machine != GRUB_ARCH_MACHINE_YEELOONG) + grub_arch_machine = GRUB_ARCH_MACHINE_YEELOONG; + break; + } /* FIXME: measure this. */ if (grub_arch_busclock == 0) diff --git a/include/grub/mips/loongson.h b/include/grub/mips/loongson.h index ce5eb5e3d..e6f0241f2 100644 --- a/include/grub/mips/loongson.h +++ b/include/grub/mips/loongson.h @@ -66,6 +66,7 @@ #define GRUB_CPU_LOONGSON_COP0_BADVADDR GRUB_CPU_REGISTER_WRAP($8) #define GRUB_CPU_LOONGSON_COP0_CAUSE GRUB_CPU_REGISTER_WRAP($13) #define GRUB_CPU_LOONGSON_COP0_EPC GRUB_CPU_REGISTER_WRAP($14) +#define GRUB_CPU_LOONGSON_COP0_PRID GRUB_CPU_REGISTER_WRAP($15) #define GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO GRUB_CPU_REGISTER_WRAP($28) #define GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI GRUB_CPU_REGISTER_WRAP($29) From d94497eacaac10d678f1d4919ac257ce7040c6d8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 19 Aug 2011 23:08:36 +0200 Subject: [PATCH 337/673] * grub-core/Makefile.core.def (kernel): Add video/radeon_fuloong2e.c on loongson. * grub-core/kern/mips/loongson/init.c (grub_machine_init): Init video_radeon_fuloong2e. * grub-core/video/radeon_fuloong2e.c: New file. * include/grub/video.h (grub_video_id_t): Add new ID GRUB_VIDEO_DRIVER_RADEON_FULOONG2E. --- ChangeLog | 10 ++ grub-core/Makefile.core.def | 1 + grub-core/kern/mips/loongson/init.c | 2 + grub-core/video/radeon_fuloong2e.c | 231 ++++++++++++++++++++++++++++ include/grub/video.h | 1 + 5 files changed, 245 insertions(+) create mode 100644 grub-core/video/radeon_fuloong2e.c diff --git a/ChangeLog b/ChangeLog index 23283d924..2bff79544 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-08-19 Vladimir Serbinenko + + * grub-core/Makefile.core.def (kernel): Add video/radeon_fuloong2e.c on + loongson. + * grub-core/kern/mips/loongson/init.c (grub_machine_init): Init + video_radeon_fuloong2e. + * grub-core/video/radeon_fuloong2e.c: New file. + * include/grub/video.h (grub_video_id_t): Add new ID + GRUB_VIDEO_DRIVER_RADEON_FULOONG2E. + 2011-08-19 Vladimir Serbinenko * include/grub/mips/loongson.h (GRUB_CPU_LOONGSON_COP0_PRID): New diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index f129e98db..e95d87d37 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -180,6 +180,7 @@ kernel = { mips_loongson = term/serial.c; mips_loongson = video/sm712.c; mips_loongson = video/sis315pro.c; + mips_loongson = video/radeon_fuloong2e.c; extra_dist = video/sm712_init.c; mips_loongson = commands/keylayouts.c; diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 7df0ec876..5a95d29ed 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -35,6 +35,7 @@ extern void grub_video_sm712_init (void); extern void grub_video_sis315pro_init (void); +extern void grub_video_radeon_fuloong2e_init (void); extern void grub_video_init (void); extern void grub_bitmap_init (void); extern void grub_font_init (void); @@ -206,6 +207,7 @@ grub_machine_init (void) grub_video_init (); grub_video_sm712_init (); grub_video_sis315pro_init (); + grub_video_radeon_fuloong2e_init (); grub_bitmap_init (); grub_font_init (); grub_gfxterm_init (); diff --git a/grub-core/video/radeon_fuloong2e.c b/grub-core/video/radeon_fuloong2e.c new file mode 100644 index 000000000..3a65b6720 --- /dev/null +++ b/grub-core/video/radeon_fuloong2e.c @@ -0,0 +1,231 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,2010,2011 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 . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GRUB_RADEON_FULOONG2E_TOTAL_MEMORY_SPACE 1048576 + +static struct +{ + struct grub_video_mode_info mode_info; + struct grub_video_render_target *render_target; + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +static grub_err_t +grub_video_radeon_fuloong2e_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_radeon_fuloong2e_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + GRUB_RADEON_FULOONG2E_TOTAL_MEMORY_SPACE); + + return grub_video_fb_fini (); +} + +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))) +{ + int depth; + grub_err_t err; + int found = 0; + +#ifndef TEST + auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); + 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 + || 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; + + if ((width != 640 && width != 0) || (height != 480 && height != 0) + || (depth != 16 && depth != 0)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Only 1024x600x16 is supported"); + + grub_pci_iterate (find_card); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); +#endif + /* Fill mode info details. */ + framebuffer.mode_info.width = 640; + framebuffer.mode_info.height = 480; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = 16; + framebuffer.mode_info.bytes_per_pixel = 2; + framebuffer.mode_info.pitch = 640 * 2; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 11; + framebuffer.mode_info.green_mask_size = 6; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; +#ifndef TEST + framebuffer.mode_info.blit_format + = grub_video_get_blit_format (&framebuffer.mode_info); +#endif + + /* We can safely discard volatile attribute. */ +#ifndef TEST + framebuffer.ptr + = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + GRUB_RADEON_FULOONG2E_TOTAL_MEMORY_SPACE); +#endif + framebuffer.mapped = 1; + + /* Prevent garbage from appearing on the screen. */ + grub_memset (framebuffer.ptr, 0x55, + framebuffer.mode_info.height * framebuffer.mode_info.pitch); + +#ifndef TEST + err = grub_video_fb_create_render_target_from_pointer (&framebuffer + .render_target, + &framebuffer.mode_info, + framebuffer.ptr); + + if (err) + return err; + + err = grub_video_fb_set_active_render_target (framebuffer.render_target); + + if (err) + return err; + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); +#endif + return err; +} + +static grub_err_t +grub_video_radeon_fuloong2e_swap_buffers (void) +{ + /* TODO: Implement buffer swapping. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_radeon_fuloong2e_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = framebuffer.render_target; + + return grub_video_fb_set_active_render_target (target); +} + +static grub_err_t +grub_video_radeon_fuloong2e_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); + *framebuf = (char *) framebuffer.ptr; + + grub_video_fb_fini (); + + return GRUB_ERR_NONE; +} + +static struct grub_video_adapter grub_video_radeon_fuloong2e_adapter = + { + .name = "RADEON RV100 QZ (Fuloong2E) Video Driver", + .id = GRUB_VIDEO_DRIVER_RADEON_FULOONG2E, + + .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, + + .init = grub_video_radeon_fuloong2e_video_init, + .fini = grub_video_radeon_fuloong2e_video_fini, + .setup = grub_video_radeon_fuloong2e_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_radeon_fuloong2e_get_info_and_fini, + .set_palette = grub_video_fb_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_radeon_fuloong2e_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_radeon_fuloong2e_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_radeon_fuloong2e) +{ + grub_video_register (&grub_video_radeon_fuloong2e_adapter); +} + +GRUB_MOD_FINI(video_radeon_fuloong2e) +{ + grub_video_unregister (&grub_video_radeon_fuloong2e_adapter); +} diff --git a/include/grub/video.h b/include/grub/video.h index e30589a3d..352544c85 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -282,6 +282,7 @@ typedef enum grub_video_driver_id GRUB_VIDEO_DRIVER_BOCHS, GRUB_VIDEO_DRIVER_SDL, GRUB_VIDEO_DRIVER_SIS315PRO, + GRUB_VIDEO_DRIVER_RADEON_FULOONG2E, } grub_video_driver_id_t; typedef enum grub_video_adapter_prio From f87abff5381b312299b37f3d2a1b9d121e8ff8ff Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 19 Aug 2011 23:11:09 +0200 Subject: [PATCH 338/673] * grub-core/kern/mips/loongson/init.c (grub_reboot): Reboot Fuloong. * include/grub/cs5536.h (GRUB_CS5536_MSR_DIVIL_RESET): New definition. --- ChangeLog | 5 +++++ grub-core/kern/mips/loongson/init.c | 23 +++++++++++++++++++++-- include/grub/cs5536.h | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2bff79544..d8ad1d634 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-19 Vladimir Serbinenko + + * grub-core/kern/mips/loongson/init.c (grub_reboot): Reboot Fuloong. + * include/grub/cs5536.h (GRUB_CS5536_MSR_DIVIL_RESET): New definition. + 2011-08-19 Vladimir Serbinenko * grub-core/Makefile.core.def (kernel): Add video/radeon_fuloong2e.c on diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 5a95d29ed..d1cac7a67 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -269,8 +269,27 @@ grub_exit (void) void grub_reboot (void) { - grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT); - + switch (grub_arch_machine) + { + case GRUB_ARCH_MACHINE_FULOONG2E: + grub_outb (grub_inb (0xbfe00104) & ~4, 0xbfe00104); + grub_outb (grub_inb (0xbfe00104) | 4, 0xbfe00104); + break; + case GRUB_ARCH_MACHINE_FULOONG2F: + { + grub_pci_device_t dev; + if (!grub_cs5536_find (&dev)) + break; + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_RESET, + grub_cs5536_read_msr (dev, + GRUB_CS5536_MSR_DIVIL_RESET) + | 1); + break; + } + case GRUB_ARCH_MACHINE_YEELOONG: + grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT); + break; + } grub_millisleep (1500); grub_printf ("Reboot failed\n"); diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index 103b30633..fcacb23e8 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -77,6 +77,7 @@ #define GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP 0x04000000 #define GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1 0x00070000 #define GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 0x00500000 +#define GRUB_CS5536_MSR_DIVIL_RESET 0x80000017 #define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK 0x80000024 #define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK 0x80000025 #define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002 From 4334690fbf512f5df2de965e8f5a89695734184e Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sat, 20 Aug 2011 02:05:08 +0200 Subject: [PATCH 339/673] More work on LZO for btrfs support. Some fixes and code refactoring. --- ChangeLog.lzo | 11 +++ grub-core/fs/btrfs.c | 176 +++++++++++++++++++++---------------------- 2 files changed, 96 insertions(+), 91 deletions(-) diff --git a/ChangeLog.lzo b/ChangeLog.lzo index 782c6b60d..2ff940e21 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,14 @@ +2011-08-20 Szymon Janc + + More work on LZO for btrfs support. Some fixes and code refactoring. + + * grub-core/fs/btrfs.c (grub_btrfs_superblock): Removed sectorsize, + nodesize, leafsize, stripsize and dummy5 fields. + (grub_btrfs_lzo_decompress): New function. + (grub_btrfs_extent_read): Use grub_btrfs_lzo_decompress for LZO blocks + decompression. + (GRUB_BTRFS_LZO_BLOCK_SIZE): New define. + 2011-08-17 Szymon Janc Add initial support for lzop files decompression. diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 1d24da3e3..7af735630 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -31,6 +31,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_BTRFS_SIGNATURE "_BHRfS_M" +#define GRUB_BTRFS_LZO_BLOCK_SIZE 4096 typedef grub_uint8_t grub_btrfs_checksum_t[0x20]; typedef grub_uint16_t grub_btrfs_uuid_t[8]; @@ -52,15 +53,10 @@ struct grub_btrfs_superblock grub_uint64_t chunk_tree; grub_uint8_t dummy2[0x20]; grub_uint64_t root_dir_objectid; - grub_uint8_t dummy3[0x8]; - grub_uint32_t sectorsize; - grub_uint32_t nodesize; - grub_uint32_t leafsize; - grub_uint32_t stripsize; - grub_uint8_t dummy4[0x29]; + grub_uint8_t dummy3[0x41]; struct grub_btrfs_device this_device; char label[0x100]; - grub_uint8_t dummy5[0x100]; + grub_uint8_t dummy4[0x100]; grub_uint8_t bootstrap_mapping[0x800]; } __attribute__ ((packed)); @@ -884,6 +880,77 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data, return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode)); } +static int +grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, + char *obuf, grub_size_t osize) +{ + grub_uint32_t total_size, cblock_size; + unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE]; + + total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (total_size); + + if (isize < total_size) + return -1; + + while (osize != 0) + { + lzo_uint usize = GRUB_BTRFS_LZO_BLOCK_SIZE; + + cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (cblock_size); + + if (cblock_size > GRUB_BTRFS_LZO_BLOCK_SIZE) + return -1; + + /* Jump forward to first block with requested data. */ + if (off >= GRUB_BTRFS_LZO_BLOCK_SIZE) + { + off -= GRUB_BTRFS_LZO_BLOCK_SIZE; + ibuf += cblock_size; + continue; + } + + /* First block partially filled with requested data. */ + if (off > 0) + { + if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize, + NULL) != LZO_E_OK) + return -1; + + grub_memcpy(obuf, buf + off, usize - off); + + osize -= usize - off; + obuf += usize - off; + ibuf += cblock_size; + off = 0; + continue; + } + + /* 'Main' case, decompress whole block directly to output buffer. */ + if (osize >= GRUB_BTRFS_LZO_BLOCK_SIZE) + { + if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, + (lzo_bytep)obuf, &usize, NULL) != LZO_E_OK) + return -1; + + osize -= usize; + obuf += usize; + ibuf += cblock_size; + } + else /* Last possible block partially filled with requested data. */ + { + if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize, + NULL) != LZO_E_OK) + return -1; + + grub_memcpy(obuf, buf, osize); + break; + } + } + return 0; +} + static grub_ssize_t grub_btrfs_extent_read (struct grub_btrfs_data *data, grub_uint64_t ino, grub_uint64_t tree, @@ -990,39 +1057,11 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, } else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) { - grub_uint32_t total_size, chunk_size; - unsigned char *obuf; - unsigned char *ibuf = (unsigned char *) data->extent->inl; - lzo_uint ocnt = extoff + csize; - int ret; - - obuf = grub_malloc (extoff + csize); - if (!obuf) + if (grub_btrfs_lzo_decompress(data->extent->inl, data->extsize - + ((grub_uint8_t *) data->extent->inl + - (grub_uint8_t *) data->extent), + extoff, buf, csize) < 0) return -1; - - total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); - ibuf += sizeof (total_size); - - chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); - ibuf += sizeof (chunk_size); - - /* Can we have multiple chunks in inline extent? */ - if (chunk_size + (sizeof (grub_uint32_t) * 2) != total_size) - { - grub_free (obuf); - return -1; - } - - ret = lzo1x_decompress_safe (ibuf, chunk_size, obuf, &ocnt, NULL); - - if (ret != LZO_E_OK) - { - grub_free (obuf); - return -1; - } - - grub_memcpy (buf, obuf + extoff, ocnt - extoff); - grub_free (obuf); } else grub_memcpy (buf, data->extent->inl + extoff, csize); @@ -1068,62 +1107,17 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, } else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) { - grub_uint32_t total_size, chunk_size, usize = 0; - grub_size_t off = extoff; - unsigned char *chunk, *ibuf = tmp; - char *obuf = buf; - /* XXX Is this correct size from sblock? */ - grub_uint32_t udata_size = grub_le_to_cpu32 (data->sblock.sectorsize); + int ret ; - chunk = grub_malloc (udata_size); - if (!chunk) - { - grub_free (tmp); - return -1; - } + ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff + + grub_le_to_cpu64 (data->extent->offset), + buf, csize); - /* XXX Use this for some sanity checks while decompressing. */ - total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); - ibuf += sizeof (total_size); + grub_free(tmp); - chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); - ibuf += sizeof (chunk_size); + if (ret < 0) + return -1; - /* Jump to first chunk with requested data. */ - while (off >= udata_size) - { - chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); - ibuf += sizeof (chunk_size); - ibuf += chunk_size; - off -= udata_size; - } - - while (usize < csize) - { - chunk_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); - lzo_uint csize2 = udata_size; - int diff; - - ibuf += sizeof (chunk_size); - - if (lzo1x_decompress_safe (ibuf, chunk_size, chunk, &csize2, NULL) != LZO_E_OK) - { - grub_free (tmp); - grub_free (chunk); - return -1; - } - - diff = grub_min (csize2 - off, csize - usize); - - grub_memcpy (obuf, chunk + off, diff); - obuf += diff; - ibuf += chunk_size; - usize += diff; - off = 0; - } - - grub_free (tmp); - grub_free (chunk); break; } } From a5219af18967bcca59478a4515b36c77caa814bd Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sat, 20 Aug 2011 11:48:46 +0200 Subject: [PATCH 340/673] * grub-core/io/gzio.c (grub_gzio_open): Always return original io if file type was not recognized correctly (not gzip or corrupted). --- ChangeLog | 5 +++++ grub-core/io/gzio.c | 7 ++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index d8ad1d634..17e39bf15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-20 Szymon Janc + + * grub-core/io/gzio.c (grub_gzio_open): Always return original io if + file type was not recognized correctly (not gzip or corrupted). + 2011-08-19 Vladimir Serbinenko * grub-core/kern/mips/loongson/init.c (grub_reboot): Reboot Fuloong. diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 5d3e5332e..7380221aa 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -1179,12 +1179,9 @@ grub_gzio_open (grub_file_t io) grub_free (gzio); grub_free (file); grub_file_seek (io, 0); + grub_errno = GRUB_ERR_NONE; - if (grub_errno == GRUB_ERR_BAD_FILE_TYPE) - { - grub_errno = GRUB_ERR_NONE; - return io; - } + return io; } return file; From fe8d4a7bc207d44170a24534f13355230250dc5b Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sat, 20 Aug 2011 11:58:41 +0200 Subject: [PATCH 341/673] * grub-core/loader/i386/linux.c (grub_linux_setup_video): Add GRUB_VIDEO_DRIVER_RADEON_FULOONG2E to switch case statement. --- ChangeLog | 5 +++++ grub-core/loader/i386/linux.c | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 17e39bf15..742a8cec2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-20 Szymon Janc + + * grub-core/loader/i386/linux.c (grub_linux_setup_video): Add + GRUB_VIDEO_DRIVER_RADEON_FULOONG2E to switch case statement. + 2011-08-20 Szymon Janc * grub-core/io/gzio.c (grub_gzio_open): Always return original io if diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 5356d7ace..fded7bb0a 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -374,6 +374,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) case GRUB_VIDEO_DRIVER_VGA: case GRUB_VIDEO_DRIVER_CIRRUS: case GRUB_VIDEO_DRIVER_BOCHS: + case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E: /* Make gcc happy. */ case GRUB_VIDEO_DRIVER_SDL: case GRUB_VIDEO_DRIVER_NONE: From 7dc3c6863edb827234ec6045026dfc9f2ab9fffd Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sat, 20 Aug 2011 13:04:38 +0200 Subject: [PATCH 342/673] Add grub-fstest option to uncompress data for commands. * util/grub-fstest.c (uncompress): New var. (options): New option -u. --- ChangeLog | 7 +++++++ util/grub-fstest.c | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 742a8cec2..76526f4ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-08-20 Szymon Janc + + Add grub-fstest option to uncompress data for commands. + + * util/grub-fstest.c (uncompress): New var. + (options): New option -u. + 2011-08-20 Szymon Janc * grub-core/loader/i386/linux.c (grub_linux_setup_video): Add diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 972d462da..ad64701a2 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -68,6 +68,7 @@ enum { #define BUF_SIZE 32256 static grub_disk_addr_t skip, leng; +static int uncompress = 0; static void read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) @@ -111,7 +112,8 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) return; } - grub_file_filter_disable_compression (); + if (uncompress == 0) + grub_file_filter_disable_compression (); file = grub_file_open (pathname); if (!file) { @@ -409,6 +411,7 @@ static struct argp_option options[] = { {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, + {"uncompress", 'u', NULL, OPTION_ARG_OPTIONAL, N_("Uncompress data."), 2}, {0, 0, 0, 0, 0, 0} }; @@ -469,6 +472,10 @@ argp_parser (int key, char *arg, struct argp_state *state) verbosity++; return 0; + case 'u': + uncompress = 1; + return 0; + case ARGP_KEY_END: if (args_count < num_disks) { From 9a8d32a24fe7d0a1865be8ae83308cc001d1d091 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sat, 20 Aug 2011 18:24:54 +0200 Subject: [PATCH 343/673] Add support for adler32 checksuming. * grub-core/lib/adler32.c: New file. * Makefile.util.def (library): Add grub-core/lib/adler32.c to common. * util/import_gcry.py (cryptolist): Add adler32. --- ChangeLog.lzo | 8 ++ Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 ++ grub-core/lib/adler32.c | 152 ++++++++++++++++++++++++++++++++++++ util/import_gcry.py | 2 + 5 files changed, 168 insertions(+) create mode 100644 grub-core/lib/adler32.c diff --git a/ChangeLog.lzo b/ChangeLog.lzo index 2ff940e21..d24d913d8 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,11 @@ +2011-08-20 Szymon Janc + + Add support for adler32 checksuming. + + * grub-core/lib/adler32.c: New file. + * Makefile.util.def (library): Add grub-core/lib/adler32.c to common. + * util/import_gcry.py (cryptolist): Add adler32. + 2011-08-20 Szymon Janc More work on LZO for btrfs support. Some fixes and code refactoring. diff --git a/Makefile.util.def b/Makefile.util.def index 3628e48f6..365f718a1 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -91,6 +91,7 @@ library = { common = grub-core/lib/LzFind.c; common = grub-core/lib/LzmaEnc.c; common = grub-core/lib/crc.c; + common = grub-core/lib/adler32.c; common = grub-core/normal/datetime.c; common = grub-core/normal/misc.c; common = grub-core/partmap/acorn.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index fc017b780..77dc7ed4b 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1687,3 +1687,8 @@ module = { common = commands/cacheinfo.c; condition = COND_ENABLE_CACHE_STATS; }; + +module = { + name = adler32; + common = lib/adler32.c; +}; diff --git a/grub-core/lib/adler32.c b/grub-core/lib/adler32.c new file mode 100644 index 000000000..cc40735cb --- /dev/null +++ b/grub-core/lib/adler32.c @@ -0,0 +1,152 @@ +/* adler32.c - adler32 check. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include + +/* Based on adler32() from adler32.c of zlib-1.2.5 library. */ + +#define BASE 65521UL +#define NMAX 5552 + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +static grub_uint32_t +update_adler32 (grub_uint32_t adler, const grub_uint8_t *buf, grub_size_t len) +{ + unsigned long sum2; + unsigned int n; + + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + if (len == 1) + { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + if (len < 16) + { + while (len--) + { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + sum2 %= BASE; + return adler | (sum2 << 16); + } + + while (len >= NMAX) + { + len -= NMAX; + n = NMAX / 16; + do + { + DO16 (buf); + buf += 16; + } + while (--n); + adler %= BASE; + sum2 %= BASE; + } + + if (len) + { + while (len >= 16) + { + len -= 16; + DO16 (buf); + buf += 16; + } + while (len--) + { + adler += *buf++; + sum2 += adler; + } + adler %= BASE; + sum2 %= BASE; + } + + return adler | (sum2 << 16); +} + +typedef struct +{ + grub_uint32_t adler; + grub_uint8_t buf[4]; +} +adler32_context; + +static void +adler32_init (void *context) +{ + adler32_context *ctx = (adler32_context *) context; + ctx->adler = 1; +} + +static void +adler32_write (void *context, const void *inbuf, grub_size_t inlen) +{ + adler32_context *ctx = (adler32_context *) context; + if (!inbuf) + return; + ctx->adler = update_adler32 (ctx->adler, inbuf, inlen); +} + +static grub_uint8_t * +adler32_read (void *context) +{ + adler32_context *ctx = (adler32_context *) context; + return ctx->buf; +} + +static void +adler32_final (void *context __attribute__ ((unused))) +{ +} + +gcry_md_spec_t _gcry_digest_spec_adler32 = { + "ADLER32",0 , 0, 0 , 4, + adler32_init, adler32_write, adler32_final, adler32_read, + sizeof (adler32_context), + .blocksize = 64 +}; + +GRUB_MOD_INIT(adler32) +{ + grub_md_register (&_gcry_digest_spec_adler32); +} + +GRUB_MOD_FINI(adler32) +{ + grub_md_unregister (&_gcry_digest_spec_adler32); +} diff --git a/util/import_gcry.py b/util/import_gcry.py index 727492f10..ee75b1b8e 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -81,6 +81,8 @@ cryptolist.write ("AES-128: gcry_rijndael\n"); cryptolist.write ("AES-192: gcry_rijndael\n"); cryptolist.write ("AES-256: gcry_rijndael\n"); +cryptolist.write ("ADLER32: adler32\n"); + for cipher_file in cipher_files: infile = os.path.join (cipher_dir_in, cipher_file) outfile = os.path.join (cipher_dir_out, cipher_file) From ab178c084a251fe568430f250d9719979957ec53 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sat, 20 Aug 2011 21:10:00 +0200 Subject: [PATCH 344/673] * acinclude.m4: Use AC_LANG_PROGRAM macro to generate source code for AC_LANG_CONFTEST macros. --- ChangeLog | 5 +++++ acinclude.m4 | 16 ++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 76526f4ec..88b883028 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-21 Szymon Janc + + * acinclude.m4: Use AC_LANG_PROGRAM macro to generate source code for + AC_LANG_CONFTEST macros. + 2011-08-20 Szymon Janc Add grub-fstest option to uncompress data for commands. diff --git a/acinclude.m4 b/acinclude.m4 index 7c38155d4..5c623baee 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -316,14 +316,14 @@ fi dnl Check if the C compiler generates calls to `__enable_execute_stack()'. AC_DEFUN([grub_CHECK_ENABLE_EXECUTE_STACK],[ AC_MSG_CHECKING([whether `$CC' generates calls to `__enable_execute_stack()']) -AC_LANG_CONFTEST([[ +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ void f (int (*p) (void)); void g (int i) { int nestedfunc (void) { return i; } f (nestedfunc); } -]]) +]])]) if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then true else @@ -346,7 +346,9 @@ AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[ ssp_possible=yes] AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector']) # Is this a reliable test case? -AC_LANG_CONFTEST([[void foo (void) { volatile char a[8]; a[3]; }]]) +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +void foo (void) { volatile char a[8]; a[3]; } +]])]) [# `$CC -c -o ...' might not be portable. But, oh, well... Is calling # `ac_compile' like this correct, after all? if eval "$ac_compile -S -fstack-protector -o conftest.s" 2> /dev/null; then] @@ -364,7 +366,9 @@ AC_DEFUN([grub_CHECK_STACK_ARG_PROBE],[ [# Smashing stack arg probe. sap_possible=yes] AC_MSG_CHECKING([whether `$CC' accepts `-mstack-arg-probe']) -AC_LANG_CONFTEST([[void foo (void) { volatile char a[8]; a[3]; }]]) +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +void foo (void) { volatile char a[8]; a[3]; } +]])]) [if eval "$ac_compile -S -mstack-arg-probe -o conftest.s" 2> /dev/null; then] AC_MSG_RESULT([yes]) [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'? @@ -399,7 +403,7 @@ AC_DEFUN([grub_CHECK_PIE],[ pie_possible=yes] AC_MSG_CHECKING([whether `$CC' has `-fPIE' as default]) # Is this a reliable test case? -AC_LANG_CONFTEST([[ +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ #ifdef __PIE__ int main() { return 0; @@ -407,7 +411,7 @@ int main() { #else #error NO __PIE__ DEFINED #endif -]]) +]])]) [# `$CC -c -o ...' might not be portable. But, oh, well... Is calling # `ac_compile' like this correct, after all? From 6401c37058fd2ea0ddf187d6a8c2563471dc0252 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 21 Aug 2011 14:49:07 +0200 Subject: [PATCH 345/673] Return correct adler32 value in read() call. --- grub-core/lib/adler32.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/grub-core/lib/adler32.c b/grub-core/lib/adler32.c index cc40735cb..6fb0b00f8 100644 --- a/grub-core/lib/adler32.c +++ b/grub-core/lib/adler32.c @@ -102,7 +102,6 @@ update_adler32 (grub_uint32_t adler, const grub_uint8_t *buf, grub_size_t len) typedef struct { grub_uint32_t adler; - grub_uint8_t buf[4]; } adler32_context; @@ -126,7 +125,7 @@ static grub_uint8_t * adler32_read (void *context) { adler32_context *ctx = (adler32_context *) context; - return ctx->buf; + return (grub_uint8_t *) &ctx->adler; } static void From 90b0a05579001a4474b69f65c98501bb8078a8c3 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sun, 21 Aug 2011 18:48:19 +0200 Subject: [PATCH 346/673] Various bug fixes and improvements in lzopio. Should properly handle more files now. Also added support for lzop checksums verification. --- grub-core/io/lzopio.c | 174 +++++++++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 61 deletions(-) diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index 4ccc41a16..f80d4beb9 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -22,17 +22,15 @@ #include #include #include - +#include #include "minilzo.h" GRUB_MOD_LICENSE ("GPLv3+"); #define LZOP_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" #define LZOP_MAGIC_SIZE 9 -#define CHECK_SIZE 4 -#define NEW_LZO_LIB 0x0940 -#define MIN_HEADER_SIZE 0 -#define MAX_HEADER_SIZE 0 +#define LZOP_CHECK_SIZE 4 +#define LZOP_NEW_LIB 0x0940 /* Header flags - copied from conf.h of LZOP source code. */ #define F_ADLER32_D 0x00000001L @@ -64,8 +62,10 @@ struct block_header struct grub_lzopio { grub_file_t file; - int ucheck; /* XXX Use gcry to validate checks. */ - int ccheck; + int has_ccheck; + int has_ucheck; + const gcry_md_spec_t *ucheck_fun; + const gcry_md_spec_t *ccheck_fun; grub_off_t saved_off; /* Rounded down to block boundary. */ grub_off_t start_block_off; struct block_header block; @@ -74,15 +74,16 @@ struct grub_lzopio typedef struct grub_lzopio *grub_lzopio_t; static struct grub_fs grub_lzopio_fs; -/* Some helper functions. Memory allocated by those function is free either - * on next read_block_header() or on close() so no risk of leaks. This makes - * those function simpler. */ +/* Some helper functions. On errors memory allocated by those function is free + * either on close() so no risk of leaks. This makes functions simpler. */ /* Read block header from file, after successful exit file points to * beginning of block data. */ static int read_block_header (struct grub_lzopio *lzopio) { + lzopio->saved_off += lzopio->block.usize; + /* Free cached block data if any. */ grub_free (lzopio->block.udata); grub_free (lzopio->block.cdata); @@ -113,26 +114,40 @@ read_block_header (struct grub_lzopio *lzopio) lzopio->block.csize = grub_be_to_cpu32 (lzopio->block.csize); - /* XXX Handle incompressible data case here rather than in uncompress_block. - * This will allow to handle switch of ccheck/ucheck easier and also - * make uncompress_block() a bit simpler. */ + /* Corrupted. */ + if (lzopio->block.csize > lzopio->block.usize) + return -1; - /* Read data checks. */ - if (lzopio->ucheck) + /* Read checksum of uncompressed data. */ + if (lzopio->has_ucheck) { if (grub_file_read (lzopio->file, &lzopio->block.ucheck, sizeof (lzopio->block.ucheck)) != sizeof (lzopio->block.ucheck)) return -1; + + lzopio->block.ucheck = grub_be_to_cpu32 (lzopio->block.ucheck); } - if (lzopio->ccheck) + /* Read checksum of compressed data. */ + if (lzopio->has_ccheck) { - if (grub_file_read (lzopio->file, &lzopio->block.ccheck, - sizeof (lzopio->block.ccheck)) != - sizeof (lzopio->block.ccheck)) - return -1; + /* Incompressible data block. */ + if (lzopio->block.csize == lzopio->block.usize) + { + lzopio->block.ccheck = lzopio->block.ucheck; + } + else + { + if (grub_file_read (lzopio->file, &lzopio->block.ccheck, + sizeof (lzopio->block.ccheck)) != + sizeof (lzopio->block.ccheck)) + return -1; + + lzopio->block.ccheck = grub_be_to_cpu32 (lzopio->block.ccheck); + } } + return 0; } @@ -149,9 +164,19 @@ read_block_data (struct grub_lzopio *lzopio) != (grub_ssize_t) lzopio->block.csize) return -1; - if (lzopio->ccheck) + if (lzopio->ccheck_fun) { - /* XXX Validate data checksum here. */ + grub_uint8_t context[lzopio->ccheck_fun->contextsize]; + + lzopio->ccheck_fun->init (context); + lzopio->ccheck_fun->write (context, lzopio->block.cdata, + lzopio->block.csize); + lzopio->ccheck_fun->final (context); + + if (grub_memcmp + (lzopio->ccheck_fun->read (context), &lzopio->block.ccheck, + sizeof (lzopio->block.ccheck)) != 0) + return -1; } return 0; @@ -159,7 +184,7 @@ read_block_data (struct grub_lzopio *lzopio) /* Read block data, uncompressed and also store it in memory. */ /* XXX Investigate possibility of in-place decompression to reduce memory - * footprint. */ + * footprint. Or try to uncompress directly to buf if possible. */ static int uncompress_block (struct grub_lzopio *lzopio) { @@ -168,35 +193,41 @@ uncompress_block (struct grub_lzopio *lzopio) if (read_block_data (lzopio) < 0) return -1; - if (lzopio->block.usize > lzopio->block.csize) - { - lzopio->block.udata = grub_malloc (lzopio->block.usize); - if (!lzopio->block.udata) - return -1; - - if (lzo1x_decompress_safe (lzopio->block.cdata, lzopio->block.csize, - lzopio->block.udata, &usize, - NULL) != LZO_E_OK) - return -1; - - if (lzopio->ucheck) - { - /* XXX Validate data checksum here. */ - } - - /* Compressed data can be free now. */ - grub_free (lzopio->block.cdata); - lzopio->block.cdata = NULL; - } - /* Incompressible block of data. */ - else if (lzopio->block.usize == lzopio->block.csize) + /* Incompressible data. */ + if (lzopio->block.csize == lzopio->block.usize) { lzopio->block.udata = lzopio->block.cdata; lzopio->block.cdata = NULL; } else { - return -1; + lzopio->block.udata = grub_malloc (lzopio->block.usize); + if (!lzopio->block.udata) + return -1; + + if (lzo1x_decompress_safe (lzopio->block.cdata, lzopio->block.csize, + lzopio->block.udata, &usize, NULL) + != LZO_E_OK) + return -1; + + if (lzopio->ucheck_fun) + { + grub_uint8_t context[lzopio->ucheck_fun->contextsize]; + + lzopio->ucheck_fun->init (context); + lzopio->ucheck_fun->write (context, lzopio->block.udata, + lzopio->block.usize); + lzopio->ucheck_fun->final (context); + + if (grub_memcmp + (lzopio->ucheck_fun->read (context), &lzopio->block.ucheck, + sizeof (lzopio->block.ucheck)) != 0) + return -1; + } + + /* Compressed data can be free now. */ + grub_free (lzopio->block.cdata); + lzopio->block.cdata = NULL; } return 0; @@ -215,8 +246,6 @@ jump_block (struct grub_lzopio *lzopio) return -1; } - lzopio->saved_off += lzopio->block.usize; - return read_block_header (lzopio); } @@ -243,7 +272,7 @@ calculate_uncompressed_size (grub_file_t file) return 1; } -/* XXX Do something with this function, it is insane now:) */ +/* XXX Do something with this function... */ static int test_header (grub_file_t file) { @@ -253,6 +282,7 @@ test_header (grub_file_t file) grub_uint8_t method, level, name_len; grub_uint32_t flags, mode, filter, mtime_lo, mtime_hi, checksum; unsigned char *name = NULL; + const gcry_md_spec_t *hcheck; if (grub_file_read (lzopio->file, magic, sizeof (magic)) != sizeof (magic)) { @@ -277,7 +307,7 @@ test_header (grub_file_t file) ver = grub_be_to_cpu16 (ver); - if (ver >= NEW_LZO_LIB) + if (ver >= LZOP_NEW_LIB) { /* Read version of lib needed to extract data. */ if (grub_file_read (lzopio->file, &ver_ext, sizeof (ver_ext)) != @@ -297,7 +327,7 @@ test_header (grub_file_t file) sizeof (method)) goto CORRUPTED; - if (ver >= NEW_LZO_LIB) + if (ver >= LZOP_NEW_LIB) { if (grub_file_read (lzopio->file, &level, sizeof (level)) != sizeof (level)) @@ -310,14 +340,33 @@ test_header (grub_file_t file) flags = grub_be_to_cpu32 (flags); if (flags & F_CRC32_D) - lzopio->ucheck = 1; + { + lzopio->has_ucheck = 1; + lzopio->ucheck_fun = grub_crypto_lookup_md_by_name ("crc32"); + } else if (flags & F_ADLER32_D) - lzopio->ucheck = 2; + { + lzopio->has_ucheck = 1; + lzopio->ucheck_fun = grub_crypto_lookup_md_by_name ("adler32"); + } if (flags & F_CRC32_C) - lzopio->ccheck = 1; + { + lzopio->has_ccheck = 1; + lzopio->ccheck_fun = grub_crypto_lookup_md_by_name ("crc32"); + } else if (flags & F_ADLER32_C) - lzopio->ccheck = 2; + { + lzopio->has_ccheck = 1; + lzopio->ccheck_fun = grub_crypto_lookup_md_by_name ("adler32"); + } + + if (flags & F_H_CRC32) + hcheck = grub_crypto_lookup_md_by_name ("crc32"); + else + hcheck = grub_crypto_lookup_md_by_name ("adler32"); + + hcheck++; if (flags & F_H_FILTER) { @@ -333,7 +382,7 @@ test_header (grub_file_t file) sizeof (mtime_lo)) goto CORRUPTED; - if (ver >= NEW_LZO_LIB) + if (ver >= LZOP_NEW_LIB) { if (grub_file_read (lzopio->file, &mtime_hi, sizeof (mtime_hi)) != sizeof (mtime_hi)) @@ -374,8 +423,6 @@ test_header (grub_file_t file) if (calculate_uncompressed_size (file) < 0) goto CORRUPTED; - lzopio->saved_off = 0; - /* Get back to start block. */ grub_file_seek (lzopio->file, lzopio->start_block_off); @@ -383,6 +430,7 @@ test_header (grub_file_t file) if (read_block_header (lzopio) < 0) goto CORRUPTED; + lzopio->saved_off = 0; return 1; } @@ -439,15 +487,17 @@ grub_lzopio_read (grub_file_t file, char *buf, grub_size_t len) { grub_lzopio_t lzopio = file->data; grub_ssize_t ret = 0; + grub_off_t off; /* Backward seek before last read block. */ if (lzopio->saved_off > grub_file_tell (file)) { - lzopio->saved_off = 0; grub_file_seek (lzopio->file, lzopio->start_block_off); if (read_block_header (lzopio) < 0) goto CORRUPTED; + + lzopio->saved_off = 0; } /* Forward to first block with requested data. */ @@ -461,9 +511,10 @@ grub_lzopio_read (grub_file_t file, char *buf, grub_size_t len) goto CORRUPTED; } + off = grub_file_tell (file) - lzopio->saved_off; + while (len != 0 && lzopio->block.usize != 0) { - grub_off_t off = grub_file_tell (file) - lzopio->saved_off; long to_copy; /* Block not decompressed yet. */ @@ -477,8 +528,9 @@ grub_lzopio_read (grub_file_t file, char *buf, grub_size_t len) len -= to_copy; buf += to_copy; ret += to_copy; + off = 0; - /* Read to next block if needed. */ + /* Read next block if needed. */ if (len > 0 && read_block_header (lzopio) < 0) goto CORRUPTED; } From 1f0e4eed6bdd61b8653625bfb5646bb3d70365be Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 22 Aug 2011 09:18:22 +0200 Subject: [PATCH 347/673] * include/grub/file.h (grub_file_filter_id): Set GRUB_FILE_FILTER_LZOPIO as GRUB_FILE_FILTER_COMPRESSION_LAST. --- ChangeLog.lzo | 5 +++++ include/grub/file.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog.lzo b/ChangeLog.lzo index d24d913d8..e3d08c6da 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,8 @@ +2011-08-22 Szymon Janc + + * include/grub/file.h (grub_file_filter_id): Set + GRUB_FILE_FILTER_LZOPIO as GRUB_FILE_FILTER_COMPRESSION_LAST. + 2011-08-20 Szymon Janc Add support for adler32 checksuming. diff --git a/include/grub/file.h b/include/grub/file.h index 8fe87e6b4..e08ac2e26 100644 --- a/include/grub/file.h +++ b/include/grub/file.h @@ -59,7 +59,7 @@ typedef enum grub_file_filter_id GRUB_FILE_FILTER_LZOPIO, GRUB_FILE_FILTER_MAX, GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO, - GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_XZIO, + GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO, } grub_file_filter_id_t; typedef grub_file_t (*grub_file_filter_t) (grub_file_t in); From 4155e6974ad15f963eff5dfbe03cb36b48c7183b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 23 Aug 2011 11:18:00 +0200 Subject: [PATCH 348/673] * util/grub-install.in: Move cryptodisk logic to appropriate place. --- ChangeLog | 4 ++++ util/grub-install.in | 13 ++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 88b883028..26af06ed3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-08-23 Vladimir Serbinenko + + * util/grub-install.in: Move cryptodisk logic to appropriate place. + 2011-08-21 Szymon Janc * acinclude.m4: Use AC_LANG_PROGRAM macro to generate source code for diff --git a/util/grub-install.in b/util/grub-install.in index f9e1510d1..d11d24421 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -558,11 +558,6 @@ if [ "x${devabstraction_module}" = "x" ] ; then exit 1 fi - if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then - for uuid in "`"${grub_probe}" --device "${device}" --target=cryptodisk_uuid`"; do - echo "cryptomount -u $uuid" - done - fi echo "search.fs_uuid ${uuid} root " >> "${grubdir}/load.cfg" echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg" @@ -577,6 +572,14 @@ if [ "x${devabstraction_module}" = "x" ] ; then fi fi else + if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then + for uuid in "`"${grub_probe}" --device "${grub_device}" --target=cryptodisk_uuid`"; do + echo "cryptomount -u $uuid" >> "${grubdir}/load.cfg" + done + fi + + config_opt="-c ${grubdir}/load.cfg " + prefix_drive=`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"` || exit 1 fi From ab80f326f47e2e83aaf35ac8b05e8b2c7e0966c8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 23 Aug 2011 11:19:26 +0200 Subject: [PATCH 349/673] * grub-core/commands/wildcard.c (make_regex): Handle @. --- ChangeLog | 4 ++++ grub-core/commands/wildcard.c | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 26af06ed3..345f8f4cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-08-23 Vladimir Serbinenko + + * grub-core/commands/wildcard.c (make_regex): Handle @. + 2011-08-23 Vladimir Serbinenko * util/grub-install.in: Move cryptodisk logic to appropriate place. diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index d2f4347d5..256c07e51 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -139,6 +139,7 @@ make_regex (const char *start, const char *end, regex_t *regexp) case '.': case '(': case ')': + case '@': buffer[i++] = '\\'; buffer[i++] = ch; break; From ca51c4a04f4a67fe86bcdbddd899a28ae508f8a4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 23 Aug 2011 11:20:56 +0200 Subject: [PATCH 350/673] * grub-core/kern/mips/loongson/init.c (grub_machine_init): Handle the case of less than 256 MiB of RAM. --- ChangeLog | 5 +++++ grub-core/kern/mips/loongson/init.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 345f8f4cd..ad7dea7c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-23 Vladimir Serbinenko + + * grub-core/kern/mips/loongson/init.c (grub_machine_init): Handle the + case of less than 256 MiB of RAM. + 2011-08-23 Vladimir Serbinenko * grub-core/commands/wildcard.c (make_regex): Handle @. diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index d1cac7a67..2d1a0653e 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -188,7 +188,7 @@ grub_machine_init (void) } else { - grub_arch_memsize = (totalmem >> 20); + grub_arch_memsize = totalmem; grub_arch_highmemsize = 0; } From 00b98c9b2ef86d4cc4254dd163798388fc1f4d52 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 23 Aug 2011 19:49:01 +0200 Subject: [PATCH 351/673] * grub-core/fs/btrfs.c (grub_btrfs_lzo_decompress): Random fixes and some cleanup. --- grub-core/fs/btrfs.c | 120 ++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 64 deletions(-) diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 7af735630..ae1ce1c7d 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -31,7 +31,17 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_BTRFS_SIGNATURE "_BHRfS_M" + +/* From http://www.oberhumer.com/opensource/lzo/lzofaq.php + * LZO will expand incompressible data by a little amount. I still haven't + * computed the exact values, but I suggest using these formulas for + * a worst-case expansion calculation: + * + * output_block_size = input_block_size + (input_block_size / 16) + 64 + 3 + * */ #define GRUB_BTRFS_LZO_BLOCK_SIZE 4096 +#define GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE (GRUB_BTRFS_LZO_BLOCK_SIZE + \ + (GRUB_BTRFS_LZO_BLOCK_SIZE / 16) + 64 + 3) typedef grub_uint8_t grub_btrfs_checksum_t[0x20]; typedef grub_uint16_t grub_btrfs_uuid_t[8]; @@ -880,11 +890,11 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data, return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode)); } -static int +static grub_ssize_t grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, char *obuf, grub_size_t osize) { - grub_uint32_t total_size, cblock_size; + grub_uint32_t total_size, cblock_size, uncompressed = 0; unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE]; total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); @@ -893,62 +903,54 @@ grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, if (isize < total_size) return -1; - while (osize != 0) + /* Jump forward to first block with requested data. */ + while (off >= GRUB_BTRFS_LZO_BLOCK_SIZE) + { + cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); + ibuf += sizeof (cblock_size); + + off -= GRUB_BTRFS_LZO_BLOCK_SIZE; + ibuf += cblock_size; + } + + while (osize > 0) { lzo_uint usize = GRUB_BTRFS_LZO_BLOCK_SIZE; cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); ibuf += sizeof (cblock_size); - if (cblock_size > GRUB_BTRFS_LZO_BLOCK_SIZE) - return -1; - - /* Jump forward to first block with requested data. */ - if (off >= GRUB_BTRFS_LZO_BLOCK_SIZE) + /* Block partially filled with requested data. */ + if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE) { - off -= GRUB_BTRFS_LZO_BLOCK_SIZE; - ibuf += cblock_size; - continue; - } + grub_size_t to_copy = grub_min(osize, GRUB_BTRFS_LZO_BLOCK_SIZE - off); - /* First block partially filled with requested data. */ - if (off > 0) - { if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize, NULL) != LZO_E_OK) return -1; - grub_memcpy(obuf, buf + off, usize - off); + grub_memcpy(obuf, buf + off, to_copy); - osize -= usize - off; - obuf += usize - off; + osize -= to_copy; + uncompressed += to_copy; + obuf += to_copy; ibuf += cblock_size; off = 0; continue; } /* 'Main' case, decompress whole block directly to output buffer. */ - if (osize >= GRUB_BTRFS_LZO_BLOCK_SIZE) - { - if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, - (lzo_bytep)obuf, &usize, NULL) != LZO_E_OK) - return -1; + if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, (lzo_bytep)obuf, + &usize, NULL) != LZO_E_OK) + return -1; - osize -= usize; - obuf += usize; - ibuf += cblock_size; - } - else /* Last possible block partially filled with requested data. */ - { - if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize, - NULL) != LZO_E_OK) - return -1; - - grub_memcpy(obuf, buf, osize); - break; - } + osize -= usize; + uncompressed += usize; + obuf += usize; + ibuf += cblock_size; } - return 0; + + return uncompressed; } static grub_ssize_t @@ -1060,7 +1062,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, if (grub_btrfs_lzo_decompress(data->extent->inl, data->extsize - ((grub_uint8_t *) data->extent->inl - (grub_uint8_t *) data->extent), - extoff, buf, csize) < 0) + extoff, buf, csize) + != (grub_ssize_t) csize) return -1; } else @@ -1075,8 +1078,10 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE) { - void *tmp; + char *tmp; grub_uint64_t zsize; + grub_ssize_t ret; + zsize = grub_le_to_cpu64 (data->extent->compressed_size); tmp = grub_malloc (zsize); if (!tmp) @@ -1091,36 +1096,23 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, } if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB) - { - grub_ssize_t ret; - - ret = grub_zlib_decompress (tmp, zsize, extoff - + grub_le_to_cpu64 (data->extent->offset), - buf, csize); - - grub_free (tmp); - - if (ret != (grub_ssize_t) csize) - return -1; - - break; - } - else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) - { - int ret ; - - ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff + ret = grub_zlib_decompress (tmp, zsize, extoff + grub_le_to_cpu64 (data->extent->offset), buf, csize); + else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) + ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff + + grub_le_to_cpu64 (data->extent->offset), + buf, csize); + else + ret = -1; - grub_free(tmp); + grub_free(tmp); - if (ret < 0) - return -1; + if (ret != (grub_ssize_t) csize) + return -1; - break; - } - } + break; + } err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (data->extent->laddr) + grub_le_to_cpu64 (data->extent->offset) From ec543969bf07fbe60423ece81b29cd315116388b Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 23 Aug 2011 19:53:49 +0200 Subject: [PATCH 352/673] * Makefile.util.def (libgrubmods.a): Add grub-core/io/lzopio.c to common. --- ChangeLog.lzo | 5 +++++ Makefile.util.def | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog.lzo b/ChangeLog.lzo index e3d08c6da..ef6145061 100644 --- a/ChangeLog.lzo +++ b/ChangeLog.lzo @@ -1,3 +1,8 @@ +2011-08-23 Szymon Janc + + * Makefile.util.def (libgrubmods.a): Add grub-core/io/lzopio.c to + common. + 2011-08-22 Szymon Janc * include/grub/file.h (grub_file_filter_id): Set diff --git a/Makefile.util.def b/Makefile.util.def index 365f718a1..1fe4f2464 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -109,6 +109,7 @@ library = { common = grub-core/script/script.c; common = grub-core/script/argv.c; common = grub-core/io/gzio.c; + common = grub-core/io/lzopio.c; common = grub-core/kern/ia64/dl_helper.c; common = grub-core/lib/minilzo/minilzo.c; }; From 579c12fbb4b757fc26cb6fcbe265250f734eaf68 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 24 Aug 2011 11:24:10 +0200 Subject: [PATCH 353/673] * grub-core/fs/btrfs.c: Some minor cleanups. --- grub-core/fs/btrfs.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index ae1ce1c7d..534ce15de 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -894,7 +894,7 @@ static grub_ssize_t grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, char *obuf, grub_size_t osize) { - grub_uint32_t total_size, cblock_size, uncompressed = 0; + grub_uint32_t total_size, cblock_size, ret = 0; unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE]; total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); @@ -909,6 +909,9 @@ grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); ibuf += sizeof (cblock_size); + if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE) + return -1; + off -= GRUB_BTRFS_LZO_BLOCK_SIZE; ibuf += cblock_size; } @@ -920,6 +923,9 @@ grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); ibuf += sizeof (cblock_size); + if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE) + return -1; + /* Block partially filled with requested data. */ if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE) { @@ -929,28 +935,29 @@ grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, NULL) != LZO_E_OK) return -1; + to_copy = grub_min(to_copy, usize); grub_memcpy(obuf, buf + off, to_copy); osize -= to_copy; - uncompressed += to_copy; + ret += to_copy; obuf += to_copy; ibuf += cblock_size; off = 0; continue; } - /* 'Main' case, decompress whole block directly to output buffer. */ + /* Decompress whole block directly to output buffer. */ if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, (lzo_bytep)obuf, &usize, NULL) != LZO_E_OK) return -1; osize -= usize; - uncompressed += usize; + ret += usize; obuf += usize; ibuf += cblock_size; } - return uncompressed; + return ret; } static grub_ssize_t From 2221ab6c62fdd6473f1ae4f147739b585fde8e1b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 5 Sep 2011 13:58:33 +0100 Subject: [PATCH 354/673] * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Return 1 for */README* as well as README*. Reported by: Axel Beckert. --- ChangeLog | 6 ++++++ util/grub-mkconfig_lib.in | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ad7dea7c8..c84aa30aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-09-05 Colin Watson + + * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Return 1 for + */README* as well as README*. + Reported by: Axel Beckert. + 2011-08-23 Vladimir Serbinenko * grub-core/kern/mips/loongson/init.c (grub_machine_init): Handle the diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 901b5752f..a453a6bb5 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -157,7 +157,7 @@ grub_file_is_not_garbage () if test -f "$1" ; then case "$1" in *.dpkg-*) return 1 ;; # debian dpkg - README*) return 1 ;; # documentation + README*|*/README*) return 1 ;; # documentation esac else return 1 From 9c4f9ca010ddf432c7c83cdabaf36c7a4b956cd6 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 6 Sep 2011 21:21:13 +0200 Subject: [PATCH 355/673] * grub-core/io/lzopio.c (test_header): Some cleanups. --- grub-core/io/lzopio.c | 177 +++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 96 deletions(-) diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index f80d4beb9..e303b29a3 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -272,72 +272,60 @@ calculate_uncompressed_size (grub_file_t file) return 1; } -/* XXX Do something with this function... */ +struct lzop_header +{ + grub_uint8_t magic[LZOP_MAGIC_SIZE]; + grub_uint16_t lzop_version; + grub_uint16_t lib_version; + grub_uint16_t lib_version_ext; + grub_uint8_t method; + grub_uint8_t level; + grub_uint32_t flags; + /* grub_uint32_t filter; */ /* No filters support. Rarely used anyway. */ + grub_uint32_t mode; + grub_uint32_t mtime_lo; + grub_uint32_t mtime_hi; + grub_uint8_t name_len; +} __attribute__ ((packed)); + static int test_header (grub_file_t file) { grub_lzopio_t lzopio = file->data; - unsigned char magic[LZOP_MAGIC_SIZE]; - grub_uint16_t lzopver, ver, ver_ext; - grub_uint8_t method, level, name_len; - grub_uint32_t flags, mode, filter, mtime_lo, mtime_hi, checksum; - unsigned char *name = NULL; + struct lzop_header header; + grub_uint32_t flags, checksum; const gcry_md_spec_t *hcheck; + grub_uint8_t *context = NULL; + grub_uint8_t *name = NULL; - if (grub_file_read (lzopio->file, magic, sizeof (magic)) != sizeof (magic)) + if (grub_file_read (lzopio->file, &header, sizeof (header)) != sizeof (header)) { grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found"); return 0; } - if (grub_memcmp (magic, LZOP_MAGIC, LZOP_MAGIC_SIZE) != 0) + if (grub_memcmp (header.magic, LZOP_MAGIC, LZOP_MAGIC_SIZE) != 0) { grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found"); return 0; } - /* LZOP version. */ - if (grub_file_read (lzopio->file, &lzopver, sizeof (lzopver)) != - sizeof (lzopver)) - goto CORRUPTED; - - /* LZO lib version. */ - if (grub_file_read (lzopio->file, &ver, sizeof (ver)) != sizeof (ver)) - goto CORRUPTED; - - ver = grub_be_to_cpu16 (ver); - - if (ver >= LZOP_NEW_LIB) + if (grub_be_to_cpu16(header.lib_version) < LZOP_NEW_LIB) { - /* Read version of lib needed to extract data. */ - if (grub_file_read (lzopio->file, &ver_ext, sizeof (ver_ext)) != - sizeof (ver_ext)) - goto CORRUPTED; - - /* Too new version, should upgrade minilzo? */ - if (grub_be_to_cpu16 (ver_ext) > MINILZO_VERSION) - { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, - "unsupported LZO version"); - return 0; - } + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "unsupported (too old) LZOP version"); + return 0; } - if (grub_file_read (lzopio->file, &method, sizeof (method)) != - sizeof (method)) - goto CORRUPTED; - - if (ver >= LZOP_NEW_LIB) + /* Too new version, should upgrade minilzo? */ + if (grub_be_to_cpu16 (header.lib_version_ext) > MINILZO_VERSION) { - if (grub_file_read (lzopio->file, &level, sizeof (level)) != - sizeof (level)) - goto CORRUPTED; + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "unsupported (too new) LZO version"); + return 0; } - if (grub_file_read (lzopio->file, &flags, sizeof (flags)) != sizeof (flags)) - goto CORRUPTED; - - flags = grub_be_to_cpu32 (flags); + flags = grub_be_to_cpu32 (header.flags); if (flags & F_CRC32_D) { @@ -366,76 +354,73 @@ test_header (grub_file_t file) else hcheck = grub_crypto_lookup_md_by_name ("adler32"); - hcheck++; + if (hcheck) { + context = grub_malloc(hcheck->contextsize); + if (! context) + return 0; - if (flags & F_H_FILTER) + hcheck->init(context); + + /* MAGIC is not included in check calculation. */ + hcheck->write(context, &header.lzop_version, sizeof(header)- LZOP_MAGIC_SIZE); + } + + if (header.name_len != 0) { - if (grub_file_read (lzopio->file, &filter, sizeof (filter)) != - sizeof (filter)) - goto CORRUPTED; - } - - if (grub_file_read (lzopio->file, &mode, sizeof (mode)) != sizeof (mode)) - goto CORRUPTED; - - if (grub_file_read (lzopio->file, &mtime_lo, sizeof (mtime_lo)) != - sizeof (mtime_lo)) - goto CORRUPTED; - - if (ver >= LZOP_NEW_LIB) - { - if (grub_file_read (lzopio->file, &mtime_hi, sizeof (mtime_hi)) != - sizeof (mtime_hi)) - goto CORRUPTED; - } - - if (grub_file_read (lzopio->file, &name_len, sizeof (name_len)) != - sizeof (name_len)) - goto CORRUPTED; - - if (name_len != 0) - { - name = grub_malloc (name_len); - if (!name) - return 0; - - if (grub_file_read (lzopio->file, name, name_len) != name_len) + name = grub_malloc (header.name_len); + if (! name) { - grub_free (name); + grub_free (context); + return 0; + } + + if (grub_file_read (lzopio->file, name, header.name_len) != + header.name_len) + { + grub_free(name); goto CORRUPTED; } + + if (hcheck) + hcheck->write(context, name, header.name_len); + + grub_free(name); } + if (hcheck) + hcheck->final(context); + if (grub_file_read (lzopio->file, &checksum, sizeof (checksum)) != sizeof (checksum)) - { - grub_free (name); + goto CORRUPTED; + + if (hcheck) + { + checksum = grub_cpu_to_be32(checksum); + if (memcmp(&checksum, hcheck->read(context), sizeof(checksum)) != 0) goto CORRUPTED; - } + } - grub_free (name); + lzopio->start_block_off = grub_file_tell (lzopio->file); - /* XXX Validate header checksum here. */ - if (checksum == checksum) - { - lzopio->start_block_off = grub_file_tell (lzopio->file); + if (calculate_uncompressed_size (file) < 0) + goto CORRUPTED; - if (calculate_uncompressed_size (file) < 0) - goto CORRUPTED; + /* Get back to start block. */ + grub_file_seek (lzopio->file, lzopio->start_block_off); - /* Get back to start block. */ - grub_file_seek (lzopio->file, lzopio->start_block_off); + /* Read first block - grub_lzopio_read() expects valid block. */ + if (read_block_header (lzopio) < 0) + goto CORRUPTED; - /* Read first block - grub_lzopio_read() expects valid block. */ - if (read_block_header (lzopio) < 0) - goto CORRUPTED; - - lzopio->saved_off = 0; - return 1; - } + lzopio->saved_off = 0; + return 1; CORRUPTED: grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "lzop file corrupted"); + + grub_free(name); + return 0; } From 1a7d7db97f34d0c38dd64655ef944b4cf0768ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Sutre?= Date: Sat, 17 Sep 2011 23:01:48 +0200 Subject: [PATCH 356/673] Get sector size from disk label for NetBSD. --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c84aa30aa..1acdce29e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-09-17 Grégoire Sutre + + * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__NetBSD__]: + Get sector size from disk label. + 2011-09-05 Colin Watson * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Return 1 for diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 000ef2f79..b4c4eef7c 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -265,10 +265,13 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (ioctl (fd, DIOCGSECTORSIZE, §or_size)) + goto fail; +# elif defined(__NetBSD__) + sector_size = label.d_secsize; # else if (ioctl (fd, BLKSSZGET, §or_size)) -# endif goto fail; +# endif if (sector_size & (sector_size - 1) || !sector_size) goto fail; From 20fd15f9db1e5379d264e29f0f28e0b96391bf95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Sutre?= Date: Sat, 17 Sep 2011 23:40:10 +0200 Subject: [PATCH 357/673] Add LIBUTIL for grub-mkrelpath and grub-fstest. Fixes build on NetBSD. --- ChangeLog | 6 ++++++ Makefile.util.def | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1acdce29e..a454f2f84 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-09-17 Grégoire Sutre + + * Makefile.util.def (grub-mkrelpath): Add LIBUTIL for getrawpartition(3) + on NetBSD. + * Makefile.util.def (grub-fstest): Likewise. + 2011-09-17 Grégoire Sutre * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__NetBSD__]: diff --git a/Makefile.util.def b/Makefile.util.def index d86cb9761..713729c55 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -147,7 +147,7 @@ program = { ldadd = libgrubgcry.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; program = { @@ -226,7 +226,7 @@ program = { ldadd = libgrubgcry.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; program = { From 69915030942771f6813ebc238e86e05b5112f3b5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 28 Sep 2011 14:07:53 +0200 Subject: [PATCH 358/673] * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Return 0 if disk isn't biosdisk. --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index a454f2f84..9d19fe450 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-09-28 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): + Return 0 if disk isn't biosdisk. + 2011-09-17 Grégoire Sutre * Makefile.util.def (grub-mkrelpath): Add LIBUTIL for getrawpartition(3) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index b4c4eef7c..a9a8c066e 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1841,6 +1841,9 @@ grub_util_biosdisk_is_floppy (grub_disk_t disk) struct stat st; int fd; + if (disk->dev != &grub_util_biosdisk_dev) + return 0; + fd = open (map[disk->id].device, O_RDONLY); /* Shouldn't happen. */ if (fd == -1) From 2ded951ef70998ebebabd7b73d1a6bf0006a93d7 Mon Sep 17 00:00:00 2001 From: Andreas Born Date: Wed, 28 Sep 2011 14:19:21 +0200 Subject: [PATCH 359/673] Fix incorrect identifiers in bash-completion. * util/bash-completion.d/grub-completion.bash.in (_grub_mkpasswd-pbkdf2): Rename to ... (_grub_mkpasswd_pbkdf2): ... this. All users updated. (_grub_script-check): Rename to ... (_grub_script_check): ... this. All users updated. --- ChangeLog | 10 ++++++++++ util/bash-completion.d/grub-completion.bash.in | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9d19fe450..5cc753c11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-09-28 Andreas Born + + Fix incorrect identifiers in bash-completion. + + * util/bash-completion.d/grub-completion.bash.in + (_grub_mkpasswd-pbkdf2): Rename to ... + (_grub_mkpasswd_pbkdf2): ... this. All users updated. + (_grub_script-check): Rename to ... + (_grub_script_check): ... this. All users updated. + 2011-09-28 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in index 65cbb80ee..64d49fe0b 100644 --- a/util/bash-completion.d/grub-completion.bash.in +++ b/util/bash-completion.d/grub-completion.bash.in @@ -402,7 +402,7 @@ unset __grub_mkimage_program # # grub-mkpasswd-pbkdf2 # -_grub_mkpasswd-pbkdf2 () { +_grub_mkpasswd_pbkdf2 () { local cur COMPREPLY=() @@ -417,7 +417,7 @@ _grub_mkpasswd-pbkdf2 () { } __grub_mkpasswd_pbkdf2_program=$( echo grub-mkpasswd-pbkdf2 | sed "@program_transform_name@" ) have ${__grub_mkpasswd_pbkdf2_program} && \ - complete -F _grub_mkpasswd-pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program} + complete -F _grub_mkpasswd_pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program} unset __grub_mkpasswd_pbkdf2_program @@ -462,7 +462,7 @@ unset __grub_probe_program # # grub-script-check # -_grub_script-check () { +_grub_script_check () { local cur COMPREPLY=() @@ -477,7 +477,7 @@ _grub_script-check () { } __grub_script_check_program=$( echo grub-script-check | sed "@program_transform_name@" ) have ${__grub_script_check_program} && \ - complete -F _grub_script-check -o filenames ${__grub_script_check_program} + complete -F _grub_script_check -o filenames ${__grub_script_check_program} # Local variables: From 91a1a164d66dfdeb4d36ac5bc4f39f62e4aee58f Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 28 Sep 2011 16:43:00 +0200 Subject: [PATCH 360/673] * grub-core/loader/multiboot_elfxx.c (Elf_Shdr): Set according to loader. --- ChangeLog | 5 +++++ grub-core/loader/multiboot_elfxx.c | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5cc753c11..d415a4bcd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-09-28 Thomas Haller + + * grub-core/loader/multiboot_elfxx.c (Elf_Shdr): Set according to + loader. + 2011-09-28 Andreas Born Fix incorrect identifiers in bash-completion. diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c index 0c29fe9c2..c6c88f177 100644 --- a/grub-core/loader/multiboot_elfxx.c +++ b/grub-core/loader/multiboot_elfxx.c @@ -22,12 +22,14 @@ # define ELFCLASSXX ELFCLASS32 # define Elf_Ehdr Elf32_Ehdr # define Elf_Phdr Elf32_Phdr +# define Elf_Shdr Elf32_Shdr #elif defined(MULTIBOOT_LOAD_ELF64) # define XX 64 # define E_MACHINE MULTIBOOT_ELF64_MACHINE # define ELFCLASSXX ELFCLASS64 # define Elf_Ehdr Elf64_Ehdr # define Elf_Phdr Elf64_Phdr +# define Elf_Shdr Elf64_Shdr #else #error "I'm confused" #endif @@ -223,3 +225,4 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) #undef ELFCLASSXX #undef Elf_Ehdr #undef Elf_Phdr +#undef Elf_Shdr From e0b0dc837b9717842584623126577c74c2dd65d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Sutre?= Date: Wed, 28 Sep 2011 23:45:57 +0200 Subject: [PATCH 361/673] Make knetbsd pass bootinfo bootdisk and bootwedge. --- ChangeLog | 12 +++++ grub-core/loader/i386/bsd.c | 84 +++++++++++++++++++++++++++++ include/grub/bsdlabel.h | 5 +- include/grub/i386/netbsd_bootinfo.h | 11 ++++ 4 files changed, 111 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d415a4bcd..8cdd158cd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-09-28 Grégoire Sutre + + * include/grub/bsdlabel.h (grub_partition_bsd_disk_label): Add fields + type and packname. + * include/grub/i386/netbsd_bootinfo.h (NETBSD_BTINFO_BOOTDISK): + Resurrected. + (NETBSD_BTINFO_BOOTWEDGE): New definition. + (grub_netbsd_btinfo_bootwedge): New struct. + * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): + New function. + (grub_cmd_netbsd): Call grub_netbsd_add_boot_disk_and_wedge. + 2011-09-28 Thomas Haller * grub-core/loader/multiboot_elfxx.c (Elf_Shdr): Set according to diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index dffe48257..18ebeb760 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -946,6 +948,86 @@ grub_netbsd_add_modules (void) return err; } +/* + * Adds NetBSD bootinfo bootdisk and bootwedge. The partition identified + * in these bootinfo fields is the root device. + */ +static void +grub_netbsd_add_boot_disk_and_wedge (void) +{ + grub_device_t dev; + grub_disk_t disk; + grub_partition_t part; + grub_uint32_t biosdev; + grub_uint32_t partmapsector; + struct grub_partition_bsd_disk_label *label; + grub_uint64_t buf[GRUB_DISK_SECTOR_SIZE / 8]; + grub_uint8_t *hash; + grub_uint64_t ctx[(GRUB_MD_MD5->contextsize + 7) / 8]; + + dev = grub_device_open (0); + if (! (dev && dev->disk && dev->disk->partition)) + goto fail; + + disk = dev->disk; + part = disk->partition; + + if (disk->dev && disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID) + biosdev = (grub_uint32_t) disk->id & 0xff; + else + biosdev = 0xff; + + /* Absolute sector of the partition map describing this partition. */ + partmapsector = grub_partition_get_start (part->parent) + part->offset; + + disk->partition = part->parent; + if (grub_disk_read (disk, part->offset, 0, GRUB_DISK_SECTOR_SIZE, buf) != GRUB_ERR_NONE) + goto fail; + disk->partition = part; + + /* Fill bootwedge. */ + { + struct grub_netbsd_btinfo_bootwedge biw; + + grub_memset (&biw, 0, sizeof (biw)); + biw.biosdev = biosdev; + biw.startblk = grub_partition_get_start (part); + biw.nblks = part->len; + biw.matchblk = partmapsector; + biw.matchnblks = 1; + + GRUB_MD_MD5->init (&ctx); + GRUB_MD_MD5->write (&ctx, buf, GRUB_DISK_SECTOR_SIZE); + GRUB_MD_MD5->final (&ctx); + hash = GRUB_MD_MD5->read (&ctx); + memcpy (biw.matchhash, hash, 16); + + grub_bsd_add_meta (NETBSD_BTINFO_BOOTWEDGE, &biw, sizeof (biw)); + } + + /* Fill bootdisk if this a NetBSD disk label. */ + label = (struct grub_partition_bsd_disk_label *) &buf; + if (part->partmap != NULL && + (grub_strcmp (part->partmap->name, "netbsd") == 0) && + label->magic == grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) + { + struct grub_netbsd_btinfo_bootdisk bid; + + grub_memset (&bid, 0, sizeof (bid)); + bid.labelsector = partmapsector; + bid.label.type = label->type; + bid.label.checksum = label->checksum; + memcpy (bid.label.packname, label->packname, 16); + bid.biosdev = biosdev; + bid.partition = part->number; + grub_bsd_add_meta (NETBSD_BTINFO_BOOTDISK, &bid, sizeof (bid)); + } + +fail: + if (dev) + grub_device_close (dev); +} + static grub_err_t grub_netbsd_boot (void) { @@ -1607,6 +1689,8 @@ grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) grub_bsd_add_meta (NETBSD_BTINFO_CONSOLE, &cons, sizeof (cons)); } + grub_netbsd_add_boot_disk_and_wedge (); + grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 0); } diff --git a/include/grub/bsdlabel.h b/include/grub/bsdlabel.h index 636bd41a1..b10336c01 100644 --- a/include/grub/bsdlabel.h +++ b/include/grub/bsdlabel.h @@ -80,7 +80,10 @@ struct grub_partition_bsd_entry struct grub_partition_bsd_disk_label { grub_uint32_t magic; - grub_uint8_t padding[128]; + grub_uint16_t type; + grub_uint8_t unused1[18]; + grub_uint8_t packname[16]; + grub_uint8_t unused2[92]; grub_uint32_t magic2; grub_uint16_t checksum; grub_uint16_t num_partitions; diff --git a/include/grub/i386/netbsd_bootinfo.h b/include/grub/i386/netbsd_bootinfo.h index fd429a251..228f26aaa 100644 --- a/include/grub/i386/netbsd_bootinfo.h +++ b/include/grub/i386/netbsd_bootinfo.h @@ -51,9 +51,11 @@ #define NETBSD_BTINFO_BOOTPATH 0 #define NETBSD_BTINFO_ROOTDEVICE 1 +#define NETBSD_BTINFO_BOOTDISK 3 #define NETBSD_BTINFO_CONSOLE 6 #define NETBSD_BTINFO_SYMTAB 8 #define NETBSD_BTINFO_MEMMAP 9 +#define NETBSD_BTINFO_BOOTWEDGE 10 #define NETBSD_BTINFO_MODULES 11 #define NETBSD_BTINFO_FRAMEBUF 12 @@ -83,6 +85,15 @@ struct grub_netbsd_btinfo_bootdisk grub_uint32_t partition; }; +struct grub_netbsd_btinfo_bootwedge { + grub_uint32_t biosdev; + grub_disk_addr_t startblk; + grub_uint64_t nblks; + grub_disk_addr_t matchblk; + grub_uint64_t matchnblks; + grub_uint8_t matchhash[16]; /* MD5 hash */ +} __packed; + struct grub_netbsd_btinfo_symtab { grub_uint32_t nsyms; From cca7ccd8ff3bd697110c8f55b9e30b78662235f8 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 29 Sep 2011 10:32:24 +0200 Subject: [PATCH 362/673] Remove extra declaration of sleep for mingw32. * util/misc.c (sleep) [__MINGW32__]: Removed. * include/grub/util/misc.h (sleep) [__MINGW32__]: Likewise. --- ChangeLog | 7 +++++++ include/grub/util/misc.h | 1 - util/misc.c | 5 ----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8cdd158cd..6e4aac746 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-09-29 Mario Limonciello + + Remove extra declaration of sleep for mingw32. + + * util/misc.c (sleep) [__MINGW32__]: Removed. + * include/grub/util/misc.h (sleep) [__MINGW32__]: Likewise. + 2011-09-28 Grégoire Sutre * include/grub/bsdlabel.h (grub_partition_bsd_disk_label): Add fields diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 48dfbb868..419c8661c 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -47,7 +47,6 @@ void grub_util_write_image_at (const void *img, size_t size, off_t offset, void sync (void); int fsync (int fno); -void sleep(int s); grub_int64_t grub_util_get_disk_size (char *name); diff --git a/util/misc.c b/util/misc.c index cfbae609b..e4425358a 100644 --- a/util/misc.c +++ b/util/misc.c @@ -316,11 +316,6 @@ int fsync (int fno __attribute__ ((unused))) return 0; } -void sleep (int s) -{ - Sleep (s * 1000); -} - grub_int64_t grub_util_get_disk_size (char *name) { From c05de0329b198bed24e8b8e120877958d9a8cead Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 29 Sep 2011 10:36:55 +0200 Subject: [PATCH 363/673] * grub-core/kern/emu/misc.c (canonicalize_file_name) [__MINGW32__]: Use _fullpath. --- ChangeLog | 5 +++++ grub-core/kern/emu/misc.c | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6e4aac746..bc5508d32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-09-29 Mario Limonciello + + * grub-core/kern/emu/misc.c (canonicalize_file_name) [__MINGW32__]: Use + _fullpath. + 2011-09-29 Mario Limonciello Remove extra declaration of sleep for mingw32. diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 737f5f1a9..6f5ea9fb9 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -224,7 +224,11 @@ char * canonicalize_file_name (const char *path) { char *ret; -#ifdef PATH_MAX +#ifdef __MINGW32__ + ret = xmalloc (PATH_MAX); + if (!_fullpath (ret, path, PATH_MAX)) + return NULL; +#elif defined (PATH_MAX) ret = xmalloc (PATH_MAX); if (!realpath (path, ret)) return NULL; From d1ab689de800eb4a7d66306c96d9dd4f502cf4e5 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Thu, 29 Sep 2011 10:39:44 +0200 Subject: [PATCH 364/673] * util/misc.c (grub_util_get_disk_size) [__MINGW32__]: Strip trailing slashes on PHYSICALDRIVE%d paths when making Windows CreateFile calls. --- ChangeLog | 5 +++++ util/misc.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index bc5508d32..df31ef3e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-09-29 Mario Limonciello + + * util/misc.c (grub_util_get_disk_size) [__MINGW32__]: Strip trailing + slashes on PHYSICALDRIVE%d paths when making Windows CreateFile calls. + 2011-09-29 Mario Limonciello * grub-core/kern/emu/misc.c (canonicalize_file_name) [__MINGW32__]: Use diff --git a/util/misc.c b/util/misc.c index e4425358a..72bedde0c 100644 --- a/util/misc.c +++ b/util/misc.c @@ -55,6 +55,7 @@ #ifdef __MINGW32__ #include #include +#include "dirname.h" #endif #ifdef GRUB_UTIL @@ -322,6 +323,7 @@ grub_util_get_disk_size (char *name) HANDLE hd; grub_int64_t size = -1LL; + strip_trailing_slashes(name); hd = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); From fc5efcc08346469bb9f4bbb3c3f0b3f4b8c5b4b6 Mon Sep 17 00:00:00 2001 From: Mads Kiilerich Date: Thu, 29 Sep 2011 10:50:25 +0200 Subject: [PATCH 365/673] * grub-core/Makefile.core.def (kernel): Add kern/i386/int.S to extra_dist. --- ChangeLog | 5 +++++ grub-core/Makefile.core.def | 1 + 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index df31ef3e3..db2e0b1f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-09-29 Mads Kiilerich + + * grub-core/Makefile.core.def (kernel): Add kern/i386/int.S to + extra_dist. + 2011-09-29 Mario Limonciello * util/misc.c (grub_util_get_disk_size) [__MINGW32__]: Strip trailing diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index e95d87d37..e9e4f06d8 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -219,6 +219,7 @@ kernel = { videoinkernel = commands/boot.c; + extra_dist = kern/i386/int.S; extra_dist = kern/i386/realmode.S; extra_dist = kern/i386/pc/lzma_decode.S; extra_dist = kern/mips/cache_flush.S; From 8667a314babe5f09580d06d86a3db6489cdcc31e Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Fri, 30 Sep 2011 18:49:37 -0700 Subject: [PATCH 366/673] * gentpl.py: Use Autogen macros so that the output template file (Makefile.tpl) size is reduced. --- ChangeLog | 5 +++ gentpl.py | 114 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 105 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index db2e0b1f6..ad0e6792f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-08-25 BVK Chaitanya + + * gentpl.py: Use Autogen macros so that the output template file + (Makefile.tpl) size is reduced. + 2011-09-29 Mads Kiilerich * grub-core/Makefile.core.def (kernel): Add kern/i386/int.S to diff --git a/gentpl.py b/gentpl.py index e431293eb..cb6b663d9 100644 --- a/gentpl.py +++ b/gentpl.py @@ -183,6 +183,17 @@ def foreach_platform_specific_value(platform, suffix, nonetag, closure): r += "[+ ELSE +][+ FOR " + nonetag + " +]" + closure("[+ ." + nonetag + " +]") + "[+ ENDFOR +][+ ENDIF +]" return r +# +# Returns autogen code that defines an autogen macro using the +# definition given in the 'snippet'. +# +def define_autogen_macro(name, snippet): + r = "" + r += "[+ DEFINE " + name + " +]" + r += snippet + r += "[+ ENDDEF +]\n" + return r + # # Template for handling values from sum of all groups for a platform, # for example: @@ -245,10 +256,18 @@ def foreach_enabled_platform(closure): # emu_condition = COND_GRUB_EMU_USB; # }; # +def define_macro_for_platform_conditionals_if_statement(p): + return define_autogen_macro( + "if_" + p + "_conditionals", + foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n")) +def define_macro_for_platform_conditionals_endif_statement(p): + return define_autogen_macro( + "endif_" + p + "_conditionals", + foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n")) def under_platform_specific_conditionals(platform, snippet): - r = foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n") + r = "[+ if_" + platform + "_conditionals +]" r += snippet - r += foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n") + r += "[+ endif_" + platform + "_conditionals +]" return r def platform_specific_values(platform, suffix, nonetag): @@ -261,18 +280,69 @@ def platform_values(platform, suffix): def extra_dist(): return foreach_value("extra_dist", lambda value: value + " ") -def platform_sources(p): return platform_values(p, "") -def platform_nodist_sources(p): return platform_values(p, "_nodist") -def platform_dependencies(p): return platform_values(p, "dependencies", "_dependencies") +def define_macro_for_platform_sources(p): + return define_autogen_macro( + "get_" + p + "_sources", + platform_values(p, "")) +def define_macro_for_platform_nodist_sources(p): + return define_autogen_macro( + "get_" + p + "_nodist_sources", + platform_values(p, "_nodist")) +def define_macro_for_platform_dependencies(p): + return define_autogen_macro( + "get_" + p + "_dependencies", + platform_values(p, "dependencies", "_dependencies")) +def platform_sources(p): return "[+ get_" + p + "_sources +]" +def platform_nodist_sources(p): return "[+ get_" + p + "_nodist_sources +]" +def platform_dependencies(p): return "[+ get_" + p + "_dependencies +]" -def platform_startup(p): return platform_specific_values(p, "_startup", "startup") -def platform_ldadd(p): return platform_specific_values(p, "_ldadd", "ldadd") -def platform_cflags(p): return platform_specific_values(p, "_cflags", "cflags") -def platform_ldflags(p): return platform_specific_values(p, "_ldflags", "ldflags") -def platform_cppflags(p): return platform_specific_values(p, "_cppflags", "cppflags") -def platform_ccasflags(p): return platform_specific_values(p, "_ccasflags", "ccasflags") -def platform_stripflags(p): return platform_specific_values(p, "_stripflags", "stripflags") -def platform_objcopyflags(p): return platform_specific_values(p, "_objcopyflags", "objcopyflags") +# +# Returns Autogen code which defines the autogen macros that collect +# platform specific values for cflags, ldflags, etc. tags. +# +def define_macro_for_platform_startup(p): + return define_autogen_macro( + "get_" + p + "_startup", + platform_specific_values(p, "_startup", "startup")) +def define_macro_for_platform_cflags(p): + return define_autogen_macro( + "get_" + p + "_cflags", + platform_specific_values(p, "_cflags", "cflags")) +def define_macro_for_platform_ldadd(p): + return define_autogen_macro( + "get_" + p + "_ldadd", + platform_specific_values(p, "_ldadd", "ldadd")) +def define_macro_for_platform_ldflags(p): + return define_autogen_macro( + "get_" + p + "_ldflags", + platform_specific_values(p, "_ldflags", "ldflags")) +def define_macro_for_platform_cppflags(p): + return define_autogen_macro( + "get_" + p + "_cppflags", + platform_specific_values(p, "_cppflags", "cppflags")) +def define_macro_for_platform_ccasflags(p): + return define_autogen_macro( + "get_" + p + "_ccasflags", + platform_specific_values(p, "_ccasflags", "ccasflags")) +def define_macro_for_platform_stripflags(p): + return define_autogen_macro( + "get_" + p + "_stripflags", + platform_specific_values(p, "_stripflags", "stripflags")) +def define_macro_for_platform_objcopyflags(p): + return define_autogen_macro( + "get_" + p + "_objcopyflags", + platform_specific_values(p, "_objcopyflags", "objcopyflags")) +# +# Autogen calls to invoke the above macros. +# +def platform_startup(p): return "[+ get_" + p + "_startup +]" +def platform_ldadd(p): return "[+ get_" + p + "_ldadd +]" +def platform_cflags(p): return "[+ get_" + p + "_cflags +]" +def platform_ldflags(p): return "[+ get_" + p + "_ldflags +]" +def platform_cppflags(p): return "[+ get_" + p + "_cppflags +]" +def platform_ccasflags(p): return "[+ get_" + p + "_ccasflags +]" +def platform_stripflags(p): return "[+ get_" + p + "_stripflags +]" +def platform_objcopyflags(p): return "[+ get_" + p + "_objcopyflags +]" # # Emit snippet only the first time through for the current name. @@ -489,7 +559,6 @@ def script_rules(): def data_rules(): return rules("data", data) -print "[+ AutoGen5 template +]\n" a = module_rules() b = kernel_rules() c = image_rules() @@ -499,6 +568,23 @@ f = script_rules() g = data_rules() z = global_variable_initializers() +print "[+ AutoGen5 template +]\n" +for p in GRUB_PLATFORMS: + print define_macro_for_platform_sources(p) + print define_macro_for_platform_nodist_sources(p) + # print define_macro_for_platform_dependencies(p) + + print define_macro_for_platform_startup(p) + print define_macro_for_platform_cflags(p) + print define_macro_for_platform_ldadd(p) + print define_macro_for_platform_ldflags(p) + print define_macro_for_platform_cppflags(p) + print define_macro_for_platform_ccasflags(p) + print define_macro_for_platform_stripflags(p) + print define_macro_for_platform_objcopyflags(p) + + print define_macro_for_platform_conditionals_if_statement(p) + print define_macro_for_platform_conditionals_endif_statement(p) # print z # initializer for all vars print a print b From ce79cc99d500a92c927a15647d0c86bde6d0448c Mon Sep 17 00:00:00 2001 From: starous Date: Sat, 1 Oct 2011 21:27:29 +0200 Subject: [PATCH 367/673] @Rock changes - fixed coreboot problem --- ChangeLog | 5 +++++ grub-core/bus/usb/uhci.c | 48 +++++++++++++++++++++++++++++++++++----- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index ad0e6792f..5d1fc0c69 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-01 Ales Nesrsta + + * grub-core/bus/usb/uhci.c: Changes made by Rock Cui - thanks! + (fixed problem related to using UHCI with coreboot). + 2011-08-25 BVK Chaitanya * gentpl.py: Use Autogen macros so that the output template file diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index 99e597f6d..260b7e876 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -36,11 +36,33 @@ GRUB_MOD_LICENSE ("GPLv3+"); typedef enum { GRUB_UHCI_REG_USBCMD = 0x00, + GRUB_UHCI_REG_USBINTR = 0x04, GRUB_UHCI_REG_FLBASEADD = 0x08, GRUB_UHCI_REG_PORTSC1 = 0x10, - GRUB_UHCI_REG_PORTSC2 = 0x12 + GRUB_UHCI_REG_PORTSC2 = 0x12, + GRUB_UHCI_REG_USBLEGSUP = 0xc0 } grub_uhci_reg_t; +/* R/WC legacy support bits */ +#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15) +#define GRUB_UHCI_TRAP_BY_64H_WSTAT (1 << 11) +#define GRUB_UHCI_TRAP_BY_64H_RSTAT (1 << 10) +#define GRUB_UHCI_TRAP_BY_60H_WSTAT (1 << 9) +#define GRUB_UHCI_TRAP_BY_60H_RSTAT (1 << 8) + +/* Reset all legacy support - clear all R/WC bits and all R/W bits */ +#define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \ + | GRUB_UHCI_TRAP_BY_64H_WSTAT \ + | GRUB_UHCI_TRAP_BY_64H_RSTAT \ + | GRUB_UHCI_TRAP_BY_60H_WSTAT \ + | GRUB_UHCI_TRAP_BY_60H_RSTAT ) + +/* Some UHCI commands */ +#define GRUB_UHCI_CMD_RUN_STOP (1 << 0) +#define GRUB_UHCI_CMD_HCRESET (1 << 1) +#define GRUB_UHCI_CMD_MAXP (1 << 7) + +/* Important bits in structures */ #define GRUB_UHCI_LINK_TERMINATE 1 #define GRUB_UHCI_LINK_QUEUE_HEAD 2 @@ -181,6 +203,11 @@ grub_uhci_pci_iter (grub_pci_device_t dev, if (class != 0x0c || subclass != 0x03 || interf != 0x00) return 0; + /* Set bus master - needed for coreboot or broken BIOSes */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word(addr, + GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr)); + /* Determine IO base address. */ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4); base = grub_pci_read (addr); @@ -195,6 +222,19 @@ grub_uhci_pci_iter (grub_pci_device_t dev, u->iobase = base & GRUB_UHCI_IOMASK; + /* Reset PIRQ and SMI */ + addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP); + grub_pci_write_word(addr, GRUB_UHCI_RESET_LEGSUP_SMI); + /* Reset the HC */ + grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET); + grub_millisleep(5); + /* Disable interrupts and commands (just to be safe) */ + grub_uhci_writereg16(u, GRUB_UHCI_REG_USBINTR, 0); + /* Finish HC reset, HC remains disabled */ + grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, 0); + /* Read back to be sure PCI write is done */ + grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD); + /* Reserve a page for the frame list. */ u->framelist = grub_memalign (4096, 4096); if (! u->framelist) @@ -252,9 +292,6 @@ grub_uhci_pci_iter (grub_pci_device_t dev, u->td[N_TD - 2].linkptr = 0; u->tdfree = u->td; - /* Make sure UHCI is disabled! */ - grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0); - /* Setup the frame list pointers. Since no isochronous transfers are and will be supported, they all point to the (same!) queue head. */ @@ -285,7 +322,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev, u->qh[N_QH - 1].linkptr = 1; /* Enable UHCI again. */ - grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7)); + grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, + GRUB_UHCI_CMD_RUN_STOP | GRUB_UHCI_CMD_MAXP); /* UHCI is initialized and ready for transfers. */ grub_dprintf ("uhci", "UHCI initialized\n"); From 139d67a82fb1738e642424e2d425916d97c8e098 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 3 Oct 2011 21:50:32 +0200 Subject: [PATCH 368/673] * grub-core/fs/btrfs.c: Fix code style regressions. --- grub-core/fs/btrfs.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 534ce15de..5b8dca559 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -330,8 +330,8 @@ next (struct grub_btrfs_data *data, for (; desc->depth > 0; desc->depth--) { desc->data[desc->depth - 1].iter++; - if (desc->data[desc->depth - 1].iter < - desc->data[desc->depth - 1].maxiter) + if (desc->data[desc->depth - 1].iter + < desc->data[desc->depth - 1].maxiter) break; } if (desc->depth == 0) @@ -376,7 +376,7 @@ lower_bound (struct grub_btrfs_data *data, const struct grub_btrfs_key *key_in, struct grub_btrfs_key *key_out, grub_disk_addr_t root, - grub_disk_addr_t * outaddr, grub_size_t * outsize, + grub_disk_addr_t *outaddr, grub_size_t *outsize, struct grub_btrfs_leaf_descriptor *desc) { grub_disk_addr_t addr = root; @@ -626,8 +626,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, grub_le_to_cpu64 (key->offset), grub_le_to_cpu64 (chunk->size)); if (grub_le_to_cpu64 (key->offset) <= addr - && addr < - grub_le_to_cpu64 (key->offset) + grub_le_to_cpu64 (chunk->size)) + && addr < grub_le_to_cpu64 (key->offset) + + grub_le_to_cpu64 (chunk->size)) goto chunk_found; ptr += sizeof (*key) + sizeof (*chunk) + sizeof (struct grub_btrfs_chunk_stripe) @@ -1007,8 +1007,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size); if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR - && (char *) &data->extent + elemsize >= - (char *) &data->extent->filled + sizeof (data->extent->filled)) + && (char *) &data->extent + elemsize + >= (char *) &data->extent->filled + sizeof (data->extent->filled)) data->extend = data->extstart + grub_le_to_cpu64 (data->extent->filled); @@ -1113,7 +1113,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, else ret = -1; - grub_free(tmp); + grub_free (tmp); if (ret != (grub_ssize_t) csize) return -1; @@ -1142,7 +1142,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, static grub_err_t find_path (struct grub_btrfs_data *data, const char *path, struct grub_btrfs_key *key, - grub_uint64_t * tree, grub_uint8_t * type) + grub_uint64_t *tree, grub_uint8_t *type) { const char *slash = path; grub_err_t err; @@ -1391,7 +1391,7 @@ find_path (struct grub_btrfs_data *data, static grub_err_t grub_btrfs_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, - const struct grub_dirhook_info * info)) + const struct grub_dirhook_info *info)) { struct grub_btrfs_data *data = grub_btrfs_mount (device); struct grub_btrfs_key key_in, key_out; From c5ed9266fc216a2c62781b87d6a4ff97315a70f0 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 3 Oct 2011 22:06:10 +0200 Subject: [PATCH 369/673] * grub-core/io/lzopio.c: Improve crypt context alignment. --- grub-core/io/lzopio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index e303b29a3..d804c31b0 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -166,7 +166,7 @@ read_block_data (struct grub_lzopio *lzopio) if (lzopio->ccheck_fun) { - grub_uint8_t context[lzopio->ccheck_fun->contextsize]; + grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8]; lzopio->ccheck_fun->init (context); lzopio->ccheck_fun->write (context, lzopio->block.cdata, @@ -212,7 +212,7 @@ uncompress_block (struct grub_lzopio *lzopio) if (lzopio->ucheck_fun) { - grub_uint8_t context[lzopio->ucheck_fun->contextsize]; + grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8]; lzopio->ucheck_fun->init (context); lzopio->ucheck_fun->write (context, lzopio->block.udata, From 0e2b7e39f2e2d9089efb307d9e58aedf3e5b1c57 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 3 Oct 2011 22:25:06 +0200 Subject: [PATCH 370/673] * grub-core/fs/btrfs.c: Include instead of "minilzo.h". * grub-core/io/lzopio.c: Likewise. --- grub-core/fs/btrfs.c | 2 +- grub-core/io/lzopio.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 5b8dca559..93642f789 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -26,7 +26,7 @@ #include #include #include -#include "minilzo.h" +#include GRUB_MOD_LICENSE ("GPLv3+"); diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index d804c31b0..e2bbf79b7 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -23,7 +23,7 @@ #include #include #include -#include "minilzo.h" +#include GRUB_MOD_LICENSE ("GPLv3+"); From b871e8ebcca01098727b1bc324e490b8de5a5a1b Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Mon, 3 Oct 2011 23:01:14 +0200 Subject: [PATCH 371/673] * grub-core/Makefile.core.def (btrfs): Remove minilzo.c from common. --- grub-core/Makefile.core.def | 1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 77dc7ed4b..b58a75f67 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -980,7 +980,6 @@ module = { name = btrfs; common = fs/btrfs.c; common = lib/crc.c; - common = lib/minilzo/minilzo.c; cflags = '$(CFLAGS_POSIX) -Wno-undef'; cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; }; From bc4d3f4809353539891a04bc218ff7ef37cb2536 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Tue, 4 Oct 2011 21:10:21 +0200 Subject: [PATCH 372/673] * grub-core/io/lzopio.c (calculate_uncompressed_size): Fix return code. --- grub-core/io/lzopio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index e2bbf79b7..02a70f4d8 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -256,7 +256,7 @@ calculate_uncompressed_size (grub_file_t file) grub_off_t usize_total = 0; if (read_block_header (lzopio) < 0) - return 0; + return -1; /* FIXME: Don't do this for not easily seekable files. */ while (lzopio->block.usize != 0) @@ -264,12 +264,12 @@ calculate_uncompressed_size (grub_file_t file) usize_total += lzopio->block.usize; if (jump_block (lzopio) < 0) - return 0; + return -1; } file->size = usize_total; - return 1; + return 0; } struct lzop_header From 805448e987bc4327ee654e4a439922827c1f3b6b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 10:21:32 +0200 Subject: [PATCH 373/673] Add network functions for grub-menulst2cfg --- grub-core/lib/legacy_parse.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 659fa7061..e3f4864ce 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -42,7 +42,8 @@ struct legacy_command TYPE_BOOL, TYPE_INT, TYPE_REST_VERBATIM, - TYPE_VBE_MODE + TYPE_VBE_MODE, + TYPE_WITH_CONFIGFILE_OPTION } argt[4]; enum { FLAG_IGNORE_REST = 0x001, @@ -64,7 +65,13 @@ static struct legacy_command legacy_commands[] = "Print the blocklist notation of the file FILE."}, {"boot", "boot\n", NULL, 0, 0, {}, 0, 0, "Boot the OS/chain-loader which has been loaded."}, - /* FIXME: bootp unsupported. */ + {"bootp", "net_bootp; net_ls_addr; if [ x%s = x--with-configfile ]; then " + "if net_get_dhcp_option configfile_name pxe 150 string; then " + "configfile $configfile_name; fi; fi\n", NULL, 0, 1, + {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", + "Initialize a network device via BOOTP. If the option `--with-configfile'" + " is given, try to load a configuration file specified by the 150 vendor" + " tag."}, {"cat", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Print the contents of the file FILE."}, {"chainloader", "chainloader %s '%s'\n", NULL, 0, @@ -102,7 +109,13 @@ static struct legacy_command legacy_commands[] = "[NUM | `saved']", "Set the default entry to entry number NUM (if not specified, it is" " 0, the first entry) or the entry number saved by savedefault."}, - /* FIXME: dhcp unsupported. */ + {"dhcp", "net_bootp; net_ls_addr; if [ x%s = x--with-configfile ]; then " + "if net_get_dhcp_option configfile_name pxe 150 string; then " + "configfile $configfile_name; fi; fi\n", NULL, 0, 1, + {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", + "Initialize a network device via BOOTP. If the option `--with-configfile'" + " is given, try to load a configuration file specified by the 150 vendor" + " tag."}, {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0, "Display APM BIOS information."}, {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, @@ -411,6 +424,8 @@ is_option (enum arg_type opt, const char *curarg, grub_size_t len) { switch (opt) { + case TYPE_WITH_CONFIGFILE_OPTION: + return check_option (curarg, "--with-configfile", len); case TYPE_NOAPM_OPTION: return check_option (curarg, "--no-apm", len); case TYPE_FORCE_OPTION: @@ -662,6 +677,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) case TYPE_VERBATIM: args[i] = grub_legacy_escape (curarg, curarglen); break; + case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: @@ -756,6 +772,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) case TYPE_FILE: case TYPE_REST_VERBATIM: case TYPE_VERBATIM: + case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: From 5c62099a8fade900d47e4c75378605a2b0a461b9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 10:22:23 +0200 Subject: [PATCH 374/673] Fix warning on i386-pc --- grub-core/net/drivers/i386/pc/pxe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 6c5f2fdc4..3343533ef 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -169,7 +169,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused))) { struct grub_pxe_undi_isr *isr; static int in_progress = 0; - char *ptr, *end; + grub_uint8_t *ptr, *end; struct grub_net_buff *buf; isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; From fe942b7dbb891a3f092acdb63a63ee0376cb5cba Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 11:53:36 +0200 Subject: [PATCH 375/673] * grub-core/Makefile.core.def: Eliminate rarely used emu_condition. This in perspective decreases the complexity of build system and fixes compilation right now. --- grub-core/Makefile.core.def | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index e9e4f06d8..3b701633c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -400,11 +400,15 @@ module = { module = { name = usb; common = bus/usb/usb.c; - noemu = bus/usb/usbtrans.c; - noemu = bus/usb/usbhub.c; - enable = emu; + common = bus/usb/usbtrans.c; + common = bus/usb/usbhub.c; enable = usb; - emu_condition = COND_GRUB_EMU_USB; +}; + +module = { + name = emuusb; + common = bus/usb/usb.c; + condition = COND_GRUB_EMU_USB; }; module = { @@ -439,18 +443,22 @@ module = { module = { name = pci; - noemu = bus/pci.c; - emu = bus/emu/pci.c; - emu = commands/lspci.c; + common = bus/pci.c; - enable = emu; enable = i386_pc; enable = i386_efi; enable = x86_64_efi; enable = i386_ieee1275; enable = i386_coreboot; enable = i386_multiboot; - emu_condition = COND_GRUB_EMU_PCI; +}; + +module = { + name = emupci; + common = bus/emu/pci.c; + common = commands/lspci.c; + + condition = COND_GRUB_EMU_PCI; }; module = { @@ -788,8 +796,6 @@ module = { name = usbtest; common = commands/usbtest.c; enable = usb; - enable = emu; - emu_condition = COND_GRUB_EMU_USB; }; module = { @@ -903,8 +909,6 @@ module = { name = usbms; common = disk/usbms.c; enable = usb; - enable = emu; - emu_condition = COND_GRUB_EMU_USB; }; module = { @@ -1446,9 +1450,7 @@ module = { common = term/serial.c; x86 = term/ns8250.c; - enable = emu; enable = x86; - emu_condition = COND_GRUB_EMU_USB; }; module = { From 4f71e077b92f521c3ec9b8d75d3fc37be57b5d55 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 17:39:13 +0200 Subject: [PATCH 376/673] HTTP seek support. Various bugfixes. --- grub-core/net/http.c | 177 ++++++++++++++++++++++++++++++----------- grub-core/net/net.c | 72 +++++++++++------ grub-core/net/tcp.c | 55 ++++++++++--- include/grub/net.h | 1 + include/grub/net/tcp.h | 9 ++- 5 files changed, 231 insertions(+), 83 deletions(-) diff --git a/grub-core/net/http.c b/grub-core/net/http.c index b5de4c5c6..e4664757c 100644 --- a/grub-core/net/http.c +++ b/grub-core/net/http.c @@ -42,7 +42,11 @@ typedef struct http_data grub_size_t current_line_len; int headers_recv; int first_line_recv; + int size_recv; grub_net_tcp_socket_t sock; + char *filename; + grub_err_t err; + char *errmsg; } *http_data_t; static grub_err_t @@ -72,19 +76,25 @@ parse_line (http_data_t data, char *ptr, grub_size_t len) { case 200: break; + case 404: + data->err = GRUB_ERR_FILE_NOT_FOUND; + data->errmsg = grub_xasprintf ("file `%s' not found", data->filename); + return GRUB_ERR_NONE; default: - return grub_error (GRUB_ERR_NET_UNKNOWN_ERROR, - "unsupported HTTP error %d: %s", - code, ptr); + data->err = GRUB_ERR_NET_UNKNOWN_ERROR; + data->errmsg = grub_xasprintf ("unsupported HTTP error %d: %s", + code, ptr); + return GRUB_ERR_NONE; } data->first_line_recv = 1; return GRUB_ERR_NONE; } if (grub_memcmp (ptr, "Content-Length: ", sizeof ("Content-Length: ") - 1) - == 0) + == 0 && !data->size_recv) { ptr += sizeof ("Content-Length: ") - 1; data->file_size = grub_strtoull (ptr, &ptr, 10); + data->size_recv = 1; return GRUB_ERR_NONE; } return GRUB_ERR_NONE; @@ -98,10 +108,10 @@ http_err (grub_net_tcp_socket_t sock __attribute__ ((unused)), http_data_t data = file->data; if (data->sock) - grub_net_tcp_close (data->sock); - grub_free (data); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); if (data->current_line) grub_free (data->current_line); + grub_free (data); file->device->net->eof = 1; } @@ -132,7 +142,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), if (!t) { grub_netbuff_free (nb); - grub_net_tcp_close (data->sock); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); return grub_errno; } @@ -151,7 +161,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), data->current_line_len = 0; if (err) { - grub_net_tcp_close (data->sock); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); grub_netbuff_free (nb); return err; } @@ -167,7 +177,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), if (!data->current_line) { grub_netbuff_free (nb); - grub_net_tcp_close (data->sock); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); return grub_errno; } data->current_line_len = (char *) nb->tail - ptr; @@ -178,7 +188,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), err = parse_line (data, ptr, ptr2 - ptr); if (err) { - grub_net_tcp_close (data->sock); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); grub_netbuff_free (nb); return err; } @@ -191,7 +201,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), err = grub_netbuff_pull (nb, ptr - (char *) nb->data); if (err) { - grub_net_tcp_close (data->sock); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); grub_netbuff_free (nb); return err; } @@ -203,57 +213,51 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), } static grub_err_t -http_open (struct grub_file *file, const char *filename) +http_establish (struct grub_file *file, grub_off_t offset, int initial) { - struct grub_net_buff *nb; - http_data_t data; - grub_err_t err; + http_data_t data = file->data; grub_uint8_t *ptr; int i; - - data = grub_zalloc (sizeof (*data)); - if (!data) - return grub_errno; + struct grub_net_buff *nb; + grub_err_t err; nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE + sizeof ("GET ") - 1 - + grub_strlen (filename) + + grub_strlen (data->filename) + sizeof (" HTTP/1.1\r\nHost: ") - 1 + grub_strlen (file->device->net->server) + sizeof ("\r\nUser-Agent: " PACKAGE_STRING - "\r\n\r\n") - 1); + "\r\n") - 1 + + sizeof ("Content-Range: bytes XXXXXXXXXXXXXXXXXXXX" + "-XXXXXXXXXXXXXXXXXXXX/" + "XXXXXXXXXXXXXXXXXXXX\r\n\r\n")); if (!nb) - { - grub_free (data); - return grub_errno; - } + return grub_errno; grub_netbuff_reserve (nb, GRUB_NET_TCP_RESERVE_SIZE); ptr = nb->tail; err = grub_netbuff_put (nb, sizeof ("GET ") - 1); if (err) { - grub_free (data); grub_netbuff_free (nb); return err; } grub_memcpy (ptr, "GET ", sizeof ("GET ") - 1); ptr = nb->tail; - err = grub_netbuff_put (nb, grub_strlen (filename)); + + err = grub_netbuff_put (nb, grub_strlen (data->filename)); if (err) { - grub_free (data); grub_netbuff_free (nb); return err; } - grub_memcpy (ptr, filename, grub_strlen (filename)); + grub_memcpy (ptr, data->filename, grub_strlen (data->filename)); ptr = nb->tail; err = grub_netbuff_put (nb, sizeof (" HTTP/1.1\r\nHost: ") - 1); if (err) { - grub_free (data); grub_netbuff_free (nb); return err; } @@ -264,7 +268,6 @@ http_open (struct grub_file *file, const char *filename) err = grub_netbuff_put (nb, grub_strlen (file->device->net->server)); if (err) { - grub_free (data); grub_netbuff_free (nb); return err; } @@ -273,19 +276,30 @@ http_open (struct grub_file *file, const char *filename) ptr = nb->tail; err = grub_netbuff_put (nb, - sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n") + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") - 1); if (err) { - grub_free (data); grub_netbuff_free (nb); return err; } - grub_memcpy (ptr, "\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n", - sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n\r\n") - 1); - - file->not_easily_seekable = 1; - file->data = data; + grub_memcpy (ptr, "\r\nUser-Agent: " PACKAGE_STRING "\r\n", + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") - 1); + if (!initial) + { + ptr = nb->tail; + grub_snprintf ((char *) ptr, + sizeof ("Content-Range: bytes XXXXXXXXXXXXXXXXXXXX-" + "XXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXX\r\n" + "\r\n"), + "Content-Range: bytes %" PRIuGRUB_UINT64_T "-%" + PRIuGRUB_UINT64_T "/%" PRIuGRUB_UINT64_T "\r\n\r\n", + offset, data->file_size - 1, data->file_size); + grub_netbuff_put (nb, grub_strlen ((char *) ptr)); + } + ptr = nb->tail; + grub_netbuff_put (nb, 2); + grub_memcpy (ptr, "\r\n", 2); data->sock = grub_net_tcp_open (file->device->net->server, HTTP_PORT, http_receive, @@ -293,7 +307,6 @@ http_open (struct grub_file *file, const char *filename) file); if (!data->sock) { - grub_free (data); grub_netbuff_free (nb); return grub_errno; } @@ -303,8 +316,7 @@ http_open (struct grub_file *file, const char *filename) err = grub_net_send_tcp_packet (data->sock, nb, 1); if (err) { - grub_free (data); - grub_net_tcp_close (data->sock); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); return err; } @@ -316,9 +328,81 @@ http_open (struct grub_file *file, const char *filename) if (!data->headers_recv) { - grub_net_tcp_close (data->sock); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + if (data->err) + { + char *str = data->errmsg; + err = grub_error (data->err, "%s", str); + grub_free (str); + return data->err; + } + return grub_error (GRUB_ERR_TIMEOUT, "timeout opening http"); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +http_seek (struct grub_file *file, grub_off_t off) +{ + struct http_data *old_data, *data; + grub_err_t err; + old_data = file->data; + /* FIXME: Reuse socket? */ + grub_net_tcp_close (old_data->sock, GRUB_NET_TCP_ABORT); + + while (file->device->net->packs.first) + grub_net_remove_packet (file->device->net->packs.first); + + data = grub_zalloc (sizeof (*data)); + if (!data) + return grub_errno; + + data->file_size = old_data->file_size; + data->size_recv = 1; + data->filename = old_data->filename; + if (!data->filename) + { grub_free (data); - return grub_error (GRUB_ERR_TIMEOUT, "Time out opening http."); + return grub_errno; + } + grub_free (old_data); + + err = http_establish (file, off, 0); + if (err) + { + grub_free (data->filename); + grub_free (data); + return err; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +http_open (struct grub_file *file, const char *filename) +{ + grub_err_t err; + struct http_data *data; + + data = grub_zalloc (sizeof (*data)); + if (!data) + return grub_errno; + + data->filename = grub_strdup (filename); + if (!data->filename) + { + grub_free (data); + return grub_errno; + } + + file->not_easily_seekable = 0; + file->data = data; + + err = http_establish (file, 0, 1); + if (err) + { + grub_free (data->filename); + grub_free (data); + return err; } file->size = data->file_size; @@ -331,10 +415,10 @@ http_close (struct grub_file *file) http_data_t data = file->data; if (data->sock) - grub_net_tcp_close (data->sock); - grub_free (data); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); if (data->current_line) grub_free (data->current_line); + grub_free (data); return GRUB_ERR_NONE; } @@ -342,7 +426,8 @@ static struct grub_net_app_protocol grub_http_protocol = { .name = "http", .open = http_open, - .close = http_close + .close = http_close, + .seek = http_seek }; GRUB_MOD_INIT (http) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 0ff8d01ff..0bde49322 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -815,17 +815,17 @@ grub_net_poll_cards_idle_real (void) static grub_ssize_t grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) { - grub_net_t sock = file->device->net; + grub_net_t net = file->device->net; struct grub_net_buff *nb; char *ptr = buf; grub_size_t amount, total = 0; int try = 0; while (try <= 3) { - while (sock->packs.first) + while (net->packs.first) { try = 0; - nb = sock->packs.first->nb; + nb = net->packs.first->nb; amount = nb->tail - nb->data; if (amount > len) amount = len; @@ -840,7 +840,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (amount == (grub_size_t) (nb->tail - nb->data)) { grub_netbuff_free (nb); - grub_net_remove_packet (sock->packs.first); + grub_net_remove_packet (net->packs.first); } else nb->data += amount; @@ -848,7 +848,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (!len) return total; } - if (!sock->eof) + if (!net->eof) { try++; grub_net_poll_cards (200); @@ -856,39 +856,59 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) else return total; } - return total; + grub_error (GRUB_ERR_TIMEOUT, "timeout reading '%s'", net->name); + return -1; +} + +static grub_off_t +have_ahead (struct grub_file *file) +{ + grub_net_t net = file->device->net; + grub_off_t ret = net->offset; + struct grub_net_packet *pack; + for (pack = net->packs.first; pack; pack = pack->next) + ret += pack->nb->tail - pack->nb->data; + return ret; } static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) { - grub_size_t len = offset - file->device->net->offset; - - if (!len) + if (offset == file->device->net->offset) return GRUB_ERR_NONE; - if (file->device->net->offset > offset) + if (offset > file->device->net->offset) { - grub_err_t err; - while (file->device->net->packs.first) + if (!file->device->net->protocol->seek || have_ahead (file) >= offset) { - grub_netbuff_free (file->device->net->packs.first->nb); - grub_net_remove_packet (file->device->net->packs.first); + grub_net_fs_read_real (file, NULL, + offset - file->device->net->offset); + return grub_errno; } - file->device->net->protocol->close (file); - - file->device->net->packs.first = NULL; - file->device->net->packs.last = NULL; - file->device->net->offset = 0; - file->device->net->eof = 0; - err = file->device->net->protocol->open (file, file->device->net->name); - if (err) - return err; - len = offset; + return file->device->net->protocol->seek (file, offset); } - grub_net_fs_read_real (file, NULL, len); - return GRUB_ERR_NONE; + { + grub_err_t err; + if (file->device->net->protocol->seek) + return file->device->net->protocol->seek (file, offset); + while (file->device->net->packs.first) + { + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } + file->device->net->protocol->close (file); + + file->device->net->packs.first = NULL; + file->device->net->packs.last = NULL; + file->device->net->offset = 0; + file->device->net->eof = 0; + err = file->device->net->protocol->open (file, file->device->net->name); + if (err) + return err; + grub_net_fs_read_real (file, NULL, offset); + return grub_errno; + } } static grub_ssize_t diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 25e8ab4ed..7f120ac16 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -56,7 +56,8 @@ struct grub_net_tcp_socket int in_port; int out_port; int errors; - int reseted; + int they_reseted; + int i_reseted; grub_uint32_t my_start_seq; grub_uint32_t my_cur_seq; grub_uint32_t their_start_seq; @@ -153,7 +154,7 @@ error (grub_net_tcp_socket_t sock) { struct unacked *unack, *next; - if (sock->established && sock->error_hook) + if (sock->error_hook) sock->error_hook (sock, sock->hook_data); for (unack = sock->unack_first; unack; unack = next) @@ -217,7 +218,8 @@ tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket) } void -grub_net_tcp_close (grub_net_tcp_socket_t sock) +grub_net_tcp_close (grub_net_tcp_socket_t sock, + int discard_received) { struct grub_net_buff *nb_fin; struct tcphdr *tcph_fin; @@ -225,6 +227,9 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock) sock->i_closed = 1; + if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING) + sock->recv_hook = NULL; + nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin) + GRUB_NET_OUR_IPV4_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE); @@ -254,6 +259,8 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock) tcph_fin->window = grub_cpu_to_be16 (0); tcph_fin->urgent = 0; err = tcp_send (nb_fin, sock); + if (discard_received == GRUB_NET_TCP_ABORT) + sock->i_reseted = 1; if (err) { grub_netbuff_free (nb_fin); @@ -264,7 +271,7 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock) } static void -ack (grub_net_tcp_socket_t sock) +ack_real (grub_net_tcp_socket_t sock, int res) { struct grub_net_buff *nb_ack; struct tcphdr *tcph_ack; @@ -291,9 +298,18 @@ ack (grub_net_tcp_socket_t sock) return; } tcph_ack = (void *) nb_ack->data; - tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq); - tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_ACK); - tcph_ack->window = grub_cpu_to_be16 (sock->my_window); + if (res) + { + tcph_ack->ack = grub_cpu_to_be32 (0); + tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_RST); + tcph_ack->window = grub_cpu_to_be16 (0); + } + else + { + tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq); + tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_ACK); + tcph_ack->window = grub_cpu_to_be16 (sock->my_window); + } tcph_ack->urgent = 0; tcph_ack->src = grub_cpu_to_be16 (sock->in_port); tcph_ack->dst = grub_cpu_to_be16 (sock->out_port); @@ -305,6 +321,18 @@ ack (grub_net_tcp_socket_t sock) } } +static void +ack (grub_net_tcp_socket_t sock) +{ + ack_real (sock, 0); +} + +static void +reset (grub_net_tcp_socket_t sock) +{ + ack_real (sock, 1); +} + void grub_net_tcp_retransmit (void) { @@ -434,6 +462,7 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock, tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN | TCP_ACK); tcph->window = grub_cpu_to_be16 (sock->my_window); tcph->urgent = 0; + sock->established = 1; tcp_socket_register (sock); err = tcp_send (nb_ack, sock); if (err) @@ -555,7 +584,7 @@ grub_net_tcp_open (char *server, { grub_list_remove (GRUB_AS_LIST_P (&tcp_sockets), GRUB_AS_LIST (socket)); - if (socket->reseted) + if (socket->they_reseted) grub_error (GRUB_ERR_NET_PORT_CLOSED, "port closed"); else grub_error (GRUB_ERR_NET_NO_ANSWER, "no answer"); @@ -693,7 +722,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, if (grub_be_to_cpu16 (tcph->flags) & TCP_RST) { - sock->reseted = 1; + sock->they_reseted = 1; error (sock); @@ -725,7 +754,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, grub_free (unack); } sock->unack_first = unack; - if (!sock->unack_last) + if (!sock->unack_first) sock->unack_last = NULL; } @@ -735,6 +764,12 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, grub_netbuff_free (nb); return GRUB_ERR_NONE; } + if (sock->i_reseted) + { + reset (sock); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } err = grub_priority_queue_push (sock->pq, &nb); if (err) diff --git a/include/grub/net.h b/include/grub/net.h index 255784315..ac011520a 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -204,6 +204,7 @@ struct grub_net_app_protocol int (*hook) (const char *filename, const struct grub_dirhook_info *info)); grub_err_t (*open) (struct grub_file *file, const char *filename); + grub_err_t (*seek) (struct grub_file *file, grub_off_t off); grub_err_t (*close) (struct grub_file *file); }; diff --git a/include/grub/net/tcp.h b/include/grub/net/tcp.h index 0ac7819bc..b25ceff1b 100644 --- a/include/grub/net/tcp.h +++ b/include/grub/net/tcp.h @@ -53,8 +53,15 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, struct grub_net_buff *nb, int push); +enum + { + GRUB_NET_TCP_CONTINUE_RECEIVING, + GRUB_NET_TCP_DISCARD, + GRUB_NET_TCP_ABORT + }; + void -grub_net_tcp_close (grub_net_tcp_socket_t sock); +grub_net_tcp_close (grub_net_tcp_socket_t sock, int discard_received); grub_err_t grub_net_tcp_accept (grub_net_tcp_socket_t sock, From 96bd62413f8781ca5d5c0d3f9ba82463f568d06a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 17:50:52 +0200 Subject: [PATCH 377/673] Don't set RST in response to empty packets --- grub-core/net/tcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 7f120ac16..cb5b6a698 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -764,11 +764,11 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, grub_netbuff_free (nb); return GRUB_ERR_NONE; } - if (sock->i_reseted) + if (sock->i_reseted && (nb->tail - nb->data + - (grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t)) > 0) { reset (sock); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; } err = grub_priority_queue_push (sock->pq, &nb); From 9aad3cd91d8e2bac585cf77c71aaaa76e53d49fe Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 22:15:30 +0200 Subject: [PATCH 378/673] IPv6 support. Several fixes and unifications --- grub-core/net/arp.c | 142 +++++++++++++++++++----- grub-core/net/bootp.c | 40 +++---- grub-core/net/ethernet.c | 20 ++-- grub-core/net/ip.c | 208 +++++++++++++++++++++++++++++------- grub-core/net/net.c | 109 ++++++++++++++++++- grub-core/net/tcp.c | 53 ++++++--- grub-core/net/tftp.c | 5 +- include/grub/err.h | 3 +- include/grub/net.h | 20 +++- include/grub/net/arp.h | 24 ----- include/grub/net/ethernet.h | 13 +-- include/grub/net/ip.h | 10 +- include/grub/types.h | 14 +-- 13 files changed, 505 insertions(+), 156 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index b45bd4c9f..b1b719dbe 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + #include #include #include @@ -6,6 +24,34 @@ #include #include +/* ARP header operation codes */ +enum + { + ARP_REQUEST = 1, + ARP_REPLY = 2 + }; + +enum + { + /* IANA ARP constant to define hardware type as ethernet. */ + GRUB_NET_ARPHRD_ETHERNET = 1 + }; + +struct arphdr { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; +} __attribute__ ((packed)); + + +struct arp_entry { + int avail; + grub_net_network_level_address_t nl_address; + grub_net_link_level_address_t ll_address; +}; + static struct arp_entry arp_table[10]; static grub_int8_t new_table_entry = -1; @@ -23,7 +69,7 @@ arp_find_entry (const grub_net_network_level_address_t *proto) for (i = 0; i < ARRAY_SIZE (arp_table); i++) { if (arp_table[i].avail == 1 && - arp_table[i].nl_address.ipv4 == proto->ipv4) + grub_net_addr_cmp (&arp_table[i].nl_address, proto) == 0) return &(arp_table[i]); } return NULL; @@ -41,6 +87,8 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, grub_uint8_t *aux, arp_data[128]; grub_err_t err; int i; + grub_size_t addrlen; + grub_uint16_t etherpro; if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 && proto_addr->ipv4 == 0xffffffff) @@ -57,22 +105,35 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, *hw_addr = entry->ll_address; return GRUB_ERR_NONE; } + + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + { + addrlen = 4; + etherpro = GRUB_NET_ETHERTYPE_IP; + } + else if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) + { + addrlen = 16; + etherpro = GRUB_NET_ETHERTYPE_IP6; + } + else + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported address family"); + /* Build a request packet. */ nb.head = arp_data; nb.end = arp_data + sizeof (arp_data); grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 128); - err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); + err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + addrlen)); if (err) return err; arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); - arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); - /* FIXME Add support to ipv6 address. */ arp_header->hln = 6; - arp_header->pln = 4; + arp_header->pro = grub_cpu_to_be16 (etherpro); + arp_header->pln = addrlen; arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); aux = (grub_uint8_t *) arp_header + sizeof (*arp_header); /* Sender hardware address. */ @@ -80,18 +141,24 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, aux += 6; /* Sender protocol address */ - grub_memcpy (aux, &inf->address.ipv4, 4); - aux += 4; + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + grub_memcpy (aux, &inf->address.ipv4, 4); + else + grub_memcpy (aux, &inf->address.ipv6, 16); + aux += addrlen; /* Target hardware address */ for (i = 0; i < 6; i++) aux[i] = 0x00; aux += 6; /* Target protocol address */ - grub_memcpy (aux, &proto_addr->ipv4, 4); + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + grub_memcpy (aux, &proto_addr->ipv4, 4); + else + grub_memcpy (aux, &proto_addr->ipv6, 16); grub_memset (&target_hw_addr.mac, 0xff, 6); send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); - for (i = 0; i < 3; i++) + for (i = 0; i < GRUB_NET_TRIES; i++) { entry = arp_find_entry (proto_addr); if (entry) @@ -99,7 +166,7 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr)); return GRUB_ERR_NONE; } - grub_net_poll_cards (200); + grub_net_poll_cards (GRUB_NET_INTERVAL); } return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address"); @@ -110,20 +177,38 @@ grub_net_arp_receive (struct grub_net_buff *nb) { struct arphdr *arp_header = (struct arphdr *) nb->data; struct arp_entry *entry; - grub_uint8_t *sender_hardware_address, *sender_protocol_address; - grub_uint8_t *target_hardware_address, *target_protocol_address; - grub_net_network_level_address_t hwaddress; + grub_uint8_t *sender_hardware_address; + grub_uint8_t *target_hardware_address; + grub_net_network_level_address_t sender_addr, target_addr; struct grub_net_network_level_interface *inf; + grub_uint8_t *sender_protocol_address, *target_protocol_address; sender_hardware_address = (grub_uint8_t *) arp_header + sizeof (*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; - grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4); - + if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP + && arp_header->pln == 4) + { + sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4); + grub_memcpy (&target_addr.ipv4, target_protocol_address, 4); + } + else if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP6 + && arp_header->pln == 16) + { + sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&sender_addr.ipv6, sender_protocol_address, 16); + grub_memcpy (&target_addr.ipv6, target_protocol_address, 16); + } + else + return GRUB_ERR_NONE; + /* Check if the sender is in the cache table. */ - entry = arp_find_entry (&hwaddress); + entry = arp_find_entry (&sender_addr); /* Update sender hardware address. */ if (entry) grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); @@ -134,7 +219,7 @@ grub_net_arp_receive (struct grub_net_buff *nb) arp_init_table (); entry = &(arp_table[new_table_entry]); entry->avail = 1; - grub_memcpy (&entry->nl_address.ipv4, sender_protocol_address, 4); + entry->nl_address = sender_addr; grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); new_table_entry++; if (new_table_entry == ARRAY_SIZE (arp_table)) @@ -144,23 +229,26 @@ grub_net_arp_receive (struct grub_net_buff *nb) FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { /* Am I the protocol address target? */ - if (inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && grub_memcmp (target_protocol_address, &inf->address.ipv4, 4) == 0 + if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy (target_hardware_address, sender_hardware_address, - arp_header->hln); + grub_net_link_level_address_t target; + /* We've already checked that pln is either 4 or 16. */ + char tmp[arp_header->pln]; + + target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (target.mac, sender_hardware_address, 6); + grub_memcpy (target_hardware_address, target.mac, 6); grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy (aux.mac, sender_protocol_address, 6); + + grub_memcpy (tmp, sender_protocol_address, arp_header->pln); grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); + grub_memcpy (target_protocol_address, tmp, arp_header->pln); + /* Change operation to REPLY and send packet */ arp_header->op = grub_be_to_cpu16 (ARP_REPLY); - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + send_ethernet_packet (inf, nb, target, GRUB_NET_ETHERTYPE_ARP); } } return GRUB_ERR_NONE; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index b1db05147..3187f2e9c 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -131,26 +131,28 @@ grub_net_configure_by_dhcp_ack (const char *name, hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; inter = grub_net_add_addr (name, card, addr, hwaddr, flags); - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - char rname[grub_strlen (name) + sizeof ("_gw")]; + if (bp->gateway_ip) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof (":gw")]; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = bp->gateway_ip; - grub_snprintf (rname, sizeof (rname), "%s_gw", name); - grub_net_add_route_gw (rname, target, gw); - } - { - grub_net_network_level_netaddress_t target; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->gateway_ip; - target.ipv4.masksize = 32; - grub_net_add_route (name, target, inter); - } + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s:gw", name); + grub_net_add_route_gw (rname, target, gw); + } + if (bp->gateway_ip || bp->server_ip) + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->gateway_ip ? bp->gateway_ip : bp->server_ip; + target.ipv4.masksize = 32; + grub_net_add_route (name, target, inter); + } if (size > OFFSET_OF (boot_file, bp)) set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index c368eda54..053f87b56 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -52,7 +52,7 @@ grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t target_addr, - grub_uint16_t ethertype) + grub_net_ethertype_t ethertype) { struct etherhdr *eth; grub_err_t err; @@ -86,7 +86,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb, struct etherhdr *eth; struct llchdr *llch; struct snaphdr *snaph; - grub_uint16_t type; + grub_net_ethertype_t type; grub_net_link_level_address_t hwaddress; grub_err_t err; @@ -114,17 +114,19 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb, hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); - /* ARP packet. */ - if (type == GRUB_NET_ETHERTYPE_ARP) + switch (type) { + /* ARP packet. */ + case GRUB_NET_ETHERTYPE_ARP: grub_net_arp_receive (nb); grub_netbuff_free (nb); return GRUB_ERR_NONE; - } - /* IP packet. */ - if (type == GRUB_NET_ETHERTYPE_IP) - { - grub_net_recv_ip_packets (nb, card, &hwaddress); + /* IP packet. */ + case GRUB_NET_ETHERTYPE_IP: + grub_net_recv_ip4_packets (nb, card, &hwaddress); + return GRUB_ERR_NONE; + case GRUB_NET_ETHERTYPE_IP6: + grub_net_recv_ip4_packets (nb, card, &hwaddress); return GRUB_ERR_NONE; } grub_netbuff_free (nb); diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 69579970f..32a7d7fe7 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -47,16 +47,16 @@ enum OFFSET_MASK = 0x1fff }; -struct ip6hdr -{ - grub_uint8_t version:4, priority:4; - grub_uint8_t flow_lbl[3]; - grub_uint16_t payload_len; - grub_uint8_t nexthdr; - grub_uint8_t hop_limit; - grub_uint8_t saddr[16]; - grub_uint8_t daddr[16]; -} __attribute__ ((packed)); +typedef grub_uint64_t ip6addr[2]; + +struct ip6hdr { + grub_uint32_t version_class_flow; + grub_uint16_t len; + grub_uint8_t protocol; + grub_uint8_t ttl; + ip6addr src; + ip6addr dest; +} __attribute__ ((packed)) ; static int cmp (const void *a__, const void *b__) @@ -179,11 +179,11 @@ send_fragmented (struct grub_net_network_level_interface * inf, return GRUB_ERR_NONE; } -grub_err_t -grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, - const grub_net_network_level_address_t * target, - struct grub_net_buff * nb, - grub_net_ip_protocol_t proto) +static grub_err_t +grub_net_send_ip4_packet (struct grub_net_network_level_interface * inf, + const grub_net_network_level_address_t * target, + struct grub_net_buff * nb, + grub_net_ip_protocol_t proto) { struct iphdr *iph; grub_net_link_level_address_t ll_target_addr; @@ -223,20 +223,13 @@ static grub_err_t handle_dgram (struct grub_net_buff *nb, const struct grub_net_card *card, const grub_net_link_level_address_t *hwaddress, - grub_net_ip_protocol_t proto, grub_uint32_t src, - grub_uint32_t dst) + grub_net_ip_protocol_t proto, + const grub_net_network_level_address_t *source, + const grub_net_network_level_address_t *dest) { struct grub_net_network_level_interface *inf = NULL; grub_err_t err; - grub_net_network_level_address_t source; - grub_net_network_level_address_t dest; - - source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - source.ipv4 = src; - - dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - dest.ipv4 = dst; - + /* DHCP needs special treatment since we don't know IP yet. */ { struct udphdr *udph; @@ -255,8 +248,8 @@ handle_dgram (struct grub_net_buff *nb, udph->chksum = 0; expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, - &source, - &dest); + source, + dest); if (expected != chk) { grub_dprintf ("net", "Invalid UDP checksum. " @@ -284,8 +277,7 @@ handle_dgram (struct grub_net_buff *nb, FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && inf->address.ipv4 == dst + && grub_net_addr_cmp (&inf->address, dest) == 0 && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) break; } @@ -299,11 +291,11 @@ handle_dgram (struct grub_net_buff *nb, switch (proto) { case GRUB_NET_IP_UDP: - return grub_net_recv_udp_packet (nb, inf, &source); + return grub_net_recv_udp_packet (nb, inf, source); case GRUB_NET_IP_TCP: - return grub_net_recv_tcp_packet (nb, inf, &source); + return grub_net_recv_tcp_packet (nb, inf, source); case GRUB_NET_IP_ICMP: - return grub_net_recv_icmp_packet (nb, inf, &source); + return grub_net_recv_icmp_packet (nb, inf, source); default: grub_netbuff_free (nb); break; @@ -339,9 +331,9 @@ free_old_fragments (void) } grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff * nb, - const struct grub_net_card * card, - const grub_net_link_level_address_t * hwaddress) +grub_net_recv_ip4_packets (struct grub_net_buff * nb, + const struct grub_net_card * card, + const grub_net_link_level_address_t * hwaddress) { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; @@ -365,8 +357,8 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, if (nb->tail - nb->data < (grub_ssize_t) ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t))) { - grub_dprintf ("net", "IP packet too short: %d\n", - (iph->verhdrlen & 0xf)); + grub_dprintf ("net", "IP packet too short: %" PRIdGRUB_SSIZE "\n", + (nb->tail - nb->data)); grub_netbuff_free (nb); return GRUB_ERR_NONE; } @@ -398,6 +390,9 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, if (((grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS) == 0) && (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) == 0) { + grub_net_network_level_address_t source; + grub_net_network_level_address_t dest; + err = grub_netbuff_pull (nb, ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t))); if (err) @@ -405,8 +400,15 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, grub_netbuff_free (nb); return err; } + + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + source.ipv4 = iph->src; + + dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + dest.ipv4 = iph->dest; + return handle_dgram (nb, card, hwaddress, iph->protocol, - iph->src, iph->dest); + &source, &dest); } for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev) @@ -469,6 +471,8 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, grub_net_ip_protocol_t proto; grub_uint32_t src; grub_uint32_t dst; + grub_net_network_level_address_t source; + grub_net_network_level_address_t dest; nb_top_p = grub_priority_queue_top (rsm->pq); if (!nb_top_p) @@ -524,8 +528,132 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, } ret->data = ret->head = res; ret->tail = ret->end = res + res_len; - return handle_dgram (ret, card, hwaddress, proto, src, dst); + + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + source.ipv4 = src; + + dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + dest.ipv4 = dst; + + return handle_dgram (ret, card, hwaddress, proto, &source, &dest); } return GRUB_ERR_NONE; } + +static grub_err_t +grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf, + const grub_net_network_level_address_t * target, + struct grub_net_buff * nb, + grub_net_ip_protocol_t proto) +{ + struct ip6hdr *iph; + grub_net_link_level_address_t ll_target_addr; + grub_err_t err; + + COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph)); + + /* Determine link layer target address via ARP. */ + err = grub_net_arp_resolve (inf, target, &ll_target_addr); + if (err) + return err; + + if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu) + return grub_error (GRUB_ERR_NET_PACKET_TOO_BIG, "packet too big"); + + grub_netbuff_push (nb, sizeof (*iph)); + iph = (struct ip6hdr *) nb->data; + + iph->version_class_flow = grub_cpu_to_be32 ((6 << 28)); + iph->len = grub_cpu_to_be16 (nb->tail - nb->data) - sizeof (*iph); + iph->protocol = proto; + iph->ttl = 0xff; + grub_memcpy (&iph->src, inf->address.ipv6, sizeof (iph->src)); + grub_memcpy (&iph->dest, target->ipv6, sizeof (iph->dest)); + + return send_ethernet_packet (inf, nb, ll_target_addr, + GRUB_NET_ETHERTYPE_IP); +} + +grub_err_t +grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, + const grub_net_network_level_address_t * target, + struct grub_net_buff * nb, + grub_net_ip_protocol_t proto) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + return grub_net_send_ip4_packet (inf, target, nb, proto); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + return grub_net_send_ip6_packet (inf, target, nb, proto); + default: + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP"); + } + +} + +grub_err_t +grub_net_recv_ip6_packets (struct grub_net_buff * nb, + const struct grub_net_card * card, + const grub_net_link_level_address_t * hwaddress) +{ + struct ip6hdr *iph = (struct ip6hdr *) nb->data; + grub_err_t err; + grub_net_network_level_address_t source; + grub_net_network_level_address_t dest; + + if ((grub_be_to_cpu32 (iph->version_class_flow) >> 28) != 6) + { + grub_dprintf ("net", "Bad IP version: %d\n", + (grub_be_to_cpu32 (iph->version_class_flow) >> 28)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*iph)) + { + grub_dprintf ("net", "IP packet too short: %" PRIdGRUB_SSIZE "\n", + nb->tail - nb->data); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + err = grub_netbuff_pull (nb, sizeof (*iph)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + + /* Check size. */ + { + grub_size_t expected_size = grub_be_to_cpu16 (iph->len); + grub_size_t actual_size = (nb->tail - nb->data); + if (actual_size > expected_size) + { + err = grub_netbuff_unput (nb, actual_size - expected_size); + if (err) + { + grub_netbuff_free (nb); + return err; + } + } + if (actual_size < expected_size) + { + grub_dprintf ("net", "Cut IP packet actual: %" PRIuGRUB_SIZE + ", expected %" PRIuGRUB_SIZE "\n", actual_size, + expected_size); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + } + + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (source.ipv6, &iph->src, sizeof (source.ipv6)); + grub_memcpy (dest.ipv6, &iph->src, sizeof (dest.ipv6)); + + return handle_dgram (nb, card, hwaddress, iph->protocol, + &source, &dest); +} diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 0bde49322..7d6ef2759 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -131,10 +131,23 @@ match_net (const grub_net_network_level_netaddress_t *net, return 0; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { - grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize); + grub_uint32_t mask = (0xffffffffU << (32 - net->ipv4.masksize)); return ((grub_be_to_cpu32 (net->ipv4.base) & mask) == (grub_be_to_cpu32 (addr->ipv4) & mask)); } + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + grub_int64_t mask[2]; + mask[1] = 0xffffffffffffffffULL << (128 - net->ipv6.masksize); + if (net->ipv6.masksize < 64) + mask[0] = 0xffffffffffffffffULL; + else + mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize); + return (((grub_be_to_cpu64 (net->ipv6.base[0]) & mask[0]) + == (grub_be_to_cpu32 (addr->ipv6[0]) & mask[0])) + && ((grub_be_to_cpu64 (net->ipv6.base[1]) & mask[1]) + == (grub_be_to_cpu32 (addr->ipv6[1]) & mask[1]))); + } } return 0; } @@ -249,6 +262,25 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: grub_strcpy (buf, "temporary"); return; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + char *ptr = buf; + grub_uint32_t n = grub_be_to_cpu32 (target->ipv6[0]); + int i; + for (i = 0; i < 4; i++) + { + grub_snprintf (ptr, 6, "%x:", (n >> (48 - 16 * i)) & 0xffff); + ptr += grub_strlen (ptr); + } + n = grub_be_to_cpu32 (target->ipv6[1]); + for (i = 0; i < 3; i++) + { + grub_snprintf (ptr, 6, "%x:", (n >> (48 - 16 * i)) & 0xffff); + ptr += grub_strlen (ptr); + } + grub_snprintf (ptr, 5, "%x", n & 0xffff); + return; + } case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); @@ -307,6 +339,27 @@ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, return 1; } +int +grub_net_addr_cmp (const grub_net_network_level_address_t *a, + const grub_net_network_level_address_t *b) +{ + if (a->type < b->type) + return -1; + if (a->type > b->type) + return +1; + switch (a->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + return grub_memcmp (&a->ipv4, &b->ipv4, sizeof (a->ipv4)); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + return grub_memcmp (&a->ipv6, &b->ipv6, sizeof (a->ipv6)); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + return 0; + } + grub_printf ("Unsupported address type %d\n", a->type); + return 1; +} + /* FIXME: implement this. */ static char * hwaddr_set_env (struct grub_env_var *var __attribute__ ((unused)), @@ -375,6 +428,43 @@ grub_net_add_addr (const char *name, grub_net_network_level_interface_register (inter); + if (addr.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + { + int mask = -1; + grub_uint32_t ip_cpu = grub_be_to_cpu32 (addr.ipv4); + if (!(ip_cpu & 0x80000000)) + mask = 8; + else if (!(ip_cpu & 0x40000000)) + mask = 16; + else if (!(ip_cpu & 0x20000000)) + mask = 24; + else + mask = -1; + if (mask != -1) + { + struct grub_net_route *route; + + route = grub_zalloc (sizeof (*route)); + if (!route) + return NULL; + + route->name = grub_xasprintf ("%s:local", name); + if (!route->name) + { + grub_free (route); + return NULL; + } + + route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + route->target.ipv4.base = grub_cpu_to_be32 (ip_cpu & (0xffffffff << (32 - mask))); + route->target.ipv4.masksize = mask; + route->is_gateway = 0; + route->interface = inter; + + grub_net_route_register (route); + } + } + return inter; } @@ -532,7 +622,7 @@ print_net_address (const grub_net_network_level_netaddress_t *target) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: grub_printf ("temporary\n"); - break; + return; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base); @@ -543,6 +633,16 @@ print_net_address (const grub_net_network_level_netaddress_t *target) target->ipv4.masksize); } return; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + struct grub_net_network_level_address base; + base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (&base.ipv6, &target->ipv6, 16); + grub_net_addr_to_str (&base, buf); + grub_printf ("%s/%d ", buf, target->ipv6.masksize); + } + return; } grub_printf ("Unknown address type %d\n", target->type); } @@ -764,6 +864,7 @@ receive_packets (struct grub_net_card *card) /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; + struct grub_net_buff *nb2; nb = card->driver->recv (card); if (!nb) @@ -820,7 +921,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) char *ptr = buf; grub_size_t amount, total = 0; int try = 0; - while (try <= 3) + while (try <= GRUB_NET_TRIES) { while (net->packs.first) { @@ -851,7 +952,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (!net->eof) { try++; - grub_net_poll_cards (200); + grub_net_poll_cards (GRUB_NET_INTERVAL); } else return total; diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index cb5b6a698..b1eb3d9a8 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -23,10 +23,10 @@ #include #include -#define TCP_SYN_RETRANSMISSION_TIMEOUT 1000 -#define TCP_SYN_RETRANSMISSION_COUNT 3 -#define TCP_RETRANSMISSION_TIMEOUT 1000 -#define TCP_RETRANSMISSION_COUNT 10 +#define TCP_SYN_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL +#define TCP_SYN_RETRANSMISSION_COUNT GRUB_NET_TRIES +#define TCP_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL +#define TCP_RETRANSMISSION_COUNT GRUB_NET_TRIES struct unacked { @@ -109,6 +109,15 @@ struct tcp_pseudohdr grub_uint16_t tcp_length; } __attribute__ ((packed)); +struct tcp6_pseudohdr +{ + grub_uint64_t src[2]; + grub_uint64_t dst[2]; + grub_uint32_t tcp_length; + grub_uint8_t zero[3]; + grub_uint8_t proto; +} __attribute__ ((packed)); + static struct grub_net_tcp_socket *tcp_sockets; static struct grub_net_tcp_listen *tcp_listens; @@ -377,19 +386,39 @@ grub_net_ip_transport_checksum (struct grub_net_buff *nb, const grub_net_network_level_address_t *src, const grub_net_network_level_address_t *dst) { - struct tcp_pseudohdr ph; grub_uint16_t a, b; grub_uint32_t c; - a = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) nb->data, nb->tail - nb->data)); - ph.src = src->ipv4; - ph.dst = dst->ipv4; - ph.zero = 0; - ph.tcp_length = grub_cpu_to_be16 (nb->tail - nb->data); - ph.proto = proto; - b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph))); + switch (dst->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + { + struct tcp_pseudohdr ph; + ph.src = src->ipv4; + ph.dst = dst->ipv4; + ph.zero = 0; + ph.tcp_length = grub_cpu_to_be16 (nb->tail - nb->data); + ph.proto = proto; + b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph))); + break; + } + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + struct tcp6_pseudohdr ph; + grub_memcpy (ph.src, src->ipv6, sizeof (ph.src)); + grub_memcpy (ph.dst, dst->ipv6, sizeof (ph.dst)); + grub_memset (ph.zero, 0, sizeof (ph.zero)); + ph.tcp_length = grub_cpu_to_be32 (nb->tail - nb->data); + ph.proto = proto; + b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph))); + break; + } + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + b = 0; + break; + } c = (grub_uint32_t) a + (grub_uint32_t) b; if (c >= 0xffff) c -= 0xffff; diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 7c58e640b..9be7294e8 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -167,6 +167,7 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), case TFTP_OACK: data->block_size = TFTP_DEFAULTSIZE_PACKET; data->have_oack = 1; + grub_printf ("OACK\n"); for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) @@ -345,7 +346,7 @@ tftp_open (struct grub_file *file, const char *filename) /* Receive OACK packet. */ nbd = nb.data; - for (i = 0; i < 3; i++) + for (i = 0; i < GRUB_NET_TRIES; i++) { nb.data = nbd; err = grub_net_send_udp_packet (data->sock, &nb); @@ -355,7 +356,7 @@ tftp_open (struct grub_file *file, const char *filename) destroy_pq (data); return err; } - grub_net_poll_cards (100); + grub_net_poll_cards (GRUB_NET_INTERVAL); if (data->have_oack) break; } diff --git a/include/grub/err.h b/include/grub/err.h index f6610193c..d13f2c9ce 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -64,7 +64,8 @@ typedef enum GRUB_ERR_BUG, GRUB_ERR_NET_PORT_CLOSED, GRUB_ERR_NET_INVALID_RESPONSE, - GRUB_ERR_NET_UNKNOWN_ERROR + GRUB_ERR_NET_UNKNOWN_ERROR, + GRUB_ERR_NET_PACKET_TOO_BIG } grub_err_t; diff --git a/include/grub/net.h b/include/grub/net.h index ac011520a..cb9d40cd0 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -33,6 +33,7 @@ enum GRUB_NET_UDP_HEADER_SIZE = 8, GRUB_NET_TCP_HEADER_SIZE = 20, GRUB_NET_OUR_IPV4_HEADER_SIZE = 20, + GRUB_NET_OUR_IPV6_HEADER_SIZE = 40, GRUB_NET_TCP_RESERVE_SIZE = GRUB_NET_TCP_HEADER_SIZE + GRUB_NET_OUR_IPV4_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE @@ -127,7 +128,8 @@ struct grub_net_network_level_interface; typedef enum grub_network_level_protocol_id { GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV, - GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4, + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 } grub_network_level_protocol_id_t; typedef struct grub_net_network_level_address @@ -136,6 +138,7 @@ typedef struct grub_net_network_level_address union { grub_uint32_t ipv4; + grub_uint64_t ipv6[2]; }; } grub_net_network_level_address_t; @@ -148,6 +151,10 @@ typedef struct grub_net_network_level_netaddress grub_uint32_t base; int masksize; } ipv4; + struct { + grub_uint64_t base[2]; + int masksize; + } ipv6; }; } grub_net_network_level_netaddress_t; @@ -389,13 +396,17 @@ grub_net_process_dhcp (struct grub_net_buff *nb, int grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, const grub_net_link_level_address_t *b); +int +grub_net_addr_cmp (const grub_net_network_level_address_t *a, + const grub_net_network_level_address_t *b); /* - Currently suppoerted adresses: + Currently supported adresses: IPv4: XXX.XXX.XXX.XXX + IPv&: XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX */ -#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") +#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX") void grub_net_addr_to_str (const grub_net_network_level_address_t *target, @@ -428,4 +439,7 @@ grub_net_tcp_retransmit (void); extern char *grub_net_default_server; +#define GRUB_NET_TRIES 40 +#define GRUB_NET_INTERVAL 400 + #endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 27a6719c4..49682184e 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -21,30 +21,6 @@ #include #include -enum -{ -/* IANA ARP constant to define hardware type as ethernet. */ - GRUB_NET_ARPHRD_ETHERNET = 1 -}; - -/* ARP header operation codes */ -#define ARP_REQUEST 1 -#define ARP_REPLY 2 - -struct arp_entry { - int avail; - grub_net_network_level_address_t nl_address; - grub_net_link_level_address_t ll_address; -}; - -struct arphdr { - grub_uint16_t hrd; - grub_uint16_t pro; - grub_uint8_t hln; - grub_uint8_t pln; - grub_uint16_t op; -} __attribute__ ((packed)); - extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb); extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf, diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index a68aafd96..0749d9d87 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -22,17 +22,18 @@ #include /* IANA Ethertype */ -enum -{ - GRUB_NET_ETHERTYPE_IP = 0x0800, - GRUB_NET_ETHERTYPE_ARP = 0x0806 -}; +typedef enum + { + GRUB_NET_ETHERTYPE_IP = 0x0800, + GRUB_NET_ETHERTYPE_ARP = 0x0806, + GRUB_NET_ETHERTYPE_IP6 = 0x86DD, + } grub_net_ethertype_t; grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t target_addr, - grub_uint16_t ethertype); + grub_net_ethertype_t ethertype); grub_err_t grub_net_recv_ethernet_packet (struct grub_net_buff *nb, const struct grub_net_card *card); diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index e385e5ac1..759577522 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -32,9 +32,13 @@ typedef enum grub_net_ip_protocol grub_uint16_t grub_net_ip_chksum(void *ipv, grub_size_t len); grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff *nb, - const struct grub_net_card *card, - const grub_net_link_level_address_t *hwaddress); +grub_net_recv_ip4_packets (struct grub_net_buff *nb, + const struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress); +grub_err_t +grub_net_recv_ip6_packets (struct grub_net_buff *nb, + const struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, diff --git a/include/grub/types.h b/include/grub/types.h index 4fd7a3a4b..4dde10a16 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -98,13 +98,15 @@ typedef grub_uint64_t grub_size_t; typedef grub_int64_t grub_ssize_t; # if GRUB_CPU_SIZEOF_LONG == 8 -# define PRIxGRUB_SIZE "lx" -# define PRIxGRUB_ADDR "lx" -# define PRIuGRUB_SIZE "lu" +# define PRIxGRUB_SIZE "lx" +# define PRIxGRUB_ADDR "lx" +# define PRIuGRUB_SIZE "lu" +# define PRIdGRUB_SSIZE "ld" # else -# define PRIxGRUB_SIZE "llx" -# define PRIxGRUB_ADDR "llx" -# define PRIuGRUB_SIZE "llu" +# define PRIxGRUB_SIZE "llx" +# define PRIxGRUB_ADDR "llx" +# define PRIuGRUB_SIZE "llu" +# define PRIdGRUB_SSIZE "lld" # endif #else typedef grub_uint32_t grub_addr_t; From faba379c969841b31a419ac36f5bbee68730ea4c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 23:18:22 +0200 Subject: [PATCH 379/673] put license on priority_queue --- grub-core/lib/priority_queue.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c index 0cf258ecf..a790910a8 100644 --- a/grub-core/lib/priority_queue.c +++ b/grub-core/lib/priority_queue.c @@ -19,6 +19,10 @@ #ifndef TEST #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + #else #include #include From 140674be60bec29fac7128ebaa6ac99df059b14c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 23:18:44 +0200 Subject: [PATCH 380/673] Remove leftover variabel --- grub-core/net/net.c | 1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 7d6ef2759..398e6f5ae 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -864,7 +864,6 @@ receive_packets (struct grub_net_card *card) /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; - struct grub_net_buff *nb2; nb = card->driver->recv (card); if (!nb) From 8530b00aa904481dd9b90970fd3c4fa412215344 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 23:19:11 +0200 Subject: [PATCH 381/673] Fix compilation on 64-bit targets --- include/grub/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grub/types.h b/include/grub/types.h index 4dde10a16..84bc97455 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -116,6 +116,7 @@ typedef grub_int32_t grub_ssize_t; # define PRIxGRUB_SIZE "x" # define PRIxGRUB_ADDR "x" # define PRIuGRUB_SIZE "u" +# define PRIdGRUB_SSIZE "d" #endif #if GRUB_CPU_SIZEOF_LONG == 8 From eb6a7b9788747839c9ce1805e86c42e5eb5de585 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 23:33:36 +0200 Subject: [PATCH 382/673] Hopefully fix EFI problem. Not tested --- grub-core/net/drivers/efi/efinet.c | 15 +++++++++++++-- include/grub/efi/api.h | 4 +++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 906a688dc..2a392bc98 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -35,11 +35,22 @@ send_card_buffer (const struct grub_net_card *dev, { grub_efi_status_t st; grub_efi_simple_network_t *net = dev->efi_net; + grub_uint64_t limit_time = grub_get_time_ms () + 4000; st = efi_call_7 (net->transmit, net, 0, (pack->tail - pack->data), pack->data, NULL, NULL, NULL); if (st != GRUB_EFI_SUCCESS) - return grub_error (GRUB_ERR_IO, "Couldn't send network packet."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_IO, "couldn't send network packet"); + while (1) + { + void *txbuf = NULL; + st = efi_call_3 (net->get_status, net, 0, &txbuf); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, "couldn't send network packet"); + if (txbuf) + return GRUB_ERR_NONE; + if (limit_time < grub_get_time_ms ()) + return grub_error (GRUB_ERR_TIMEOUT, "couldn't send network packet"); + } } static struct grub_net_buff * diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index b20baa015..6f3e2a71d 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -1301,7 +1301,9 @@ struct grub_efi_simple_network void (*statistics) (void); void (*mcastiptomac) (void); void (*nvdata) (void); - void (*getstatus) (void); + grub_efi_status_t (*get_status) (struct grub_efi_simple_network *this, + grub_uint32_t *int_status, + void **txbuf); grub_efi_status_t (*transmit) (struct grub_efi_simple_network *this, grub_efi_uintn_t header_size, grub_efi_uintn_t buffer_size, From d5e60b1ba06af4a63605e4f23b1299cf3422d5e7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 5 Oct 2011 23:50:43 +0200 Subject: [PATCH 383/673] Add license statement to the emunet --- grub-core/net/drivers/emu/emunet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index ff333d370..2aba28d23 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -28,6 +28,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static int fd; static grub_err_t From a98f4a0808308815c5580d3ac23b2442d02ced33 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sun, 9 Oct 2011 21:13:00 +0200 Subject: [PATCH 384/673] 2011-10-09 Robert Millan LVM support for FreeBSD and GNU/kFreeBSD. * util/lvm.c (grub_util_lvm_isvolume): Enable on FreeBSD and GNU/kFreeBSD. (LVM_DEV_MAPPER_STRING): Move from here ... * include/grub/util/lvm.h (LVM_DEV_MAPPER_STRING): ... to here. * util/getroot.c: Include `'. (grub_util_get_dev_abstraction): Enable grub_util_biosdisk_is_present() on FreeBSD and GNU/kFreeBSD. Check for LVM abstraction on FreeBSD and GNU/kFreeBSD. (grub_util_get_grub_dev): Replace "/dev/mapper/" with `LVM_DEV_MAPPER_STRING'. Enable LVM and mdRAID only on platforms that support it. * util/grub-setup.c (main): Check for LVM also on FreeBSD and GNU/kFreeBSD. * util/grub.d/10_kfreebsd.in: Load `geom_linux_lvm' kernel module when LVM abstraction is required for ${GRUB_DEVICE}. --- ChangeLog | 20 ++++++++++++++++++++ include/grub/util/lvm.h | 9 ++++++++- util/getroot.c | 24 ++++++++++++++++-------- util/grub-setup.c | 6 ++++-- util/grub.d/10_kfreebsd.in | 8 +++++++- util/lvm.c | 9 +++------ 6 files changed, 58 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6484cf826..19db47e04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2011-10-09 Robert Millan + + LVM support for FreeBSD and GNU/kFreeBSD. + + * util/lvm.c (grub_util_lvm_isvolume): Enable on FreeBSD and + GNU/kFreeBSD. + (LVM_DEV_MAPPER_STRING): Move from here ... + * include/grub/util/lvm.h (LVM_DEV_MAPPER_STRING): ... to here. + * util/getroot.c: Include `'. + (grub_util_get_dev_abstraction): Enable + grub_util_biosdisk_is_present() on FreeBSD and GNU/kFreeBSD. + Check for LVM abstraction on FreeBSD and GNU/kFreeBSD. + (grub_util_get_grub_dev): Replace "/dev/mapper/" with + `LVM_DEV_MAPPER_STRING'. Enable LVM and mdRAID only on platforms that + support it. + * util/grub-setup.c (main): Check for LVM also on FreeBSD and + GNU/kFreeBSD. + * util/grub.d/10_kfreebsd.in: Load `geom_linux_lvm' kernel module + when LVM abstraction is required for ${GRUB_DEVICE}. + 2011-10-06 Szymon Janc Add support for LZO compression in GRUB: diff --git a/include/grub/util/lvm.h b/include/grub/util/lvm.h index 7a4c76c6b..ff268f83f 100644 --- a/include/grub/util/lvm.h +++ b/include/grub/util/lvm.h @@ -1,7 +1,7 @@ /* lvm.h - LVM support for GRUB utils. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2011 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 @@ -20,7 +20,14 @@ #ifndef GRUB_LVM_UTIL_HEADER #define GRUB_LVM_UTIL_HEADER 1 +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + #ifdef __linux__ +#define LVM_DEV_MAPPER_STRING "/dev/mapper/" +#else +#define LVM_DEV_MAPPER_STRING "/dev/linux_lvm/" +#endif + int grub_util_lvm_isvolume (char *name); #endif diff --git a/util/getroot.c b/util/getroot.c index 71064583f..7c5602e71 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -1,7 +1,7 @@ /* getroot.c - Get root device */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011 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 @@ -33,6 +33,7 @@ #include #include #include +#include #include #ifdef HAVE_DEVICE_MAPPER @@ -856,12 +857,14 @@ grub_util_get_geom_abstraction (const char *dev) int grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) { -#ifdef __linux__ - enum grub_dev_abstraction_types ret; - +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) /* User explicitly claims that this drive is visible by BIOS. */ if (grub_util_biosdisk_is_present (os_dev)) return GRUB_DEV_ABSTRACTION_NONE; +#endif + +#ifdef __linux__ + enum grub_dev_abstraction_types ret; /* Check for LVM and LUKS. */ ret = grub_util_get_dm_abstraction (os_dev); @@ -880,6 +883,10 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) grub_util_info ("abstraction of %s is %s", os_dev, abs); if (abs && grub_strcasecmp (abs, "eli") == 0) return GRUB_DEV_ABSTRACTION_GELI; + + /* Check for LVM. */ + if (!strncmp (os_dev, LVM_DEV_MAPPER_STRING, sizeof(LVM_DEV_MAPPER_STRING)-1)) + return GRUB_DEV_ABSTRACTION_LVM; #endif /* No abstraction found. */ @@ -1111,11 +1118,12 @@ grub_util_get_grub_dev (const char *os_dev) switch (grub_util_get_dev_abstraction (os_dev)) { +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) case GRUB_DEV_ABSTRACTION_LVM: { unsigned short i, len; - grub_size_t offset = sizeof ("/dev/mapper/") - 1; + grub_size_t offset = sizeof (LVM_DEV_MAPPER_STRING) - 1; len = strlen (os_dev) - offset + 1; grub_dev = xmalloc (len + sizeof ("lvm/")); @@ -1191,7 +1199,9 @@ grub_util_get_grub_dev (const char *os_dev) } #endif break; +#endif +#ifdef __linux__ case GRUB_DEV_ABSTRACTION_RAID: if (os_dev[7] == '_' && os_dev[8] == 'd') @@ -1267,7 +1277,6 @@ grub_util_get_grub_dev (const char *os_dev) else grub_util_error ("unknown kind of RAID device `%s'", os_dev); -#ifdef __linux__ { char *mdadm_name = get_mdadm_uuid (os_dev); struct stat st; @@ -1292,9 +1301,8 @@ grub_util_get_grub_dev (const char *os_dev) free (mdadm_name); } } -#endif /* __linux__ */ - break; +#endif /* __linux__ */ default: /* GRUB_DEV_ABSTRACTION_NONE */ grub_dev = grub_util_biosdisk_get_grub_dev (os_dev); diff --git a/util/grub-setup.c b/util/grub-setup.c index 2505c03a4..b3a6c5c76 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -1,7 +1,7 @@ /* grub-setup.c - make GRUB usable */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 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 @@ -954,10 +954,12 @@ main (int argc, char *argv[]) arguments.dir ? : DEFAULT_DIRECTORY); } -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (grub_util_lvm_isvolume (root_dev)) must_embed = 1; +#endif +#ifdef __linux__ if (root_dev[0] == 'm' && root_dev[1] == 'd' && ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/')) { diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 2ade4ea35..e4bfc06cb 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -2,7 +2,7 @@ set -e # grub-mkconfig helper script. -# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. +# Copyright (C) 2006,2007,2008,2009,2010,2011 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 @@ -98,6 +98,12 @@ EOF load_kfreebsd_module acpi true + for abstraction in dummy $(grub-probe -t abstraction --device ${GRUB_DEVICE}) ; do + case $abstraction in + lvm) load_kfreebsd_module geom_linux_lvm false ;; + esac + done + case "${kfreebsd_fs}" in zfs) load_kfreebsd_module opensolaris false diff --git a/util/lvm.c b/util/lvm.c index bb2c19fe3..0bc271e46 100644 --- a/util/lvm.c +++ b/util/lvm.c @@ -1,7 +1,7 @@ /* lvm.c - LVM support for GRUB utils. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008,2011 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 @@ -17,8 +17,7 @@ * along with GRUB. If not, see . */ -/* We only support LVM on Linux. */ -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #include #include #include @@ -26,8 +25,6 @@ #include #include -#define LVM_DEV_MAPPER_STRING "/dev/mapper/" - int grub_util_lvm_isvolume (char *name) { @@ -49,4 +46,4 @@ grub_util_lvm_isvolume (char *name) return 1; } -#endif /* ! __linux__ */ +#endif From a53cf6534d5a0acd02120c6dff949bf01dfe38a9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 Oct 2011 10:20:55 +0200 Subject: [PATCH 385/673] some more ipv6 code --- grub-core/Makefile.core.def | 1 + grub-core/net/bootp.c | 3 +- grub-core/net/ethernet.c | 7 +- grub-core/net/icmp.c | 23 +++- grub-core/net/icmp6.c | 235 ++++++++++++++++++++++++++++++++++++ grub-core/net/ip.c | 37 ++++-- grub-core/net/net.c | 207 ++++++++++++++++++++++++++----- grub-core/net/tcp.c | 7 ++ grub-core/net/udp.c | 7 ++ include/grub/net.h | 24 +++- include/grub/net/ethernet.h | 2 +- include/grub/net/ip.h | 35 ++++-- 12 files changed, 528 insertions(+), 60 deletions(-) create mode 100644 grub-core/net/icmp6.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index aa5f2bfe7..3827227b8 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1603,6 +1603,7 @@ module = { common = net/udp.c; common = net/tcp.c; common = net/icmp.c; + common = net/icmp6.c; common = net/ethernet.c; common = net/arp.c; common = net/netbuff.c; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 3187f2e9c..1b8527255 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -130,7 +130,7 @@ grub_net_configure_by_dhcp_ack (const char *name, : sizeof (hwaddr.mac)); hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - inter = grub_net_add_addr (name, card, addr, hwaddr, flags); + inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); if (bp->gateway_ip) { grub_net_network_level_netaddress_t target; @@ -379,6 +379,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), "unrecognised format specification %s", args[3]); } +/* FIXME: allow to specify mac address. */ static grub_err_t grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 053f87b56..8d7f66830 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -81,7 +81,7 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_err_t grub_net_recv_ethernet_packet (struct grub_net_buff * nb, - const struct grub_net_card * card) + struct grub_net_card * card) { struct etherhdr *eth; struct llchdr *llch; @@ -123,11 +123,8 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb, return GRUB_ERR_NONE; /* IP packet. */ case GRUB_NET_ETHERTYPE_IP: - grub_net_recv_ip4_packets (nb, card, &hwaddress); - return GRUB_ERR_NONE; case GRUB_NET_ETHERTYPE_IP6: - grub_net_recv_ip4_packets (nb, card, &hwaddress); - return GRUB_ERR_NONE; + return grub_net_recv_ip_packets (nb, card, &hwaddress); } grub_netbuff_free (nb); return GRUB_ERR_NONE; diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c index 8ea020107..88132b142 100644 --- a/grub-core/net/icmp.c +++ b/grub-core/net/icmp.c @@ -25,13 +25,13 @@ struct icmp_header grub_uint8_t type; grub_uint8_t code; grub_uint16_t checksum; -}; +} __attribute__ ((packed)); struct ping_header { grub_uint16_t id; grub_uint16_t seq; -}; +} __attribute__ ((packed)); enum { @@ -40,7 +40,7 @@ enum }; grub_err_t -grub_net_recv_icmp_packet (struct grub_net_buff * nb, +grub_net_recv_icmp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *src) { @@ -48,15 +48,28 @@ grub_net_recv_icmp_packet (struct grub_net_buff * nb, grub_err_t err; grub_uint16_t checksum; + /* Ignore broadcast. */ + if (!inf) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + icmph = (struct icmp_header *) nb->data; if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "ICMP packet too small"); + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } checksum = icmph->checksum; icmph->checksum = 0; if (checksum != grub_net_ip_chksum (nb->data, nb->tail - nb->data)) - return GRUB_ERR_NONE; + { + icmph->checksum = checksum; + return GRUB_ERR_NONE; + } icmph->checksum = checksum; err = grub_netbuff_pull (nb, sizeof (*icmph)); diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c new file mode 100644 index 000000000..ac12c5733 --- /dev/null +++ b/grub-core/net/icmp6.c @@ -0,0 +1,235 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#include +#include +#include + +struct icmp_header +{ + grub_uint8_t type; + grub_uint8_t code; + grub_uint16_t checksum; +} __attribute__ ((packed)); + +struct ping_header +{ + grub_uint16_t id; + grub_uint16_t seq; +} __attribute__ ((packed)); + +struct router_adv +{ + grub_uint8_t ttl; + grub_uint8_t flags; + grub_uint16_t router_lifetime; + grub_uint32_t reachable_time; + grub_uint32_t retrans_timer; + grub_uint8_t options[0]; +} __attribute__ ((packed)); + +struct prefix_option +{ + grub_uint8_t type; + grub_uint8_t len; + grub_uint8_t prefixlen; + grub_uint8_t flags; + grub_uint32_t valid_lifetime; + grub_uint32_t prefered_lifetime; + grub_uint32_t reserved; + grub_uint64_t prefix[2]; +} __attribute__ ((packed)); + +enum + { + FLAG_SLAAC = 0x40 + }; + +enum + { + ICMP6_ECHO = 128, + ICMP6_ECHO_REPLY = 129, + ICMP6_ROUTER_ADVERTISE = 134 + }; + +grub_err_t +grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + struct grub_net_card *card, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source, + const grub_net_network_level_address_t *dest) +{ + struct icmp_header *icmph; + grub_err_t err; + grub_uint16_t checksum; + + icmph = (struct icmp_header *) nb->data; + + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph)) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + checksum = icmph->checksum; + icmph->checksum = 0; + if (checksum != grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_ICMPV6, + source, + dest)) + { + grub_dprintf ("net", "invalid ICMPv6 checksum: %04x instead of %04x\n", + checksum, + grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_ICMPV6, + source, + dest)); + icmph->checksum = checksum; + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + icmph->checksum = checksum; + + err = grub_netbuff_pull (nb, sizeof (*icmph)); + if (err) + return err; + + grub_dprintf ("net", "ICMPv6 message: %02x, %02x\n", + icmph->type, icmph->code); + switch (icmph->type) + { + case ICMP6_ECHO: + /* Don't accept multicast pings. */ + if (!inf) + break; + { + struct grub_net_buff *nb_reply; + struct icmp_header *icmphr; + if (icmph->code) + break; + nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512); + if (!nb_reply) + { + grub_netbuff_free (nb); + return grub_errno; + } + err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512); + if (err) + goto ping_fail; + err = grub_netbuff_push (nb_reply, nb->tail - nb->data); + if (err) + goto ping_fail; + grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data); + err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); + if (err) + goto ping_fail; + icmphr = (struct icmp_header *) nb_reply->data; + icmphr->type = ICMP6_ECHO_REPLY; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_transport_checksum (nb_reply, + GRUB_NET_IP_ICMPV6, + &inf->address, + source); + err = grub_net_send_ip_packet (inf, source, nb_reply, + GRUB_NET_IP_ICMPV6); + + ping_fail: + grub_netbuff_free (nb); + grub_netbuff_free (nb_reply); + return err; + } + case ICMP6_ROUTER_ADVERTISE: + { + grub_uint8_t *ptr; + if (icmph->code) + break; + err = grub_netbuff_pull (nb, sizeof (struct router_adv)); + if (err) + return err; + for (ptr = (grub_uint8_t *) nb->data + sizeof (struct router_adv); + ptr < nb->tail; ) + { + grub_dprintf ("net", "option %02x, %02x\n", ptr[0], ptr[1]); + if (ptr + 2 >= nb->tail || ptr[1] == 0) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (ptr[0] == 3 && ptr[1] == 4) + { + struct prefix_option *opt = (struct prefix_option *) ptr; + struct grub_net_slaac_mac_list *slaac; + if (!(opt->flags & FLAG_SLAAC) + || (grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80 + || (grub_be_to_cpu32 (opt->prefered_lifetime) + > grub_be_to_cpu32 (opt->valid_lifetime)) + || opt->prefixlen != 64) + { + ptr += ptr[1] * 8; + grub_dprintf ("net", "discarded prefix: %d, %d, %d, %d\n", + !(opt->flags & FLAG_SLAAC), + (grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80, + (grub_be_to_cpu32 (opt->prefered_lifetime) + > grub_be_to_cpu32 (opt->valid_lifetime)), + opt->prefixlen != 64); + continue; + } + for (slaac = card->slaac_list; slaac; slaac = slaac->next) + { + grub_net_network_level_address_t addr; + if (slaac->address.type + != GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET) + continue; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + addr.ipv6[0] = opt->prefix[0]; + addr.ipv6[1] = grub_net_ipv6_get_id (&slaac->address); + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && grub_net_addr_cmp (&inf->address, &addr) == 0) + break; + } + /* Update lease time if needed here once we have + lease times. */ + if (inf) + continue; + + grub_dprintf ("net", "creating slaac\n"); + + { + char name[grub_strlen (slaac->name) + + sizeof (":XXXXXXXXXXXXXXXXXXXX")]; + grub_snprintf (name, sizeof (name), "%s:%d", + slaac->name, slaac->slaac_counter++); + grub_net_add_addr (name, + card, &addr, + &slaac->address, 0); + } + } + } + ptr += ptr[1] * 8; + } + if (ptr != nb->tail) + break; + } + }; + + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 32a7d7fe7..18593da49 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -221,7 +221,7 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface * inf, static grub_err_t handle_dgram (struct grub_net_buff *nb, - const struct grub_net_card *card, + struct grub_net_card *card, const grub_net_link_level_address_t *hwaddress, grub_net_ip_protocol_t proto, const grub_net_network_level_address_t *source, @@ -282,8 +282,12 @@ handle_dgram (struct grub_net_buff *nb, break; } - if (!inf) + if (!inf && !(dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && dest->ipv6[0] == grub_be_to_cpu64 (0xff02ULL << 48) + && dest->ipv6[1] == grub_be_to_cpu64 (1))) { + grub_dprintf ("net", "undirected dgram discarded: %x, %lx, %lx\n", + dest->type, dest->ipv6[0], dest->ipv6[1]); grub_netbuff_free (nb); return GRUB_ERR_NONE; } @@ -296,6 +300,8 @@ handle_dgram (struct grub_net_buff *nb, return grub_net_recv_tcp_packet (nb, inf, source); case GRUB_NET_IP_ICMP: return grub_net_recv_icmp_packet (nb, inf, source); + case GRUB_NET_IP_ICMPV6: + return grub_net_recv_icmp6_packet (nb, card, inf, source, dest); default: grub_netbuff_free (nb); break; @@ -330,9 +336,9 @@ free_old_fragments (void) } } -grub_err_t +static grub_err_t grub_net_recv_ip4_packets (struct grub_net_buff * nb, - const struct grub_net_card * card, + struct grub_net_card * card, const grub_net_link_level_address_t * hwaddress) { struct iphdr *iph = (struct iphdr *) nb->data; @@ -590,12 +596,11 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, default: return grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP"); } - } -grub_err_t +static grub_err_t grub_net_recv_ip6_packets (struct grub_net_buff * nb, - const struct grub_net_card * card, + struct grub_net_card * card, const grub_net_link_level_address_t * hwaddress) { struct ip6hdr *iph = (struct ip6hdr *) nb->data; @@ -652,8 +657,24 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb, source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; grub_memcpy (source.ipv6, &iph->src, sizeof (source.ipv6)); - grub_memcpy (dest.ipv6, &iph->src, sizeof (dest.ipv6)); + grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6)); return handle_dgram (nb, card, hwaddress, iph->protocol, &source, &dest); } + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff * nb, + struct grub_net_card * card, + const grub_net_link_level_address_t * hwaddress) +{ + struct iphdr *iph = (struct iphdr *) nb->data; + + if ((iph->verhdrlen >> 4) == 4) + return grub_net_recv_ip4_packets (nb, card, hwaddress); + if ((iph->verhdrlen >> 4) == 6) + return grub_net_recv_ip6_packets (nb, card, hwaddress); + grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 398e6f5ae..1c6d47757 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,151 @@ grub_net_card_unregister (struct grub_net_card *card) GRUB_AS_LIST (card)); } +static struct grub_net_slaac_mac_list * +grub_net_ipv6_get_slaac (struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddr) +{ + struct grub_net_slaac_mac_list *slaac; + char *ptr; + + for (slaac = card->slaac_list; slaac; slaac = slaac->next) + if (grub_net_hwaddr_cmp (&slaac->address, hwaddr) == 0) + return slaac; + + slaac = grub_zalloc (sizeof (*slaac)); + if (!slaac) + return NULL; + + slaac->name = grub_malloc (grub_strlen (card->name) + + GRUB_NET_MAX_STR_HWADDR_LEN + + sizeof (":slaac")); + ptr = grub_stpcpy (slaac->name, card->name); + if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0) + { + ptr = grub_stpcpy (ptr, ":"); + grub_net_hwaddr_to_str (hwaddr, ptr); + ptr += grub_strlen (ptr); + } + ptr = grub_stpcpy (ptr, ":slaac"); + + grub_memcpy (&slaac->address, hwaddr, sizeof (slaac->address)); + slaac->next = card->slaac_list; + card->slaac_list = slaac; + return slaac; +} + +struct grub_net_network_level_interface * +grub_net_ipv6_get_link_local (struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddr) +{ + struct grub_net_network_level_interface *inf; + char name[grub_strlen (card->name) + + GRUB_NET_MAX_STR_HWADDR_LEN + + sizeof (":link")]; + char *ptr; + grub_net_network_level_address_t addr; + + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + addr.ipv6[0] = grub_cpu_to_be64 (0xfe80ULL << 48); + addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddr) == 0 + && grub_net_addr_cmp (&inf->address, &addr) == 0) + return inf; + } + + ptr = grub_stpcpy (name, card->name); + if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0) + { + ptr = grub_stpcpy (ptr, ":"); + grub_net_hwaddr_to_str (hwaddr, ptr); + ptr += grub_strlen (ptr); + } + ptr = grub_stpcpy (ptr, ":link"); + return grub_net_add_addr (name, card, &addr, hwaddr, 0); +} + +/* FIXME: allow to specify mac address. */ +static grub_err_t +grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_interface **ifaces; + grub_size_t ncards = 0; + unsigned j = 0; + int interval; + grub_err_t err; + struct grub_net_slaac_mac_list **slaacs; + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ncards++; + } + + ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); + slaacs = grub_zalloc (ncards * sizeof (slaacs[0])); + if (!ifaces || !slaacs) + { + grub_free (ifaces); + grub_free (slaacs); + return grub_errno; + } + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ifaces[j] = grub_net_ipv6_get_link_local (card, &card->default_address); + if (!ifaces[j]) + { + grub_free (ifaces); + grub_free (slaacs); + return grub_errno; + } + slaacs[j] = grub_net_ipv6_get_slaac (card, &card->default_address); + if (!slaacs[j]) + { + grub_free (ifaces); + grub_free (slaacs); + return grub_errno; + } + j++; + } + + for (interval = 200; interval < 10000; interval *= 2) + { + /* FIXME: send router solicitation. */ + int done = 1; + for (j = 0; j < ncards; j++) + { + if (slaacs[j]->slaac_counter) + continue; + done = 0; + } + if (done) + break; + grub_net_poll_cards (interval); + } + + err = GRUB_ERR_NONE; + for (j = 0; j < ncards; j++) + { + if (slaacs[j]->slaac_counter) + continue; + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", + ifaces[j]->card->name); + } + + grub_free (ifaces); + grub_free (slaacs); + return err; +} static inline void grub_net_route_register (struct grub_net_route *route) @@ -265,20 +411,22 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: { char *ptr = buf; - grub_uint32_t n = grub_be_to_cpu32 (target->ipv6[0]); + grub_uint64_t n = grub_be_to_cpu64 (target->ipv6[0]); int i; for (i = 0; i < 4; i++) { - grub_snprintf (ptr, 6, "%x:", (n >> (48 - 16 * i)) & 0xffff); + grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":", + (n >> (48 - 16 * i)) & 0xffff); ptr += grub_strlen (ptr); } - n = grub_be_to_cpu32 (target->ipv6[1]); + n = grub_be_to_cpu64 (target->ipv6[1]); for (i = 0; i < 3; i++) { - grub_snprintf (ptr, 6, "%x:", (n >> (48 - 16 * i)) & 0xffff); + grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":", + (n >> (48 - 16 * i)) & 0xffff); ptr += grub_strlen (ptr); } - grub_snprintf (ptr, 5, "%x", n & 0xffff); + grub_snprintf (ptr, 5, "%" PRIxGRUB_UINT64_T, n & 0xffff); return; } case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: @@ -290,18 +438,13 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) } return; } - grub_printf ("Unknown address type %d\n", target->type); + grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN, + "Unknown address type %d", target->type); } -/* - Currently suppoerted adresses: - ethernet: XX:XX:XX:XX:XX:XX - */ -#define MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) - -static void -hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) +void +grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) { str[0] = 0; switch (addr->type) @@ -312,7 +455,7 @@ hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) unsigned i; for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++) { - grub_snprintf (ptr, MAX_STR_HWADDR_LEN - (ptr - str), + grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str), "%02x:", addr->mac[i] & 0xff); ptr += (sizeof ("XX:") - 1); } @@ -380,9 +523,9 @@ static void grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) { { - char buf[MAX_STR_HWADDR_LEN]; + char buf[GRUB_NET_MAX_STR_HWADDR_LEN]; char name[grub_strlen (inter->name) + sizeof ("net__mac")]; - hwaddr_to_str (&inter->hwaddress, buf); + grub_net_hwaddr_to_str (&inter->hwaddress, buf); grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name); grub_env_set (name, buf); grub_register_variable_hook (name, 0, hwaddr_set_env); @@ -408,8 +551,8 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr, - grub_net_link_level_address_t hwaddress, + const grub_net_network_level_address_t *addr, + const grub_net_link_level_address_t *hwaddress, grub_net_interface_flags_t flags) { struct grub_net_network_level_interface *inter; @@ -419,8 +562,8 @@ grub_net_add_addr (const char *name, return NULL; inter->name = grub_strdup (name); - grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); - grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress)); + grub_memcpy (&(inter->address), addr, sizeof (inter->address)); + grub_memcpy (&(inter->hwaddress), hwaddress, sizeof (inter->hwaddress)); inter->flags = flags; inter->card = card; inter->dhcp_ack = NULL; @@ -428,10 +571,10 @@ grub_net_add_addr (const char *name, grub_net_network_level_interface_register (inter); - if (addr.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + if (addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) { int mask = -1; - grub_uint32_t ip_cpu = grub_be_to_cpu32 (addr.ipv4); + grub_uint32_t ip_cpu = grub_be_to_cpu32 (addr->ipv4); if (!(ip_cpu & 0x80000000)) mask = 8; else if (!(ip_cpu & 0x40000000)) @@ -498,7 +641,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE) flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE; - grub_net_add_addr (args[0], card, addr, card->default_address, + grub_net_add_addr (args[0], card, &addr, &card->default_address, flags); return grub_errno; } @@ -685,8 +828,8 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_card *card; FOR_NET_CARDS(card) { - char buf[MAX_STR_HWADDR_LEN]; - hwaddr_to_str (&card->default_address, buf); + char buf[GRUB_NET_MAX_STR_HWADDR_LEN]; + grub_net_hwaddr_to_str (&card->default_address, buf); grub_printf ("%s %s\n", card->name, buf); } return GRUB_ERR_NONE; @@ -700,9 +843,9 @@ grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_network_level_interface *inf; FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { - char bufh[MAX_STR_HWADDR_LEN]; + char bufh[GRUB_NET_MAX_STR_HWADDR_LEN]; char bufn[GRUB_NET_MAX_STR_ADDR_LEN]; - hwaddr_to_str (&inf->hwaddress, bufh); + grub_net_hwaddr_to_str (&inf->hwaddress, bufh); grub_net_addr_to_str (&inf->address, bufn); grub_printf ("%s %s %s\n", inf->name, bufh, bufn); } @@ -1060,13 +1203,18 @@ static void *fini_hnd; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards; -static grub_command_t cmd_lsaddr; +static grub_command_t cmd_lsaddr, cmd_slaac; GRUB_MOD_INIT(net) { cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, "SHORTNAME CARD ADDRESS [HWADDRESS]", N_("Add a network address.")); + cmd_slaac = grub_register_command ("net_ipv6_autoconf", + grub_cmd_ipv6_autoconf, + "[CARD [HWADDRESS]]", + N_("Perform an IPV6 autoconfiguration")); + cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, "SHORTNAME", N_("Delete a network address.")); @@ -1102,6 +1250,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_lsaddr); + grub_unregister_command (cmd_slaac); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; grub_net_fini_hw (0); diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index b1eb3d9a8..72ee8a239 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -695,6 +695,13 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, grub_net_tcp_socket_t sock; grub_err_t err; + /* Ignore broadcast. */ + if (!inf) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + tcph = (struct tcphdr *) nb->data; if ((grub_be_to_cpu16 (tcph->flags) >> 12) < 5) { diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index e816547ac..a2315dd3f 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -140,6 +140,13 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb, grub_net_udp_socket_t sock; grub_err_t err; + /* Ignore broadcast. */ + if (!inf) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + udph = (struct udphdr *) nb->data; if (nb->tail - nb->data < (grub_ssize_t) sizeof (*udph)) { diff --git a/include/grub/net.h b/include/grub/net.h index cb9d40cd0..a4785d48c 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -97,6 +97,14 @@ typedef struct grub_net_packets #include #endif +struct grub_net_slaac_mac_list +{ + struct grub_net_slaac_mac_list *next; + grub_net_link_level_address_t address; + int slaac_counter; + char *name; +}; + struct grub_net_card { struct grub_net_card *next; @@ -109,6 +117,7 @@ struct grub_net_card unsigned idle_poll_delay_ms; grub_uint64_t last_poll; grub_size_t mtu; + struct grub_net_slaac_mac_list *slaac_list; union { #ifdef GRUB_MACHINE_EFI @@ -282,8 +291,8 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr, - grub_net_link_level_address_t hwaddress, + const grub_net_network_level_address_t *addr, + const grub_net_link_level_address_t *hwaddress, grub_net_interface_flags_t flags); extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; @@ -404,13 +413,22 @@ grub_net_addr_cmp (const grub_net_network_level_address_t *a, /* Currently supported adresses: IPv4: XXX.XXX.XXX.XXX - IPv&: XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX + IPv6: XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX */ #define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX") +/* + Currently suppoerted adresses: + ethernet: XX:XX:XX:XX:XX:XX + */ + +#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) + void grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf); +void +grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; #define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index 0749d9d87..23a935e98 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -36,6 +36,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, grub_net_ethertype_t ethertype); grub_err_t grub_net_recv_ethernet_packet (struct grub_net_buff *nb, - const struct grub_net_card *card); + struct grub_net_card *card); #endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 759577522..e086f4411 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -25,20 +25,29 @@ typedef enum grub_net_ip_protocol { GRUB_NET_IP_ICMP = 1, GRUB_NET_IP_TCP = 6, - GRUB_NET_IP_UDP = 17 + GRUB_NET_IP_UDP = 17, + GRUB_NET_IP_ICMPV6 = 58 } grub_net_ip_protocol_t; #define GRUB_NET_IP_BROADCAST 0xFFFFFFFF +static inline grub_uint64_t +grub_net_ipv6_get_id (const grub_net_link_level_address_t *addr) +{ + return grub_cpu_to_be64 (((grub_uint64_t) (addr->mac[0] ^ 2) << 56) + | ((grub_uint64_t) addr->mac[1] << 48) + | ((grub_uint64_t) addr->mac[2] << 40) + | 0xfffe000000ULL + | ((grub_uint64_t) addr->mac[3] << 16) + | ((grub_uint64_t) addr->mac[4] << 8) + | ((grub_uint64_t) addr->mac[5])); +} + grub_uint16_t grub_net_ip_chksum(void *ipv, grub_size_t len); grub_err_t -grub_net_recv_ip4_packets (struct grub_net_buff *nb, - const struct grub_net_card *card, - const grub_net_link_level_address_t *hwaddress); -grub_err_t -grub_net_recv_ip6_packets (struct grub_net_buff *nb, - const struct grub_net_card *card, - const grub_net_link_level_address_t *hwaddress); +grub_net_recv_ip_packets (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, @@ -51,6 +60,12 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *src); grub_err_t +grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + struct grub_net_card *card, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source, + const grub_net_network_level_address_t *dest); +grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *src); @@ -65,4 +80,8 @@ grub_net_ip_transport_checksum (struct grub_net_buff *nb, const grub_net_network_level_address_t *src, const grub_net_network_level_address_t *dst); +struct grub_net_network_level_interface * +grub_net_ipv6_get_link_local (struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddr); + #endif From 7c006811f8a641b32fc483182e83eaecf9645116 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 Oct 2011 23:15:02 +0200 Subject: [PATCH 386/673] more ipv6 code. Now ipv6 ping succeeds --- grub-core/net/arp.c | 116 +++------------ grub-core/net/ethernet.c | 6 +- grub-core/net/icmp6.c | 304 +++++++++++++++++++++++++++++++++++++-- grub-core/net/ip.c | 66 ++++++--- grub-core/net/net.c | 139 ++++++++++++++++++ include/grub/net.h | 17 +++ include/grub/net/arp.h | 9 +- include/grub/net/ip.h | 6 +- include/grub/types.h | 19 +++ 9 files changed, 541 insertions(+), 141 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index b1b719dbe..b4c10531b 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -46,41 +46,10 @@ struct arphdr { } __attribute__ ((packed)); -struct arp_entry { - int avail; - grub_net_network_level_address_t nl_address; - grub_net_link_level_address_t ll_address; -}; - -static struct arp_entry arp_table[10]; -static grub_int8_t new_table_entry = -1; - -static void -arp_init_table (void) -{ - grub_memset (arp_table, 0, sizeof (arp_table)); - new_table_entry = 0; -} - -static struct arp_entry * -arp_find_entry (const grub_net_network_level_address_t *proto) -{ - unsigned i; - for (i = 0; i < ARRAY_SIZE (arp_table); i++) - { - if (arp_table[i].avail == 1 && - grub_net_addr_cmp (&arp_table[i].nl_address, proto) == 0) - return &(arp_table[i]); - } - return NULL; -} - grub_err_t -grub_net_arp_resolve (struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *proto_addr, - grub_net_link_level_address_t *hw_addr) +grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) { - struct arp_entry *entry; struct grub_net_buff nb; struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; @@ -90,32 +59,11 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, grub_size_t addrlen; grub_uint16_t etherpro; - if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && proto_addr->ipv4 == 0xffffffff) - { - hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - grub_memset (hw_addr->mac, -1, 6); - return GRUB_ERR_NONE; - } - - /* Check cache table. */ - entry = arp_find_entry (proto_addr); - if (entry) - { - *hw_addr = entry->ll_address; - return GRUB_ERR_NONE; - } - if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) { addrlen = 4; etherpro = GRUB_NET_ETHERTYPE_IP; } - else if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) - { - addrlen = 16; - etherpro = GRUB_NET_ETHERTYPE_IP6; - } else return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported address family"); @@ -141,45 +89,39 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, aux += 6; /* Sender protocol address */ - if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) - grub_memcpy (aux, &inf->address.ipv4, 4); - else - grub_memcpy (aux, &inf->address.ipv6, 16); + grub_memcpy (aux, &inf->address.ipv4, 4); aux += addrlen; /* Target hardware address */ for (i = 0; i < 6; i++) aux[i] = 0x00; aux += 6; /* Target protocol address */ - if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) - grub_memcpy (aux, &proto_addr->ipv4, 4); - else - grub_memcpy (aux, &proto_addr->ipv6, 16); + grub_memcpy (aux, &proto_addr->ipv4, 4); grub_memset (&target_hw_addr.mac, 0xff, 6); send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); for (i = 0; i < GRUB_NET_TRIES; i++) { - entry = arp_find_entry (proto_addr); - if (entry) - { - grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr)); - return GRUB_ERR_NONE; - } + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + return GRUB_ERR_NONE; grub_net_poll_cards (GRUB_NET_INTERVAL); + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + return GRUB_ERR_NONE; + send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); } - return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address"); + return GRUB_ERR_NONE; } grub_err_t -grub_net_arp_receive (struct grub_net_buff *nb) +grub_net_arp_receive (struct grub_net_buff *nb, + struct grub_net_card *card) { struct arphdr *arp_header = (struct arphdr *) nb->data; - struct arp_entry *entry; grub_uint8_t *sender_hardware_address; grub_uint8_t *target_hardware_address; grub_net_network_level_address_t sender_addr, target_addr; + grub_net_link_level_address_t sender_hw_addr; struct grub_net_network_level_interface *inf; grub_uint8_t *sender_protocol_address, *target_protocol_address; @@ -196,35 +138,13 @@ grub_net_arp_receive (struct grub_net_buff *nb) grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4); grub_memcpy (&target_addr.ipv4, target_protocol_address, 4); } - else if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP6 - && arp_header->pln == 16) - { - sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; - target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - grub_memcpy (&sender_addr.ipv6, sender_protocol_address, 16); - grub_memcpy (&target_addr.ipv6, target_protocol_address, 16); - } else return GRUB_ERR_NONE; - - /* Check if the sender is in the cache table. */ - entry = arp_find_entry (&sender_addr); - /* Update sender hardware address. */ - if (entry) - grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); - else - { - /* Add sender to cache table. */ - if (new_table_entry == -1) - arp_init_table (); - entry = &(arp_table[new_table_entry]); - entry->avail = 1; - entry->nl_address = sender_addr; - grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); - new_table_entry++; - if (new_table_entry == ARRAY_SIZE (arp_table)) - new_table_entry = 0; - } + + sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (sender_hw_addr.mac, &sender_hardware_address, + sizeof (sender_hw_addr.mac)); + grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1); FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 8d7f66830..6b5db9aaa 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -80,8 +80,8 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, } grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_buff * nb, - struct grub_net_card * card) +grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + struct grub_net_card *card) { struct etherhdr *eth; struct llchdr *llch; @@ -118,7 +118,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb, { /* ARP packet. */ case GRUB_NET_ETHERTYPE_ARP: - grub_net_arp_receive (nb); + grub_net_arp_receive (nb, card); grub_netbuff_free (nb); return GRUB_ERR_NONE; /* IP packet. */ diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c index ac12c5733..1f9278910 100644 --- a/grub-core/net/icmp6.c +++ b/grub-core/net/icmp6.c @@ -43,10 +43,15 @@ struct router_adv grub_uint8_t options[0]; } __attribute__ ((packed)); -struct prefix_option +struct option_header { grub_uint8_t type; grub_uint8_t len; +} __attribute__ ((packed)); + +struct prefix_option +{ + struct option_header header; grub_uint8_t prefixlen; grub_uint8_t flags; grub_uint32_t valid_lifetime; @@ -55,6 +60,18 @@ struct prefix_option grub_uint64_t prefix[2]; } __attribute__ ((packed)); +struct neighbour_solicit +{ + grub_uint32_t reserved; + grub_uint64_t target[2]; +} __attribute__ ((packed)); + +struct neighbour_advertise +{ + grub_uint32_t flags; + grub_uint64_t target[2]; +} __attribute__ ((packed)); + enum { FLAG_SLAAC = 0x40 @@ -64,7 +81,22 @@ enum { ICMP6_ECHO = 128, ICMP6_ECHO_REPLY = 129, - ICMP6_ROUTER_ADVERTISE = 134 + ICMP6_ROUTER_ADVERTISE = 134, + ICMP6_NEIGHBOUR_SOLICIT = 135, + ICMP6_NEIGHBOUR_ADVERTISE = 136, + }; + +enum + { + OPTION_SOURCE_LINK_LAYER_ADDRESS = 1, + OPTION_TARGET_LINK_LAYER_ADDRESS = 2, + OPTION_PREFIX = 3 + }; + +enum + { + FLAG_SOLICITED = (1 << 30), + FLAG_OVERRIDE = (1 << 29) }; grub_err_t @@ -72,7 +104,8 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, struct grub_net_card *card, struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *source, - const grub_net_network_level_address_t *dest) + const grub_net_network_level_address_t *dest, + grub_uint8_t ttl) { struct icmp_header *icmph; grub_err_t err; @@ -107,7 +140,10 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, err = grub_netbuff_pull (nb, sizeof (*icmph)); if (err) - return err; + { + grub_netbuff_free (nb); + return err; + } grub_dprintf ("net", "ICMPv6 message: %02x, %02x\n", icmph->type, icmph->code); @@ -154,24 +190,180 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, grub_netbuff_free (nb_reply); return err; } - case ICMP6_ROUTER_ADVERTISE: + case ICMP6_NEIGHBOUR_SOLICIT: { + struct neighbour_solicit *nbh; + struct grub_net_buff *nb_reply; + struct option_header *ohdr; + struct neighbour_advertise *adv; + struct icmp_header *icmphr; grub_uint8_t *ptr; + if (icmph->code) break; + if (ttl != 0xff) + break; + nbh = (struct neighbour_solicit *) nb->data; err = grub_netbuff_pull (nb, sizeof (struct router_adv)); if (err) - return err; - for (ptr = (grub_uint8_t *) nb->data + sizeof (struct router_adv); - ptr < nb->tail; ) { - grub_dprintf ("net", "option %02x, %02x\n", ptr[0], ptr[1]); - if (ptr + 2 >= nb->tail || ptr[1] == 0) + grub_netbuff_free (nb); + return err; + } + for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail; + ptr += ohdr->len * 8) + { + ohdr = (struct option_header *) ptr; + if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail) { grub_netbuff_free (nb); return GRUB_ERR_NONE; } - if (ptr[0] == 3 && ptr[1] == 4) + if (ohdr->type == OPTION_SOURCE_LINK_LAYER_ADDRESS + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; + ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && grub_memcmp (&inf->address.ipv6, &nbh->target, 16) == 0) + break; + } + if (!inf) + break; + + nb_reply = grub_netbuff_alloc (sizeof (struct neighbour_advertise) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb_reply) + { + grub_netbuff_free (nb); + return grub_errno; + } + err = grub_netbuff_reserve (nb_reply, + sizeof (struct neighbour_advertise) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + goto ndp_fail; + + err = grub_netbuff_push (nb_reply, 6); + if (err) + goto ndp_fail; + grub_memcpy (nb_reply->data, inf->hwaddress.mac, 6); + err = grub_netbuff_push (nb_reply, sizeof (*ohdr)); + if (err) + goto ndp_fail; + ohdr = (struct option_header *) nb_reply->data; + ohdr->type = OPTION_TARGET_LINK_LAYER_ADDRESS; + ohdr->len = 1; + err = grub_netbuff_push (nb_reply, sizeof (*adv)); + if (err) + goto ndp_fail; + adv = (struct neighbour_advertise *) nb_reply->data; + adv->flags = grub_cpu_to_be32_compile_time (FLAG_SOLICITED + | FLAG_OVERRIDE); + grub_memcpy (&adv->target, &nbh->target, 16); + + err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); + if (err) + goto ndp_fail; + icmphr = (struct icmp_header *) nb_reply->data; + icmphr->type = ICMP6_NEIGHBOUR_ADVERTISE; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_transport_checksum (nb_reply, + GRUB_NET_IP_ICMPV6, + &inf->address, + source); + err = grub_net_send_ip_packet (inf, source, nb_reply, + GRUB_NET_IP_ICMPV6); + + ndp_fail: + grub_netbuff_free (nb); + grub_netbuff_free (nb_reply); + return err; + } + case ICMP6_NEIGHBOUR_ADVERTISE: + { + struct neighbour_advertise *nbh; + grub_uint8_t *ptr; + struct option_header *ohdr; + + if (icmph->code) + break; + if (ttl != 0xff) + break; + nbh = (struct neighbour_advertise *) nb->data; + err = grub_netbuff_pull (nb, sizeof (*nbh)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + + for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail; + ptr += ohdr->len * 8) + { + ohdr = (struct option_header *) ptr; + if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (ohdr->type == OPTION_TARGET_LINK_LAYER_ADDRESS + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; + ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } + break; + } + case ICMP6_ROUTER_ADVERTISE: + { + grub_uint8_t *ptr; + struct option_header *ohdr; + if (icmph->code) + break; + err = grub_netbuff_pull (nb, sizeof (struct router_adv)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail; + ptr += ohdr->len * 8) + { + ohdr = (struct option_header *) ptr; + if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (ohdr->type == OPTION_SOURCE_LINK_LAYER_ADDRESS + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; + ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + if (ohdr->type == OPTION_PREFIX && ohdr->len == 4) { struct prefix_option *opt = (struct prefix_option *) ptr; struct grub_net_slaac_mac_list *slaac; @@ -181,7 +373,6 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, > grub_be_to_cpu32 (opt->valid_lifetime)) || opt->prefixlen != 64) { - ptr += ptr[1] * 8; grub_dprintf ("net", "discarded prefix: %d, %d, %d, %d\n", !(opt->flags & FLAG_SLAAC), (grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80, @@ -223,7 +414,6 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, } } } - ptr += ptr[1] * 8; } if (ptr != nb->tail) break; @@ -233,3 +423,91 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, grub_netbuff_free (nb); return GRUB_ERR_NONE; } + +grub_err_t +grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) +{ + struct grub_net_buff *nb; + grub_err_t err = GRUB_ERR_NONE; + int i; + struct option_header *ohdr; + struct neighbour_solicit *sol; + struct icmp_header *icmphr; + grub_net_network_level_address_t multicast; + + multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + multicast.ipv6[0] = grub_be_to_cpu64_compile_time (0xff02ULL << 48); + multicast.ipv6[1] = (grub_be_to_cpu64_compile_time (0x01ff000000ULL) + | (proto_addr->ipv6[1] + & grub_be_to_cpu64_compile_time (0xffffff))); + + nb = grub_netbuff_alloc (sizeof (struct neighbour_solicit) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb) + return grub_errno; + err = grub_netbuff_reserve (nb, + sizeof (struct neighbour_solicit) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + err = grub_netbuff_push (nb, 6); + if (err) + goto fail; + + grub_memcpy (nb->data, inf->hwaddress.mac, 6); + err = grub_netbuff_push (nb, sizeof (*ohdr)); + if (err) + goto fail; + + ohdr = (struct option_header *) nb->data; + ohdr->type = OPTION_TARGET_LINK_LAYER_ADDRESS; + ohdr->len = 1; + err = grub_netbuff_push (nb, sizeof (*sol)); + if (err) + goto fail; + + sol = (struct neighbour_solicit *) nb->data; + sol->reserved = 0; + grub_memcpy (&sol->target, &proto_addr->ipv6, 16); + + err = grub_netbuff_push (nb, sizeof (*icmphr)); + if (err) + goto fail; + + icmphr = (struct icmp_header *) nb->data; + icmphr->type = ICMP6_NEIGHBOUR_ADVERTISE; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_ICMPV6, + &inf->address, + &multicast); + err = grub_net_send_ip_packet (inf, &multicast, nb, + GRUB_NET_IP_ICMPV6); + if (err) + goto fail; + + for (i = 0; i < GRUB_NET_TRIES; i++) + { + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + break; + grub_net_poll_cards (GRUB_NET_INTERVAL); + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + break; + err = grub_net_send_ip_packet (inf, &multicast, nb, + GRUB_NET_IP_ICMPV6); + if (err) + break; + } + + fail: + grub_netbuff_free (nb); + return err; +} diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 18593da49..27b8221fb 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -87,6 +87,7 @@ struct reassemble grub_uint8_t *asm_buffer; grub_size_t total_len; grub_size_t cur_ptr; + grub_uint8_t ttl; }; struct reassemble *reassembles; @@ -192,7 +193,7 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface * inf, COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph)); /* Determine link layer target address via ARP. */ - err = grub_net_arp_resolve (inf, target, &ll_target_addr); + err = grub_net_link_layer_resolve (inf, target, &ll_target_addr); if (err) return err; @@ -225,10 +226,12 @@ handle_dgram (struct grub_net_buff *nb, const grub_net_link_level_address_t *hwaddress, grub_net_ip_protocol_t proto, const grub_net_network_level_address_t *source, - const grub_net_network_level_address_t *dest) + const grub_net_network_level_address_t *dest, + grub_uint8_t ttl) { struct grub_net_network_level_interface *inf = NULL; grub_err_t err; + int multicast = 0; /* DHCP needs special treatment since we don't know IP yet. */ { @@ -280,17 +283,39 @@ handle_dgram (struct grub_net_buff *nb, && grub_net_addr_cmp (&inf->address, dest) == 0 && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) break; + /* Solicited node multicast. */ + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && dest->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL << 48) + && dest->ipv6[1] == (grub_be_to_cpu64_compile_time (0x01ff000000ULL) + | (inf->address.ipv6[1] + & grub_be_to_cpu64_compile_time (0xffffff))) + && hwaddress->type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET + && hwaddress->mac[0] == 0x33 && hwaddress->mac[1] == 0x33 + && hwaddress->mac[2] == 0xff + && hwaddress->mac[3] == ((grub_be_to_cpu64 (inf->address.ipv6[1]) + >> 16) & 0xff) + && hwaddress->mac[4] == ((grub_be_to_cpu64 (inf->address.ipv6[1]) + >> 8) & 0xff) + && hwaddress->mac[5] == ((grub_be_to_cpu64 (inf->address.ipv6[1]) + >> 0) & 0xff)) + { + multicast = 1; + break; + } } if (!inf && !(dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 - && dest->ipv6[0] == grub_be_to_cpu64 (0xff02ULL << 48) - && dest->ipv6[1] == grub_be_to_cpu64 (1))) + && dest->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL + << 48) + && dest->ipv6[1] == grub_be_to_cpu64_compile_time (1))) { - grub_dprintf ("net", "undirected dgram discarded: %x, %lx, %lx\n", - dest->type, dest->ipv6[0], dest->ipv6[1]); grub_netbuff_free (nb); return GRUB_ERR_NONE; } + if (multicast) + inf = NULL; switch (proto) { @@ -301,7 +326,7 @@ handle_dgram (struct grub_net_buff *nb, case GRUB_NET_IP_ICMP: return grub_net_recv_icmp_packet (nb, inf, source); case GRUB_NET_IP_ICMPV6: - return grub_net_recv_icmp6_packet (nb, card, inf, source, dest); + return grub_net_recv_icmp6_packet (nb, card, inf, source, dest, ttl); default: grub_netbuff_free (nb); break; @@ -414,7 +439,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, dest.ipv4 = iph->dest; return handle_dgram (nb, card, hwaddress, iph->protocol, - &source, &dest); + &source, &dest, iph->ttl); } for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev) @@ -442,8 +467,10 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, rsm->asm_buffer = 0; rsm->total_len = 0; rsm->cur_ptr = 0; + rsm->ttl = 0xff; } - + if (rsm->ttl > iph->ttl) + rsm->ttl = iph->ttl; rsm->last_time = grub_get_time_ms (); free_old_fragments (); @@ -479,6 +506,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, grub_uint32_t dst; grub_net_network_level_address_t source; grub_net_network_level_address_t dest; + grub_uint8_t ttl; nb_top_p = grub_priority_queue_top (rsm->pq); if (!nb_top_p) @@ -521,6 +549,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, proto = rsm->proto; src = rsm->source; dst = rsm->dest; + ttl = rsm->ttl; rsm->asm_buffer = 0; res_len = rsm->total_len; @@ -541,7 +570,8 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; dest.ipv4 = dst; - return handle_dgram (ret, card, hwaddress, proto, &source, &dest); + return handle_dgram (ret, card, hwaddress, proto, &source, &dest, + ttl); } return GRUB_ERR_NONE; @@ -560,7 +590,7 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf, COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph)); /* Determine link layer target address via ARP. */ - err = grub_net_arp_resolve (inf, target, &ll_target_addr); + err = grub_net_link_layer_resolve (inf, target, &ll_target_addr); if (err) return err; @@ -571,14 +601,14 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf, iph = (struct ip6hdr *) nb->data; iph->version_class_flow = grub_cpu_to_be32 ((6 << 28)); - iph->len = grub_cpu_to_be16 (nb->tail - nb->data) - sizeof (*iph); + iph->len = grub_cpu_to_be16 (nb->tail - nb->data - sizeof (*iph)); iph->protocol = proto; iph->ttl = 0xff; grub_memcpy (&iph->src, inf->address.ipv6, sizeof (iph->src)); grub_memcpy (&iph->dest, target->ipv6, sizeof (iph->dest)); return send_ethernet_packet (inf, nb, ll_target_addr, - GRUB_NET_ETHERTYPE_IP); + GRUB_NET_ETHERTYPE_IP6); } grub_err_t @@ -608,14 +638,6 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb, grub_net_network_level_address_t source; grub_net_network_level_address_t dest; - if ((grub_be_to_cpu32 (iph->version_class_flow) >> 28) != 6) - { - grub_dprintf ("net", "Bad IP version: %d\n", - (grub_be_to_cpu32 (iph->version_class_flow) >> 28)); - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - if (nb->tail - nb->data < (grub_ssize_t) sizeof (*iph)) { grub_dprintf ("net", "IP packet too short: %" PRIdGRUB_SSIZE "\n", @@ -660,7 +682,7 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb, grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6)); return handle_dgram (nb, card, hwaddress, iph->protocol, - &source, &dest); + &source, &dest, iph->ttl); } grub_err_t diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1c6d47757..1134223b2 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,144 @@ struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static struct grub_fs grub_net_fs; +struct grub_net_link_layer_entry { + int avail; + grub_net_network_level_address_t nl_address; + grub_net_link_level_address_t ll_address; +}; + +#define LINK_LAYER_CACHE_SIZE 256 + +static struct grub_net_link_layer_entry * +link_layer_find_entry (const grub_net_network_level_address_t *proto, + const struct grub_net_card *card) +{ + unsigned i; + if (!card->link_layer_table) + return NULL; + for (i = 0; i < LINK_LAYER_CACHE_SIZE; i++) + { + if (card->link_layer_table[i].avail == 1 + && grub_net_addr_cmp (&card->link_layer_table[i].nl_address, + proto) == 0) + return &card->link_layer_table[i]; + } + return NULL; +} + +void +grub_net_link_layer_add_address (struct grub_net_card *card, + const grub_net_network_level_address_t *nl, + const grub_net_link_level_address_t *ll, + int override) +{ + struct grub_net_link_layer_entry *entry; + + /* Check if the sender is in the cache table. */ + entry = link_layer_find_entry (nl, card); + /* Update sender hardware address. */ + if (entry && override) + grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address)); + if (entry) + return; + + /* Add sender to cache table. */ + if (card->link_layer_table == NULL) + card->link_layer_table = grub_zalloc (LINK_LAYER_CACHE_SIZE + * sizeof (card->link_layer_table[0])); + entry = &(card->link_layer_table[card->new_ll_entry]); + entry->avail = 1; + grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address)); + grub_memcpy (&entry->nl_address, nl, sizeof (entry->nl_address)); + card->new_ll_entry++; + if (card->new_ll_entry == LINK_LAYER_CACHE_SIZE) + card->new_ll_entry = 0; +} + +int +grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) +{ + struct grub_net_link_layer_entry *entry; + + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && proto_addr->ipv4 == 0xffffffff) + return 1; + entry = link_layer_find_entry (proto_addr, inf->card); + if (entry) + return 1; + return 0; +} + +grub_err_t +grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr, + grub_net_link_level_address_t *hw_addr) +{ + struct grub_net_link_layer_entry *entry; + grub_err_t err; + + if ((proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && proto_addr->ipv4 == 0xffffffff) + || proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV + || (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && proto_addr->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL + << 48) + && proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1)))) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memset (hw_addr->mac, -1, 6); + return GRUB_ERR_NONE; + } + + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff)) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + hw_addr->mac[0] = 0x33; + hw_addr->mac[1] = 0x33; + hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff); + hw_addr->mac[3] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 16) & 0xff); + hw_addr->mac[4] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 8) & 0xff); + hw_addr->mac[5] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 0) & 0xff); + return GRUB_ERR_NONE; + } + + + + /* Check cache table. */ + entry = link_layer_find_entry (proto_addr, inf->card); + if (entry) + { + *hw_addr = entry->ll_address; + return GRUB_ERR_NONE; + } + switch (proto_addr->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + err = grub_net_arp_send_request (inf, proto_addr); + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + err = grub_net_icmp6_send_request (inf, proto_addr); + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + return grub_error (GRUB_ERR_BUG, "shouldn't reach here"); + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported address type %d", proto_addr->type); + } + if (err) + return err; + entry = link_layer_find_entry (proto_addr, inf->card); + if (entry) + { + *hw_addr = entry->ll_address; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_TIMEOUT, + "timeout: could not resolve hardware address"); +} + void grub_net_card_unregister (struct grub_net_card *card) { diff --git a/include/grub/net.h b/include/grub/net.h index a4785d48c..e3f7525be 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -105,6 +105,8 @@ struct grub_net_slaac_mac_list char *name; }; +struct grub_net_link_layer_entry; + struct grub_net_card { struct grub_net_card *next; @@ -118,6 +120,8 @@ struct grub_net_card grub_uint64_t last_poll; grub_size_t mtu; struct grub_net_slaac_mac_list *slaac_list; + grub_ssize_t new_ll_entry; + struct grub_net_link_layer_entry *link_layer_table; union { #ifdef GRUB_MACHINE_EFI @@ -455,6 +459,19 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter void grub_net_tcp_retransmit (void); +void +grub_net_link_layer_add_address (struct grub_net_card *card, + const grub_net_network_level_address_t *nl, + const grub_net_link_level_address_t *ll, + int override); +int +grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr); +grub_err_t +grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr, + grub_net_link_level_address_t *hw_addr); + extern char *grub_net_default_server; #define GRUB_NET_TRIES 40 diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index 49682184e..bb1703622 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -21,10 +21,11 @@ #include #include -extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb); +extern grub_err_t grub_net_arp_receive (struct grub_net_buff *nb, + struct grub_net_card *card); -extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *addr, - grub_net_link_level_address_t *hw_addr); +grub_err_t +grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr); #endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index e086f4411..78053de60 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -64,7 +64,8 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, struct grub_net_card *card, struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *source, - const grub_net_network_level_address_t *dest); + const grub_net_network_level_address_t *dest, + grub_uint8_t ttl); grub_err_t grub_net_recv_udp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf, @@ -83,5 +84,8 @@ grub_net_ip_transport_checksum (struct grub_net_buff *nb, struct grub_net_network_level_interface * grub_net_ipv6_get_link_local (struct grub_net_card *card, const grub_net_link_level_address_t *hwaddr); +grub_err_t +grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr); #endif diff --git a/include/grub/types.h b/include/grub/types.h index 84bc97455..61cfb0291 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -154,6 +154,18 @@ typedef grub_uint64_t grub_disk_addr_t; #define grub_swap_bytes16_compile_time(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) #define grub_swap_bytes32_compile_time(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000UL) >> 24)) +#define grub_swap_bytes64_compile_time(x) \ +({ \ + grub_uint64_t _x = (x); \ + (grub_uint64_t) ((_x << 56) \ + | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \ + | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \ + | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \ + | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \ + | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \ + | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \ + | (_x >> 56)); \ +}) #if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x) @@ -202,6 +214,9 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_be_to_cpu16(x) ((grub_uint16_t) (x)) # define grub_be_to_cpu32(x) ((grub_uint32_t) (x)) # define grub_be_to_cpu64(x) ((grub_uint64_t) (x)) +# define grub_cpu_to_be32_compile_time(x) ((grub_uint32_t) (x)) +# define grub_cpu_to_be64_compile_time(x) ((grub_uint64_t) (x)) +# define grub_be_to_cpu64_compile_time(x) ((grub_uint64_t) (x)) # define grub_cpu_to_le32_compile_time(x) grub_swap_bytes32_compile_time(x) # define grub_cpu_to_le16_compile_time(x) grub_swap_bytes16_compile_time(x) #else /* ! WORDS_BIGENDIAN */ @@ -217,8 +232,12 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_be_to_cpu16(x) grub_swap_bytes16(x) # define grub_be_to_cpu32(x) grub_swap_bytes32(x) # define grub_be_to_cpu64(x) grub_swap_bytes64(x) +# define grub_cpu_to_be32_compile_time(x) grub_swap_bytes32_compile_time(x) +# define grub_cpu_to_be64_compile_time(x) grub_swap_bytes64_compile_time(x) +# define grub_be_to_cpu64_compile_time(x) grub_swap_bytes64_compile_time(x) # define grub_cpu_to_le16_compile_time(x) ((grub_uint16_t) (x)) # define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x)) + #endif /* ! WORDS_BIGENDIAN */ #endif /* ! GRUB_TYPES_HEADER */ From da1b289afc78bec05607972a832f6efa70383560 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 13 Oct 2011 01:22:56 +0200 Subject: [PATCH 387/673] IPv6. Apparently working. At least I could retrieve a file with http6 --- grub-core/net/arp.c | 5 +- grub-core/net/bootp.c | 2 +- grub-core/net/icmp.c | 4 +- grub-core/net/icmp6.c | 31 ++++++---- grub-core/net/ip.c | 29 ++++----- grub-core/net/net.c | 117 +++++++++++++++++++++++++++++++------ grub-core/net/tcp.c | 40 +++++++------ grub-core/net/udp.c | 15 ++--- include/grub/net.h | 1 + include/grub/net/ip.h | 1 + include/grub/net/netbuff.h | 12 ++-- 11 files changed, 184 insertions(+), 73 deletions(-) diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index b4c10531b..c9a7cb21e 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -58,6 +58,7 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, int i; grub_size_t addrlen; grub_uint16_t etherpro; + grub_uint8_t *nbd; if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) { @@ -99,6 +100,7 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, grub_memcpy (aux, &proto_addr->ipv4, 4); grub_memset (&target_hw_addr.mac, 0xff, 6); + nbd = nb.data; send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); for (i = 0; i < GRUB_NET_TRIES; i++) { @@ -107,6 +109,7 @@ grub_net_arp_send_request (struct grub_net_network_level_interface *inf, grub_net_poll_cards (GRUB_NET_INTERVAL); if (grub_net_link_layer_resolve_check (inf, proto_addr)) return GRUB_ERR_NONE; + nb.data = nbd; send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); } @@ -142,7 +145,7 @@ grub_net_arp_receive (struct grub_net_buff *nb, return GRUB_ERR_NONE; sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - grub_memcpy (sender_hw_addr.mac, &sender_hardware_address, + grub_memcpy (sender_hw_addr.mac, sender_hardware_address, sizeof (sender_hw_addr.mac)); grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1); diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 1b8527255..be79463ce 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -493,7 +493,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), &ifaces[j].address, &target); - err = grub_net_send_ip_packet (&ifaces[j], &target, nb, + err = grub_net_send_ip_packet (&ifaces[j], &target, NULL, nb, GRUB_NET_IP_UDP); grub_netbuff_free (nb); if (err) diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c index 88132b142..9e6bc5c6f 100644 --- a/grub-core/net/icmp.c +++ b/grub-core/net/icmp.c @@ -106,7 +106,9 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb, icmphr->checksum = 0; icmphr->checksum = grub_net_ip_chksum ((void *) nb_reply->data, nb_reply->tail - nb_reply->data); - err = grub_net_send_ip_packet (inf, src, nb_reply, GRUB_NET_IP_ICMP); + /* FIXME: gateway pings. */ + err = grub_net_send_ip_packet (inf, src, NULL, + nb_reply, GRUB_NET_IP_ICMP); ping_fail: grub_netbuff_free (nb); diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c index 1f9278910..b231f17e9 100644 --- a/grub-core/net/icmp6.c +++ b/grub-core/net/icmp6.c @@ -182,7 +182,8 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, GRUB_NET_IP_ICMPV6, &inf->address, source); - err = grub_net_send_ip_packet (inf, source, nb_reply, + /* FIXME: gateway pings. */ + err = grub_net_send_ip_packet (inf, source, NULL, nb_reply, GRUB_NET_IP_ICMPV6); ping_fail: @@ -288,7 +289,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, GRUB_NET_IP_ICMPV6, &inf->address, source); - err = grub_net_send_ip_packet (inf, source, nb_reply, + err = grub_net_send_ip_packet (inf, source, NULL, nb_reply, GRUB_NET_IP_ICMPV6); ndp_fail: @@ -384,12 +385,19 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, for (slaac = card->slaac_list; slaac; slaac = slaac->next) { grub_net_network_level_address_t addr; + grub_net_network_level_netaddress_t netaddr; + if (slaac->address.type != GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET) continue; addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; addr.ipv6[0] = opt->prefix[0]; addr.ipv6[1] = grub_net_ipv6_get_id (&slaac->address); + netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + netaddr.ipv6.base[0] = opt->prefix[0]; + netaddr.ipv6.base[1] = 0; + netaddr.ipv6.masksize = 64; + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { if (inf->card == card @@ -408,9 +416,10 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + sizeof (":XXXXXXXXXXXXXXXXXXXX")]; grub_snprintf (name, sizeof (name), "%s:%d", slaac->name, slaac->slaac_counter++); - grub_net_add_addr (name, - card, &addr, - &slaac->address, 0); + inf = grub_net_add_addr (name, + card, &addr, + &slaac->address, 0); + grub_net_add_route (name, netaddr, inf); } } } @@ -435,7 +444,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, struct neighbour_solicit *sol; struct icmp_header *icmphr; grub_net_network_level_address_t multicast; - + grub_uint8_t *nbd; multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; multicast.ipv6[0] = grub_be_to_cpu64_compile_time (0xff02ULL << 48); multicast.ipv6[1] = (grub_be_to_cpu64_compile_time (0x01ff000000ULL) @@ -467,7 +476,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, goto fail; ohdr = (struct option_header *) nb->data; - ohdr->type = OPTION_TARGET_LINK_LAYER_ADDRESS; + ohdr->type = OPTION_SOURCE_LINK_LAYER_ADDRESS; ohdr->len = 1; err = grub_netbuff_push (nb, sizeof (*sol)); if (err) @@ -482,14 +491,15 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, goto fail; icmphr = (struct icmp_header *) nb->data; - icmphr->type = ICMP6_NEIGHBOUR_ADVERTISE; + icmphr->type = ICMP6_NEIGHBOUR_SOLICIT; icmphr->code = 0; icmphr->checksum = 0; icmphr->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_ICMPV6, &inf->address, &multicast); - err = grub_net_send_ip_packet (inf, &multicast, nb, + nbd = nb->data; + err = grub_net_send_ip_packet (inf, &multicast, NULL, nb, GRUB_NET_IP_ICMPV6); if (err) goto fail; @@ -501,7 +511,8 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, grub_net_poll_cards (GRUB_NET_INTERVAL); if (grub_net_link_layer_resolve_check (inf, proto_addr)) break; - err = grub_net_send_ip_packet (inf, &multicast, nb, + nb->data = nbd; + err = grub_net_send_ip_packet (inf, &multicast, NULL, nb, GRUB_NET_IP_ICMPV6); if (err) break; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 27b8221fb..19e12ddac 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -181,9 +181,10 @@ send_fragmented (struct grub_net_network_level_interface * inf, } static grub_err_t -grub_net_send_ip4_packet (struct grub_net_network_level_interface * inf, - const grub_net_network_level_address_t * target, - struct grub_net_buff * nb, +grub_net_send_ip4_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + const grub_net_network_level_address_t *gw, + struct grub_net_buff *nb, grub_net_ip_protocol_t proto) { struct iphdr *iph; @@ -193,7 +194,7 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface * inf, COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph)); /* Determine link layer target address via ARP. */ - err = grub_net_link_layer_resolve (inf, target, &ll_target_addr); + err = grub_net_link_layer_resolve (inf, gw ? : target, &ll_target_addr); if (err) return err; @@ -578,9 +579,10 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, } static grub_err_t -grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf, - const grub_net_network_level_address_t * target, - struct grub_net_buff * nb, +grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + const grub_net_network_level_address_t *gw, + struct grub_net_buff *nb, grub_net_ip_protocol_t proto) { struct ip6hdr *iph; @@ -590,7 +592,7 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf, COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph)); /* Determine link layer target address via ARP. */ - err = grub_net_link_layer_resolve (inf, target, &ll_target_addr); + err = grub_net_link_layer_resolve (inf, gw ? : target, &ll_target_addr); if (err) return err; @@ -612,17 +614,18 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf, } grub_err_t -grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, - const grub_net_network_level_address_t * target, - struct grub_net_buff * nb, +grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + const grub_net_network_level_address_t *gw, + struct grub_net_buff *nb, grub_net_ip_protocol_t proto) { switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - return grub_net_send_ip4_packet (inf, target, nb, proto); + return grub_net_send_ip4_packet (inf, target, gw, nb, proto); case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: - return grub_net_send_ip6_packet (inf, target, nb, proto); + return grub_net_send_ip6_packet (inf, target, gw, nb, proto); default: return grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP"); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 1134223b2..2e8d9678e 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -160,8 +160,6 @@ grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, return GRUB_ERR_NONE; } - - /* Check cache table. */ entry = link_layer_find_entry (proto_addr, inf->card); if (entry) @@ -378,18 +376,23 @@ static int parse_ip (const char *val, grub_uint32_t *ip, const char **rest) { grub_uint32_t newip = 0; - unsigned long t; int i; const char *ptr = val; for (i = 0; i < 4; i++) { + unsigned long t; t = grub_strtoul (ptr, (char **) &ptr, 0); if (grub_errno) { grub_errno = GRUB_ERR_NONE; return 0; } + if (*ptr != '.' && i == 0) + { + newip = t; + break; + } if (t & ~0xff) return 0; newip >>= 8; @@ -400,7 +403,56 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) } *ip = grub_cpu_to_le32 (newip); if (rest) - *rest = ptr - 1; + *rest = (ptr - 1); + return 1; +} + +static int +parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) +{ + grub_uint16_t newip[8]; + const char *ptr = val; + int word, quaddot = -1; + + if (ptr[0] == ':' && ptr[1] != ':') + return 0; + if (ptr[0] == ':') + ptr++; + + for (word = 0; word < 8; word++) + { + unsigned long t; + if (*ptr == ':') + { + quaddot = word; + word--; + ptr++; + continue; + } + t = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; + break; + } + if (t & ~0xffff) + return 0; + newip[word] = grub_cpu_to_be16 (t); + if (*ptr != ':') + break; + ptr++; + } + if (quaddot == -1 && word < 7) + return 0; + if (quaddot != -1) + { + grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], + (word - quaddot + 1) * sizeof (newip[0])); + grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); + } + grub_memcpy (ip, newip, 16); + if (rest) + *rest = ptr; return 1; } @@ -422,16 +474,21 @@ match_net (const grub_net_network_level_netaddress_t *net, } case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: { - grub_int64_t mask[2]; - mask[1] = 0xffffffffffffffffULL << (128 - net->ipv6.masksize); - if (net->ipv6.masksize < 64) - mask[0] = 0xffffffffffffffffULL; + grub_uint64_t mask[2]; + if (net->ipv6.masksize <= 64) + { + mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize); + mask[1] = 0; + } else - mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize); + { + mask[0] = 0xffffffffffffffffULL; + mask[1] = 0xffffffffffffffffULL << (128 - net->ipv6.masksize); + } return (((grub_be_to_cpu64 (net->ipv6.base[0]) & mask[0]) - == (grub_be_to_cpu32 (addr->ipv6[0]) & mask[0])) + == (grub_be_to_cpu64 (addr->ipv6[0]) & mask[0])) && ((grub_be_to_cpu64 (net->ipv6.base[1]) & mask[1]) - == (grub_be_to_cpu32 (addr->ipv6[1]) & mask[1]))); + == (grub_be_to_cpu64 (addr->ipv6[1]) & mask[1]))); } } return 0; @@ -441,11 +498,17 @@ grub_err_t grub_net_resolve_address (const char *name, grub_net_network_level_address_t *addr) { - if (parse_ip (name, &addr->ipv4, NULL)) + const char *rest; + if (parse_ip (name, &addr->ipv4, &rest) && *rest == 0) { addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; return GRUB_ERR_NONE; } + if (parse_ip6 (name, addr->ipv6, &rest) && *rest == 0) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + return GRUB_ERR_NONE; + } return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), name); } @@ -460,12 +523,32 @@ grub_net_resolve_net_address (const char *name, addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; if (*rest == '/') { - addr->ipv4.masksize = grub_strtoul (rest + 1, NULL, 0); - if (!grub_errno) - return GRUB_ERR_NONE; + addr->ipv4.masksize = grub_strtoul (rest + 1, (char **) &rest, 0); + if (!grub_errno && *rest == 0) + return GRUB_ERR_NONE; + grub_errno = GRUB_ERR_NONE; + } + else if (*rest == 0) + { + addr->ipv4.masksize = 32; + return GRUB_ERR_NONE; + } + } + if (parse_ip6 (name, addr->ipv6.base, &rest)) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + if (*rest == '/') + { + addr->ipv6.masksize = grub_strtoul (rest + 1, (char **) &rest, 0); + if (!grub_errno && *rest == 0) + return GRUB_ERR_NONE; + grub_errno = GRUB_ERR_NONE; + } + else if (*rest == 0) + { + addr->ipv6.masksize = 128; + return GRUB_ERR_NONE; } - addr->ipv4.masksize = 32; - return GRUB_ERR_NONE; } return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), name); diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 72ee8a239..ae1dc57ed 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -69,7 +69,7 @@ struct grub_net_tcp_socket void *recv); void (*error_hook) (grub_net_tcp_socket_t sock, void *recv); void *hook_data; - grub_net_network_level_address_t out_nla; + grub_net_network_level_address_t out_nla, gw; struct grub_net_network_level_interface *inf; grub_net_packets_t packs; grub_priority_queue_t pq; @@ -216,8 +216,8 @@ tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket) socket->unack_last->next = unack; } - err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb, - GRUB_NET_IP_TCP); + err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), + &(socket->gw),nb, GRUB_NET_IP_TCP); if (err) return err; nb->data = nbd; @@ -240,11 +240,11 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock, sock->recv_hook = NULL; nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin) - + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE); if (!nb_fin) return; - err = grub_netbuff_reserve (nb_fin, GRUB_NET_OUR_IPV4_HEADER_SIZE + err = grub_netbuff_reserve (nb_fin, GRUB_NET_OUR_MAX_IP_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE); if (err) { @@ -368,7 +368,8 @@ grub_net_tcp_retransmit (void) unack->try_count++; unack->last_try = ctime; nbd = unack->nb->data; - err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla), unack->nb, + err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla), + &(sock->gw), unack->nb, GRUB_NET_IP_TCP); unack->nb->data = nbd; if (err) @@ -468,11 +469,11 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock, sock->error_hook = error_hook; sock->hook_data = hook_data; nb_ack = grub_netbuff_alloc (sizeof (*tcph) - + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE); if (!nb_ack) return grub_errno; - err = grub_netbuff_reserve (nb_ack, GRUB_NET_OUR_IPV4_HEADER_SIZE + err = grub_netbuff_reserve (nb_ack, GRUB_NET_OUR_MAX_IP_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE); if (err) { @@ -525,9 +526,10 @@ grub_net_tcp_open (char *server, if (err) return NULL; - if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "not a IPv4 address"); + grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP address"); return NULL; } @@ -542,6 +544,7 @@ grub_net_tcp_open (char *server, socket->out_port = out_port; socket->inf = inf; socket->out_nla = addr; + socket->gw = gateway; socket->in_port = in_port++; socket->recv_hook = recv_hook; socket->error_hook = error_hook; @@ -593,7 +596,8 @@ grub_net_tcp_open (char *server, { int j; nb->data = nbd; - err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb, + err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), + &(socket->gw), nb, GRUB_NET_IP_TCP); if (err) { @@ -636,20 +640,23 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, grub_err_t err; grub_ssize_t fraglen; COMPILE_TIME_ASSERT (sizeof (struct tcphdr) == GRUB_NET_TCP_HEADER_SIZE); - fraglen = (socket->inf->card->mtu - GRUB_NET_OUR_IPV4_HEADER_SIZE - - sizeof (*tcph)); + if (socket->out_nla.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + fraglen = (socket->inf->card->mtu - GRUB_NET_OUR_IPV4_HEADER_SIZE + - sizeof (*tcph)); + else + fraglen = 1280 - GRUB_NET_OUR_IPV6_HEADER_SIZE; while (nb->tail - nb->data > fraglen) { struct grub_net_buff *nb2; nb2 = grub_netbuff_alloc (fraglen + sizeof (*tcph) - + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE); if (!nb2) return grub_errno; err = grub_netbuff_reserve (nb2, GRUB_NET_MAX_LINK_HEADER_SIZE - + GRUB_NET_OUR_IPV4_HEADER_SIZE); + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE); if (err) return err; err = grub_netbuff_put (nb2, sizeof (*tcph)); @@ -724,8 +731,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, if (!(grub_be_to_cpu16 (tcph->dst) == sock->in_port && grub_be_to_cpu16 (tcph->src) == sock->out_port && inf == sock->inf - && source->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && source->ipv4 == sock->out_nla.ipv4)) + && grub_net_addr_cmp (source, &sock->out_nla) == 0)) continue; if (tcph->checksum) { diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index a2315dd3f..2284d8f6c 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -34,7 +34,7 @@ struct grub_net_udp_socket grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, void *recv); void *recv_hook_data; - grub_net_network_level_address_t out_nla; + grub_net_network_level_address_t out_nla, gw; struct grub_net_network_level_interface *inf; }; @@ -76,9 +76,10 @@ grub_net_udp_open (char *server, if (err) return NULL; - if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "not a IPv4 address"); + grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP address"); return NULL; } @@ -93,6 +94,7 @@ grub_net_udp_open (char *server, socket->out_port = out_port; socket->inf = inf; socket->out_nla = addr; + socket->gw = gateway; socket->in_port = in_port++; socket->status = GRUB_NET_SOCKET_START; socket->recv_hook = recv_hook; @@ -127,8 +129,8 @@ grub_net_send_udp_packet (const grub_net_udp_socket_t socket, &socket->inf->address, &socket->out_nla); - return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), nb, - GRUB_NET_IP_UDP); + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), + &(socket->gw), nb, GRUB_NET_IP_UDP); } grub_err_t @@ -160,8 +162,7 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb, { if (grub_be_to_cpu16 (udph->dst) == sock->in_port && inf == sock->inf - && source->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && source->ipv4 == sock->out_nla.ipv4 + && grub_net_addr_cmp (source, &sock->out_nla) == 0 && (sock->status == GRUB_NET_SOCKET_START || grub_be_to_cpu16 (udph->src) == sock->out_port)) { diff --git a/include/grub/net.h b/include/grub/net.h index e3f7525be..b3adb74f9 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -34,6 +34,7 @@ enum GRUB_NET_TCP_HEADER_SIZE = 20, GRUB_NET_OUR_IPV4_HEADER_SIZE = 20, GRUB_NET_OUR_IPV6_HEADER_SIZE = 40, + GRUB_NET_OUR_MAX_IP_HEADER_SIZE = 40, GRUB_NET_TCP_RESERVE_SIZE = GRUB_NET_TCP_HEADER_SIZE + GRUB_NET_OUR_IPV4_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 78053de60..1b3c0893a 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -52,6 +52,7 @@ grub_net_recv_ip_packets (struct grub_net_buff *nb, grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, + const grub_net_network_level_address_t *gw, struct grub_net_buff *nb, grub_net_ip_protocol_t proto); diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h index 5fafd89f6..c745d51d7 100644 --- a/include/grub/net/netbuff.h +++ b/include/grub/net/netbuff.h @@ -18,13 +18,13 @@ struct grub_net_buff grub_uint8_t *end; }; -grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff, grub_size_t len); grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); -struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); +struct grub_net_buff * grub_netbuff_alloc (grub_size_t len); grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff); #endif From bd40efbf0b38c0398bf732504e3219df55862012 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 13 Oct 2011 18:31:53 +0200 Subject: [PATCH 388/673] several net bugfixes and improvements and fix some memory leaks --- grub-core/io/bufio.c | 124 +++++++++++----------- grub-core/kern/disk.c | 3 + grub-core/net/bootp.c | 16 +++ grub-core/net/http.c | 227 +++++++++++++++++++++++++++-------------- grub-core/net/net.c | 60 +++++++++-- grub-core/net/tcp.c | 109 ++++++++++++++------ include/grub/net/tcp.h | 4 + include/grub/types.h | 2 + 8 files changed, 365 insertions(+), 180 deletions(-) diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c index adb38af56..0d01e62f9 100644 --- a/grub-core/io/bufio.c +++ b/grub-core/io/bufio.c @@ -35,6 +35,7 @@ struct grub_bufio grub_file_t file; grub_size_t block_size; grub_size_t buffer_len; + grub_off_t buffer_at; char buffer[0]; }; typedef struct grub_bufio *grub_bufio_t; @@ -70,6 +71,7 @@ grub_bufio_open (grub_file_t io, int size) bufio->file = io; bufio->block_size = size; bufio->buffer_len = 0; + bufio->buffer_at = 0; file->device = io->device; file->offset = 0; @@ -104,83 +106,87 @@ grub_buffile_open (const char *name, int size) static grub_ssize_t grub_bufio_read (grub_file_t file, char *buf, grub_size_t len) { - grub_size_t res = len; + grub_size_t res = 0; grub_bufio_t bufio = file->data; - grub_uint64_t pos; - if ((file->offset >= bufio->file->offset) && - (file->offset < bufio->file->offset + bufio->buffer_len)) + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = bufio->file->size; + + /* First part: use whatever we already have in the buffer. */ + if ((file->offset >= bufio->buffer_at) && + (file->offset < bufio->buffer_at + bufio->buffer_len)) { grub_size_t n; + grub_uint64_t pos; - pos = file->offset - bufio->file->offset; + pos = file->offset - bufio->buffer_at; n = bufio->buffer_len - pos; if (n > len) n = len; grub_memcpy (buf, &bufio->buffer[pos], n); len -= n; - if (! len) - return res; + res += n; buf += n; - bufio->file->offset += bufio->buffer_len; - pos = 0; + } + if (! len) + return res; + + /* Need to read some more. */ + bufio->buffer_at = grub_divmod64 (file->offset + res + len, bufio->block_size, + 0) * bufio->block_size; + + /* Now read between file->offset + res and bufio->buffer_at. */ + if (file->offset + res < bufio->buffer_at) + { + grub_size_t read_now; + grub_ssize_t really_read; + read_now = bufio->buffer_at - (file->offset + res); + grub_file_seek (bufio->file, file->offset + res); + really_read = grub_file_read (bufio->file, buf, read_now); + if (grub_errno) + return -1; + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = bufio->file->size; + len -= really_read; + buf += really_read; + res += really_read; + + /* Partial read. File ended unexpectedly. Save the last chunk in buffer. + */ + if (really_read != (grub_ssize_t) read_now) + { + bufio->buffer_len = really_read; + if (bufio->buffer_len > bufio->block_size) + bufio->buffer_len = bufio->block_size; + bufio->buffer_at = file->offset + res - bufio->buffer_len; + grub_memcpy (&bufio->buffer[0], buf - bufio->buffer_len, + bufio->buffer_len); + return res; + } + } + + /* Read into buffer. */ + grub_file_seek (bufio->file, bufio->buffer_at); + bufio->buffer_len = grub_file_read (bufio->file, bufio->buffer, + bufio->block_size); + if (grub_errno) + return -1; + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = bufio->file->size; + + if (len < bufio->buffer_len) + { + grub_memcpy (buf, &bufio->buffer[0], len); + res += len; } else { - bufio->file->offset = grub_divmod64 (file->offset, bufio->block_size, - &pos); - bufio->file->offset *= bufio->block_size; + grub_memcpy (buf, &bufio->buffer[0], bufio->buffer_len); + res += bufio->buffer_len; } - if (pos + len >= bufio->block_size) - { - if (pos) - { - grub_size_t n; - - bufio->file->fs->read (bufio->file, bufio->buffer, - bufio->block_size); - if (grub_errno) - return -1; - - n = bufio->block_size - pos; - grub_memcpy (buf, &bufio->buffer[pos], n); - len -= n; - buf += n; - bufio->file->offset += bufio->block_size; - pos = 0; - } - - while (len >= bufio->block_size) - { - bufio->file->fs->read (bufio->file, buf, bufio->block_size); - if (grub_errno) - return -1; - - len -= bufio->block_size; - buf += bufio->block_size; - bufio->file->offset += bufio->block_size; - } - - if (! len) - { - bufio->buffer_len = 0; - return res; - } - } - - bufio->buffer_len = bufio->file->size - bufio->file->offset; - if (bufio->buffer_len > bufio->block_size) - bufio->buffer_len = bufio->block_size; - - bufio->file->fs->read (bufio->file, bufio->buffer, bufio->buffer_len); - if (grub_errno) - return -1; - - grub_memcpy (buf, &bufio->buffer[pos], len); - return res; } diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index f296b9d0f..460d8778f 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -442,6 +442,7 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, } } + grub_free (tmp_buf); grub_errno = GRUB_ERR_NONE; { @@ -468,9 +469,11 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, grub_error_push (); grub_dprintf ("disk", "%s read failed\n", disk->name); grub_error_pop (); + grub_free (tmp_buf); return grub_errno; } grub_memcpy (buf, tmp_buf + offset, size); + grub_free (tmp_buf); return GRUB_ERR_NONE; } } diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index be79463ce..c41e9968a 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -79,6 +79,22 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) switch (tagtype) { + case 3: + if (taglength == 4) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof (":default")]; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = 0; + target.ipv4.masksize = 0; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4)); + grub_snprintf (rname, sizeof (rname), "%s:default", name); + grub_net_add_route_gw (rname, target, gw); + } + break; case 12: set_env_limn_ro (name, "hostname", (char *) ptr, taglength); break; diff --git a/grub-core/net/http.c b/grub-core/net/http.c index e4664757c..9f6628cb9 100644 --- a/grub-core/net/http.c +++ b/grub-core/net/http.c @@ -36,8 +36,6 @@ enum typedef struct http_data { - grub_uint64_t file_size; - grub_uint64_t position; char *current_line; grub_size_t current_line_len; int headers_recv; @@ -47,18 +45,53 @@ typedef struct http_data char *filename; grub_err_t err; char *errmsg; + int chunked; + grub_size_t chunk_rem; + int in_chunk_len; } *http_data_t; +static grub_off_t +have_ahead (struct grub_file *file) +{ + grub_net_t net = file->device->net; + grub_off_t ret = net->offset; + struct grub_net_packet *pack; + for (pack = net->packs.first; pack; pack = pack->next) + ret += pack->nb->tail - pack->nb->data; + return ret; +} + static grub_err_t -parse_line (http_data_t data, char *ptr, grub_size_t len) +parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) { char *end = ptr + len; while (end > ptr && *(end - 1) == '\r') end--; *end = 0; + /* Trailing CRLF. */ + if (data->in_chunk_len == 1) + { + data->in_chunk_len = 2; + return GRUB_ERR_NONE; + } + if (data->in_chunk_len == 2) + { + data->chunk_rem = grub_strtoul (ptr, 0, 16); + grub_errno = GRUB_ERR_NONE; + if (data->chunk_rem == 0) + { + file->device->net->eof = 1; + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = have_ahead (file); + } + data->in_chunk_len = 0; + return GRUB_ERR_NONE; + } if (ptr == end) { data->headers_recv = 1; + if (data->chunked) + data->in_chunk_len = 2; return GRUB_ERR_NONE; } @@ -93,10 +126,17 @@ parse_line (http_data_t data, char *ptr, grub_size_t len) == 0 && !data->size_recv) { ptr += sizeof ("Content-Length: ") - 1; - data->file_size = grub_strtoull (ptr, &ptr, 10); + file->size = grub_strtoull (ptr, &ptr, 10); data->size_recv = 1; return GRUB_ERR_NONE; } + if (grub_memcmp (ptr, "Transfer-Encoding: chunked", + sizeof ("Transfer-Encoding: chunked") - 1) == 0) + { + data->chunked = 1; + return GRUB_ERR_NONE; + } + return GRUB_ERR_NONE; } @@ -113,6 +153,8 @@ http_err (grub_net_tcp_socket_t sock __attribute__ ((unused)), grub_free (data->current_line); grub_free (data); file->device->net->eof = 1; + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = have_ahead (file); } static grub_err_t @@ -122,94 +164,116 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), { grub_file_t file = f; http_data_t data = file->data; - char *ptr = (char *) nb->data; grub_err_t err; - if (!data->headers_recv && data->current_line) + while (1) { - int have_line = 1; - char *t; - ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); - if (ptr) - ptr++; - else + char *ptr = (char *) nb->data; + if ((!data->headers_recv || data->in_chunk_len) && data->current_line) { - have_line = 0; - ptr = (char *) nb->tail; - } - t = grub_realloc (data->current_line, - data->current_line_len + (ptr - (char *) nb->data)); - if (!t) - { - grub_netbuff_free (nb); - grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); - return grub_errno; - } - - data->current_line = t; - grub_memcpy (data->current_line + data->current_line_len, - nb->data, ptr - (char *) nb->data); - data->current_line_len += ptr - (char *) nb->data; - if (!have_line) - { - grub_netbuff_free (nb); - return GRUB_ERR_NONE; - } - err = parse_line (data, data->current_line, data->current_line_len); - grub_free (data->current_line); - data->current_line = 0; - data->current_line_len = 0; - if (err) - { - grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); - grub_netbuff_free (nb); - return err; - } - } - - while (ptr < (char *) nb->tail && !data->headers_recv) - { - char *ptr2; - ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr); - if (!ptr2) - { - data->current_line = grub_malloc ((char *) nb->tail - ptr); - if (!data->current_line) + int have_line = 1; + char *t; + ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); + if (ptr) + ptr++; + else + { + have_line = 0; + ptr = (char *) nb->tail; + } + t = grub_realloc (data->current_line, + data->current_line_len + (ptr - (char *) nb->data)); + if (!t) { grub_netbuff_free (nb); grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); return grub_errno; } - data->current_line_len = (char *) nb->tail - ptr; - grub_memcpy (data->current_line, ptr, data->current_line_len); + + data->current_line = t; + grub_memcpy (data->current_line + data->current_line_len, + nb->data, ptr - (char *) nb->data); + data->current_line_len += ptr - (char *) nb->data; + if (!have_line) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + err = parse_line (file, data, data->current_line, + data->current_line_len); + grub_free (data->current_line); + data->current_line = 0; + data->current_line_len = 0; + if (err) + { + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + grub_netbuff_free (nb); + return err; + } + } + + while (ptr < (char *) nb->tail && (!data->headers_recv + || data->in_chunk_len)) + { + char *ptr2; + ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr); + if (!ptr2) + { + data->current_line = grub_malloc ((char *) nb->tail - ptr); + if (!data->current_line) + { + grub_netbuff_free (nb); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + return grub_errno; + } + data->current_line_len = (char *) nb->tail - ptr; + grub_memcpy (data->current_line, ptr, data->current_line_len); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + err = parse_line (file, data, ptr, ptr2 - ptr); + if (err) + { + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + grub_netbuff_free (nb); + return err; + } + ptr = ptr2 + 1; + } + + if (((char *) nb->tail - ptr) <= 0) + { grub_netbuff_free (nb); return GRUB_ERR_NONE; - } - err = parse_line (data, ptr, ptr2 - ptr); - if (err) - { - grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); - grub_netbuff_free (nb); - return err; - } - ptr = ptr2 + 1; - } - - if (((char *) nb->tail - ptr) > 0) - { - data->position += ((char *) nb->tail - ptr); + } err = grub_netbuff_pull (nb, ptr - (char *) nb->data); if (err) { grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); grub_netbuff_free (nb); return err; - } - grub_net_put_packet (&file->device->net->packs, nb); + } + if (!(data->chunked && (grub_ssize_t) data->chunk_rem + < nb->tail - nb->data)) + { + grub_net_put_packet (&file->device->net->packs, nb); + if (data->chunked) + data->chunk_rem -= nb->tail - nb->data; + return GRUB_ERR_NONE; + } + if (data->chunk_rem) + { + struct grub_net_buff *nb2; + nb2 = grub_netbuff_alloc (data->chunk_rem); + if (!nb2) + return grub_errno; + grub_netbuff_put (nb2, data->chunk_rem); + grub_memcpy (nb2->data, nb->data, data->chunk_rem); + grub_net_put_packet (&file->device->net->packs, nb2); + grub_netbuff_pull (nb, data->chunk_rem); + } + data->in_chunk_len = 1; } - else - grub_netbuff_free (nb); - return GRUB_ERR_NONE; } static grub_err_t @@ -294,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) "\r\n"), "Content-Range: bytes %" PRIuGRUB_UINT64_T "-%" PRIuGRUB_UINT64_T "/%" PRIuGRUB_UINT64_T "\r\n\r\n", - offset, data->file_size - 1, data->file_size); + offset, file->size - 1, file->size); grub_netbuff_put (nb, grub_strlen ((char *) ptr)); } ptr = nb->tail; @@ -303,7 +367,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial) data->sock = grub_net_tcp_open (file->device->net->server, HTTP_PORT, http_receive, - http_err, + http_err, http_err, file); if (!data->sock) { @@ -351,13 +415,17 @@ http_seek (struct grub_file *file, grub_off_t off) grub_net_tcp_close (old_data->sock, GRUB_NET_TCP_ABORT); while (file->device->net->packs.first) - grub_net_remove_packet (file->device->net->packs.first); + { + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } + + file->device->net->offset = off; data = grub_zalloc (sizeof (*data)); if (!data) return grub_errno; - data->file_size = old_data->file_size; data->size_recv = 1; data->filename = old_data->filename; if (!data->filename) @@ -367,6 +435,7 @@ http_seek (struct grub_file *file, grub_off_t off) } grub_free (old_data); + file->data = data; err = http_establish (file, off, 0); if (err) { @@ -386,6 +455,7 @@ http_open (struct grub_file *file, const char *filename) data = grub_zalloc (sizeof (*data)); if (!data) return grub_errno; + file->size = GRUB_FILE_SIZE_UNKNOWN; data->filename = grub_strdup (filename); if (!data->filename) @@ -404,7 +474,6 @@ http_open (struct grub_file *file, const char *filename) grub_free (data); return err; } - file->size = data->file_size; return GRUB_ERR_NONE; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 2e8d9678e..fe713f05c 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -469,6 +469,8 @@ match_net (const grub_net_network_level_netaddress_t *net, case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t mask = (0xffffffffU << (32 - net->ipv4.masksize)); + if (net->ipv4.masksize == 0) + mask = 0; return ((grub_be_to_cpu32 (net->ipv4.base) & mask) == (grub_be_to_cpu32 (addr->ipv4) & mask)); } @@ -554,6 +556,39 @@ grub_net_resolve_net_address (const char *name, name); } +static int +route_cmp (const struct grub_net_route *a, const struct grub_net_route *b) +{ + if (a == NULL && b == NULL) + return 0; + if (b == NULL) + return +1; + if (a == NULL) + return -1; + if (a->target.type < b->target.type) + return -1; + if (a->target.type > b->target.type) + return +1; + switch (a->target.type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + if (a->target.ipv6.masksize > b->target.ipv6.masksize) + return +1; + if (a->target.ipv6.masksize < b->target.ipv6.masksize) + return -1; + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + if (a->target.ipv4.masksize > b->target.ipv4.masksize) + return +1; + if (a->target.ipv4.masksize < b->target.ipv4.masksize) + return -1; + break; + } + return 0; +} + grub_err_t grub_net_route_address (grub_net_network_level_address_t addr, grub_net_network_level_address_t *gateway, @@ -572,25 +607,27 @@ grub_net_route_address (grub_net_network_level_address_t addr, for (depth = 0; depth < routecnt + 2; depth++) { + struct grub_net_route *bestroute = NULL; FOR_NET_ROUTES(route) { if (depth && prot != route->prot) continue; if (!match_net (&route->target, &curtarget)) continue; - - if (route->is_gateway) - { - if (depth == 0) - *gateway = route->gw; - curtarget = route->gw; - break; - } - *interf = route->interface; - return GRUB_ERR_NONE; + if (route_cmp (route, bestroute) > 0) + bestroute = route; } - if (route == NULL) + if (bestroute == NULL) return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable"); + + if (!bestroute->is_gateway) + { + *interf = bestroute->interface; + return GRUB_ERR_NONE; + } + if (depth == 0) + *gateway = bestroute->gw; + curtarget = bestroute->gw; } return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected"); @@ -1285,6 +1322,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) char *ptr = buf; grub_size_t amount, total = 0; int try = 0; + while (try <= GRUB_NET_TRIES) { while (net->packs.first) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index ae1dc57ed..579f94e99 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -68,6 +68,7 @@ struct grub_net_tcp_socket grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, struct grub_net_buff *nb, void *recv); void (*error_hook) (grub_net_tcp_socket_t sock, void *recv); + void (*fin_hook) (grub_net_tcp_socket_t sock, void *recv); void *hook_data; grub_net_network_level_address_t out_nla, gw; struct grub_net_network_level_interface *inf; @@ -234,10 +235,20 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock, struct tcphdr *tcph_fin; grub_err_t err; - sock->i_closed = 1; - if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING) - sock->recv_hook = NULL; + { + sock->recv_hook = NULL; + sock->error_hook = NULL; + sock->fin_hook = NULL; + } + + if (discard_received == GRUB_NET_TCP_ABORT) + sock->i_reseted = 1; + + if (sock->i_closed) + return; + + sock->i_closed = 1; nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin) + GRUB_NET_OUR_MAX_IP_HEADER_SIZE @@ -263,13 +274,12 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock, return; } tcph_fin = (void *) nb_fin->data; - tcph_fin->ack = grub_cpu_to_be32 (0); - tcph_fin->flags = grub_cpu_to_be16 ((5 << 12) | TCP_FIN); - tcph_fin->window = grub_cpu_to_be16 (0); + tcph_fin->ack = grub_cpu_to_be32 (sock->their_cur_seq); + tcph_fin->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_FIN + | TCP_ACK); + tcph_fin->window = grub_cpu_to_be16_compile_time (0); tcph_fin->urgent = 0; err = tcp_send (nb_fin, sock); - if (discard_received == GRUB_NET_TCP_ABORT) - sock->i_reseted = 1; if (err) { grub_netbuff_free (nb_fin); @@ -309,14 +319,14 @@ ack_real (grub_net_tcp_socket_t sock, int res) tcph_ack = (void *) nb_ack->data; if (res) { - tcph_ack->ack = grub_cpu_to_be32 (0); - tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_RST); - tcph_ack->window = grub_cpu_to_be16 (0); + tcph_ack->ack = grub_cpu_to_be32_compile_time (0); + tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_RST); + tcph_ack->window = grub_cpu_to_be16_compile_time (0); } else { tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq); - tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_ACK); + tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK); tcph_ack->window = grub_cpu_to_be16 (sock->my_window); } tcph_ack->urgent = 0; @@ -354,6 +364,7 @@ grub_net_tcp_retransmit (void) struct unacked *unack; for (unack = sock->unack_first; unack; unack = unack->next) { + struct tcphdr *tcph; grub_uint8_t *nbd; grub_err_t err; @@ -368,6 +379,18 @@ grub_net_tcp_retransmit (void) unack->try_count++; unack->last_try = ctime; nbd = unack->nb->data; + tcph = (struct tcphdr *) nbd; + + if ((tcph->flags & grub_cpu_to_be16_compile_time (TCP_ACK)) + && tcph->ack != grub_cpu_to_be32 (sock->their_cur_seq)) + { + tcph->checksum = 0; + tcph->checksum = grub_net_ip_transport_checksum (unack->nb, + GRUB_NET_IP_TCP, + &sock->inf->address, + &sock->out_nla); + } + err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla), &(sock->gw), unack->nb, GRUB_NET_IP_TCP); @@ -447,7 +470,10 @@ destroy_pq (grub_net_tcp_socket_t sock) { struct grub_net_buff **nb_p; while ((nb_p = grub_priority_queue_top (sock->pq))) - grub_netbuff_free (*nb_p); + { + grub_netbuff_free (*nb_p); + grub_priority_queue_pop (sock->pq); + } grub_priority_queue_destroy (sock->pq); } @@ -459,6 +485,8 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock, void *data), void (*error_hook) (grub_net_tcp_socket_t sock, void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), void *hook_data) { struct grub_net_buff *nb_ack; @@ -467,6 +495,7 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock, sock->recv_hook = recv_hook; sock->error_hook = error_hook; + sock->fin_hook = fin_hook; sock->hook_data = hook_data; nb_ack = grub_netbuff_alloc (sizeof (*tcph) + GRUB_NET_OUR_MAX_IP_HEADER_SIZE @@ -489,7 +518,7 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock, } tcph = (void *) nb_ack->data; tcph->ack = grub_cpu_to_be32 (sock->their_cur_seq); - tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN | TCP_ACK); + tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN | TCP_ACK); tcph->window = grub_cpu_to_be16 (sock->my_window); tcph->urgent = 0; sock->established = 1; @@ -509,6 +538,8 @@ grub_net_tcp_open (char *server, void *data), void (*error_hook) (grub_net_tcp_socket_t sock, void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), void *hook_data) { grub_err_t err; @@ -548,6 +579,7 @@ grub_net_tcp_open (char *server, socket->in_port = in_port++; socket->recv_hook = recv_hook; socket->error_hook = error_hook; + socket->fin_hook = fin_hook; socket->hook_data = hook_data; nb = grub_netbuff_alloc (sizeof (*tcph) + 128); @@ -578,8 +610,8 @@ grub_net_tcp_open (char *server, socket->my_cur_seq = socket->my_start_seq + 1; socket->my_window = 8192; tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq); - tcph->ack = grub_cpu_to_be32 (0); - tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN); + tcph->ack = grub_cpu_to_be32_compile_time (0); + tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN); tcph->window = grub_cpu_to_be16 (socket->my_window); tcph->urgent = 0; tcph->src = grub_cpu_to_be16 (socket->in_port); @@ -664,8 +696,8 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, return err; tcph = (struct tcphdr *) nb2->data; - tcph->ack = grub_cpu_to_be32 (0); - tcph->flags = grub_cpu_to_be16 ((5 << 12)); + tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq); + tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK); tcph->window = grub_cpu_to_be16 (socket->my_window); tcph->urgent = 0; err = grub_netbuff_put (nb2, fraglen); @@ -686,8 +718,9 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, return err; tcph = (struct tcphdr *) nb->data; - tcph->ack = grub_cpu_to_be32 (0); - tcph->flags = grub_cpu_to_be16 ((5 << 12) | (push ? TCP_PUSH : 0)); + tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq); + tcph->flags = (grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK) + | (push ? grub_cpu_to_be16_compile_time (TCP_PUSH) : 0)); tcph->window = grub_cpu_to_be16 (socket->my_window); tcph->urgent = 0; return tcp_send (nb, socket); @@ -815,11 +848,15 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, err = grub_priority_queue_push (sock->pq, &nb); if (err) - return err; + { + grub_netbuff_free (nb); + return err; + } { struct grub_net_buff **nb_top_p, *nb_top; int do_ack = 0; + int just_closed = 0; while (1) { nb_top_p = grub_priority_queue_top (sock->pq); @@ -829,6 +866,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, tcph = (struct tcphdr *) nb_top->data; if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq) break; + grub_netbuff_free (nb_top); grub_priority_queue_pop (sock->pq); } if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) @@ -845,15 +883,19 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, break; grub_priority_queue_pop (sock->pq); - err = grub_netbuff_pull (nb, (grub_be_to_cpu16 (tcph->flags) - >> 12) * sizeof (grub_uint32_t)); + err = grub_netbuff_pull (nb_top, (grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t)); if (err) - return err; + { + grub_netbuff_free (nb_top); + return err; + } sock->their_cur_seq += (nb_top->tail - nb_top->data); if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) { sock->they_closed = 1; + just_closed = 1; sock->their_cur_seq++; do_ack = 1; } @@ -868,14 +910,19 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb, } if (do_ack) ack (sock); + while (sock->packs.first) + { + nb = sock->packs.first->nb; + if (sock->recv_hook) + sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data); + else + grub_netbuff_free (nb); + grub_net_remove_packet (sock->packs.first); + } + + if (sock->fin_hook && just_closed) + sock->fin_hook (sock, sock->hook_data); } - while (sock->packs.first) - { - nb = sock->packs.first->nb; - if (sock->recv_hook) - sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data); - grub_net_remove_packet (sock->packs.first); - } return GRUB_ERR_NONE; } diff --git a/include/grub/net/tcp.h b/include/grub/net/tcp.h index b25ceff1b..62bfd2eba 100644 --- a/include/grub/net/tcp.h +++ b/include/grub/net/tcp.h @@ -35,6 +35,8 @@ grub_net_tcp_open (char *server, void *data), void (*error_hook) (grub_net_tcp_socket_t sock, void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), void *hook_data); grub_net_tcp_listen_t @@ -70,6 +72,8 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock, void *data), void (*error_hook) (grub_net_tcp_socket_t sock, void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), void *hook_data); #endif diff --git a/include/grub/types.h b/include/grub/types.h index 61cfb0291..68f28d01d 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -214,6 +214,7 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_be_to_cpu16(x) ((grub_uint16_t) (x)) # define grub_be_to_cpu32(x) ((grub_uint32_t) (x)) # define grub_be_to_cpu64(x) ((grub_uint64_t) (x)) +# define grub_cpu_to_be16_compile_time(x) ((grub_uint16_t) (x)) # define grub_cpu_to_be32_compile_time(x) ((grub_uint32_t) (x)) # define grub_cpu_to_be64_compile_time(x) ((grub_uint64_t) (x)) # define grub_be_to_cpu64_compile_time(x) ((grub_uint64_t) (x)) @@ -232,6 +233,7 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_be_to_cpu16(x) grub_swap_bytes16(x) # define grub_be_to_cpu32(x) grub_swap_bytes32(x) # define grub_be_to_cpu64(x) grub_swap_bytes64(x) +# define grub_cpu_to_be16_compile_time(x) grub_swap_bytes16_compile_time(x) # define grub_cpu_to_be32_compile_time(x) grub_swap_bytes32_compile_time(x) # define grub_cpu_to_be64_compile_time(x) grub_swap_bytes64_compile_time(x) # define grub_be_to_cpu64_compile_time(x) grub_swap_bytes64_compile_time(x) From 0cb9503b70136eca27b56c607a57d352d5764715 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 13 Oct 2011 20:53:22 +0200 Subject: [PATCH 389/673] support routed pings --- grub-core/net/bootp.c | 7 ++++- grub-core/net/ethernet.c | 5 ++- grub-core/net/icmp.c | 4 +-- grub-core/net/icmp6.c | 15 ++++++--- grub-core/net/ip.c | 68 ++++++++++++++++++---------------------- grub-core/net/tcp.c | 17 +++++++--- grub-core/net/udp.c | 13 ++++++-- include/grub/net/ip.h | 7 +++-- 8 files changed, 79 insertions(+), 57 deletions(-) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index c41e9968a..0c060fe19 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -458,6 +458,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_buff *nb; struct udphdr *udph; grub_net_network_level_address_t target; + grub_net_link_level_address_t ll_target; if (!ifaces[j].prev) continue; @@ -505,11 +506,15 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), udph->len = grub_cpu_to_be16 (nb->tail - nb->data); target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; target.ipv4 = 0xffffffff; + err = grub_net_link_layer_resolve (&ifaces[j], &target, &ll_target); + if (err) + return err; + udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, &ifaces[j].address, &target); - err = grub_net_send_ip_packet (&ifaces[j], &target, NULL, nb, + err = grub_net_send_ip_packet (&ifaces[j], &target, &ll_target, nb, GRUB_NET_IP_UDP); grub_netbuff_free (nb); if (err) diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index 6b5db9aaa..b38e2c83e 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -88,6 +88,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb, struct snaphdr *snaph; grub_net_ethertype_t type; grub_net_link_level_address_t hwaddress; + grub_net_link_level_address_t src_hwaddress; grub_err_t err; eth = (struct etherhdr *) nb->data; @@ -113,6 +114,8 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb, hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); + src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac)); switch (type) { @@ -124,7 +127,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff *nb, /* IP packet. */ case GRUB_NET_ETHERTYPE_IP: case GRUB_NET_ETHERTYPE_IP6: - return grub_net_recv_ip_packets (nb, card, &hwaddress); + return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress); } grub_netbuff_free (nb); return GRUB_ERR_NONE; diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c index 9e6bc5c6f..e55a0d86a 100644 --- a/grub-core/net/icmp.c +++ b/grub-core/net/icmp.c @@ -42,6 +42,7 @@ enum grub_err_t grub_net_recv_icmp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, const grub_net_network_level_address_t *src) { struct icmp_header *icmph; @@ -106,8 +107,7 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb, icmphr->checksum = 0; icmphr->checksum = grub_net_ip_chksum ((void *) nb_reply->data, nb_reply->tail - nb_reply->data); - /* FIXME: gateway pings. */ - err = grub_net_send_ip_packet (inf, src, NULL, + err = grub_net_send_ip_packet (inf, src, ll_src, nb_reply, GRUB_NET_IP_ICMP); ping_fail: diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c index b231f17e9..9a5f3cafe 100644 --- a/grub-core/net/icmp6.c +++ b/grub-core/net/icmp6.c @@ -103,6 +103,7 @@ grub_err_t grub_net_recv_icmp6_packet (struct grub_net_buff *nb, struct grub_net_card *card, struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, const grub_net_network_level_address_t *source, const grub_net_network_level_address_t *dest, grub_uint8_t ttl) @@ -182,8 +183,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, GRUB_NET_IP_ICMPV6, &inf->address, source); - /* FIXME: gateway pings. */ - err = grub_net_send_ip_packet (inf, source, NULL, nb_reply, + err = grub_net_send_ip_packet (inf, source, ll_src, nb_reply, GRUB_NET_IP_ICMPV6); ping_fail: @@ -289,7 +289,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb, GRUB_NET_IP_ICMPV6, &inf->address, source); - err = grub_net_send_ip_packet (inf, source, NULL, nb_reply, + err = grub_net_send_ip_packet (inf, source, ll_src, nb_reply, GRUB_NET_IP_ICMPV6); ndp_fail: @@ -444,6 +444,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, struct neighbour_solicit *sol; struct icmp_header *icmphr; grub_net_network_level_address_t multicast; + grub_net_link_level_address_t ll_multicast; grub_uint8_t *nbd; multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; multicast.ipv6[0] = grub_be_to_cpu64_compile_time (0xff02ULL << 48); @@ -451,6 +452,10 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, | (proto_addr->ipv6[1] & grub_be_to_cpu64_compile_time (0xffffff))); + err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); + if (err) + return err; + nb = grub_netbuff_alloc (sizeof (struct neighbour_solicit) + sizeof (struct option_header) + 6 @@ -499,7 +504,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, &inf->address, &multicast); nbd = nb->data; - err = grub_net_send_ip_packet (inf, &multicast, NULL, nb, + err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, GRUB_NET_IP_ICMPV6); if (err) goto fail; @@ -512,7 +517,7 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, if (grub_net_link_layer_resolve_check (inf, proto_addr)) break; nb->data = nbd; - err = grub_net_send_ip_packet (inf, &multicast, NULL, nb, + err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, GRUB_NET_IP_ICMPV6); if (err) break; diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 19e12ddac..b56c9d14a 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -183,23 +183,16 @@ send_fragmented (struct grub_net_network_level_interface * inf, static grub_err_t grub_net_send_ip4_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, - const grub_net_network_level_address_t *gw, + const grub_net_link_level_address_t *ll_target_addr, struct grub_net_buff *nb, grub_net_ip_protocol_t proto) { struct iphdr *iph; - grub_net_link_level_address_t ll_target_addr; - grub_err_t err; COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph)); - /* Determine link layer target address via ARP. */ - err = grub_net_link_layer_resolve (inf, gw ? : target, &ll_target_addr); - if (err) - return err; - if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu) - return send_fragmented (inf, target, nb, proto, ll_target_addr); + return send_fragmented (inf, target, nb, proto, *ll_target_addr); grub_netbuff_push (nb, sizeof (*iph)); iph = (struct iphdr *) nb->data; @@ -217,13 +210,14 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface *inf, iph->chksum = 0; iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph)); - return send_ethernet_packet (inf, nb, ll_target_addr, + return send_ethernet_packet (inf, nb, *ll_target_addr, GRUB_NET_ETHERTYPE_IP); } static grub_err_t handle_dgram (struct grub_net_buff *nb, struct grub_net_card *card, + const grub_net_link_level_address_t *source_hwaddress, const grub_net_link_level_address_t *hwaddress, grub_net_ip_protocol_t proto, const grub_net_network_level_address_t *source, @@ -325,9 +319,10 @@ handle_dgram (struct grub_net_buff *nb, case GRUB_NET_IP_TCP: return grub_net_recv_tcp_packet (nb, inf, source); case GRUB_NET_IP_ICMP: - return grub_net_recv_icmp_packet (nb, inf, source); + return grub_net_recv_icmp_packet (nb, inf, source_hwaddress, source); case GRUB_NET_IP_ICMPV6: - return grub_net_recv_icmp6_packet (nb, card, inf, source, dest, ttl); + return grub_net_recv_icmp6_packet (nb, card, inf, source_hwaddress, + source, dest, ttl); default: grub_netbuff_free (nb); break; @@ -363,9 +358,10 @@ free_old_fragments (void) } static grub_err_t -grub_net_recv_ip4_packets (struct grub_net_buff * nb, - struct grub_net_card * card, - const grub_net_link_level_address_t * hwaddress) +grub_net_recv_ip4_packets (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress) { struct iphdr *iph = (struct iphdr *) nb->data; grub_err_t err; @@ -439,7 +435,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; dest.ipv4 = iph->dest; - return handle_dgram (nb, card, hwaddress, iph->protocol, + return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol, &source, &dest, iph->ttl); } @@ -571,7 +567,8 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; dest.ipv4 = dst; - return handle_dgram (ret, card, hwaddress, proto, &source, &dest, + return handle_dgram (ret, card, src_hwaddress, + hwaddress, proto, &source, &dest, ttl); } @@ -581,21 +578,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb, static grub_err_t grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, - const grub_net_network_level_address_t *gw, + const grub_net_link_level_address_t *ll_target_addr, struct grub_net_buff *nb, grub_net_ip_protocol_t proto) { struct ip6hdr *iph; - grub_net_link_level_address_t ll_target_addr; - grub_err_t err; COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph)); - /* Determine link layer target address via ARP. */ - err = grub_net_link_layer_resolve (inf, gw ? : target, &ll_target_addr); - if (err) - return err; - if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu) return grub_error (GRUB_ERR_NET_PACKET_TOO_BIG, "packet too big"); @@ -609,32 +599,33 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf, grub_memcpy (&iph->src, inf->address.ipv6, sizeof (iph->src)); grub_memcpy (&iph->dest, target->ipv6, sizeof (iph->dest)); - return send_ethernet_packet (inf, nb, ll_target_addr, + return send_ethernet_packet (inf, nb, *ll_target_addr, GRUB_NET_ETHERTYPE_IP6); } grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, - const grub_net_network_level_address_t *gw, + const grub_net_link_level_address_t *ll_target_addr, struct grub_net_buff *nb, grub_net_ip_protocol_t proto) { switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: - return grub_net_send_ip4_packet (inf, target, gw, nb, proto); + return grub_net_send_ip4_packet (inf, target, ll_target_addr, nb, proto); case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: - return grub_net_send_ip6_packet (inf, target, gw, nb, proto); + return grub_net_send_ip6_packet (inf, target, ll_target_addr, nb, proto); default: return grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP"); } } static grub_err_t -grub_net_recv_ip6_packets (struct grub_net_buff * nb, - struct grub_net_card * card, - const grub_net_link_level_address_t * hwaddress) +grub_net_recv_ip6_packets (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress) { struct ip6hdr *iph = (struct ip6hdr *) nb->data; grub_err_t err; @@ -684,21 +675,22 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb, grub_memcpy (source.ipv6, &iph->src, sizeof (source.ipv6)); grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6)); - return handle_dgram (nb, card, hwaddress, iph->protocol, + return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol, &source, &dest, iph->ttl); } grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff * nb, - struct grub_net_card * card, - const grub_net_link_level_address_t * hwaddress) +grub_net_recv_ip_packets (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress) { struct iphdr *iph = (struct iphdr *) nb->data; if ((iph->verhdrlen >> 4) == 4) - return grub_net_recv_ip4_packets (nb, card, hwaddress); + return grub_net_recv_ip4_packets (nb, card, hwaddress, src_hwaddress); if ((iph->verhdrlen >> 4) == 6) - return grub_net_recv_ip6_packets (nb, card, hwaddress); + return grub_net_recv_ip6_packets (nb, card, hwaddress, src_hwaddress); grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); grub_netbuff_free (nb); return GRUB_ERR_NONE; diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 579f94e99..77cf073ee 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -70,7 +70,8 @@ struct grub_net_tcp_socket void (*error_hook) (grub_net_tcp_socket_t sock, void *recv); void (*fin_hook) (grub_net_tcp_socket_t sock, void *recv); void *hook_data; - grub_net_network_level_address_t out_nla, gw; + grub_net_network_level_address_t out_nla; + grub_net_link_level_address_t ll_target_addr; struct grub_net_network_level_interface *inf; grub_net_packets_t packs; grub_priority_queue_t pq; @@ -218,7 +219,8 @@ tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket) } err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), - &(socket->gw),nb, GRUB_NET_IP_TCP); + &(socket->ll_target_addr), nb, + GRUB_NET_IP_TCP); if (err) return err; nb->data = nbd; @@ -392,7 +394,7 @@ grub_net_tcp_retransmit (void) } err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla), - &(sock->gw), unack->nb, + &(sock->ll_target_addr), unack->nb, GRUB_NET_IP_TCP); unack->nb->data = nbd; if (err) @@ -552,6 +554,7 @@ grub_net_tcp_open (char *server, struct tcphdr *tcph; int i; grub_uint8_t *nbd; + grub_net_link_level_address_t ll_target_addr; err = grub_net_resolve_address (server, &addr); if (err) @@ -568,6 +571,10 @@ grub_net_tcp_open (char *server, if (err) return NULL; + err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr); + if (err) + return NULL; + socket = grub_zalloc (sizeof (*socket)); if (socket == NULL) return NULL; @@ -575,7 +582,7 @@ grub_net_tcp_open (char *server, socket->out_port = out_port; socket->inf = inf; socket->out_nla = addr; - socket->gw = gateway; + socket->ll_target_addr = ll_target_addr; socket->in_port = in_port++; socket->recv_hook = recv_hook; socket->error_hook = error_hook; @@ -629,7 +636,7 @@ grub_net_tcp_open (char *server, int j; nb->data = nbd; err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), - &(socket->gw), nb, + &(socket->ll_target_addr), nb, GRUB_NET_IP_TCP); if (err) { diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 2284d8f6c..739541097 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -34,7 +34,8 @@ struct grub_net_udp_socket grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, void *recv); void *recv_hook_data; - grub_net_network_level_address_t out_nla, gw; + grub_net_network_level_address_t out_nla; + grub_net_link_level_address_t ll_target_addr; struct grub_net_network_level_interface *inf; }; @@ -71,6 +72,7 @@ grub_net_udp_open (char *server, grub_net_network_level_address_t gateway; grub_net_udp_socket_t socket; static int in_port = 25300; + grub_net_link_level_address_t ll_target_addr; err = grub_net_resolve_address (server, &addr); if (err) @@ -87,6 +89,10 @@ grub_net_udp_open (char *server, if (err) return NULL; + err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr); + if (err) + return NULL; + socket = grub_zalloc (sizeof (*socket)); if (socket == NULL) return NULL; @@ -94,7 +100,7 @@ grub_net_udp_open (char *server, socket->out_port = out_port; socket->inf = inf; socket->out_nla = addr; - socket->gw = gateway; + socket->ll_target_addr = ll_target_addr; socket->in_port = in_port++; socket->status = GRUB_NET_SOCKET_START; socket->recv_hook = recv_hook; @@ -130,7 +136,8 @@ grub_net_send_udp_packet (const grub_net_udp_socket_t socket, &socket->out_nla); return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), - &(socket->gw), nb, GRUB_NET_IP_UDP); + &(socket->ll_target_addr), nb, + GRUB_NET_IP_UDP); } grub_err_t diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 1b3c0893a..7a8e61479 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -47,23 +47,26 @@ grub_uint16_t grub_net_ip_chksum(void *ipv, grub_size_t len); grub_err_t grub_net_recv_ip_packets (struct grub_net_buff *nb, struct grub_net_card *card, - const grub_net_link_level_address_t *hwaddress); + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, - const grub_net_network_level_address_t *gw, + const grub_net_link_level_address_t *ll_target_addr, struct grub_net_buff *nb, grub_net_ip_protocol_t proto); grub_err_t grub_net_recv_icmp_packet (struct grub_net_buff *nb, struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, const grub_net_network_level_address_t *src); grub_err_t grub_net_recv_icmp6_packet (struct grub_net_buff *nb, struct grub_net_card *card, struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, const grub_net_network_level_address_t *source, const grub_net_network_level_address_t *dest, grub_uint8_t ttl); From 0eb8ffb1f579d4507d78a822c843e334417f9ba1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 14 Oct 2011 19:16:37 +0200 Subject: [PATCH 390/673] * grub-core/lib/posix_wrap/ctype.h (isxdigit): Use grub_isxdigit. * include/grub/misc.h (grub_isxdigit): New function. * grub-core/video/colors.c (my_isxdigit): Removed. All users switched to grub_isxdigit. * grub-core/term/serial.c (grub_serial_find): Fix in case of port number starting with a letter. --- ChangeLog | 15 +++++++++++++++ grub-core/lib/posix_wrap/ctype.h | 3 +-- grub-core/term/serial.c | 2 +- grub-core/video/colors.c | 10 +--------- include/grub/misc.h | 6 ++++++ 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 19db47e04..44882054c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-14 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/ctype.h (isxdigit): Use grub_isxdigit. + * include/grub/misc.h (grub_isxdigit): New function. + * grub-core/video/colors.c (my_isxdigit): Removed. All users + switched to grub_isxdigit. + * grub-core/term/serial.c (grub_serial_find): Fix in case of port + number starting with a letter. + 2011-10-09 Robert Millan LVM support for FreeBSD and GNU/kFreeBSD. @@ -63,6 +72,12 @@ (grub_get_unaligned64): Likewise. * util/import_gcry.py (cryptolist): Add adler32. +2011-10-05 Vladimir Serbinenko + + * grub-core/Makefile.core.def: Eliminate rarely used emu_condition. This + in perspective decreases the complexity of build system and fixes + compilation right now. + 2011-10-01 Ales Nesrsta * grub-core/bus/usb/uhci.c: Changes made by Rock Cui - thanks! diff --git a/grub-core/lib/posix_wrap/ctype.h b/grub-core/lib/posix_wrap/ctype.h index 2dc3e53e9..9589778b6 100644 --- a/grub-core/lib/posix_wrap/ctype.h +++ b/grub-core/lib/posix_wrap/ctype.h @@ -54,8 +54,7 @@ isupper (int c) static inline int isxdigit (int c) { - return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') - || (c >= '0' && c <= '9'); + return grub_isxdigit (c); } static inline int diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index b724a945a..306694192 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -136,7 +136,7 @@ grub_serial_find (char *name) #ifndef GRUB_MACHINE_EMU if (!port && grub_memcmp (name, "port", sizeof ("port") - 1) == 0 - && grub_isdigit (name [sizeof ("port") - 1])) + && grub_isxdigit (name [sizeof ("port") - 1])) { name = grub_serial_ns8250_add_port (grub_strtoul (&name[sizeof ("port") - 1], 0, 16)); diff --git a/grub-core/video/colors.c b/grub-core/video/colors.c index 3119c0249..06625183e 100644 --- a/grub-core/video/colors.c +++ b/grub-core/video/colors.c @@ -211,14 +211,6 @@ grub_video_get_named_color (const char *name, return 0; } -static __inline int -my_isxdigit (char c) -{ - return ((c >= '0' && c <= '9') - || (c >= 'a' && c <= 'f') - || (c >= 'A' && c <= 'F')); -} - static int parse_hex_color_component (const char *s, unsigned start, unsigned end) { @@ -267,7 +259,7 @@ grub_video_parse_color (const char *s, grub_video_rgba_color_t *color) /* Count the hexits to determine the format. */ int hexits = 0; const char *end = s; - while (my_isxdigit (*end)) + while (grub_isxdigit (*end)) { end++; hexits++; diff --git a/include/grub/misc.h b/include/grub/misc.h index da4bd4a7e..66e74d8a8 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -136,6 +136,12 @@ grub_isdigit (int c) return (c >= '0' && c <= '9'); } +static inline int +grub_isxdigit (int c) +{ + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} + static inline int grub_isalnum (int c) { From c81296b65fad1d9bb4e5e2bb433719e5644827f0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 14 Oct 2011 19:20:44 +0200 Subject: [PATCH 391/673] * grub-core/kern/emu/hostdisk.c (convert_system_partition_to_system_disk): Don't assume that children of mapper nodes are mapper nodes. --- ChangeLog | 6 ++++++ grub-core/kern/emu/hostdisk.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 44882054c..3be8005a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-10-14 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Don't assume that children + of mapper nodes are mapper nodes. + 2011-10-14 Vladimir Serbinenko * grub-core/lib/posix_wrap/ctype.h (isxdigit): Use grub_isxdigit. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index a9a8c066e..23417a64d 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1416,7 +1416,7 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) if (tree) dm_tree_free (tree); free (path); - char *ret = grub_find_device ("/dev/mapper", + char *ret = grub_find_device ("/dev", (major << 8) | minor); return ret; } From 038ec56a31bb55a928905daf8b4eb46824c8939d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 14 Oct 2011 19:21:59 +0200 Subject: [PATCH 392/673] nslookup implementation --- grub-core/Makefile.core.def | 1 + grub-core/net/bootp.c | 6 +----- grub-core/net/net.c | 2 ++ grub-core/net/tftp.c | 10 +++++++++- grub-core/net/udp.c | 7 +------ include/grub/err.h | 3 ++- include/grub/net.h | 10 ++++++++++ include/grub/net/udp.h | 2 +- 8 files changed, 27 insertions(+), 14 deletions(-) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 3827227b8..2b4c22e01 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1598,6 +1598,7 @@ module = { module = { name = net; common = net/net.c; + common = net/dns.c; common = net/bootp.c; common = net/ip.c; common = net/udp.c; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 0c060fe19..b83b343c8 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -541,7 +541,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), return err; } -static grub_command_t cmd_dhcp, cmd_getdhcp, cmd_bootp; +static grub_command_t cmd_getdhcp, cmd_bootp; void grub_bootp_init (void) @@ -549,9 +549,6 @@ grub_bootp_init (void) cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, "[CARD]", N_("perform a bootp autoconfiguration")); - cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, - "[CARD]", - N_("perform a bootp autoconfiguration")); cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, N_("VAR INTERFACE NUMBER DESCRIPTION"), N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); @@ -561,6 +558,5 @@ void grub_bootp_fini (void) { grub_unregister_command (cmd_getdhcp); - grub_unregister_command (cmd_dhcp); grub_unregister_command (cmd_bootp); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index fe713f05c..269786fd8 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -1491,6 +1491,7 @@ GRUB_MOD_INIT(net) cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs, "", N_("list network addresses")); grub_bootp_init (); + grub_dns_init (); grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; @@ -1503,6 +1504,7 @@ GRUB_MOD_INIT(net) GRUB_MOD_FINI(net) { grub_bootp_fini (); + grub_dns_fini (); grub_unregister_command (cmd_addaddr); grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index 9be7294e8..9accdf5d2 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -279,6 +279,7 @@ tftp_open (struct grub_file *file, const char *filename) tftp_data_t data; grub_err_t err; grub_uint8_t *nbd; + grub_net_network_level_address_t addr; data = grub_zalloc (sizeof (*data)); if (!data) @@ -335,7 +336,14 @@ tftp_open (struct grub_file *file, const char *filename) if (!data->pq) return grub_errno; - data->sock = grub_net_udp_open (file->device->net->server, + err = grub_net_resolve_address (file->device->net->server, &addr); + if (err) + { + destroy_pq (data); + return err; + } + + data->sock = grub_net_udp_open (addr, TFTP_SERVER_PORT, tftp_receive, file); if (!data->sock) diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 739541097..e26608e36 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -59,7 +59,7 @@ grub_net_udp_close (grub_net_udp_socket_t sock) } grub_net_udp_socket_t -grub_net_udp_open (char *server, +grub_net_udp_open (grub_net_network_level_address_t addr, grub_uint16_t out_port, grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, @@ -67,17 +67,12 @@ grub_net_udp_open (char *server, void *recv_hook_data) { grub_err_t err; - grub_net_network_level_address_t addr; struct grub_net_network_level_interface *inf; grub_net_network_level_address_t gateway; grub_net_udp_socket_t socket; static int in_port = 25300; grub_net_link_level_address_t ll_target_addr; - err = grub_net_resolve_address (server, &addr); - if (err) - return NULL; - if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 && addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) { diff --git a/include/grub/err.h b/include/grub/err.h index d13f2c9ce..3a75f5698 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -65,7 +65,8 @@ typedef enum GRUB_ERR_NET_PORT_CLOSED, GRUB_ERR_NET_INVALID_RESPONSE, GRUB_ERR_NET_UNKNOWN_ERROR, - GRUB_ERR_NET_PACKET_TOO_BIG + GRUB_ERR_NET_PACKET_TOO_BIG, + GRUB_ERR_NET_NO_DOMAIN } grub_err_t; diff --git a/include/grub/net.h b/include/grub/net.h index b3adb74f9..f39c9d70b 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -446,6 +446,9 @@ grub_net_poll_cards (unsigned time); void grub_bootp_init (void); void grub_bootp_fini (void); +void grub_dns_init (void); +void grub_dns_fini (void); + static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { @@ -472,6 +475,13 @@ grub_err_t grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *proto_addr, grub_net_link_level_address_t *hw_addr); +grub_err_t +grub_net_dns_lookup (const char *name, + const struct grub_net_network_level_address *servers, + grub_size_t n_servers, + grub_size_t *naddresses, + struct grub_net_network_level_address **addresses, + int cache); extern char *grub_net_default_server; diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index fca94ba47..1a7efa777 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -33,7 +33,7 @@ struct grub_net_udp_socket; typedef struct grub_net_udp_socket *grub_net_udp_socket_t; grub_net_udp_socket_t -grub_net_udp_open (char *server, +grub_net_udp_open (grub_net_network_level_address_t addr, grub_uint16_t out_port, grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, From d891955241a5976694738b63c752bb9e35d248a5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 14 Oct 2011 22:41:21 +0200 Subject: [PATCH 393/673] Fix overflow with >2GiB file on HFS+. >4GiB wasn't tested. * grub-core/fs/hfsplus.c (grub_hfsplus_btree): Use more appropriate types. (grub_hfsplus_btree_recoffset): Likewise. (grub_hfsplus_btree_recptr): Likewise. (grub_hfsplus_find_block): Likewise. (grub_hfsplus_btree_search): Likewise. (grub_hfsplus_read_block): Likewise. (grub_hfsplus_read_file): Likewise. (grub_hfsplus_mount): Likewise. (grub_hfsplus_btree_iterate_node): Likewise. (grub_hfsplus_btree_search): Likewise. (grub_hfsplus_iterate_dir): Likewise. (grub_hfsplus_read): A small code simplification. --- ChangeLog | 18 +++++++++++++++ grub-core/fs/hfsplus.c | 52 ++++++++++++++++++++---------------------- 2 files changed, 43 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3be8005a7..9a8b38fd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-10-14 Vladimir Serbinenko + + Fix overflow with >2GiB file on HFS+. >4GiB wasn't tested. + + * grub-core/fs/hfsplus.c (grub_hfsplus_btree): Use more appropriate + types. + (grub_hfsplus_btree_recoffset): Likewise. + (grub_hfsplus_btree_recptr): Likewise. + (grub_hfsplus_find_block): Likewise. + (grub_hfsplus_btree_search): Likewise. + (grub_hfsplus_read_block): Likewise. + (grub_hfsplus_read_file): Likewise. + (grub_hfsplus_mount): Likewise. + (grub_hfsplus_btree_iterate_node): Likewise. + (grub_hfsplus_btree_search): Likewise. + (grub_hfsplus_iterate_dir): Likewise. + (grub_hfsplus_read): A small code simplification. + 2011-10-14 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 304b32126..245cd93a5 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -214,7 +214,7 @@ struct grub_fshelp_node struct grub_hfsplus_btree { grub_uint32_t root; - int nodesize; + grub_size_t nodesize; /* Catalog file node. */ struct grub_fshelp_node file; @@ -236,7 +236,7 @@ struct grub_hfsplus_data /* This is the offset into the physical disk for an embedded HFS+ filesystem (one inside a plain HFS wrapper). */ - int embedded_offset; + grub_disk_addr_t embedded_offset; int case_sensitive; }; @@ -245,7 +245,7 @@ static grub_dl_t my_mod; /* Return the offset of the record with the index INDEX, in the node NODE which is part of the B+ tree BTREE. */ -static inline unsigned int +static inline grub_off_t grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *node, int index) { @@ -263,7 +263,7 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *node, int index) { char *cnode = (char *) node; - unsigned int offset; + grub_off_t offset; offset = grub_hfsplus_btree_recoffset (btree, node, index); return (struct grub_hfsplus_key *) &cnode[offset]; } @@ -272,12 +272,12 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree, /* Find the extent that points to FILEBLOCK. If it is not in one of the 8 extents described by EXTENT, return -1. In that case set FILEBLOCK to the next block. */ -static int +static grub_disk_addr_t grub_hfsplus_find_block (struct grub_hfsplus_extent *extent, - int *fileblock) + grub_disk_addr_t *fileblock) { int i; - grub_size_t blksleft = *fileblock; + grub_disk_addr_t blksleft = *fileblock; /* First lookup the file in the given extents. */ for (i = 0; i < 8; i++) @@ -288,7 +288,7 @@ grub_hfsplus_find_block (struct grub_hfsplus_extent *extent, } *fileblock = blksleft; - return -1; + return 0xffffffffffffffffULL; } static grub_err_t @@ -296,7 +296,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, struct grub_hfsplus_key_internal *key, int (*compare_keys) (struct grub_hfsplus_key *keya, struct grub_hfsplus_key_internal *keyb), - struct grub_hfsplus_btnode **matchnode, int *keyoffset); + struct grub_hfsplus_btnode **matchnode, + grub_off_t *keyoffset); static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, struct grub_hfsplus_key_internal *keyb); @@ -307,15 +308,15 @@ static grub_disk_addr_t grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_hfsplus_btnode *nnode = 0; - int blksleft = fileblock; + grub_disk_addr_t blksleft = fileblock; struct grub_hfsplus_extent *extents = &node->extents[0]; while (1) { struct grub_hfsplus_extkey *key; struct grub_hfsplus_extkey_internal extoverflow; - int blk; - int ptr; + grub_disk_addr_t blk; + grub_off_t ptr; /* Try to find this block in the current set of extents. */ blk = grub_hfsplus_find_block (extents, &blksleft); @@ -325,7 +326,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_free (nnode); nnode = 0; - if (blk != -1) + if (blk != 0xffffffffffffffffULL) return (blk + (node->data->embedded_offset >> (node->data->log2blksize - GRUB_DISK_SECTOR_BITS))); @@ -376,7 +377,7 @@ static grub_ssize_t grub_hfsplus_read_file (grub_fshelp_node_t node, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_hfsplus_read_block, @@ -411,9 +412,9 @@ grub_hfsplus_mount (grub_disk_t disk) data->embedded_offset = 0; if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC) { - int extent_start; - int ablk_size; - int ablk_start; + grub_disk_addr_t extent_start; + grub_disk_addr_t ablk_size; + grub_disk_addr_t ablk_start; /* See if there's an embedded HFS+ filesystem. */ if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC) @@ -601,10 +602,10 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node) static int grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *first_node, - int first_rec, + grub_disk_addr_t first_rec, int (*hook) (void *record)) { - int rec; + grub_disk_addr_t rec; for (;;) { @@ -642,12 +643,13 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, struct grub_hfsplus_key_internal *key, int (*compare_keys) (struct grub_hfsplus_key *keya, struct grub_hfsplus_key_internal *keyb), - struct grub_hfsplus_btnode **matchnode, int *keyoffset) + struct grub_hfsplus_btnode **matchnode, + grub_off_t *keyoffset) { grub_uint64_t currnode; char *node; struct grub_hfsplus_btnode *nodedesc; - int rec; + grub_disk_addr_t rec; node = grub_malloc (btree->nodesize); if (! node) @@ -825,7 +827,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, struct grub_hfsplus_key_internal intern; struct grub_hfsplus_btnode *node; - int ptr; + grub_disk_addr_t ptr; /* Create a key that points to the first entry in the directory. */ intern.catkey.parent = dir->fileid; @@ -894,7 +896,6 @@ grub_hfsplus_close (grub_file_t file) return GRUB_ERR_NONE; } - /* Read LEN bytes data from FILE into BUF. */ static grub_ssize_t grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len) @@ -902,13 +903,10 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hfsplus_data *data = (struct grub_hfsplus_data *) file->data; - int size = grub_hfsplus_read_file (&data->opened_file, file->read_hook, + return grub_hfsplus_read_file (&data->opened_file, file->read_hook, file->offset, len, buf); - - return size; } - static grub_err_t grub_hfsplus_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, From 0017e5ef84cb4c7ac135254a52256d700e1c7dcb Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sat, 15 Oct 2011 13:33:41 +0200 Subject: [PATCH 394/673] 2011-10-15 Robert Millan Fix build problem on FreeBSD and GNU/kFreeBSD. * util/getroot.c [__FreeBSD_kernel__]: Include `'. --- ChangeLog | 6 ++++++ util/getroot.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9a8b38fd0..723531f5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-10-15 Robert Millan + + Fix build problem on FreeBSD and GNU/kFreeBSD. + + * util/getroot.c [__FreeBSD_kernel__]: Include `'. + 2011-10-14 Vladimir Serbinenko Fix overflow with >2GiB file on HFS+. >4GiB wasn't tested. diff --git a/util/getroot.c b/util/getroot.c index 7c5602e71..510049acb 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -52,6 +52,10 @@ # include #endif +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# include +#endif + #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) # include # include From 8bcebcb8e4cb75b0b6deffeb735c9fe26eb437b1 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Sat, 15 Oct 2011 18:37:55 +0200 Subject: [PATCH 395/673] 2011-10-15 Robert Millan * util/getroot.c (grub_util_get_grub_dev): Fix OS selection #ifdefs. --- ChangeLog | 4 ++++ util/getroot.c | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 723531f5c..11b14ec28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-15 Robert Millan + + * util/getroot.c (grub_util_get_grub_dev): Fix OS selection #ifdefs. + 2011-10-15 Robert Millan Fix build problem on FreeBSD and GNU/kFreeBSD. diff --git a/util/getroot.c b/util/getroot.c index 510049acb..3d6f9370c 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -1137,7 +1137,9 @@ grub_util_get_grub_dev (const char *os_dev) } break; +#endif +#ifdef __linux__ case GRUB_DEV_ABSTRACTION_LUKS: { char *uuid, *dash; @@ -1152,9 +1154,10 @@ grub_util_get_grub_dev (const char *os_dev) grub_free (uuid); } break; +#endif - case GRUB_DEV_ABSTRACTION_GELI: #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) + case GRUB_DEV_ABSTRACTION_GELI: { char *whole; struct gmesh mesh; @@ -1201,7 +1204,6 @@ grub_util_get_grub_dev (const char *os_dev) } } } -#endif break; #endif From 3b619ae116833fa8624d72f4c83b9c8f266ab5a5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 Oct 2011 11:48:54 +0200 Subject: [PATCH 396/673] * grub-core/fs/xfs.c (grub_xfs_inode): New field fork_offset. (GRUB_XFS_INO_AGBITS): Make into inline function. (GRUB_XFS_INO_INOINAG): Likewise. (GRUB_XFS_INO_AG): Likewise. (GRUB_XFS_FSB_TO_BLOCK): Likewise. (GRUB_XFS_EXTENT_OFFSET): Likewise. (GRUB_XFS_EXTENT_BLOCK): Likewise. (GRUB_XFS_EXTENT_SIZE): Likewise. (GRUB_XFS_ROUND_TO_DIRENT): Likewise. (GRUB_XFS_NEXT_DIRENT): Likewise. (grub_xfs_read_block): Rewrite the btree parsing. Fixes invalid BMAP. (grub_xfs_read_file): Fix offset type. --- ChangeLog | 15 ++++++ grub-core/fs/xfs.c | 111 ++++++++++++++++++++++++++++++++------------- 2 files changed, 94 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11b14ec28..abe19dc78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-10-16 Vladimir Serbinenko + + * grub-core/fs/xfs.c (grub_xfs_inode): New field fork_offset. + (GRUB_XFS_INO_AGBITS): Make into inline function. + (GRUB_XFS_INO_INOINAG): Likewise. + (GRUB_XFS_INO_AG): Likewise. + (GRUB_XFS_FSB_TO_BLOCK): Likewise. + (GRUB_XFS_EXTENT_OFFSET): Likewise. + (GRUB_XFS_EXTENT_BLOCK): Likewise. + (GRUB_XFS_EXTENT_SIZE): Likewise. + (GRUB_XFS_ROUND_TO_DIRENT): Likewise. + (GRUB_XFS_NEXT_DIRENT): Likewise. + (grub_xfs_read_block): Rewrite the btree parsing. Fixes invalid BMAP. + (grub_xfs_read_file): Fix offset type. + 2011-10-15 Robert Millan * util/getroot.c (grub_util_get_grub_dev): Fix OS selection #ifdefs. diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index eb0783407..3dc5e0af0 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -120,7 +120,9 @@ struct grub_xfs_inode grub_uint64_t nblocks; grub_uint32_t extsize; grub_uint32_t nextents; - grub_uint8_t unused3[20]; + grub_uint16_t unused3; + grub_uint8_t fork_offset; + grub_uint8_t unused4[17]; union { char raw[156]; @@ -154,7 +156,7 @@ struct grub_xfs_data grub_disk_t disk; int pos; int bsize; - int agsize; + grub_uint32_t agsize; struct grub_fshelp_node diropen; }; @@ -168,33 +170,67 @@ static grub_dl_t my_mod; #define FILETYPE_INO_DIRECTORY 0040000 #define FILETYPE_INO_SYMLINK 0120000 -#define GRUB_XFS_INO_AGBITS(data) \ - ((data)->sblock.log2_agblk + (data)->sblock.log2_inop) -#define GRUB_XFS_INO_INOINAG(data, ino) \ - (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)) -#define GRUB_XFS_INO_AG(data,ino) \ - (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)) +static inline int +GRUB_XFS_INO_AGBITS(struct grub_xfs_data *data) +{ + return ((data)->sblock.log2_agblk + (data)->sblock.log2_inop); +} -#define GRUB_XFS_FSB_TO_BLOCK(data, fsb) \ - (((fsb) >> (data)->sblock.log2_agblk) * (data)->agsize \ - + ((fsb) & ((1LL << (data)->sblock.log2_agblk) - 1))) +static inline grub_uint64_t +GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data, + grub_uint64_t ino) +{ + return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); +} -#define GRUB_XFS_EXTENT_OFFSET(exts,ex) \ - ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 \ - | grub_be_to_cpu32 (exts[ex][1]) >> 9) +static inline grub_uint64_t +GRUB_XFS_INO_AG (struct grub_xfs_data *data, + grub_uint64_t ino) +{ + return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)); +} -#define GRUB_XFS_EXTENT_BLOCK(exts,ex) \ - ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) \ - & (0x1ff)) << 43 \ - | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 \ - | grub_be_to_cpu32 (exts[ex][3]) >> 21) +static inline grub_disk_addr_t +GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb) +{ + return ((fsb >> data->sblock.log2_agblk) * data->agsize + + (fsb & ((1LL << data->sblock.log2_agblk) - 1))); +} -#define GRUB_XFS_EXTENT_SIZE(exts,ex) \ - (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1)) +static inline grub_uint64_t +GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex) +{ + return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 + | grub_be_to_cpu32 (exts[ex][1]) >> 9); +} + +static inline grub_uint64_t +GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex) +{ + return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) + & (0x1ff)) << 43 + | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 + | grub_be_to_cpu32 (exts[ex][3]) >> 21); +} + +static inline grub_uint64_t +GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex) +{ + return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 20) - 1)); +} + +static inline int +GRUB_XFS_ROUND_TO_DIRENT (int pos) +{ + return ((((pos) + 8 - 1) / 8) * 8); +} + +static inline int +GRUB_XFS_NEXT_DIRENT (int pos, int len) +{ + return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2); +} -#define GRUB_XFS_ROUND_TO_DIRENT(pos) ((((pos) + 8 - 1) / 8) * 8) -#define GRUB_XFS_NEXT_DIRENT(pos,len) \ - (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2) static inline grub_uint64_t grub_xfs_inode_block (struct grub_xfs_data *data, @@ -250,13 +286,23 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) if (node->inode.format == XFS_INODE_FORMAT_BTREE) { grub_uint64_t *keys; + int recoffset; - leaf = grub_malloc (node->data->sblock.bsize); + leaf = grub_malloc (node->data->bsize); if (leaf == 0) return 0; nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); keys = &node->inode.data.btree.keys[0]; + if (node->inode.fork_offset) + recoffset = (node->inode.fork_offset + - ((char *) &node->inode.data.btree.keys - (char *) &node->inode)) + / (2 * sizeof (grub_uint64_t)); + else + recoffset = ((1 << node->data->sblock.log2_inode) + - ((char *) &node->inode.data.btree.keys + - (char *) &node->inode)) + / (2 * sizeof (grub_uint64_t)); do { int i; @@ -273,12 +319,9 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_free (leaf); return 0; } - if (grub_disk_read (node->data->disk, - grub_be_to_cpu64 (keys[i - 1 + nrec]) - << (node->data->sblock.log2_bsize - - GRUB_DISK_SECTOR_BITS), - 0, node->data->sblock.bsize, leaf)) + GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), + 0, node->data->bsize, leaf)) return 0; if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) @@ -290,7 +333,11 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) nrec = grub_be_to_cpu16 (leaf->numrecs); keys = &leaf->keys[0]; - } while (leaf->level); + recoffset = ((node->data->bsize - ((char *) &leaf->keys + - (char *) leaf)) + / (2 * sizeof (grub_uint64_t))); + } + while (leaf->level); exts = (grub_xfs_extent *) keys; } else if (node->inode.format == XFS_INODE_FORMAT_EXT) @@ -336,7 +383,7 @@ static grub_ssize_t grub_xfs_read_file (grub_fshelp_node_t node, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_xfs_read_block, From 177b960ea44f146bb6b9e3c7be87bd3669b0d823 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 Oct 2011 11:53:27 +0200 Subject: [PATCH 397/673] Fix python 3.x incompatibilities. * gentpl.py: Put brackets around print strings. * util/import_gcry.py: Open explicitly as utf-8. Use in instead of has_key. --- ChangeLog | 8 ++++++++ gentpl.py | 40 ++++++++++++++++++++-------------------- util/import_gcry.py | 28 +++++++++++++++------------- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index abe19dc78..d5fbffcd4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-10-16 Vladimir Serbinenko + + Fix python 3.x incompatibilities. + + * gentpl.py: Put brackets around print strings. + * util/import_gcry.py: Open explicitly as utf-8. + Use in instead of has_key. + 2011-10-16 Vladimir Serbinenko * grub-core/fs/xfs.c (grub_xfs_inode): New field fork_offset. diff --git a/gentpl.py b/gentpl.py index cb6b663d9..af210a040 100644 --- a/gentpl.py +++ b/gentpl.py @@ -568,28 +568,28 @@ f = script_rules() g = data_rules() z = global_variable_initializers() -print "[+ AutoGen5 template +]\n" +print ("[+ AutoGen5 template +]\n") for p in GRUB_PLATFORMS: - print define_macro_for_platform_sources(p) - print define_macro_for_platform_nodist_sources(p) + print (define_macro_for_platform_sources(p)) + print (define_macro_for_platform_nodist_sources(p)) # print define_macro_for_platform_dependencies(p) - print define_macro_for_platform_startup(p) - print define_macro_for_platform_cflags(p) - print define_macro_for_platform_ldadd(p) - print define_macro_for_platform_ldflags(p) - print define_macro_for_platform_cppflags(p) - print define_macro_for_platform_ccasflags(p) - print define_macro_for_platform_stripflags(p) - print define_macro_for_platform_objcopyflags(p) + print (define_macro_for_platform_startup(p)) + print (define_macro_for_platform_cflags(p)) + print (define_macro_for_platform_ldadd(p)) + print (define_macro_for_platform_ldflags(p)) + print (define_macro_for_platform_cppflags(p)) + print (define_macro_for_platform_ccasflags(p)) + print (define_macro_for_platform_stripflags(p)) + print (define_macro_for_platform_objcopyflags(p)) - print define_macro_for_platform_conditionals_if_statement(p) - print define_macro_for_platform_conditionals_endif_statement(p) + print (define_macro_for_platform_conditionals_if_statement(p)) + print (define_macro_for_platform_conditionals_endif_statement(p)) # print z # initializer for all vars -print a -print b -print c -print d -print e -print f -print g +print (a) +print (b) +print (c) +print (d) +print (e) +print (f) +print (g) diff --git a/util/import_gcry.py b/util/import_gcry.py index ee75b1b8e..720f19303 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -20,6 +20,7 @@ import re import sys import os import datetime +import codecs if len (sys.argv) < 3: print ("Usage: %s SOURCE DESTINATION" % sys.argv[0]) @@ -40,9 +41,9 @@ except: print ("WARNING: %s already exists" % cipher_dir_out) cipher_files = os.listdir (cipher_dir_in) -conf = open (os.path.join ("grub-core", "Makefile.gcry.def"), "w") +conf = codecs.open (os.path.join ("grub-core", "Makefile.gcry.def"), "w", "utf-8") conf.write ("AutoGen definitions Makefile.tpl;\n\n") -confutil = open ("Makefile.utilgcry.def", "w") +confutil = codecs.open ("Makefile.utilgcry.def", "w", "utf-8") confutil.write ("AutoGen definitions Makefile.tpl;\n\n") confutil.write ("library = {\n"); confutil.write (" name = libgrubgcry.a;\n"); @@ -69,7 +70,7 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64, "_gcry_digest_spec_tiger" : 64, "_gcry_digest_spec_whirlpool" : 64} -cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w") +cryptolist = codecs.open (os.path.join (cipher_dir_out, "crypto.lst"), "w", "utf-8") # rijndael is the only cipher using aliases. So no need for mangling, just # hardcode it @@ -98,8 +99,8 @@ for cipher_file in cipher_files: nch = False if re.match (".*\.[ch]$", cipher_file): isc = re.match (".*\.c$", cipher_file) - f = open (infile, "r") - fw = open (outfile, "w") + f = codecs.open (infile, "r", "utf-8") + fw = codecs.open (outfile, "w", "utf-8") fw.write ("/* This file was automatically imported with \n") fw.write (" import_gcry.py. Please don't modify it */\n") fw.write ("#include \n") @@ -125,6 +126,7 @@ for cipher_file in cipher_files: isglue = True modname = "gcry_%s" % modname for line in f: + line = line if skip_statement: if not re.search (";", line) is None: skip_statement = False @@ -151,7 +153,7 @@ for cipher_file in cipher_files: fw.write (" .modname = \"%s\",\n" % modname); fw.write ("#endif\n"); if ismd: - if not mdblocksizes.has_key (mdname): + if not (mdname in mdblocksizes): print ("ERROR: Unknown digest blocksize: %s\n" % mdname) exit (1) @@ -324,28 +326,28 @@ cryptolist.close () chlog = "%s * crypto.lst: New file.\n" % chlog outfile = os.path.join (cipher_dir_out, "types.h") -fw=open (outfile, "w") +fw=codecs.open (outfile, "w", "utf-8") fw.write ("#include \n") fw.write ("#include \n") chlog = "%s * types.h: New file.\n" % chlog fw.close () outfile = os.path.join (cipher_dir_out, "memory.h") -fw=open (outfile, "w") +fw=codecs.open (outfile, "w", "utf-8") fw.write ("#include \n") chlog = "%s * memory.h: New file.\n" % chlog fw.close () outfile = os.path.join (cipher_dir_out, "cipher.h") -fw=open (outfile, "w") +fw=codecs.open (outfile, "w", "utf-8") fw.write ("#include \n") fw.write ("#include \n") chlog = "%s * cipher.h: Likewise.\n" % chlog fw.close () outfile = os.path.join (cipher_dir_out, "g10lib.h") -fw=open (outfile, "w") +fw=codecs.open (outfile, "w", "utf-8") fw.write ("#include \n") chlog = "%s * g10lib.h: Likewise.\n" % chlog fw.close () @@ -355,7 +357,7 @@ outfile = os.path.join (cipher_dir_out, "ChangeLog") conf.close (); -initfile = open (os.path.join (cipher_dir_out, "init.c"), "w") +initfile = codecs.open (os.path.join (cipher_dir_out, "init.c"), "w", "utf-8") for module in modules: initfile.write ("extern void grub_%s_init (void);\n" % module) initfile.write ("extern void grub_%s_fini (void);\n" % module) @@ -380,8 +382,8 @@ confutil.write ("};\n"); confutil.close (); -f=open (infile, "r") -fw=open (outfile, "w") +f=codecs.open (infile, "r", "utf-8") +fw=codecs.open (outfile, "w", "utf-8") dt = datetime.date.today () fw.write ("%04d-%02d-%02d Automatic import tool\n" % \ (dt.year,dt.month, dt.day)) From 366e34fa5a49d022f3f01861c7d6ee6d7268a8a1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 Oct 2011 11:57:48 +0200 Subject: [PATCH 398/673] Fix few obvious type discrepancies. * grub-core/fs/affs.c (grub_affs_read_file): Use grub_off_t for offset. * grub-core/fs/afs.c (grub_afs_read_file): Likewise. * grub-core/fs/fshelp.c (grub_fshelp_find_file): Remove leftover variable. * grub-core/fs/hfs.c (grub_hfs_read_file): Use grub_off_t for offset and connected types. * grub-core/fs/nilfs2.c (grub_nilfs2_read_file): Use grub_off_t for offset. (grub_nilfs2_iterate_dir): Use grub_off_t for fpos. * grub-core/fs/sfs.c (grub_sfs_read_file): Use grub_off_t for offset. * grub-core/fs/ufs.c (grub_ufs_read_file): Use grub_off_t for offset and connected types. --- ChangeLog | 17 +++++++++++++++++ grub-core/fs/affs.c | 2 +- grub-core/fs/afs.c | 2 +- grub-core/fs/fshelp.c | 1 - grub-core/fs/hfs.c | 24 +++++++++++++----------- grub-core/fs/nilfs2.c | 4 ++-- grub-core/fs/sfs.c | 2 +- grub-core/fs/ufs.c | 23 +++++++++++++---------- 8 files changed, 48 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5fbffcd4..2e44b4c26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-10-16 Vladimir Serbinenko + + Fix few obvious type discrepancies. + + * grub-core/fs/affs.c (grub_affs_read_file): Use grub_off_t for offset. + * grub-core/fs/afs.c (grub_afs_read_file): Likewise. + * grub-core/fs/fshelp.c (grub_fshelp_find_file): Remove leftover + variable. + * grub-core/fs/hfs.c (grub_hfs_read_file): Use grub_off_t for offset + and connected types. + * grub-core/fs/nilfs2.c (grub_nilfs2_read_file): Use grub_off_t for + offset. + (grub_nilfs2_iterate_dir): Use grub_off_t for fpos. + * grub-core/fs/sfs.c (grub_sfs_read_file): Use grub_off_t for offset. + * grub-core/fs/ufs.c (grub_ufs_read_file): Use grub_off_t for offset + and connected types. + 2011-10-16 Vladimir Serbinenko Fix python 3.x incompatibilities. diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index e17540e2f..adf2932bd 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -160,7 +160,7 @@ static grub_ssize_t grub_affs_read_file (grub_fshelp_node_t node, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_affs_read_block, diff --git a/grub-core/fs/afs.c b/grub-core/fs/afs.c index 35ef49937..b64ebb52c 100644 --- a/grub-core/fs/afs.c +++ b/grub-core/fs/afs.c @@ -336,7 +336,7 @@ static grub_ssize_t grub_afs_read_file (grub_fshelp_node_t node, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_afs_read_block, diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index 2ff78c423..275cb9e1b 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -61,7 +61,6 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, char fpath[grub_strlen (currpath) + 1]; char *name = fpath; char *next; - // unsigned int pos = 0; enum grub_fshelp_filetype type = GRUB_FSHELP_DIR; grub_fshelp_node_t currnode = currroot; grub_fshelp_node_t oldnode = currroot; diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 6f27c69c4..973a2d2ef 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -244,22 +244,24 @@ static grub_ssize_t grub_hfs_read_file (struct grub_hfs_data *data, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { - int i; - int blockcnt; + grub_off_t i; + grub_off_t blockcnt; - blockcnt = ((len + pos) - + data->blksz - 1) / data->blksz; + blockcnt = grub_divmod64 (((len + pos) + + data->blksz - 1), data->blksz, 0); - for (i = pos / data->blksz; i < blockcnt; i++) + for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++) { - int blknr; - int blockoff = pos % data->blksz; - int blockend = data->blksz; + grub_disk_addr_t blknr; + grub_off_t blockoff; + grub_off_t blockend = data->blksz; int skipfirst = 0; + grub_divmod64 (pos, data->blksz, &blockoff); + blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); if (grub_errno) return -1; @@ -267,7 +269,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, /* Last block. */ if (i == blockcnt - 1) { - blockend = (len + pos) % data->blksz; + grub_divmod64 ((len + pos), data->blksz, &blockend); /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ if (! blockend) @@ -275,7 +277,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, } /* First block. */ - if (i == pos / data->blksz) + if (i == grub_divmod64 (pos, data->blksz, 0)) { skipfirst = blockoff; blockend -= skipfirst; diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 44fb213bd..62cf167c7 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -628,7 +628,7 @@ grub_nilfs2_read_file (grub_fshelp_node_t node, sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_nilfs2_read_block, @@ -866,7 +866,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, enum grub_fshelp_filetype filetype, grub_fshelp_node_t node)) { - unsigned int fpos = 0; + grub_off_t fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; if (!diro->inode_read) diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index 19ae90715..f1e09ccbd 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -250,7 +250,7 @@ static grub_ssize_t grub_sfs_read_file (grub_fshelp_node_t node, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { return grub_fshelp_read_file (node->data->disk, node, read_hook, pos, len, buf, grub_sfs_read_block, diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index 0f4ea0019..435fec6a5 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -285,26 +285,29 @@ static grub_ssize_t grub_ufs_read_file (struct grub_ufs_data *data, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - int pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { struct grub_ufs_sblock *sblock = &data->sblock; - int i; - int blockcnt; + grub_off_t i; + grub_off_t blockcnt; /* Adjust len so it we can't read past the end of the file. */ if (len + pos > INODE_SIZE (data)) len = INODE_SIZE (data) - pos; - blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) / UFS_BLKSZ (sblock); + blockcnt = grub_divmod64 ((len + pos + UFS_BLKSZ (sblock) - 1), + UFS_BLKSZ (sblock), 0); - for (i = pos / UFS_BLKSZ (sblock); i < blockcnt; i++) + for (i = grub_divmod64 (pos, UFS_BLKSZ (sblock), 0); i < blockcnt; i++) { - int blknr; - int blockoff = pos % UFS_BLKSZ (sblock); - int blockend = UFS_BLKSZ (sblock); + grub_disk_addr_t blknr; + grub_off_t blockoff; + grub_off_t blockend = UFS_BLKSZ (sblock); int skipfirst = 0; + grub_divmod64 (pos, UFS_BLKSZ (sblock), &blockoff); + blknr = grub_ufs_get_file_block (data, i); if (grub_errno) return -1; @@ -312,14 +315,14 @@ grub_ufs_read_file (struct grub_ufs_data *data, /* Last block. */ if (i == blockcnt - 1) { - blockend = (len + pos) % UFS_BLKSZ (sblock); + grub_divmod64 (len + pos, UFS_BLKSZ (sblock), &blockend); if (!blockend) blockend = UFS_BLKSZ (sblock); } /* First block. */ - if (i == (pos / (int) UFS_BLKSZ (sblock))) + if (i == grub_divmod64 (pos, UFS_BLKSZ (sblock), 0)) { skipfirst = blockoff; blockend -= skipfirst; From 2afb7f6cbf5ca5c49750c70b07f67d4733f66061 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 Oct 2011 15:15:35 +0200 Subject: [PATCH 399/673] * configure.ac: Check for __ctzdi2 and __ctzsi2. * include/grub/libgcc.h: Include __ctzdi2 and __ctzsi2 if present. --- ChangeLog | 5 +++++ configure.ac | 2 +- include/grub/libgcc.h | 6 ++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 2e44b4c26..0592459c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-16 Vladimir Serbinenko + + * configure.ac: Check for __ctzdi2 and __ctzsi2. + * include/grub/libgcc.h: Include __ctzdi2 and __ctzsi2 if present. + 2011-10-16 Vladimir Serbinenko Fix few obvious type discrepancies. diff --git a/configure.ac b/configure.ac index 9cfbd2340..6aafdf13d 100644 --- a/configure.ac +++ b/configure.ac @@ -587,7 +587,7 @@ CFLAGS="$CFLAGS -Wl,--defsym,abort=main" fi # Check for libgcc symbols -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3) +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3 __ctzdi2 __ctzsi2) if test "x$TARGET_APPLE_CC" = x1 ; then CFLAGS="$TARGET_CFLAGS -nostdlib" diff --git a/include/grub/libgcc.h b/include/grub/libgcc.h index 19723fd23..7a433dc68 100644 --- a/include/grub/libgcc.h +++ b/include/grub/libgcc.h @@ -63,6 +63,12 @@ void EXPORT_FUNC (__divsi3) (void); # ifdef HAVE___MODSI3 void EXPORT_FUNC (__modsi3) (void); # endif +# ifdef HAVE___CTZDI2 +void EXPORT_FUNC (__ctzdi2) (void); +# endif +# ifdef HAVE___CTZSI2 +void EXPORT_FUNC (__ctzsi2) (void); +# endif #endif # ifdef HAVE___IA64_TRAMPOLINE From 39705fadd7ed2d4f78df6f48abc13150464a5698 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 16 Oct 2011 15:23:29 +0200 Subject: [PATCH 400/673] Replace grub_module_iterate with FOR_MODULES. * grub-core/disk/memdisk.c (GRUB_MOD_INIT): Switched to new interface. * grub-core/kern/efi/efi.c (grub_arch_modules_addr): Renamed to... (grub_efi_modules_addr): ...this. * grub-core/kern/efi/init.c (grub_modbase): New variable. (grub_efi_init): Set grub_modbase. * grub-core/kern/emu/main.c (grub_arch_modules_addr): Removed. (grub_modbase): New variable. * grub-core/kern/i386/coreboot/init.c (grub_arch_modules_addr): Removed. (grub_modbase): New variable. (grub_machine_init): Set grub_modbase. * grub-core/kern/i386/pc/init.c (grub_arch_modules_addr): Removed. (grub_modbase): New variable. (grub_machine_init): Set grub_modbase. * grub-core/kern/ieee1275/init.c (grub_arch_modules_addr): Removed. (grub_modbase): New variable. (grub_machine_init): Set grub_modbase. * grub-core/kern/main.c (grub_module_iterate): Remove. (grub_modules_get_end): Use grub_modbase. (grub_load_modules): Use FOR_MODULES. (grub_load_config): Likewise. * grub-core/kern/mips/arc/init.c (grub_arch_modules_addr): Removed. (grub_modbase): New variable. (grub_machine_init): Set grub_modbase. * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): Removed. (grub_modbase): New variable. (grub_machine_init): Set grub_modbase. * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr): Removed. (grub_modbase): New variable. (grub_machine_init): Set grub_modbase. * include/grub/efi/efi.h (grub_efi_modules_addr): New declaration. * include/grub/kernel.h (grub_arch_modules_addr): Removed. (grub_module_iterate): Likewise. (grub_modbase): New variable declaration. (FOR_MODULES): New macro. --- ChangeLog | 40 ++++++++++++++ grub-core/disk/memdisk.c | 34 +++++------- grub-core/kern/efi/efi.c | 2 +- grub-core/kern/efi/init.c | 3 + grub-core/kern/emu/main.c | 6 +- grub-core/kern/i386/coreboot/init.c | 19 +++---- grub-core/kern/i386/pc/init.c | 13 ++--- grub-core/kern/ieee1275/init.c | 11 ++-- grub-core/kern/main.c | 83 +++++++++------------------- grub-core/kern/mips/arc/init.c | 8 +-- grub-core/kern/mips/loongson/init.c | 6 +- grub-core/kern/mips/qemu_mips/init.c | 6 +- include/grub/efi/efi.h | 2 + include/grub/kernel.h | 10 +++- 14 files changed, 117 insertions(+), 126 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0592459c3..2ce132a14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2011-10-16 Vladimir Serbinenko + + Replace grub_module_iterate with FOR_MODULES. + + * grub-core/disk/memdisk.c (GRUB_MOD_INIT): Switched to new interface. + * grub-core/kern/efi/efi.c (grub_arch_modules_addr): Renamed to... + (grub_efi_modules_addr): ...this. + * grub-core/kern/efi/init.c (grub_modbase): New variable. + (grub_efi_init): Set grub_modbase. + * grub-core/kern/emu/main.c (grub_arch_modules_addr): Removed. + (grub_modbase): New variable. + * grub-core/kern/i386/coreboot/init.c (grub_arch_modules_addr): Removed. + (grub_modbase): New variable. + (grub_machine_init): Set grub_modbase. + * grub-core/kern/i386/pc/init.c (grub_arch_modules_addr): Removed. + (grub_modbase): New variable. + (grub_machine_init): Set grub_modbase. + * grub-core/kern/ieee1275/init.c (grub_arch_modules_addr): Removed. + (grub_modbase): New variable. + (grub_machine_init): Set grub_modbase. + * grub-core/kern/main.c (grub_module_iterate): Remove. + (grub_modules_get_end): Use grub_modbase. + (grub_load_modules): Use FOR_MODULES. + (grub_load_config): Likewise. + * grub-core/kern/mips/arc/init.c (grub_arch_modules_addr): Removed. + (grub_modbase): New variable. + (grub_machine_init): Set grub_modbase. + * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): Removed. + (grub_modbase): New variable. + (grub_machine_init): Set grub_modbase. + * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr): + Removed. + (grub_modbase): New variable. + (grub_machine_init): Set grub_modbase. + * include/grub/efi/efi.h (grub_efi_modules_addr): New declaration. + * include/grub/kernel.h (grub_arch_modules_addr): Removed. + (grub_module_iterate): Likewise. + (grub_modbase): New variable declaration. + (FOR_MODULES): New macro. + 2011-10-16 Vladimir Serbinenko * configure.ac: Check for __ctzdi2 and __ctzsi2. diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index ed570c6a0..4de0971ae 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -86,30 +86,24 @@ static struct grub_disk_dev grub_memdisk_dev = GRUB_MOD_INIT(memdisk) { - auto int hook (struct grub_module_header *); - int hook (struct grub_module_header *header) - { - if (header->type == OBJ_TYPE_MEMDISK) - { - char *memdisk_orig_addr; - memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header); + struct grub_module_header *header; + FOR_MODULES (header) + if (header->type == OBJ_TYPE_MEMDISK) + { + char *memdisk_orig_addr; + memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header); - grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr); + grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr); - memdisk_size = header->size - sizeof (struct grub_module_header); - memdisk_addr = grub_malloc (memdisk_size); + memdisk_size = header->size - sizeof (struct grub_module_header); + memdisk_addr = grub_malloc (memdisk_size); - grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n"); - grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size); + grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n"); + grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size); - grub_disk_dev_register (&grub_memdisk_dev); - return 1; - } - - return 0; - } - - grub_module_iterate (hook); + grub_disk_dev_register (&grub_memdisk_dev); + break; + } } GRUB_MOD_FINI(memdisk) diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index d0994a940..e27dd1ad0 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -218,7 +218,7 @@ grub_get_rtc (void) /* Search the mods section from the PE32/PE32+ image. This code uses a PE32 header, but should work with PE32+ as well. */ grub_addr_t -grub_arch_modules_addr (void) +grub_efi_modules_addr (void) { grub_efi_loaded_image_t *image; struct grub_pe32_header *header; diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 4dfb06284..942ab0256 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -26,9 +26,12 @@ #include #include +grub_addr_t grub_modbase; + void grub_efi_init (void) { + grub_modbase = grub_efi_modules_addr (); /* First of all, initialize the console so that GRUB can display messages. */ grub_console_init (); diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 9a58acd9e..d5c09ad47 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -53,11 +53,7 @@ static char *root_dev = NULL, *dir = NULL; int grub_no_autoload; -grub_addr_t -grub_arch_modules_addr (void) -{ - return 0; -} +grub_addr_t grub_modbase = 0; void grub_reboot (void) diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index ebbea2523..b7510ff98 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -56,10 +56,18 @@ grub_exit (void) grub_cpu_idle (); } +#ifdef GRUB_MACHINE_QEMU +grub_addr_t grub_modbase; +#else +grub_addr_t grub_modbase = ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN); +#endif + void grub_machine_init (void) { #ifdef GRUB_MACHINE_QEMU + grub_modbase = grub_core_entry_addr + grub_kernel_image_size; + grub_qemu_init_cirrus (); #endif /* Initialize the console as early as possible. */ @@ -118,14 +126,3 @@ grub_machine_fini (void) grub_vga_text_fini (); grub_stop_floppy (); } - -/* Return the end of the core image. */ -grub_addr_t -grub_arch_modules_addr (void) -{ -#ifdef GRUB_MACHINE_QEMU - return grub_core_entry_addr + grub_kernel_image_size; -#else - return ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN); -#endif -} diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 24fe8fed9..62269de78 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -129,6 +129,8 @@ compact_mem_regions (void) } } +grub_addr_t grub_modbase; + void grub_machine_init (void) { @@ -137,6 +139,9 @@ grub_machine_init (void) int grub_lower_mem; #endif + grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE); + /* Initialize the console as early as possible. */ grub_console_init (); @@ -206,11 +211,3 @@ grub_machine_fini (void) grub_console_fini (); grub_stop_floppy (); } - -/* Return the end of the core image. */ -grub_addr_t -grub_arch_modules_addr (void) -{ - return GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR - + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE); -} diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 81b06c88e..76f932d09 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -256,9 +256,14 @@ grub_parse_cmdline (void) static grub_uint64_t ieee1275_get_time_ms (void); +grub_addr_t grub_modbase; + void grub_machine_init (void) { + grub_modbase = ALIGN_UP((grub_addr_t) _end + + GRUB_KERNEL_MACHINE_MOD_GAP, + GRUB_KERNEL_MACHINE_MOD_ALIGN); grub_ieee1275_init (); grub_console_init_early (); @@ -293,9 +298,3 @@ 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_KERNEL_MACHINE_MOD_GAP, GRUB_KERNEL_MACHINE_MOD_ALIGN); -} diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 0cec93d89..9e1971773 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -30,45 +30,20 @@ #include #include -void -grub_module_iterate (int (*hook) (struct grub_module_header *header)) -{ - struct grub_module_info *modinfo; - struct grub_module_header *header; - grub_addr_t modbase; - - modbase = grub_arch_modules_addr (); - modinfo = (struct grub_module_info *) modbase; - - /* Check if there are any modules. */ - if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC) - return; - - for (header = (struct grub_module_header *) (modbase + modinfo->offset); - header < (struct grub_module_header *) (modbase + modinfo->size); - header = (struct grub_module_header *) ((char *) header + header->size)) - { - if (hook (header)) - break; - } -} - /* This is actualy platform-independant but used only on loongson and sparc. */ #if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64) grub_addr_t grub_modules_get_end (void) { struct grub_module_info *modinfo; - grub_addr_t modbase; - modbase = grub_arch_modules_addr (); - modinfo = (struct grub_module_info *) modbase; + modinfo = (struct grub_module_info *) grub_modbase; /* Check if there are any modules. */ if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC) - return modbase; + return grub_modbase; - return modbase + modinfo->size; + return grub_modbase + modinfo->size; } #endif @@ -76,42 +51,36 @@ grub_modules_get_end (void) static void grub_load_modules (void) { - auto int hook (struct grub_module_header *); - int hook (struct grub_module_header *header) - { - /* Not an ELF module, skip. */ - if (header->type != OBJ_TYPE_ELF) - return 0; + struct grub_module_header *header; + FOR_MODULES (header) + { + /* Not an ELF module, skip. */ + if (header->type != OBJ_TYPE_ELF) + continue; - if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header), - (header->size - sizeof (struct grub_module_header)))) - grub_fatal ("%s", grub_errmsg); + if (! grub_dl_load_core ((char *) header + sizeof (struct grub_module_header), + (header->size - sizeof (struct grub_module_header)))) + grub_fatal ("%s", grub_errmsg); - if (grub_errno) - grub_print_error (); - - return 0; - } - - grub_module_iterate (hook); + if (grub_errno) + grub_print_error (); + } } static void grub_load_config (void) { - auto int hook (struct grub_module_header *); - int hook (struct grub_module_header *header) - { - /* Not an embedded config, skip. */ - if (header->type != OBJ_TYPE_CONFIG) - return 0; - - grub_parser_execute ((char *) header + - sizeof (struct grub_module_header)); - return 1; - } - - grub_module_iterate (hook); + struct grub_module_header *header; + FOR_MODULES (header) + { + /* Not an embedded config, skip. */ + if (header->type != OBJ_TYPE_CONFIG) + continue; + + grub_parser_execute ((char *) header + + sizeof (struct grub_module_header)); + break; + } } /* Write hook for the environment variables of root. Remove surrounding diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index 514b481f6..2e25335ca 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -125,12 +125,14 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) } extern grub_uint32_t grub_total_modules_size; +grub_addr_t grub_modbase; void grub_machine_init (void) { struct grub_arc_memory_descriptor *cur = NULL; + grub_modbase = GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size; grub_console_init_early (); /* FIXME: measure this. */ @@ -164,12 +166,6 @@ grub_machine_init (void) grub_arcdisk_init (); } -grub_addr_t -grub_arch_modules_addr (void) -{ - return GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size; -} - void grub_machine_fini (void) { diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 2d1a0653e..8acfb0767 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -298,9 +298,5 @@ grub_reboot (void) } extern char _end[]; +grub_addr_t grub_modbase = (grub_addr_t) _end; -grub_addr_t -grub_arch_modules_addr (void) -{ - return (grub_addr_t) _end; -} diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index db9cc796a..4921c42bf 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -113,9 +113,5 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) } extern char _end[]; +grub_addr_t grub_modbase = (grub_addr_t) _end; -grub_addr_t -grub_arch_modules_addr (void) -{ - return (grub_addr_t) _end; -} diff --git a/include/grub/efi/efi.h b/include/grub/efi/efi.h index e98f99507..7ecda58ab 100644 --- a/include/grub/efi/efi.h +++ b/include/grub/efi/efi.h @@ -70,6 +70,8 @@ extern void (*EXPORT_VAR(grub_efi_net_config)) (grub_efi_handle_t hnd, char **device, char **path); +grub_addr_t grub_efi_modules_addr (void); + void grub_efi_mm_init (void); void grub_efi_mm_fini (void); void grub_efi_init (void); diff --git a/include/grub/kernel.h b/include/grub/kernel.h index aef585668..d8c0fed33 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -68,9 +68,15 @@ struct grub_module_info64 #define grub_module_info grub_module_info32 #endif -extern grub_addr_t grub_arch_modules_addr (void); +extern grub_addr_t EXPORT_VAR (grub_modbase); -extern void EXPORT_FUNC(grub_module_iterate) (int (*hook) (struct grub_module_header *)); +#define FOR_MODULES(var) for (\ + var = grub_modbase ? (struct grub_module_header *) \ + (grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\ + var && (grub_addr_t) var \ + < (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \ + var = (struct grub_module_header *) \ + ((char *) var + ((struct grub_module_header *) var)->size)) grub_addr_t grub_modules_get_end (void); From a97501d2389d524323293395636b43aec73f1761 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 18 Oct 2011 15:21:51 +0200 Subject: [PATCH 401/673] Make grub_prefix into module to fix the arbitrary limit and save some space. * grub-core/kern/emu/main.c (grub_prefix): Removed. * grub-core/kern/i386/coreboot/startup.S (grub_prefix): Likewise. * grub-core/kern/i386/efi/startup.S (grub_prefix): Likewise. * grub-core/kern/i386/ieee1275/startup.S (grub_prefix): Likewise. * grub-core/kern/i386/pc/startup.S (grub_prefix): Likewise. * grub-core/kern/i386/qemu/startup.S (grub_prefix): Likewise. * grub-core/kern/ia64/efi/startup.S (grub_prefix): Likewise. * grub-core/kern/mips/startup.S (grub_prefix): Likewise. * grub-core/kern/powerpc/ieee1275/startup.S (grub_prefix): Likewise. * grub-core/kern/sparc64/ieee1275/crt0.S (grub_prefix): Likewise. * grub-core/kern/x86_64/efi/startup.S (grub_prefix): Likewise. * include/grub/ia64/efi/kernel.h: Removed. * include/grub/kernel.h: New module type OBJ_TYPE_PREFIX. (grub_prefix): Removed. * include/grub/offsets.h (GRUB_KERNEL_I386_PC_PREFIX): Removed. (GRUB_KERNEL_I386_PC_PREFIX_END): Likewise. (GRUB_KERNEL_I386_QEMU_PREFIX): Likewise. (GRUB_KERNEL_I386_QEMU_PREFIX_END): Likewise. (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX): Likewise. (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END): Likewise. (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX): Likewise. (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END): Likewise. (GRUB_KERNEL_MIPS_LOONGSON_PREFIX): Likewise. (GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END): Likewise. (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX): Likewise. (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END): Likewise. (GRUB_KERNEL_MIPS_ARC_PREFIX): Likewise. (GRUB_KERNEL_MIPS_ARC_PREFIX_END): Likewise. (GRUB_KERNEL_I386_EFI_PREFIX): Likewise. (GRUB_KERNEL_I386_EFI_PREFIX_END): Likewise. (GRUB_KERNEL_IA64_EFI_PREFIX): Likewise. (GRUB_KERNEL_IA64_EFI_PREFIX_END): Likewise. (GRUB_KERNEL_X86_64_EFI_PREFIX): Likewise. (GRUB_KERNEL_X86_64_EFI_PREFIX_END): Likewise. (GRUB_KERNEL_I386_COREBOOT_PREFIX): Likewise. (GRUB_KERNEL_I386_COREBOOT_PREFIX_END): Likewise. (GRUB_KERNEL_I386_MULTIBOOT_PREFIX): Likewise. (GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END): Likewise. (GRUB_KERNEL_I386_IEEE1275_PREFIX): Likewise. (GRUB_KERNEL_I386_IEEE1275_PREFIX_END): Likewise. (GRUB_KERNEL_MACHINE_PREFIX): Likewise. (GRUB_KERNEL_MACHINE_PREFIX_END): Likewise. * grub-core/kern/main.c (grub_set_prefix_and_root): Retrieve grub_prefix from module. * util/grub-mkimage.c (image_target_desc): Removed prefix and prefix_end. (image_targets): Likewise. (generate_image): Put prefix as a module. --- ChangeLog | 54 ++++++++++++++++++ grub-core/kern/emu/main.c | 2 - grub-core/kern/i386/coreboot/startup.S | 15 ----- grub-core/kern/i386/efi/startup.S | 11 ---- grub-core/kern/i386/ieee1275/startup.S | 18 ------ grub-core/kern/i386/pc/startup.S | 11 ---- grub-core/kern/i386/qemu/startup.S | 8 --- grub-core/kern/ia64/efi/startup.S | 10 ---- grub-core/kern/main.c | 49 +++++++++------- grub-core/kern/mips/startup.S | 11 ---- grub-core/kern/powerpc/ieee1275/startup.S | 14 ----- grub-core/kern/sparc64/ieee1275/crt0.S | 8 --- grub-core/kern/x86_64/efi/startup.S | 15 ----- include/grub/ia64/efi/kernel.h | 34 ------------ include/grub/kernel.h | 8 +-- include/grub/offsets.h | 53 ------------------ util/grub-mkimage.c | 68 ++++++++--------------- 17 files changed, 106 insertions(+), 283 deletions(-) delete mode 100644 include/grub/ia64/efi/kernel.h diff --git a/ChangeLog b/ChangeLog index 2ce132a14..a758fc275 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,57 @@ +2011-10-18 Vladimir Serbinenko + + Make grub_prefix into module to fix the arbitrary limit and save + some space. + + * grub-core/kern/emu/main.c (grub_prefix): Removed. + * grub-core/kern/i386/coreboot/startup.S (grub_prefix): Likewise. + * grub-core/kern/i386/efi/startup.S (grub_prefix): Likewise. + * grub-core/kern/i386/ieee1275/startup.S (grub_prefix): Likewise. + * grub-core/kern/i386/pc/startup.S (grub_prefix): Likewise. + * grub-core/kern/i386/qemu/startup.S (grub_prefix): Likewise. + * grub-core/kern/ia64/efi/startup.S (grub_prefix): Likewise. + * grub-core/kern/mips/startup.S (grub_prefix): Likewise. + * grub-core/kern/powerpc/ieee1275/startup.S (grub_prefix): Likewise. + * grub-core/kern/sparc64/ieee1275/crt0.S (grub_prefix): Likewise. + * grub-core/kern/x86_64/efi/startup.S (grub_prefix): Likewise. + * include/grub/ia64/efi/kernel.h: Removed. + * include/grub/kernel.h: New module type OBJ_TYPE_PREFIX. + (grub_prefix): Removed. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_PREFIX): Removed. + (GRUB_KERNEL_I386_PC_PREFIX_END): Likewise. + (GRUB_KERNEL_I386_QEMU_PREFIX): Likewise. + (GRUB_KERNEL_I386_QEMU_PREFIX_END): Likewise. + (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX): Likewise. + (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END): Likewise. + (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX): Likewise. + (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END): Likewise. + (GRUB_KERNEL_MIPS_LOONGSON_PREFIX): Likewise. + (GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END): Likewise. + (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX): Likewise. + (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END): Likewise. + (GRUB_KERNEL_MIPS_ARC_PREFIX): Likewise. + (GRUB_KERNEL_MIPS_ARC_PREFIX_END): Likewise. + (GRUB_KERNEL_I386_EFI_PREFIX): Likewise. + (GRUB_KERNEL_I386_EFI_PREFIX_END): Likewise. + (GRUB_KERNEL_IA64_EFI_PREFIX): Likewise. + (GRUB_KERNEL_IA64_EFI_PREFIX_END): Likewise. + (GRUB_KERNEL_X86_64_EFI_PREFIX): Likewise. + (GRUB_KERNEL_X86_64_EFI_PREFIX_END): Likewise. + (GRUB_KERNEL_I386_COREBOOT_PREFIX): Likewise. + (GRUB_KERNEL_I386_COREBOOT_PREFIX_END): Likewise. + (GRUB_KERNEL_I386_MULTIBOOT_PREFIX): Likewise. + (GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END): Likewise. + (GRUB_KERNEL_I386_IEEE1275_PREFIX): Likewise. + (GRUB_KERNEL_I386_IEEE1275_PREFIX_END): Likewise. + (GRUB_KERNEL_MACHINE_PREFIX): Likewise. + (GRUB_KERNEL_MACHINE_PREFIX_END): Likewise. + * grub-core/kern/main.c (grub_set_prefix_and_root): Retrieve grub_prefix + from module. + * util/grub-mkimage.c (image_target_desc): Removed prefix and + prefix_end. + (image_targets): Likewise. + (generate_image): Put prefix as a module. + 2011-10-16 Vladimir Serbinenko Replace grub_module_iterate with FOR_MODULES. diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index d5c09ad47..8d15f17c5 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -79,8 +79,6 @@ grub_machine_fini (void) grub_console_fini (); } -char grub_prefix[64] = ""; - static struct option options[] = diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S index 07c5437c0..5e7767bb9 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -40,21 +40,6 @@ start: _start: jmp codestart - /* - * This is a special data area at a fixed offset from the beginning. - */ - - . = _start + GRUB_KERNEL_MACHINE_PREFIX - -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + GRUB_KERNEL_MACHINE_PREFIX_END - /* * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). */ diff --git a/grub-core/kern/i386/efi/startup.S b/grub-core/kern/i386/efi/startup.S index 5b464ab83..49b05c1e6 100644 --- a/grub-core/kern/i386/efi/startup.S +++ b/grub-core/kern/i386/efi/startup.S @@ -41,17 +41,6 @@ _start: * This is a special data area 8 bytes from the beginning. */ - . = _start + 0x8 - -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + 0x50 - codestart: /* * EFI_SYSTEM_TABLE * and EFI_HANDLE are passed on the stack. diff --git a/grub-core/kern/i386/ieee1275/startup.S b/grub-core/kern/i386/ieee1275/startup.S index 82087323b..6b39f5f3a 100644 --- a/grub-core/kern/i386/ieee1275/startup.S +++ b/grub-core/kern/i386/ieee1275/startup.S @@ -36,24 +36,6 @@ start: _start: - jmp codestart - - /* - * This is a special data area at a fixed offset from the beginning. - */ - - . = _start + GRUB_KERNEL_MACHINE_PREFIX - -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + GRUB_KERNEL_MACHINE_PREFIX_END - -codestart: movl %eax, EXT_C(grub_ieee1275_entry_fn) jmp EXT_C(grub_main) diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 0fe114add..3bbe34753 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -455,17 +455,6 @@ gate_a20_check_state: */ . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE - . = _start + GRUB_KERNEL_MACHINE_PREFIX -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - . = _start + GRUB_KERNEL_MACHINE_PREFIX_END - - - /* * grub_exit() * diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S index 7834d1df5..6500de620 100644 --- a/grub-core/kern/i386/qemu/startup.S +++ b/grub-core/kern/i386/qemu/startup.S @@ -34,14 +34,6 @@ VARIABLE(grub_core_entry_addr) .long 0 VARIABLE(grub_kernel_image_size) .long 0 -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + GRUB_KERNEL_MACHINE_PREFIX_END codestart: /* Relocate to low memory. First we figure out our location. diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S index b5e26a204..d75c6d7cc 100644 --- a/grub-core/kern/ia64/efi/startup.S +++ b/grub-core/kern/ia64/efi/startup.S @@ -42,13 +42,3 @@ _start: br.ret.sptk.few rp .endp _start - - . = _start + GRUB_KERNEL_MACHINE_PREFIX -VARIABLE(grub_prefix) - .byte 0 - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - . = _start + GRUB_KERNEL_MACHINE_PREFIX_END diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 9e1971773..77be11422 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -105,25 +105,32 @@ grub_set_prefix_and_root (void) char *path = NULL; char *fwdevice = NULL; char *fwpath = NULL; + char *prefix; + struct grub_module_header *header; + + FOR_MODULES (header) + if (header->type == OBJ_TYPE_PREFIX) + prefix = (char *) header + sizeof (struct grub_module_header); grub_register_variable_hook ("root", 0, grub_env_write_root); - { - char *pptr = NULL; - if (grub_prefix[0] == '(') - { - pptr = grub_strrchr (grub_prefix, ')'); - if (pptr) - { - device = grub_strndup (grub_prefix + 1, pptr - grub_prefix - 1); - pptr++; - } - } - if (!pptr) - pptr = grub_prefix; - if (pptr[0]) - path = grub_strdup (pptr); - } + if (prefix) + { + char *pptr = NULL; + if (prefix[0] == '(') + { + pptr = grub_strrchr (prefix, ')'); + if (pptr) + { + device = grub_strndup (prefix + 1, pptr - prefix - 1); + pptr++; + } + } + if (!pptr) + pptr = prefix; + if (pptr[0]) + path = grub_strdup (pptr); + } if ((!device || device[0] == ',' || !device[0]) || !path) grub_machine_get_bootlocation (&fwdevice, &fwpath); @@ -152,13 +159,13 @@ grub_set_prefix_and_root (void) path = fwpath; if (device) { - char *prefix; + char *prefix_set; - prefix = grub_xasprintf ("(%s)%s", device, path ? : ""); - if (prefix) + prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); + if (prefix_set) { - grub_env_set ("prefix", prefix); - grub_free (prefix); + grub_env_set ("prefix", prefix_set); + grub_free (prefix_set); } grub_env_set ("root", device); } diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index da6450237..2476038bc 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -40,17 +40,6 @@ start: VARIABLE(grub_total_modules_size) .long 0 - . = _start + GRUB_KERNEL_MACHINE_PREFIX - -VARIABLE(grub_prefix) - - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + GRUB_KERNEL_MACHINE_PREFIX_END VARIABLE (grub_arch_busclock) .long 0 VARIABLE (grub_arch_cpuclock) diff --git a/grub-core/kern/powerpc/ieee1275/startup.S b/grub-core/kern/powerpc/ieee1275/startup.S index 0b1c23346..b26c47edb 100644 --- a/grub-core/kern/powerpc/ieee1275/startup.S +++ b/grub-core/kern/powerpc/ieee1275/startup.S @@ -28,20 +28,6 @@ .globl start, _start start: _start: - b codestart - - . = _start + GRUB_KERNEL_MACHINE_PREFIX - -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + GRUB_KERNEL_MACHINE_PREFIX_END - -codestart: li 2, 0 li 13, 0 diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S index cebdca2b6..1466a56f8 100644 --- a/grub-core/kern/sparc64/ieee1275/crt0.S +++ b/grub-core/kern/sparc64/ieee1275/crt0.S @@ -35,14 +35,6 @@ VARIABLE(grub_kernel_image_size) .word 0 VARIABLE(grub_compressed_size) .word 0 -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = EXT_C(_start) + GRUB_KERNEL_MACHINE_PREFIX_END codestart: /* Copy the modules past the end of the kernel image. diff --git a/grub-core/kern/x86_64/efi/startup.S b/grub-core/kern/x86_64/efi/startup.S index fb4fc7b64..37efde7fc 100644 --- a/grub-core/kern/x86_64/efi/startup.S +++ b/grub-core/kern/x86_64/efi/startup.S @@ -39,21 +39,6 @@ _start: . = _start + 0x6 .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR - /* - * This is a special data area 8 bytes from the beginning. - */ - - . = _start + 0x8 - -VARIABLE(grub_prefix) - /* to be filled by grub-mkimage */ - - /* - * Leave some breathing room for the prefix. - */ - - . = _start + 0x50 - codestart: movq %rcx, EXT_C(grub_efi_image_handle)(%rip) movq %rdx, EXT_C(grub_efi_system_table)(%rip) diff --git a/include/grub/ia64/efi/kernel.h b/include/grub/ia64/efi/kernel.h deleted file mode 100644 index ae75380f0..000000000 --- a/include/grub/ia64/efi/kernel.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2007,2008,2010 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 . - */ - -#ifndef GRUB_MACHINE_KERNEL_HEADER -#define GRUB_MACHINE_KERNEL_HEADER 1 - -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_MACHINE_PREFIX 0x8 - -/* End of the data section. */ -#define GRUB_KERNEL_MACHINE_DATA_END 0x50 - -#ifndef ASM_FILE -/* The prefix which points to the directory where GRUB modules and its - configuration file are located. */ -extern char grub_prefix[]; -#endif - -#endif /* ! GRUB_MACHINE_KERNEL_HEADER */ diff --git a/include/grub/kernel.h b/include/grub/kernel.h index d8c0fed33..2ff6b2469 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -26,7 +26,8 @@ enum { OBJ_TYPE_ELF, OBJ_TYPE_MEMDISK, - OBJ_TYPE_CONFIG + OBJ_TYPE_CONFIG, + OBJ_TYPE_PREFIX }; /* The module header. */ @@ -98,9 +99,4 @@ void grub_register_exported_symbols (void); extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void); - -#if ! defined (ASM_FILE) -extern char grub_prefix[]; -#endif - #endif /* ! GRUB_KERNEL_HEADER */ diff --git a/include/grub/offsets.h b/include/grub/offsets.h index e8170fcbe..526cfee68 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -42,12 +42,6 @@ #define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x730 -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_I386_PC_PREFIX GRUB_KERNEL_I386_PC_RAW_SIZE - -/* End of the data section. */ -#define GRUB_KERNEL_I386_PC_PREFIX_END (GRUB_KERNEL_I386_PC_PREFIX + 0x40) - /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 @@ -66,12 +60,6 @@ /* The offset of GRUB_KERNEL_IMAGE_SIZE. */ #define GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE 0xc -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_I386_QEMU_PREFIX 0x10 - -/* End of the data section. */ -#define GRUB_KERNEL_I386_QEMU_PREFIX_END 0x50 - #define GRUB_KERNEL_I386_QEMU_LINK_ADDR 0x8200 /* The offset of GRUB_TOTAL_MODULE_SIZE. */ @@ -83,20 +71,12 @@ /* The offset of GRUB_COMPRESSED_SIZE. */ #define GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE 0x10 -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX 0x14 - -/* End of the data section. */ -#define GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END 0x114 - #define GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE 12 #define GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS 0x4400 #define GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE 0 #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 -#define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX 0x4 -#define GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END 0x44 #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR 0x200000 @@ -109,8 +89,6 @@ #define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE 0x08 -#define GRUB_KERNEL_MIPS_LOONGSON_PREFIX 0x0c -#define GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END 0x54 #define GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR 0x80200000 #define GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN 32 @@ -118,8 +96,6 @@ #define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE 0xc #define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE 0x08 -#define GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX 0x0c -#define GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END 0x54 #define GRUB_KERNEL_MIPS_ARC_LINK_ADDR 0x8bd00000 @@ -130,36 +106,9 @@ #define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE 0x08 -#define GRUB_KERNEL_MIPS_ARC_PREFIX 0x0c -#define GRUB_KERNEL_MIPS_ARC_PREFIX_END 0x54 -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_I386_EFI_PREFIX 0x8 - -/* End of the data section. */ -#define GRUB_KERNEL_I386_EFI_PREFIX_END 0x50 - -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_IA64_EFI_PREFIX 0x50 - -/* End of the data section. */ -#define GRUB_KERNEL_IA64_EFI_PREFIX_END 0xa0 - -/* The offset of GRUB_PREFIX. */ -#define GRUB_KERNEL_X86_64_EFI_PREFIX 0x8 - -/* End of the data section. */ -#define GRUB_KERNEL_X86_64_EFI_PREFIX_END 0x50 - -#define GRUB_KERNEL_I386_COREBOOT_PREFIX 0x2 -#define GRUB_KERNEL_I386_COREBOOT_PREFIX_END 0x42 #define GRUB_KERNEL_I386_COREBOOT_LINK_ADDR 0x8200 -#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX GRUB_KERNEL_I386_COREBOOT_PREFIX -#define GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END GRUB_KERNEL_I386_COREBOOT_PREFIX_END - -#define GRUB_KERNEL_I386_IEEE1275_PREFIX 0x2 -#define GRUB_KERNEL_I386_IEEE1275_PREFIX_END 0x42 #define GRUB_KERNEL_I386_IEEE1275_LINK_ADDR 0x10000 #define GRUB_KERNEL_I386_IEEE1275_MOD_ALIGN 0x1000 @@ -194,8 +143,6 @@ #define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_SIZE) #define GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_ADDR) -#define GRUB_KERNEL_MACHINE_PREFIX GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX) -#define GRUB_KERNEL_MACHINE_PREFIX_END GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _PREFIX_END) #define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG) #define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER) #define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _RAW_SIZE) diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 420690923..4440fdd12 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -77,8 +77,6 @@ struct image_target_desc PLATFORM_FLAGS_DECOMPRESSORS = 2, PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4, } flags; - unsigned prefix; - unsigned prefix_end; unsigned raw_size; unsigned total_module_size; unsigned kernel_image_size; @@ -110,8 +108,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_I386_COREBOOT_PREFIX, - .prefix_end = GRUB_KERNEL_I386_COREBOOT_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -133,8 +129,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_I386_MULTIBOOT_PREFIX, - .prefix_end = GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -156,8 +150,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_I386_PC, .flags = PLATFORM_FLAGS_LZMA, - .prefix = GRUB_KERNEL_I386_PC_PREFIX, - .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END, .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE, @@ -175,8 +167,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_I386_PC_PXE, .flags = PLATFORM_FLAGS_LZMA, - .prefix = GRUB_KERNEL_I386_PC_PREFIX, - .prefix_end = GRUB_KERNEL_I386_PC_PREFIX_END, .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE, @@ -194,8 +184,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_I386_EFI_PREFIX, - .prefix_end = GRUB_KERNEL_I386_EFI_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -219,8 +207,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_I386_IEEE1275, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_I386_IEEE1275_PREFIX, - .prefix_end = GRUB_KERNEL_I386_IEEE1275_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -242,8 +228,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_QEMU, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_I386_QEMU_PREFIX, - .prefix_end = GRUB_KERNEL_I386_QEMU_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, @@ -261,8 +245,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_X86_64_EFI_PREFIX, - .prefix_end = GRUB_KERNEL_X86_64_EFI_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -281,8 +263,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_LOONGSON_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -303,8 +283,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_FULOONG2F_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_LOONGSON_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -327,8 +305,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_LOONGSON_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -349,8 +325,6 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_PPC, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX, - .prefix_end = GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -372,8 +346,6 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_SPARC64_RAW, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX, - .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END, .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE, @@ -391,8 +363,6 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_SPARC64_AOUT, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX, - .prefix_end = GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END, .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE, @@ -410,8 +380,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .prefix = GRUB_KERNEL_IA64_EFI_PREFIX, - .prefix_end = GRUB_KERNEL_IA64_EFI_PREFIX_END, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .kernel_image_size = TARGET_NO_FIELD, @@ -431,8 +399,6 @@ struct image_target_desc image_targets[] = .id = IMAGE_MIPS_ARC, .flags = (PLATFORM_FLAGS_DECOMPRESSORS | PLATFORM_FLAGS_MODULES_BEFORE_KERNEL), - .prefix = GRUB_KERNEL_MIPS_ARC_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_ARC_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -453,8 +419,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -475,8 +439,6 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -497,8 +459,6 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -519,8 +479,6 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .prefix = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX, - .prefix_end = GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END, .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, @@ -797,6 +755,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *kernel_img, *core_img; size_t kernel_size, total_module_size, core_size, exec_size; size_t memdisk_size = 0, config_size = 0, config_size_pure = 0; + size_t prefix_size = 0; char *kernel_path; size_t offset; struct grub_util_path_list *path_list, *p, *next; @@ -833,6 +792,12 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], total_module_size += config_size + sizeof (struct grub_module_header); } + if (prefix) + { + prefix_size = ALIGN_ADDR (strlen (prefix) + 1); + total_module_size += prefix_size + sizeof (struct grub_module_header); + } + for (p = path_list; p; p = p->next) total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name)) + sizeof (struct grub_module_header)); @@ -848,10 +813,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], total_module_size, &start_address, &rel_section, &reloc_size, &align, image_target); - if (image_target->prefix + strlen (prefix) + 1 > image_target->prefix_end) - grub_util_error (_("prefix is too long")); - strcpy (kernel_img + image_target->prefix, prefix); - if ((image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) && (image_target->total_module_size != TARGET_NO_FIELD)) *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) @@ -943,6 +904,21 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], offset += config_size; } + if (prefix) + { + struct grub_module_header *header; + + header = (struct grub_module_header *) (kernel_img + offset); + memset (header, 0, sizeof (struct grub_module_header)); + header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX); + header->size = grub_host_to_target32 (prefix_size + sizeof (*header)); + offset += sizeof (*header); + + grub_memset (kernel_img + offset, 0, prefix_size); + grub_strcpy (kernel_img + offset, prefix); + offset += prefix_size; + } + grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); compress_kernel (image_target, kernel_img, kernel_size + total_module_size, &core_img, &core_size, comp); From 544c24876e2f20e217c615e10cb802aa1d8295be Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 19 Oct 2011 16:53:18 +0200 Subject: [PATCH 402/673] Move grub_reboot out of the kernel. * grub-core/Makefile.core.def (reboot): Add platform-specific files. * grub-core/kern/efi/efi.c (grub_reboot): Moved to ... * grub-core/lib/efi/reboot.c: ... here. * grub-core/kern/i386/efi/startup.S: Remove including of realmode.S. * grub-core/kern/i386/ieee1275/startup.S: Likewise. * grub-core/kern/i386/pc/startup.S (grub_exit): Inline cold_reboot. * grub-core/kern/i386/realmode.S (grub_reboot): Moved to... * grub-core/lib/i386/reboot_trampoline.S: ... here. * grub-core/kern/ieee1275/openfw.c (grub_reboot): Moved to... * grub-core/lib/ieee1275/reboot.c: ... here. * grub-core/kern/mips/arc/init.c (grub_reboot): Moved to... * grub-core/lib/mips/arc/reboot.c: ... here. * grub-core/kern/mips/loongson/init.c (grub_reboot): Moved to... * grub-core/lib/mips/loongson/reboot.c: ...here. * grub-core/kern/mips/qemu_mips/init.c (grub_reboot): Moved to... * grub-core/lib/mips/qemu_mips/reboot.c: ... here. * include/grub/emu/misc.h (grub_reboot): New function declaration. * include/grub/i386/reboot.h: New file. * include/grub/mips/loongson/ec.h: Fix includes. * include/grub/mips/qemu_mips/kernel.h (grub_reboot): Removed. * include/grub/misc.h (grub_reboot): Don't mark as kernel function. * grub-core/lib/i386/reboot.c: New file. --- ChangeLog | 27 ++++++++++++ grub-core/Makefile.core.def | 19 ++++++--- grub-core/kern/efi/efi.c | 12 ------ grub-core/kern/i386/efi/startup.S | 2 - grub-core/kern/i386/ieee1275/startup.S | 6 --- grub-core/kern/i386/pc/startup.S | 5 ++- grub-core/kern/i386/realmode.S | 15 ------- grub-core/kern/ieee1275/openfw.c | 10 ----- grub-core/kern/mips/arc/init.c | 12 ------ grub-core/kern/mips/loongson/init.c | 32 -------------- grub-core/kern/mips/qemu_mips/init.c | 6 --- grub-core/lib/efi/reboot.c | 32 ++++++++++++++ grub-core/lib/i386/reboot.c | 59 ++++++++++++++++++++++++++ grub-core/lib/i386/reboot_trampoline.S | 33 ++++++++++++++ grub-core/lib/ieee1275/reboot.c | 27 ++++++++++++ grub-core/lib/mips/arc/reboot.c | 34 +++++++++++++++ grub-core/lib/mips/loongson/reboot.c | 57 +++++++++++++++++++++++++ grub-core/lib/mips/qemu_mips/reboot.c | 25 +++++++++++ include/grub/emu/misc.h | 3 ++ include/grub/i386/reboot.h | 28 ++++++++++++ include/grub/mips/loongson/ec.h | 4 ++ include/grub/mips/qemu_mips/kernel.h | 1 - include/grub/misc.h | 2 +- 23 files changed, 348 insertions(+), 103 deletions(-) create mode 100644 grub-core/lib/efi/reboot.c create mode 100644 grub-core/lib/i386/reboot.c create mode 100644 grub-core/lib/i386/reboot_trampoline.S create mode 100644 grub-core/lib/ieee1275/reboot.c create mode 100644 grub-core/lib/mips/arc/reboot.c create mode 100644 grub-core/lib/mips/loongson/reboot.c create mode 100644 grub-core/lib/mips/qemu_mips/reboot.c create mode 100644 include/grub/i386/reboot.h diff --git a/ChangeLog b/ChangeLog index a758fc275..9bea2dc0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2011-10-19 Vladimir Serbinenko + + Move grub_reboot out of the kernel. + + * grub-core/Makefile.core.def (reboot): Add platform-specific files. + * grub-core/kern/efi/efi.c (grub_reboot): Moved to ... + * grub-core/lib/efi/reboot.c: ... here. + * grub-core/kern/i386/efi/startup.S: Remove including of realmode.S. + * grub-core/kern/i386/ieee1275/startup.S: Likewise. + * grub-core/kern/i386/pc/startup.S (grub_exit): Inline cold_reboot. + * grub-core/kern/i386/realmode.S (grub_reboot): Moved to... + * grub-core/lib/i386/reboot_trampoline.S: ... here. + * grub-core/kern/ieee1275/openfw.c (grub_reboot): Moved to... + * grub-core/lib/ieee1275/reboot.c: ... here. + * grub-core/kern/mips/arc/init.c (grub_reboot): Moved to... + * grub-core/lib/mips/arc/reboot.c: ... here. + * grub-core/kern/mips/loongson/init.c (grub_reboot): Moved to... + * grub-core/lib/mips/loongson/reboot.c: ...here. + * grub-core/kern/mips/qemu_mips/init.c (grub_reboot): Moved to... + * grub-core/lib/mips/qemu_mips/reboot.c: ... here. + * include/grub/emu/misc.h (grub_reboot): New function declaration. + * include/grub/i386/reboot.h: New file. + * include/grub/mips/loongson/ec.h: Fix includes. + * include/grub/mips/qemu_mips/kernel.h (grub_reboot): Removed. + * include/grub/misc.h (grub_reboot): Don't mark as kernel function. + * grub-core/lib/i386/reboot.c: New file. + 2011-10-18 Vladimir Serbinenko Make grub_prefix into module to fix the arbitrary limit and save diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 84739e8fa..396f73b44 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -633,6 +633,20 @@ module = { emu = lib/emu/halt.c; }; +module = { + name = reboot; + i386 = lib/i386/reboot.c; + i386 = lib/i386/reboot_trampoline.S; + ia64_efi = lib/efi/reboot.c; + x86_64_efi = lib/efi/reboot.c; + powerpc_ieee1275 = lib/ieee1275/reboot.c; + sparc64_ieee1275 = lib/ieee1275/reboot.c; + mips_arc = lib/mips/arc/reboot.c; + mips_loongson = lib/mips/loongson/reboot.c; + mips_qemu_mips = lib/mips/qemu_mips/reboot.c; + common = commands/reboot.c; +}; + module = { name = hashsum; common = commands/hashsum.c; @@ -733,11 +747,6 @@ module = { common = commands/read.c; }; -module = { - name = reboot; - common = commands/reboot.c; -}; - module = { name = search; common = commands/search_wrap.c; diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index e27dd1ad0..9a2c5e64d 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -163,18 +163,6 @@ grub_exit (void) for (;;) ; } -/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */ -#ifndef __i386__ -void -grub_reboot (void) -{ - grub_efi_fini (); - efi_call_4 (grub_efi_system_table->runtime_services->reset_system, - GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); - for (;;) ; -} -#endif - grub_err_t grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, grub_efi_uintn_t descriptor_size, diff --git a/grub-core/kern/i386/efi/startup.S b/grub-core/kern/i386/efi/startup.S index 49b05c1e6..0f904d7b3 100644 --- a/grub-core/kern/i386/efi/startup.S +++ b/grub-core/kern/i386/efi/startup.S @@ -51,5 +51,3 @@ codestart: movl %eax, EXT_C(grub_efi_system_table) call EXT_C(grub_main) ret - -#include "../realmode.S" diff --git a/grub-core/kern/i386/ieee1275/startup.S b/grub-core/kern/i386/ieee1275/startup.S index 6b39f5f3a..245583bdb 100644 --- a/grub-core/kern/i386/ieee1275/startup.S +++ b/grub-core/kern/i386/ieee1275/startup.S @@ -39,9 +39,3 @@ _start: movl %eax, EXT_C(grub_ieee1275_entry_fn) jmp EXT_C(grub_main) -/* - * prot_to_real and associated structures (but NOT real_to_prot, that is - * only needed for BIOS gates). - */ -#include "../realmode.S" - diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 3bbe34753..a70a2a7db 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -465,7 +465,10 @@ FUNCTION(grub_exit) .code16 /* Tell the BIOS a boot failure. If this does not work, reboot. */ int $0x18 - jmp cold_reboot + /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */ + movw $0x0472, %di + movw %ax, (%di) + ljmp $0xf000, $0xfff0 .code32 /* diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S index 578c8d2a8..3e8a13892 100644 --- a/grub-core/kern/i386/realmode.S +++ b/grub-core/kern/i386/realmode.S @@ -225,18 +225,3 @@ realcseg: DATA32 ret .code32 - -/* - * grub_reboot() - * - * Reboot the system. At the moment, rely on BIOS. - */ -FUNCTION(grub_reboot) - call prot_to_real - .code16 -cold_reboot: - /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */ - movw $0x0472, %di - movw %ax, (%di) - ljmp $0xf000, $0xfff0 - .code32 diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 4e705a4d8..23065e3e3 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -456,16 +456,6 @@ grub_ieee1275_encode_devname (const char *path) 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); - for (;;) ; -} -#endif - /* Resolve aliases. */ char * grub_ieee1275_canonicalise_devname (const char *path) diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index 2e25335ca..ec0fa521a 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -195,15 +195,3 @@ grub_exit (void) while (1); } -void -grub_reboot (void) -{ - GRUB_ARC_FIRMWARE_VECTOR->restart (); - - grub_millisleep (1500); - - grub_printf ("Reboot failed\n"); - grub_refresh (); - while (1); -} - diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 8acfb0767..6ddf151f2 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -30,7 +30,6 @@ #include #include #include -#include #include extern void grub_video_sm712_init (void); @@ -266,37 +265,6 @@ grub_exit (void) grub_halt (); } -void -grub_reboot (void) -{ - switch (grub_arch_machine) - { - case GRUB_ARCH_MACHINE_FULOONG2E: - grub_outb (grub_inb (0xbfe00104) & ~4, 0xbfe00104); - grub_outb (grub_inb (0xbfe00104) | 4, 0xbfe00104); - break; - case GRUB_ARCH_MACHINE_FULOONG2F: - { - grub_pci_device_t dev; - if (!grub_cs5536_find (&dev)) - break; - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_RESET, - grub_cs5536_read_msr (dev, - GRUB_CS5536_MSR_DIVIL_RESET) - | 1); - break; - } - case GRUB_ARCH_MACHINE_YEELOONG: - grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT); - break; - } - grub_millisleep (1500); - - grub_printf ("Reboot failed\n"); - grub_refresh (); - while (1); -} - extern char _end[]; grub_addr_t grub_modbase = (grub_addr_t) _end; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 4921c42bf..d331e1b24 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -99,12 +99,6 @@ grub_halt (void) while (1); } -void -grub_reboot (void) -{ - while (1); -} - grub_err_t grub_machine_mmap_iterate (grub_memory_hook_t hook) { diff --git a/grub-core/lib/efi/reboot.c b/grub-core/lib/efi/reboot.c new file mode 100644 index 000000000..9382370f7 --- /dev/null +++ b/grub-core/lib/efi/reboot.c @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include + +void +grub_reboot (void) +{ + grub_machine_fini (); + efi_call_4 (grub_efi_system_table->runtime_services->reset_system, + GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); + for (;;) ; +} diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c new file mode 100644 index 000000000..ef28f7f65 --- /dev/null +++ b/grub-core/lib/i386/reboot.c @@ -0,0 +1,59 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include +#include + +void +grub_reboot (void) +{ + struct grub_relocator *relocator = NULL; + grub_relocator_chunk_t ch; + grub_err_t err; + void *buf; + struct grub_relocator16_state state; + grub_uint16_t segment; + + relocator = grub_relocator_new (); + if (!relocator) + while (1); + err = grub_relocator_alloc_chunk_align (relocator, &ch, 0x1000, 0x1000, + grub_reboot_end - grub_reboot_start, + 16, GRUB_RELOCATOR_PREFERENCE_NONE); + if (err) + while (1); + buf = get_virtual_current_address (ch); + grub_memcpy (buf, grub_reboot_start, grub_reboot_end - grub_reboot_start); + + segment = ((grub_addr_t) get_physical_target_address (ch)) >> 4; + state.gs = state.fs = state.es = state.ds = state.ss = segment; + state.sp = 0; + state.cs = segment; + state.ip = 0; + + grub_stop_floppy (); + + err = grub_relocator16_boot (relocator, state); + + while (1); +} + diff --git a/grub-core/lib/i386/reboot_trampoline.S b/grub-core/lib/i386/reboot_trampoline.S new file mode 100644 index 000000000..18bcfb287 --- /dev/null +++ b/grub-core/lib/i386/reboot_trampoline.S @@ -0,0 +1,33 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include + + .p2align 4 + +VARIABLE(grub_reboot_start) + .code16 + + /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */ + movw $0x0472, %di + movw %ax, (%di) + ljmp $0xf000, $0xfff0 + + .code32 +VARIABLE(grub_reboot_end) diff --git a/grub-core/lib/ieee1275/reboot.c b/grub-core/lib/ieee1275/reboot.c new file mode 100644 index 000000000..91c8779f2 --- /dev/null +++ b/grub-core/lib/ieee1275/reboot.c @@ -0,0 +1,27 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include + +void +grub_reboot (void) +{ + grub_ieee1275_interpret ("reset-all", 0); + for (;;) ; +} diff --git a/grub-core/lib/mips/arc/reboot.c b/grub-core/lib/mips/arc/reboot.c new file mode 100644 index 000000000..f0d085765 --- /dev/null +++ b/grub-core/lib/mips/arc/reboot.c @@ -0,0 +1,34 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include + +void +grub_reboot (void) +{ + GRUB_ARC_FIRMWARE_VECTOR->restart (); + + grub_millisleep (1500); + + grub_printf ("Reboot failed\n"); + grub_refresh (); + while (1); +} diff --git a/grub-core/lib/mips/loongson/reboot.c b/grub-core/lib/mips/loongson/reboot.c new file mode 100644 index 000000000..f099ba250 --- /dev/null +++ b/grub-core/lib/mips/loongson/reboot.c @@ -0,0 +1,57 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void +grub_reboot (void) +{ + switch (grub_arch_machine) + { + case GRUB_ARCH_MACHINE_FULOONG2E: + grub_outb (grub_inb (0xbfe00104) & ~4, 0xbfe00104); + grub_outb (grub_inb (0xbfe00104) | 4, 0xbfe00104); + break; + case GRUB_ARCH_MACHINE_FULOONG2F: + { + grub_pci_device_t dev; + if (!grub_cs5536_find (&dev)) + break; + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_RESET, + grub_cs5536_read_msr (dev, + GRUB_CS5536_MSR_DIVIL_RESET) + | 1); + break; + } + case GRUB_ARCH_MACHINE_YEELOONG: + grub_write_ec (GRUB_MACHINE_EC_COMMAND_REBOOT); + break; + } + grub_millisleep (1500); + + grub_printf ("Reboot failed\n"); + grub_refresh (); + while (1); +} diff --git a/grub-core/lib/mips/qemu_mips/reboot.c b/grub-core/lib/mips/qemu_mips/reboot.c new file mode 100644 index 000000000..a5c41ee78 --- /dev/null +++ b/grub-core/lib/mips/qemu_mips/reboot.c @@ -0,0 +1,25 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include + +void +grub_reboot (void) +{ + while (1); +} diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index fcf9da473..b4b8f7d28 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -82,4 +82,7 @@ int grub_device_mapper_supported (void); char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot); +void EXPORT_FUNC(grub_reboot) (void); + + #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/i386/reboot.h b/include/grub/i386/reboot.h new file mode 100644 index 000000000..c2716f3fa --- /dev/null +++ b/include/grub/i386/reboot.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#ifndef GRUB_REBOOT_H +#define GRUB_REBOOT_H 1 + +#ifndef ASM_FILE + +extern grub_uint8_t grub_reboot_end[], grub_reboot_start[]; + +#endif + +#endif diff --git a/include/grub/mips/loongson/ec.h b/include/grub/mips/loongson/ec.h index 62d1d33d9..3f8ff9931 100644 --- a/include/grub/mips/loongson/ec.h +++ b/include/grub/mips/loongson/ec.h @@ -19,6 +19,10 @@ #ifndef GRUB_EC_MACHINE_HEADER #define GRUB_EC_MACHINE_HEADER 1 +#include +#include +#include + #define GRUB_MACHINE_EC_MAGIC_PORT1 0x381 #define GRUB_MACHINE_EC_MAGIC_PORT2 0x382 #define GRUB_MACHINE_EC_DATA_PORT 0x383 diff --git a/include/grub/mips/qemu_mips/kernel.h b/include/grub/mips/qemu_mips/kernel.h index 66add4b2e..1e7e32401 100644 --- a/include/grub/mips/qemu_mips/kernel.h +++ b/include/grub/mips/qemu_mips/kernel.h @@ -23,7 +23,6 @@ #ifndef ASM_FILE -void EXPORT_FUNC (grub_reboot) (void); void EXPORT_FUNC (grub_halt) (void); void grub_qemu_init_cirrus (void); diff --git a/include/grub/misc.h b/include/grub/misc.h index 66e74d8a8..0a0a4135e 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -343,7 +343,7 @@ grub_div_roundup (unsigned int x, unsigned int y) } /* Reboot the machine. */ -void EXPORT_FUNC (grub_reboot) (void) __attribute__ ((noreturn)); +void grub_reboot (void) __attribute__ ((noreturn)); #ifdef GRUB_MACHINE_PCBIOS /* Halt the system, using APM if possible. If NO_APM is true, don't From f8f72eb890273c7dc6cae48420d21a3d4e437213 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 19 Oct 2011 20:28:09 +0200 Subject: [PATCH 403/673] * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): Don't add the bogus brackets. --- ChangeLog | 5 +++++ grub-core/kern/ieee1275/openfw.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d66419216..ee678a9e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-19 Vladimir Serbinenko + + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): + Don't add the bogus brackets. + 2011-10-19 Vladimir Serbinenko ExFAT support. diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 23065e3e3..57252d96b 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -445,10 +445,10 @@ grub_ieee1275_encode_devname (const char *path) /* GRUB partition 1 is OF partition 0. */ partno++; - encoding = grub_xasprintf ("(%s,%d)", device, partno); + encoding = grub_xasprintf ("%s,%d", device, partno); } else - encoding = grub_xasprintf ("(%s)", device); + encoding = grub_strdup (device); grub_free (partition); grub_free (device); From 36dd20ad0bc2bd9b46ce48cc0425512018cac21f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 19 Oct 2011 20:30:06 +0200 Subject: [PATCH 404/673] * grub-core/kern/main.c (grub_set_prefix_and_root): Init prefix. --- ChangeLog | 4 ++++ grub-core/kern/main.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ee678a9e3..6210a4eab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-19 Vladimir Serbinenko + + * grub-core/kern/main.c (grub_set_prefix_and_root): Init prefix. + 2011-10-19 Vladimir Serbinenko * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 77be11422..bf2789860 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -105,7 +105,7 @@ grub_set_prefix_and_root (void) char *path = NULL; char *fwdevice = NULL; char *fwpath = NULL; - char *prefix; + char *prefix = NULL; struct grub_module_header *header; FOR_MODULES (header) From e55599dcbf2f4773674995703cbf1a71cba3e355 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 19 Oct 2011 20:35:41 +0200 Subject: [PATCH 405/673] * util/grub-install.in: Declare IEEE1275 as able to find out the disk name. --- ChangeLog | 5 +++++ util/grub-install.in | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6210a4eab..afbc8aec7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-19 Vladimir Serbinenko + + * util/grub-install.in: Declare IEEE1275 as able to find out the disk + name. + 2011-10-19 Vladimir Serbinenko * grub-core/kern/main.c (grub_set_prefix_and_root): Init prefix. diff --git a/util/grub-install.in b/util/grub-install.in index d11d24421..e1255f4f7 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -544,11 +544,11 @@ if [ "x${devabstraction_module}" = "x" ] ; then # Strip partition number grub_partition="`echo "${grub_drive}" | sed -e 's/^[^,]*[,)]//; s/)$//'`" grub_drive="`echo "${grub_drive}" | sed -e s/,[a-z0-9,]*//g`" - if ([ "x$disk_module" != x ] && [ "x$disk_module" != xbiosdisk ]) || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]); then + if ([ "x$disk_module" != x ] && [ "x$disk_module" != xbiosdisk ]) || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${platform}" != x"ieee1275" ]); then # generic method (used on coreboot and ata mod) uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`" if [ "x${uuid}" = "x" ] ; then - if [ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${target_cpu}-${platform}" != x"sparc64-ieee1275" ]; then + if [ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${platform}" != x"ieee1275" ]; then echo "UUID needed with $platform, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 elif [ "$disk_module" = ata ]; then echo "UUID needed with ata mod, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 @@ -563,7 +563,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg" config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" - elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ]; then + elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ] || [ "x$platform" = xieee1275 ]; then # we need to hardcode the partition number in the core image's prefix. if [ x"$grub_partition" = x ]; then prefix_drive="()" From de9c615e5c5b9d692ac00be91b16a0576a371e25 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 19 Oct 2011 23:01:44 +0200 Subject: [PATCH 406/673] Removed unused GRUB_BOOT_VERSION. Check for kernel version is better done with a dedicated section. * grub-core/boot/sparc64/ieee1275/boot.S: Remove GRUB_BOOT_VERSION. Ensure the correct position of boot_path. * grub-core/kern/i386/efi/startup.S: Remove GRUB_BOOT_VERSION. * grub-core/kern/i386/pc/startup.S: Likewise. Ensure correct position of other fields. * grub-core/kern/x86_64/efi/startup.S: Remove GRUB_BOOT_VERSION. * include/grub/boot.h: Removed. All references removed. * include/grub/sparc64/ieee1275/boot.h (GRUB_BOOT_MACHINE_VER_MAJ): Removed. (GRUB_BOOT_MACHINE_BOOT_DEVPATH): Make it lower. --- ChangeLog | 16 +++++++++++++ grub-core/Makefile.am | 1 - grub-core/boot/i386/pc/boot.S | 1 - grub-core/boot/i386/pc/cdboot.S | 1 - grub-core/boot/i386/pc/lnxboot.S | 1 - grub-core/boot/sparc64/ieee1275/boot.S | 5 +--- grub-core/boot/sparc64/ieee1275/diskboot.S | 1 - grub-core/kern/i386/efi/startup.S | 17 -------------- grub-core/kern/i386/pc/startup.S | 19 ++++++--------- grub-core/kern/x86_64/efi/callwrap.S | 1 - grub-core/kern/x86_64/efi/startup.S | 13 ----------- include/grub/boot.h | 27 ---------------------- include/grub/sparc64/ieee1275/boot.h | 4 +--- 13 files changed, 25 insertions(+), 82 deletions(-) delete mode 100644 include/grub/boot.h diff --git a/ChangeLog b/ChangeLog index afbc8aec7..1159d32a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-10-19 Vladimir Serbinenko + + Removed unused GRUB_BOOT_VERSION. Check for kernel version is better + done with a dedicated section. + + * grub-core/boot/sparc64/ieee1275/boot.S: Remove GRUB_BOOT_VERSION. + Ensure the correct position of boot_path. + * grub-core/kern/i386/efi/startup.S: Remove GRUB_BOOT_VERSION. + * grub-core/kern/i386/pc/startup.S: Likewise. Ensure correct position of + other fields. + * grub-core/kern/x86_64/efi/startup.S: Remove GRUB_BOOT_VERSION. + * include/grub/boot.h: Removed. All references removed. + * include/grub/sparc64/ieee1275/boot.h (GRUB_BOOT_MACHINE_VER_MAJ): + Removed. + (GRUB_BOOT_MACHINE_BOOT_DEVPATH): Make it lower. + 2011-10-19 Vladimir Serbinenko * util/grub-install.in: Declare IEEE1275 as able to find out the disk diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index f30014635..3bd192602 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -78,7 +78,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S index 635599a24..314f14016 100644 --- a/grub-core/boot/i386/pc/boot.S +++ b/grub-core/boot/i386/pc/boot.S @@ -18,7 +18,6 @@ */ #include -#include #include /* diff --git a/grub-core/boot/i386/pc/cdboot.S b/grub-core/boot/i386/pc/cdboot.S index 33569ce9d..d939835a9 100644 --- a/grub-core/boot/i386/pc/cdboot.S +++ b/grub-core/boot/i386/pc/cdboot.S @@ -18,7 +18,6 @@ */ #include -#include #include #include #include diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index 2c7596026..bb43ed73c 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/grub-core/boot/sparc64/ieee1275/boot.S b/grub-core/boot/sparc64/ieee1275/boot.S index f08258f47..f79699502 100644 --- a/grub-core/boot/sparc64/ieee1275/boot.S +++ b/grub-core/boot/sparc64/ieee1275/boot.S @@ -17,7 +17,6 @@ * along with GRUB. If not, see . */ -#include #include .text @@ -29,9 +28,6 @@ pic_base: call boot_continue mov %o4, CIF_REG - . = _start + GRUB_BOOT_MACHINE_VER_MAJ -boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR - /* The offsets to these locations are defined by the * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h, * and grub-setup uses this to patch these next three values as needed. @@ -44,6 +40,7 @@ boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR * After loading in that block we will execute it by jumping to the * load address plus the size of the prepended A.OUT header (32 bytes). */ + . = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH boot_path: . = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE boot_path_end: diff --git a/grub-core/boot/sparc64/ieee1275/diskboot.S b/grub-core/boot/sparc64/ieee1275/diskboot.S index 83dfee098..e020f6221 100644 --- a/grub-core/boot/sparc64/ieee1275/diskboot.S +++ b/grub-core/boot/sparc64/ieee1275/diskboot.S @@ -17,7 +17,6 @@ * along with GRUB. If not, see . */ -#include #include #include diff --git a/grub-core/kern/i386/efi/startup.S b/grub-core/kern/i386/efi/startup.S index 0f904d7b3..fc5ea3dac 100644 --- a/grub-core/kern/i386/efi/startup.S +++ b/grub-core/kern/i386/efi/startup.S @@ -19,29 +19,12 @@ #include #include -#include .file "startup.S" .text .globl start, _start start: _start: - jmp codestart - - /* - * Compatibility version number - * - * These MUST be at byte offset 6 and 7 of the executable - * DO NOT MOVE !!! - */ - . = _start + 0x6 - .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR - - /* - * This is a special data area 8 bytes from the beginning. - */ - -codestart: /* * EFI_SYSTEM_TABLE * and EFI_HANDLE are passed on the stack. */ diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index a70a2a7db..0350431d9 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -43,7 +43,6 @@ #include #include -#include #include #include #include @@ -75,31 +74,27 @@ LOCAL (base): #else ljmp $0, $ABS(LOCAL (codestart)) #endif - /* - * Compatibility version number - * - * These MUST be at byte offset 6 and 7 of the executable - * DO NOT MOVE !!! - */ - . = _start + 0x6 - .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR /* - * This is a special data area 8 bytes from the beginning. + * This is a special data area. */ - . = _start + 0x8 - + . = _start + GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE VARIABLE(grub_total_module_size) .long 0 + . = _start + GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE VARIABLE(grub_kernel_image_size) .long 0 + . = _start + GRUB_KERNEL_I386_PC_COMPRESSED_SIZE VARIABLE(grub_compressed_size) .long 0 + . = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART VARIABLE(grub_install_dos_part) .long 0xFFFFFFFF + . = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART VARIABLE(grub_install_bsd_part) .long 0xFFFFFFFF + . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY reed_solomon_redundancy: .long 0 diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S index cc2c8aa05..dced859ac 100644 --- a/grub-core/kern/x86_64/efi/callwrap.S +++ b/grub-core/kern/x86_64/efi/callwrap.S @@ -19,7 +19,6 @@ #include #include -#include /* * x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use diff --git a/grub-core/kern/x86_64/efi/startup.S b/grub-core/kern/x86_64/efi/startup.S index 37efde7fc..f86f01969 100644 --- a/grub-core/kern/x86_64/efi/startup.S +++ b/grub-core/kern/x86_64/efi/startup.S @@ -19,7 +19,6 @@ #include #include -#include .file "startup.S" .text @@ -28,18 +27,6 @@ start: _start: - jmp codestart - - /* - * Compatibility version number - * - * These MUST be at byte offset 6 and 7 of the executable - * DO NOT MOVE !!! - */ - . = _start + 0x6 - .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR - -codestart: movq %rcx, EXT_C(grub_efi_image_handle)(%rip) movq %rdx, EXT_C(grub_efi_system_table)(%rip) diff --git a/include/grub/boot.h b/include/grub/boot.h deleted file mode 100644 index 235774863..000000000 --- a/include/grub/boot.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2007 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 . - */ - -#ifndef GRUB_BOOT_HEADER -#define GRUB_BOOT_HEADER 1 - -#define GRUB_BOOT_VERSION_MAJOR 4 -#define GRUB_BOOT_VERSION_MINOR 0 -#define GRUB_BOOT_VERSION ((GRUB_BOOT_VERSION_MINOR << 8) \ - | GRUB_BOOT_VERSION_MAJOR) - -#endif /* ! GRUB_BOOT_HEADER */ diff --git a/include/grub/sparc64/ieee1275/boot.h b/include/grub/sparc64/ieee1275/boot.h index 112d19bc7..60edc712e 100644 --- a/include/grub/sparc64/ieee1275/boot.h +++ b/include/grub/sparc64/ieee1275/boot.h @@ -39,9 +39,7 @@ #define GRUB_BOOT_MACHINE_SIGNATURE 0xbb44aa55 -#define GRUB_BOOT_MACHINE_VER_MAJ 0x08 - -#define GRUB_BOOT_MACHINE_BOOT_DEVPATH 0x0a +#define GRUB_BOOT_MACHINE_BOOT_DEVPATH 0x08 #define GRUB_BOOT_MACHINE_BOOT_DEVPATH_END 0x80 From fcf1d67219695832a42525d3f9c9dc0730e72bf5 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 19 Oct 2011 23:11:48 +0200 Subject: [PATCH 407/673] * grub-core/bus/usb/uhci.c (grub_uhci_setup_transfer): Fix possible NULL pointer dereference. --- ChangeLog | 5 +++++ grub-core/bus/usb/uhci.c | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1159d32a5..96abe1229 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-19 Szymon Janc + + * grub-core/bus/usb/uhci.c (grub_uhci_setup_transfer): Fix possible + NULL pointer dereference. + 2011-10-19 Vladimir Serbinenko Removed unused GRUB_BOOT_VERSION. Check for kernel version is better diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index 260b7e876..a9a4c45a2 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -544,8 +544,11 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev, { grub_size_t actual = 0; /* Terminate and free. */ - td_prev->linkptr2 = 0; - td_prev->linkptr = 1; + if (td_prev) + { + td_prev->linkptr2 = 0; + td_prev->linkptr = 1; + } if (cdata->td_first) grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual); From 766f7d08092a0904cb00af1b419fb8b8edcdb51b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 20 Oct 2011 08:13:00 +0200 Subject: [PATCH 408/673] Remove redundant grub_kernel_image_size. * grub-core/kern/i386/coreboot/init.c (grub_machine_init): Use _edata and _start. * grub-core/kern/i386/coreboot/startup.S: Move multiboot header after the small code. It moves it only by few bytes but simplifies the code. * grub-core/kern/i386/pc/init.c (grub_machine_init): Use _edata and _start. * grub-core/kern/i386/pc/startup.S: Use _edata and _start. (grub_kernel_image_size): Removed. * grub-core/kern/i386/qemu/startup.S: Use _edata and _start. (grub_kernel_image_size): Removed. [APPLE_CC]: Remove apple compiler support. i386-qemu port can't be compiled with Apple toolchain. * grub-core/kern/sparc64/ieee1275/crt0.S: Remove leftover fields. * include/grub/i386/pc/kernel.h (grub_kernel_image_size): Removed. * include/grub/i386/qemu/kernel.h (grub_kernel_image_size): Removed. (grub_total_module_size): Likewise. * include/grub/offsets.h (GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE): Removed. (GRUB_KERNEL_I386_PC_COMPRESSED_SIZE): Put it lower. (GRUB_KERNEL_I386_PC_INSTALL_DOS_PART): Likewise. (GRUB_KERNEL_I386_PC_INSTALL_BSD_PART): Likewise. (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): Likewise. (GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE): Removed. (GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE): Likewise. (GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE): Likewise. * include/grub/sparc64/ieee1275/kernel.h (grub_kernel_image_size): Removed. (grub_total_module_size): Removed. * util/grub-mkimage.c (image_target_desc): Remove image_size. (image_targets): Likewise. Set .compressed_size to no field on sparc. (generate_image): Remove kernel_image_size handling. --- ChangeLog | 37 ++++++++++++++++++++++++++ grub-core/kern/i386/coreboot/init.c | 7 ++--- grub-core/kern/i386/coreboot/startup.S | 27 +++++++++---------- grub-core/kern/i386/pc/init.c | 3 ++- grub-core/kern/i386/pc/startup.S | 5 +--- grub-core/kern/i386/qemu/startup.S | 20 +------------- grub-core/kern/sparc64/ieee1275/crt0.S | 4 --- include/grub/i386/pc/kernel.h | 3 --- include/grub/i386/qemu/kernel.h | 6 ----- include/grub/offsets.h | 20 +++----------- include/grub/sparc64/ieee1275/kernel.h | 6 ----- util/grub-mkimage.c | 28 ++----------------- 12 files changed, 63 insertions(+), 103 deletions(-) diff --git a/ChangeLog b/ChangeLog index 96abe1229..bf96dc095 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2011-10-20 Vladimir Serbinenko + + Remove redundant grub_kernel_image_size. + + * grub-core/kern/i386/coreboot/init.c (grub_machine_init): Use + _edata and _start. + * grub-core/kern/i386/coreboot/startup.S: Move multiboot header after + the small code. It moves it only by few bytes but simplifies the code. + * grub-core/kern/i386/pc/init.c (grub_machine_init): Use _edata and + _start. + * grub-core/kern/i386/pc/startup.S: Use _edata and _start. + (grub_kernel_image_size): Removed. + * grub-core/kern/i386/qemu/startup.S: Use _edata and _start. + (grub_kernel_image_size): Removed. + [APPLE_CC]: Remove apple compiler support. i386-qemu port can't be + compiled with Apple toolchain. + * grub-core/kern/sparc64/ieee1275/crt0.S: Remove leftover fields. + * include/grub/i386/pc/kernel.h (grub_kernel_image_size): Removed. + * include/grub/i386/qemu/kernel.h (grub_kernel_image_size): Removed. + (grub_total_module_size): Likewise. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE): + Removed. + (GRUB_KERNEL_I386_PC_COMPRESSED_SIZE): Put it lower. + (GRUB_KERNEL_I386_PC_INSTALL_DOS_PART): Likewise. + (GRUB_KERNEL_I386_PC_INSTALL_BSD_PART): Likewise. + (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): Likewise. + (GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE): Removed. + (GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE): Likewise. + (GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE): Likewise. + * include/grub/sparc64/ieee1275/kernel.h (grub_kernel_image_size): + Removed. + (grub_total_module_size): Removed. + * util/grub-mkimage.c (image_target_desc): Remove image_size. + (image_targets): Likewise. + Set .compressed_size to no field on sparc. + (generate_image): Remove kernel_image_size handling. + 2011-10-19 Szymon Janc * grub-core/bus/usb/uhci.c (grub_uhci_setup_transfer): Fix possible diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index b7510ff98..95209bb70 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -38,8 +38,9 @@ #include #endif -extern char _start[]; -extern char _end[]; +extern grub_uint8_t _start[]; +extern grub_uint8_t _end[]; +extern grub_uint8_t _edata[]; grub_uint32_t grub_get_rtc (void) @@ -66,7 +67,7 @@ void grub_machine_init (void) { #ifdef GRUB_MACHINE_QEMU - grub_modbase = grub_core_entry_addr + grub_kernel_image_size; + grub_modbase = grub_core_entry_addr + (_edata - _start); grub_qemu_init_cirrus (); #endif diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S index 5e7767bb9..dc2c62a25 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -38,21 +38,6 @@ .globl start, _start start: _start: - jmp codestart - -/* - * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). - */ - .p2align 2 /* force 4-byte alignment */ -multiboot_header: - /* magic */ - .long 0x1BADB002 - /* flags */ - .long MULTIBOOT_MEMORY_INFO - /* checksum */ - .long -0x1BADB002 - MULTIBOOT_MEMORY_INFO - -codestart: #ifdef GRUB_MACHINE_MULTIBOOT cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax jne 0f @@ -66,6 +51,18 @@ codestart: /* jump to the main body of C code */ jmp EXT_C(grub_main) +/* + * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). + */ + .p2align 2 /* force 4-byte alignment */ +multiboot_header: + /* magic */ + .long 0x1BADB002 + /* flags */ + .long MULTIBOOT_MEMORY_INFO + /* checksum */ + .long -0x1BADB002 - MULTIBOOT_MEMORY_INFO + /* * prot_to_real and associated structures (but NOT real_to_prot, that is * only needed for BIOS gates). diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 62269de78..be26fdea1 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -130,6 +130,7 @@ compact_mem_regions (void) } grub_addr_t grub_modbase; +extern grub_uint8_t _start[], _edata[]; void grub_machine_init (void) @@ -140,7 +141,7 @@ grub_machine_init (void) #endif grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR - + (grub_kernel_image_size - GRUB_KERNEL_MACHINE_RAW_SIZE); + + ((_edata - _start) - GRUB_KERNEL_MACHINE_RAW_SIZE); /* Initialize the console as early as possible. */ grub_console_init (); diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 0350431d9..a0ef71f90 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -81,9 +81,6 @@ LOCAL (base): . = _start + GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE VARIABLE(grub_total_module_size) - .long 0 - . = _start + GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE -VARIABLE(grub_kernel_image_size) .long 0 . = _start + GRUB_KERNEL_I386_PC_COMPRESSED_SIZE VARIABLE(grub_compressed_size) @@ -226,7 +223,7 @@ post_reed_solomon: movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi pushl %edi pushl %esi - movl EXT_C(grub_kernel_image_size), %ecx + movl $(BSS_START_SYMBOL - _start), %ecx addl EXT_C(grub_total_module_size), %ecx subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx pushl %ecx diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S index 6500de620..0761807ed 100644 --- a/grub-core/kern/i386/qemu/startup.S +++ b/grub-core/kern/i386/qemu/startup.S @@ -32,8 +32,6 @@ _start: . = _start + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR VARIABLE(grub_core_entry_addr) .long 0 -VARIABLE(grub_kernel_image_size) - .long 0 codestart: /* Relocate to low memory. First we figure out our location. @@ -45,11 +43,7 @@ codestart: value of `grub_core_entry_addr' in %esi. */ xorw %si, %si - /* ... which allows us to access `grub_kernel_image_size' - before relocation. */ - movl (grub_kernel_image_size - _start)(%esi), %ecx - - + movl $(_edata - _start), %ecx movl $_start, %edi cld rep @@ -57,24 +51,12 @@ codestart: ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $1f 1: -#ifdef APPLE_CC - /* clean out the bss */ - bss_start_abs = ABS (bss_start) - bss_end_abs = ABS (bss_end) - - movl bss_start_abs, %edi - - /* compute the bss length */ - movl bss_end_abs, %ecx - subl %edi, %ecx -#else /* clean out the bss */ movl $BSS_START_SYMBOL, %edi /* compute the bss length */ movl $END_SYMBOL, %ecx subl %edi, %ecx -#endif /* clean out */ xorl %eax, %eax diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S index 1466a56f8..9d91fba48 100644 --- a/grub-core/kern/sparc64/ieee1275/crt0.S +++ b/grub-core/kern/sparc64/ieee1275/crt0.S @@ -31,10 +31,6 @@ _start: VARIABLE(grub_total_module_size) .word 0 -VARIABLE(grub_kernel_image_size) - .word 0 -VARIABLE(grub_compressed_size) - .word 0 codestart: /* Copy the modules past the end of the kernel image. diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index dd50aa833..2dcdbb7a6 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -29,9 +29,6 @@ #include #include -/* The size of kernel image. */ -extern grub_int32_t grub_kernel_image_size; - /* The total size of module images following the kernel. */ extern grub_int32_t grub_total_module_size; diff --git a/include/grub/i386/qemu/kernel.h b/include/grub/i386/qemu/kernel.h index df06e6731..f34206b3a 100644 --- a/include/grub/i386/qemu/kernel.h +++ b/include/grub/i386/qemu/kernel.h @@ -28,12 +28,6 @@ extern grub_addr_t grub_core_entry_addr; -/* The size of kernel image. */ -extern grub_int32_t grub_kernel_image_size; - -/* The total size of module images following the kernel. */ -extern grub_int32_t grub_total_module_size; - void grub_qemu_init_cirrus (void); #endif /* ! ASM_FILE */ diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 526cfee68..aa65cd5cc 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -22,20 +22,17 @@ /* The offset of GRUB_TOTAL_MODULE_SIZE. */ #define GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE 0x8 -/* The offset of GRUB_KERNEL_IMAGE_SIZE. */ -#define GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE 0xc - /* The offset of GRUB_COMPRESSED_SIZE. */ -#define GRUB_KERNEL_I386_PC_COMPRESSED_SIZE 0x10 +#define GRUB_KERNEL_I386_PC_COMPRESSED_SIZE 0x0c /* The offset of GRUB_INSTALL_DOS_PART. */ -#define GRUB_KERNEL_I386_PC_INSTALL_DOS_PART 0x14 +#define GRUB_KERNEL_I386_PC_INSTALL_DOS_PART 0x10 /* The offset of GRUB_INSTALL_BSD_PART. */ -#define GRUB_KERNEL_I386_PC_INSTALL_BSD_PART 0x18 +#define GRUB_KERNEL_I386_PC_INSTALL_BSD_PART 0x14 /* Offset of reed_solomon_redundancy. */ -#define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x1c +#define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x18 /* The size of the first region which won't be compressed. */ #define GRUB_KERNEL_I386_PC_RAW_SIZE 0xcd0 @@ -57,20 +54,11 @@ /* The offset of GRUB_CORE_ENTRY_ADDR. */ #define GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR 0x8 -/* The offset of GRUB_KERNEL_IMAGE_SIZE. */ -#define GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE 0xc - #define GRUB_KERNEL_I386_QEMU_LINK_ADDR 0x8200 /* The offset of GRUB_TOTAL_MODULE_SIZE. */ #define GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE 0x8 -/* The offset of GRUB_KERNEL_IMAGE_SIZE. */ -#define GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE 0xc - -/* The offset of GRUB_COMPRESSED_SIZE. */ -#define GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE 0x10 - #define GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE 12 #define GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS 0x4400 diff --git a/include/grub/sparc64/ieee1275/kernel.h b/include/grub/sparc64/ieee1275/kernel.h index 5aa50b852..9a00bea61 100644 --- a/include/grub/sparc64/ieee1275/kernel.h +++ b/include/grub/sparc64/ieee1275/kernel.h @@ -26,12 +26,6 @@ #include #include -/* The size of kernel image. */ -extern grub_int32_t grub_kernel_image_size; - -/* The total size of module images following the kernel. */ -extern grub_int32_t grub_total_module_size; - #endif /* ! ASM_FILE */ #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 4440fdd12..fb1c5babe 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -79,7 +79,6 @@ struct image_target_desc } flags; unsigned raw_size; unsigned total_module_size; - unsigned kernel_image_size; unsigned compressed_size; unsigned link_align; grub_uint16_t elf_target; @@ -110,7 +109,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, @@ -131,7 +129,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, @@ -152,7 +149,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_LZMA, .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, - .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE, .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE, .section_align = 1, .vaddr_offset = 0, @@ -169,7 +165,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_LZMA, .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, - .kernel_image_size = GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE, .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE, .section_align = 1, .vaddr_offset = 0, @@ -186,7 +181,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE @@ -209,7 +203,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, @@ -231,7 +224,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -247,7 +239,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = EFI64_HEADER_SIZE, @@ -266,7 +257,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -286,7 +276,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -308,7 +297,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -327,7 +315,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, @@ -348,8 +335,7 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, - .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE, - .compressed_size = GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE, + .compressed_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -365,8 +351,7 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, - .kernel_image_size = GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE, - .compressed_size = GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE, + .compressed_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -382,7 +367,6 @@ struct image_target_desc image_targets[] = .flags = PLATFORM_FLAGS_NONE, .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .compressed_size = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = EFI64_HEADER_SIZE, @@ -402,7 +386,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -422,7 +405,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -442,7 +424,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -462,7 +443,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -482,7 +462,6 @@ struct image_target_desc image_targets[] = .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, .compressed_size = TARGET_NO_FIELD, - .kernel_image_size = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -935,9 +914,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], && image_target->total_module_size != TARGET_NO_FIELD) *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) = grub_host_to_target32 (total_module_size); - if (image_target->kernel_image_size != TARGET_NO_FIELD) - *((grub_uint32_t *) (kernel_img + image_target->kernel_image_size)) - = grub_host_to_target32 (kernel_size); if (image_target->compressed_size != TARGET_NO_FIELD) *((grub_uint32_t *) (kernel_img + image_target->compressed_size)) = grub_host_to_target32 (core_size - image_target->raw_size); From db1326f5fbdbe15651dafb5ee628118018f1d53c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 21 Oct 2011 00:16:59 +0200 Subject: [PATCH 409/673] Move chainloader_real_boot out of the kernel --- grub-core/Makefile.am | 1 - grub-core/kern/i386/pc/startup.S | 25 -------- grub-core/lib/i386/reboot.c | 1 + grub-core/lib/i386/relocator.c | 9 ++- grub-core/lib/i386/relocator16.S | 85 ++++++++++++++++++++++++++ grub-core/loader/i386/pc/chainloader.c | 59 ++++++++++++++---- grub-core/loader/i386/pc/freedos.c | 3 +- grub-core/loader/i386/pc/linux.c | 2 +- grub-core/loader/i386/pc/ntldr.c | 3 +- include/grub/i386/pc/loader.h | 27 -------- include/grub/i386/relocator.h | 2 + 11 files changed, 148 insertions(+), 69 deletions(-) delete mode 100644 include/grub/i386/pc/loader.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 3bd192602..4a46e1d9c 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -83,7 +83,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h if COND_i386_pc -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index a0ef71f90..e75f3ab90 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -463,31 +463,6 @@ FUNCTION(grub_exit) ljmp $0xf000, $0xfff0 .code32 -/* - * void grub_chainloader_real_boot (int drive, void *part_addr) - * - * This starts another boot loader. - */ - -FUNCTION(grub_chainloader_real_boot) - pushl %edx - pushl %eax - - /* Turn off Gate A20 */ - xorl %eax, %eax - call grub_gate_a20 - - /* set up to pass boot drive */ - popl %edx - - /* ESI must point to a partition table entry */ - popl %esi - - call prot_to_real - .code16 - ljmp $0, $GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR - .code32 - /* * void grub_console_putchar (int c) * diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c index ef28f7f65..45a2259cf 100644 --- a/grub-core/lib/i386/reboot.c +++ b/grub-core/lib/i386/reboot.c @@ -49,6 +49,7 @@ grub_reboot (void) state.sp = 0; state.cs = segment; state.ip = 0; + state.a20 = 0; grub_stop_floppy (); diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index 2f10feb5e..1f0aa0dd1 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -51,6 +51,9 @@ extern grub_uint16_t grub_relocator16_ss; extern grub_uint16_t grub_relocator16_sp; extern grub_uint32_t grub_relocator16_edx; extern grub_uint32_t grub_relocator16_ebx; +extern grub_uint32_t grub_relocator16_esi; + +extern grub_uint16_t grub_relocator16_keep_a20_enabled; extern grub_uint8_t grub_relocator32_start; extern grub_uint8_t grub_relocator32_end; @@ -195,7 +198,8 @@ grub_relocator16_boot (struct grub_relocator *rel, void *relst; grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align (rel, &ch, 0, + /* Put it higher than the byte it checks for A20 check. */ + err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010, 0xa0000 - RELOCATOR_SIZEOF (16), RELOCATOR_SIZEOF (16), 16, GRUB_RELOCATOR_PREFERENCE_NONE); @@ -215,6 +219,9 @@ grub_relocator16_boot (struct grub_relocator *rel, grub_relocator16_ebx = state.ebx; grub_relocator16_edx = state.edx; + grub_relocator16_esi = state.esi; + + grub_relocator16_keep_a20_enabled = state.a20; grub_memmove (get_virtual_current_address (ch), &grub_relocator16_start, RELOCATOR_SIZEOF (16)); diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index d6673fade..babe69e1d 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -93,6 +93,85 @@ LOCAL(segment): .word 0 LOCAL(cont3): + + /* movw imm16, %ax. */ + .byte 0xb8 +VARIABLE(grub_relocator16_keep_a20_enabled) + .word 0 + test %ax, %ax + jnz LOCAL(gate_a20_done) + + /* first of all, test if already in a good state */ + call LOCAL(gate_a20_check_state) + testb %al, %al + jz LOCAL(gate_a20_done) + + /* second, try a BIOS call */ + movw $0x2400, %ax + int $0x15 + + call LOCAL(gate_a20_check_state) + testb %al, %al + jz LOCAL(gate_a20_done) + + /* + * In macbook, the keyboard test would hang the machine, so we move + * this forward. + */ + /* fourth, try the system control port A */ + inb $0x92 + andb $(~0x03), %al + outb $0x92 + + /* When turning off Gate A20, do not check the state strictly, + because a failure is not fatal usually, and Gate A20 is always + on some modern machines. */ + jmp LOCAL(gate_a20_done) + +LOCAL(gate_a20_check_state): + /* iterate the checking for a while */ + movw $100, %cx +1: + call 3f + testb %al, %al + jz 2f + loop 1b +2: + ret + +3: + xorw %ax, %ax + movw %ax, %ds + decw %ax + movw %ax, %es + xorw %ax, %ax + + movw $0x8000, %ax + /* compare the byte at ADDR with that at 0x100000 + ADDR */ + movw %ax, %si + addw $0x10, %ax + movw %ax, %di + + /* save the original byte in DL */ + movb %ds:(%si), %dl + movb %es:(%di), %al + /* try to set one less value at ADDR */ + movb %al, %dh + decb %dh + movb %dh, %ds:(%si) + /* serialize */ + outb %al, $0x80 + outb %al, $0x80 + /* obtain the value at 0x100000 + ADDR in CH */ + movb %es:(%di), %dh + /* this result is 1 if A20 is on or 0 if it is off */ + subb %dh, %al + xorb $1, %al + /* restore the original */ + movb %dl, %es:(%di) + ret + +LOCAL(gate_a20_done): /* we are in real mode now * set up the real mode segment registers : DS, SS, ES */ @@ -132,6 +211,12 @@ VARIABLE(grub_relocator16_sp) .word 0 movzwl %ax, %esp + /* movw imm32, %eax. */ + .byte 0x66, 0xb8 +VARIABLE(grub_relocator16_esi) + .long 0 + movl %eax, %esi + /* movw imm32, %edx. */ .byte 0x66, 0xba VARIABLE(grub_relocator16_edx) diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index 8d6ec8f20..929569921 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include @@ -39,12 +38,14 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); static grub_dl_t my_mod; static int boot_drive; -static void *boot_part_addr; +static grub_addr_t boot_part_addr; +static struct grub_relocator *rel; typedef enum { @@ -55,16 +56,29 @@ typedef enum static grub_err_t grub_chainloader_boot (void) { + struct grub_relocator16_state state = { + .edx = boot_drive, + .esi = boot_part_addr, + .ds = 0, + .es = 0, + .fs = 0, + .gs = 0, + .ss = 0, + .cs = 0, + .sp = GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR, + .ip = GRUB_MEMORY_MACHINE_BOOT_LOADER_ADDR, + .a20 = 0 + }; grub_video_set_mode ("text", 0, 0); - grub_chainloader_real_boot (boot_drive, boot_part_addr); - /* Never reach here. */ - return GRUB_ERR_NONE; + return grub_relocator16_boot (rel, state); } static grub_err_t grub_chainloader_unload (void) { + grub_relocator_unload (rel); + rel = NULL; grub_dl_unref (my_mod); return GRUB_ERR_NONE; } @@ -133,7 +147,12 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) grub_uint16_t signature; grub_device_t dev; int drive = -1; - void *part_addr = 0; + grub_addr_t part_addr = 0; + grub_uint8_t *bs, *ptable; + + rel = grub_relocator_new (); + if (!rel) + goto fail; grub_dl_ref (my_mod); @@ -142,8 +161,25 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) if (! file) goto fail; + { + grub_relocator_chunk_t ch; + grub_err_t err; + + err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7C00, + GRUB_DISK_SECTOR_SIZE); + if (err) + goto fail; + bs = get_virtual_current_address (ch); + err = grub_relocator_alloc_chunk_addr (rel, &ch, + GRUB_MEMORY_MACHINE_PART_TABLE_ADDR, + 64); + if (err) + goto fail; + ptable = get_virtual_current_address (ch); + } + /* Read the first block. */ - if (grub_file_read (file, (void *) 0x7C00, GRUB_DISK_SECTOR_SIZE) + if (grub_file_read (file, bs, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) { if (grub_errno == GRUB_ERR_NONE) @@ -153,7 +189,7 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) } /* Check the signature. */ - signature = *((grub_uint16_t *) (0x7C00 + GRUB_DISK_SECTOR_SIZE - 2)); + signature = *((grub_uint16_t *) (bs + GRUB_DISK_SECTOR_SIZE - 2)); if (signature != grub_le_to_cpu16 (0xaa55) && ! (flags & GRUB_CHAINLOADER_FORCE)) { @@ -177,10 +213,9 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) if (p && grub_strcmp (p->partmap->name, "msdos") == 0) { disk->partition = p->parent; - grub_disk_read (disk, p->offset, 446, 64, - (void *) GRUB_MEMORY_MACHINE_PART_TABLE_ADDR); - part_addr = (void *) (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR - + (p->index << 4)); + grub_disk_read (disk, p->offset, 446, 64, ptable); + part_addr = (GRUB_MEMORY_MACHINE_PART_TABLE_ADDR + + (p->index << 4)); disk->partition = p; } } diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c index f796e08f4..1f088e2b5 100644 --- a/grub-core/loader/i386/pc/freedos.c +++ b/grub-core/loader/i386/pc/freedos.c @@ -56,7 +56,8 @@ grub_freedos_boot (void) .ss = GRUB_FREEDOS_STACK_SEGMENT, .sp = GRUB_FREEDOS_STACK_POINTER, .ebx = ebx, - .edx = 0 + .edx = 0, + .a20 = 1 }; grub_video_set_mode ("text", 0, 0); diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index adc6e8b99..c7c099174 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include @@ -61,6 +60,7 @@ grub_linux16_boot (void) state.sp = GRUB_LINUX_SETUP_STACK; state.cs = segment + 0x20; state.ip = 0; + state.a20 = 1; grub_video_set_mode ("text", 0, 0); diff --git a/grub-core/loader/i386/pc/ntldr.c b/grub-core/loader/i386/pc/ntldr.c index b2909c191..153b605ed 100644 --- a/grub-core/loader/i386/pc/ntldr.c +++ b/grub-core/loader/i386/pc/ntldr.c @@ -54,7 +54,8 @@ grub_ntldr_boot (void) .gs = 0, .ss = 0, .sp = 0x7c00, - .edx = edx + .edx = edx, + .a20 = 1 }; grub_video_set_mode ("text", 0, 0); diff --git a/include/grub/i386/pc/loader.h b/include/grub/i386/pc/loader.h deleted file mode 100644 index bfbcaac5a..000000000 --- a/include/grub/i386/pc/loader.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2007 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 . - */ - -#ifndef GRUB_LOADER_MACHINE_HEADER -#define GRUB_LOADER_MACHINE_HEADER 1 - -#include - -/* This is an asm part of the chainloader. */ -void EXPORT_FUNC(grub_chainloader_real_boot) (int drive, void *part_addr) __attribute__ ((noreturn)); - -#endif /* ! GRUB_LOADER_MACHINE_HEADER */ diff --git a/include/grub/i386/relocator.h b/include/grub/i386/relocator.h index 778049eef..b2fe900b6 100644 --- a/include/grub/i386/relocator.h +++ b/include/grub/i386/relocator.h @@ -48,6 +48,8 @@ struct grub_relocator16_state grub_uint16_t ip; grub_uint32_t ebx; grub_uint32_t edx; + grub_uint32_t esi; + int a20; }; struct grub_relocator64_state From 7bec1053db4da195301d418bd82dd5316b28002e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 22:40:26 +0200 Subject: [PATCH 410/673] * util/grub.d/10_hurd.in: Add datarootdir as per automake manual suggestion. * util/grub.d/10_kfreebsd.in: Likewise. * util/grub.d/10_linux.in: Likewise. * util/grub.d/10_netbsd.in: Likewise. * util/grub.d/10_windows.in: Likewise. * util/grub.d/20_linux_xen.in: Likewise. --- ChangeLog | 10 ++++++++++ util/grub.d/10_hurd.in | 1 + util/grub.d/10_kfreebsd.in | 1 + util/grub.d/10_linux.in | 1 + util/grub.d/10_netbsd.in | 1 + util/grub.d/10_windows.in | 1 + util/grub.d/20_linux_xen.in | 1 + 7 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index bf96dc095..0b179811c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-10-20 Vladimir Serbinenko + + * util/grub.d/10_hurd.in: Add datarootdir as per automake manual + suggestion. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/10_netbsd.in: Likewise. + * util/grub.d/10_windows.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + 2011-10-20 Vladimir Serbinenko Remove redundant grub_kernel_image_size. diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 9ca01f0a8..d04b0a4fe 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -20,6 +20,7 @@ set -e prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ +datarootdir=@datarootdir@ . ${libdir}/@PACKAGE@/grub-mkconfig_lib CLASS="--class gnu --class os" diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index e4bfc06cb..e668f3fd9 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -21,6 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ +datarootdir=@datarootdir@ . ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 97e7c6523..c3565096b 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -21,6 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ +datarootdir=@datarootdir@ . ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in index c257aeb3c..8c232b01b 100644 --- a/util/grub.d/10_netbsd.in +++ b/util/grub.d/10_netbsd.in @@ -21,6 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ +datarootdir=@datarootdir@ . ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index 941267a9f..0a848880d 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -20,6 +20,7 @@ set -e prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ +datarootdir=@datarootdir@ . ${libdir}/@PACKAGE@/grub-mkconfig_lib case "`uname 2>/dev/null`" in diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index c0b255598..2f1b4af88 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -21,6 +21,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ +datarootdir=@datarootdir@ . ${libdir}/@PACKAGE@/grub-mkconfig_lib export TEXTDOMAIN=@PACKAGE@ From 7a5c54a437d148d3f8de45b3adaa9a77d6e5de44 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 22:53:21 +0200 Subject: [PATCH 411/673] * util/grub-install.in: Add datarootdir as per automake manual suggestion. * util/grub-mknetdir.in: Likewise. --- ChangeLog | 8 +++++++- util/grub-install.in | 1 + util/grub-mknetdir.in | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0b179811c..17db9da19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,10 @@ -2011-10-20 Vladimir Serbinenko +2011-10-23 Vladimir Serbinenko + + * util/grub-install.in: Add datarootdir as per automake manual + suggestion. + * util/grub-mknetdir.in: Likewise. + +2011-10-23 Vladimir Serbinenko * util/grub.d/10_hurd.in: Add datarootdir as per automake manual suggestion. diff --git a/util/grub-install.in b/util/grub-install.in index e1255f4f7..fdbe10e76 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -31,6 +31,7 @@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ platform=@platform@ host_os=@host_os@ +datarootdir=@datarootdir@ pkglibdir="${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`" localedir="@datadir@/locale" diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index 52598a8c9..e5a2172fd 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -29,6 +29,7 @@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ host_os=@host_os@ localedir=@datadir@/locale +datarootdir=@datarootdir@ pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" self=`basename $0` From d1e293bbfac2f1890d6d8ab4fbc72adb43536adf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 22:55:32 +0200 Subject: [PATCH 412/673] * grub-core/io/lzopio.c (test_header): Fix incorrect memcmp instead of grub_memcmp usage. --- ChangeLog | 5 +++++ grub-core/io/lzopio.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 17db9da19..5899c1e95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-23 Vladimir Serbinenko + + * grub-core/io/lzopio.c (test_header): Fix incorrect memcmp instead of + grub_memcmp usage. + 2011-10-23 Vladimir Serbinenko * util/grub-install.in: Add datarootdir as per automake manual diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index 02a70f4d8..bd6f8e738 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -397,7 +397,7 @@ test_header (grub_file_t file) if (hcheck) { checksum = grub_cpu_to_be32(checksum); - if (memcmp(&checksum, hcheck->read(context), sizeof(checksum)) != 0) + if (grub_memcmp (&checksum, hcheck->read(context), sizeof(checksum)) != 0) goto CORRUPTED; } From 3ce69fc90f62b3ca01239bdc826d4960df15ce83 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:04:57 +0200 Subject: [PATCH 413/673] * grub-core/kern/i386/pc/startup.S (grub_exit): Add missing zeroing-out. * grub-core/lib/i386/reboot_trampoline.S (grub_reboot_start): Likewise. --- ChangeLog | 6 ++++++ grub-core/kern/i386/pc/startup.S | 1 + grub-core/lib/i386/reboot_trampoline.S | 1 + 3 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5899c1e95..f5b846ddd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-10-23 Vladimir Serbinenko + + * grub-core/kern/i386/pc/startup.S (grub_exit): Add missing zeroing-out. + * grub-core/lib/i386/reboot_trampoline.S (grub_reboot_start): + Likewise. + 2011-10-23 Vladimir Serbinenko * grub-core/io/lzopio.c (test_header): Fix incorrect memcmp instead of diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index a0ef71f90..5277695b1 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -458,6 +458,7 @@ FUNCTION(grub_exit) /* Tell the BIOS a boot failure. If this does not work, reboot. */ int $0x18 /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */ + xorw %ax, %ax movw $0x0472, %di movw %ax, (%di) ljmp $0xf000, $0xfff0 diff --git a/grub-core/lib/i386/reboot_trampoline.S b/grub-core/lib/i386/reboot_trampoline.S index 18bcfb287..c088cd081 100644 --- a/grub-core/lib/i386/reboot_trampoline.S +++ b/grub-core/lib/i386/reboot_trampoline.S @@ -26,6 +26,7 @@ VARIABLE(grub_reboot_start) /* set 0x472 to 0x0000 for cold boot (0x1234 for warm boot) */ movw $0x0472, %di + xorw %ax, %ax movw %ax, (%di) ljmp $0xf000, $0xfff0 From f8bc22a832e290cd5fa80572e248762f71a7274f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:20:11 +0200 Subject: [PATCH 414/673] * util/ieee1275/grub-ofpathname.c: Add missing include. --- ChangeLog | 4 ++++ util/ieee1275/grub-ofpathname.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index f5b846ddd..39a85696e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-23 Vladimir Serbinenko + + * util/ieee1275/grub-ofpathname.c: Add missing include. + 2011-10-23 Vladimir Serbinenko * grub-core/kern/i386/pc/startup.S (grub_exit): Add missing zeroing-out. diff --git a/util/ieee1275/grub-ofpathname.c b/util/ieee1275/grub-ofpathname.c index a9bc2cfda..ee81457b3 100644 --- a/util/ieee1275/grub-ofpathname.c +++ b/util/ieee1275/grub-ofpathname.c @@ -24,6 +24,8 @@ #include "progname.h" +#include + int main(int argc, char **argv) { char *of_path; From 18c575e5c5c4a1df3aadb602244e31677bb8631d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:22:38 +0200 Subject: [PATCH 415/673] * util/grub-setup.c: Add missing include. --- ChangeLog | 4 ++++ util/grub-setup.c | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 39a85696e..7eb57b134 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-23 Vladimir Serbinenko + + * util/grub-setup.c: Add missing include. + 2011-10-23 Vladimir Serbinenko * util/ieee1275/grub-ofpathname.c: Add missing include. diff --git a/util/grub-setup.c b/util/grub-setup.c index b3a6c5c76..99de26f76 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -49,6 +49,7 @@ #include "progname.h" #include #include +#include #define _GNU_SOURCE 1 #include From 4e94ae657595a0b13656ebf16e65fbd071783663 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:25:06 +0200 Subject: [PATCH 416/673] * include/grub/misc.h (grub_memcpy): Declare grub_memcpy with static inline function rather than a define. --- ChangeLog | 5 +++++ include/grub/misc.h | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7eb57b134..782da923e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-23 Vladimir Serbinenko + + * include/grub/misc.h (grub_memcpy): Declare grub_memcpy with static + inline function rather than a define. + 2011-10-23 Vladimir Serbinenko * util/grub-setup.c: Add missing include. diff --git a/include/grub/misc.h b/include/grub/misc.h index 0a0a4135e..5bc159e7d 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -49,14 +49,19 @@ #define COMPILE_TIME_ASSERT(cond) switch (0) { case 1: case !(cond): ; } #define grub_dprintf(condition, fmt, args...) grub_real_dprintf(GRUB_FILE, __LINE__, condition, fmt, ## args) -/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */ -#define grub_memcpy(d,s,n) grub_memmove ((d), (s), (n)) void *EXPORT_FUNC(grub_memmove) (void *dest, const void *src, grub_size_t n); char *EXPORT_FUNC(grub_strcpy) (char *dest, const char *src); char *EXPORT_FUNC(grub_strncpy) (char *dest, const char *src, int c); char *EXPORT_FUNC(grub_stpcpy) (char *dest, const char *src); +/* XXX: If grub_memmove is too slow, we must implement grub_memcpy. */ +static inline void * +grub_memcpy (void *dest, const void *src, grub_size_t n) +{ + return grub_memmove (dest, src, n); +} + static inline char * grub_strcat (char *dest, const char *src) { From 4defb8d59b16c713460ea0929b4439ace3dc2705 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:28:23 +0200 Subject: [PATCH 417/673] * grub-core/lib/posix_wrap/string.h (memcpy) [GRUB_UTIL]: New inline function. * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (memcpy) [GRUB_UTIL]: Likewise. (memset) [GRUB_UTIL]: Likewise. (memcmp) [GRUB_UTIL]: Likewise. --- ChangeLog | 9 +++++++++ grub-core/lib/libgcrypt_wrap/cipher_wrap.h | 21 ++++++++++++++++++++- grub-core/lib/posix_wrap/string.h | 8 ++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 782da923e..579f510b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-23 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/string.h (memcpy) [GRUB_UTIL]: + New inline function. + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (memcpy) [GRUB_UTIL]: + Likewise. + (memset) [GRUB_UTIL]: Likewise. + (memcmp) [GRUB_UTIL]: Likewise. + 2011-10-23 Vladimir Serbinenko * include/grub/misc.h (grub_memcpy): Declare grub_memcpy with static diff --git a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h index 59febaeb5..0141400fc 100644 --- a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h +++ b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h @@ -87,6 +87,25 @@ fips_mode (void) return 0; } -#define memset grub_memset +#ifdef GRUB_UTIL +static inline void * +memcpy (void *dest, const void *src, grub_size_t n) +{ + return grub_memcpy (dest, src, n); +} + +static inline void * +memset (void *s, int c, grub_size_t n) +{ + return grub_memset (s, c, n); +} + +static inline int +memcmp (const void *s1, const void *s2, grub_size_t n) +{ + return grub_memcmp (s1, s2, n); +} +#endif + #endif diff --git a/grub-core/lib/posix_wrap/string.h b/grub-core/lib/posix_wrap/string.h index 4224836e2..f38c97ba4 100644 --- a/grub-core/lib/posix_wrap/string.h +++ b/grub-core/lib/posix_wrap/string.h @@ -39,4 +39,12 @@ strcasecmp (const char *s1, const char *s2) return grub_strcasecmp (s1, s2); } +#ifdef GRUB_UTIL +static inline void * +memcpy (void *dest, const void *src, grub_size_t n) +{ + return grub_memcpy (dest, src, n); +} +#endif + #endif From 124df5f6caabf6be40434c75b4c945f908d01904 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:32:06 +0200 Subject: [PATCH 418/673] Fine grainely disable warnings on lexer. Remove Wno-error on it. * grub-core/Makefile.core.def (normal): Remove -Wno-error. * grub-core/script/lexer.c: Declare yytext_ptr to avoid having yylex_strncpy. * grub-core/script/yylex.l: Add fine-grained #pragma. --- ChangeLog | 9 +++++++++ grub-core/Makefile.core.def | 2 +- grub-core/script/lexer.c | 1 + grub-core/script/yylex.l | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 579f510b0..637fa622b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-23 Vladimir Serbinenko + + Fine grainely disable warnings on lexer. Remove Wno-error on it. + + * grub-core/Makefile.core.def (normal): Remove -Wno-error. + * grub-core/script/lexer.c: Declare yytext_ptr to avoid having + yylex_strncpy. + * grub-core/script/yylex.l: Add fine-grained #pragma. + 2011-10-23 Vladimir Serbinenko * grub-core/lib/posix_wrap/string.h (memcpy) [GRUB_UTIL]: diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 7cb83924c..6d3c31ea6 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1395,7 +1395,7 @@ module = { extra_dist = script/yylex.l; extra_dist = script/parser.y; - cflags = '$(CFLAGS_POSIX) -Wno-error'; + cflags = '$(CFLAGS_POSIX)'; cppflags = '$(CPPFLAGS_POSIX)'; }; diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c index 98279079f..53697c734 100644 --- a/grub-core/script/lexer.c +++ b/grub-core/script/lexer.c @@ -24,6 +24,7 @@ #include #include +#define yytext_ptr char * #include "grub_script.tab.h" #include "grub_script.yy.h" diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index 7195a880d..012d88dbc 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -24,6 +24,9 @@ #include #include "grub_script.tab.h" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wmissing-prototypes" + #define yyfree grub_lexer_yyfree #define yyalloc grub_lexer_yyalloc #define yyrealloc grub_lexer_yyrealloc From 3471ecdfd9c08e59f37f8ec8fd530aef26e9f1e4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:34:30 +0200 Subject: [PATCH 419/673] * grub-core/lib/setjmp.S [__ia64__]: Include ./ia64/longjmp.S. --- ChangeLog | 4 ++++ grub-core/lib/setjmp.S | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 637fa622b..6daca7214 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-23 Vladimir Serbinenko + + * grub-core/lib/setjmp.S [__ia64__]: Include ./ia64/longjmp.S. + 2011-10-23 Vladimir Serbinenko Fine grainely disable warnings on lexer. Remove Wno-error on it. diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S index b04fd7439..fb7f94767 100644 --- a/grub-core/lib/setjmp.S +++ b/grub-core/lib/setjmp.S @@ -10,6 +10,7 @@ #include "./powerpc/setjmp.S" #elif defined(__ia64__) #include "./ia64/setjmp.S" +#include "./ia64/longjmp.S" #else #error "Unknown target cpu type" #endif From e084ba18957266042721af925a58d744daf8b842 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:39:00 +0200 Subject: [PATCH 420/673] * util/import_gcry.py: Accept space between # and include. --- ChangeLog | 4 ++++ util/import_gcry.py | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6daca7214..fc5ab9806 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-23 Vladimir Serbinenko + + * util/import_gcry.py: Accept space between # and include. + 2011-10-23 Vladimir Serbinenko * grub-core/lib/setjmp.S [__ia64__]: Include ./ia64/longjmp.S. diff --git a/util/import_gcry.py b/util/import_gcry.py index 720f19303..befa5ef5f 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -189,10 +189,9 @@ for cipher_file in cipher_files: continue else: fw.write (holdline) - m = re.match ("#include <.*>", line) + m = re.match ("# *include <(.*)>", line) if not m is None: - chmsg = "Removed including of %s" % \ - m.group () [len ("#include <"):len (m.group ()) - 1] + chmsg = "Removed including of %s" % m.groups ()[0] if nch: chlognew = "%s\n %s" % (chlognew, chmsg) else: From 534d769e579ad77100d11a397387ebff68fb90cd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:40:53 +0200 Subject: [PATCH 421/673] * util/import_gcry.py: Automatically fix camellia.c and camellia.h. --- ChangeLog | 4 ++++ util/import_gcry.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index fc5ab9806..0198ba4ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-23 Vladimir Serbinenko + + * util/import_gcry.py: Automatically fix camellia.c and camellia.h. + 2011-10-23 Vladimir Serbinenko * util/import_gcry.py: Accept space between # and include. diff --git a/util/import_gcry.py b/util/import_gcry.py index befa5ef5f..7591d8f0e 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -104,6 +104,20 @@ for cipher_file in cipher_files: fw.write ("/* This file was automatically imported with \n") fw.write (" import_gcry.py. Please don't modify it */\n") fw.write ("#include \n") + if cipher_file == "camellia.c": + fw.write ("#include \"camellia.h\"\n") + if cipher_file == "camellia.h": + fw.write ("#include \n") + fw.write ("void camellia_setup128(const unsigned char *key, grub_uint32_t *subkey);\n") + fw.write ("void camellia_setup192(const unsigned char *key, grub_uint32_t *subkey);\n") + fw.write ("void camellia_setup256(const unsigned char *key, grub_uint32_t *subkey);\n") + fw.write ("void camellia_encrypt128(const grub_uint32_t *subkey, grub_uint32_t *io);\n") + fw.write ("void camellia_encrypt192(const grub_uint32_t *subkey, grub_uint32_t *io);\n") + fw.write ("void camellia_encrypt256(const grub_uint32_t *subkey, grub_uint32_t *io);\n") + fw.write ("void camellia_decrypt128(const grub_uint32_t *subkey, grub_uint32_t *io);\n") + fw.write ("void camellia_decrypt192(const grub_uint32_t *subkey, grub_uint32_t *io);\n") + fw.write ("void camellia_decrypt256(const grub_uint32_t *subkey, grub_uint32_t *io);\n") + fw.write ("#define memcpy grub_memcpy\n") # Whole libgcrypt is distributed under GPLv3+ or compatible if isc: fw.write ("GRUB_MOD_LICENSE (\"GPLv3+\");\n") From f646e143090e26fc8087f3395fc2c1e03190c584 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 23 Oct 2011 23:55:38 +0200 Subject: [PATCH 422/673] * grub-core/lib/reed_solomon.c (gf_invert): Declare as const and save some space. * include/grub/offsets.h (GRUB_KERNEL_I386_PC_RAW_SIZE): Decrease. (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): Likewise. --- ChangeLog | 7 +++++++ grub-core/lib/reed_solomon.c | 4 ++-- include/grub/offsets.h | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0198ba4ee..ea8804bd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-10-23 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (gf_invert): Declare as const and + save some space. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_RAW_SIZE): Decrease. + (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): Likewise. + 2011-10-23 Vladimir Serbinenko * util/import_gcry.py: Automatically fix camellia.c and camellia.h. diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 365b76003..78d249c2f 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -57,13 +57,13 @@ typedef grub_uint16_t gf_double_t; #define GF_POLYNOMIAL 0x1d #define GF_INVERT2 0x8e #if defined (STANDALONE) && !defined (TEST) -static char *gf_invert __attribute__ ((section(".text"))) = (void *) 0x100000; +static gf_single_t * const gf_invert __attribute__ ((section(".text"))) = (void *) 0x100000; static char *scratch __attribute__ ((section(".text"))) = (void *) 0x100100; #else #if defined (STANDALONE) static char *scratch; #endif -static grub_uint8_t gf_invert[256]; +static gf_single_t gf_invert[256]; #endif #define SECTOR_SIZE 512 diff --git a/include/grub/offsets.h b/include/grub/offsets.h index aa65cd5cc..92354f700 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -35,9 +35,9 @@ #define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x18 /* The size of the first region which won't be compressed. */ -#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xcd0 +#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xc70 -#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x730 +#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x6e0 /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 From 89481cabbdbbf8dfd937f06f6195bc4135fb86d0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Oct 2011 01:31:06 +0200 Subject: [PATCH 423/673] * grub-core/fs/fat.c (grub_fat_label) [MODE_EXFAT]: Set *label to 0 if no label is found. (grub_fat_iterate_dir): Fix file size type. (grub_fat_iterate_dir): Likewise. --- ChangeLog | 7 +++++++ grub-core/fs/fat.c | 8 +++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index ea8804bd1..306358faa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-10-23 Vladimir Serbinenko + + * grub-core/fs/fat.c (grub_fat_label) [MODE_EXFAT]: Set *label to 0 + if no label is found. + (grub_fat_iterate_dir): Fix file size type. + (grub_fat_iterate_dir): Likewise. + 2011-10-23 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (gf_invert): Declare as const and diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index ae705bcfb..36a43fca0 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -485,7 +485,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, + data->logical_sector_bits + GRUB_DISK_SECTOR_BITS); logical_cluster = offset >> logical_cluster_bits; - offset &= (1 << logical_cluster_bits) - 1; + offset &= (1ULL << logical_cluster_bits) - 1; if (logical_cluster < data->cur_cluster_num) { @@ -631,9 +631,9 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, case 0xc0: node.first_cluster = grub_cpu_to_le32 (sec.type_specific.stream_extension.first_cluster); node.valid_size - = grub_cpu_to_le32 (sec.type_specific.stream_extension.valid_size); + = grub_cpu_to_le64 (sec.type_specific.stream_extension.valid_size); node.file_size - = grub_cpu_to_le32 (sec.type_specific.stream_extension.file_size); + = grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size); node.have_stream = 1; break; case 0xc1: @@ -1026,6 +1026,8 @@ grub_fat_label (grub_device_t device, char **label) if (! data) return grub_errno; + *label = NULL; + while (1) { offset += sizeof (dir); From e0864e7ab7b79f2f08ab749e6be84dadfa0119e3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Oct 2011 10:45:47 +0200 Subject: [PATCH 424/673] Minix FS fixes. * grub-core/fs/minix.c (GRUB_MINIX_INODE_SIZE): Size is always 32-bit. (grub_minix_inode) [!MODE_MINIX2 && !MODE_MINIX3]: Make size 32-bit. Rename ctime to mtime. All users updated. (grub_minix_get_file_block): Fix types and double indirect computations. --- ChangeLog | 9 +++++++++ grub-core/fs/minix.c | 34 ++++++++++++++++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 306358faa..9065162fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-24 Vladimir Serbinenko + + Minix FS fixes. + + * grub-core/fs/minix.c (GRUB_MINIX_INODE_SIZE): Size is always 32-bit. + (grub_minix_inode) [!MODE_MINIX2 && !MODE_MINIX3]: Make size 32-bit. + Rename ctime to mtime. All users updated. + (grub_minix_get_file_block): Fix types and double indirect computations. + 2011-10-23 Vladimir Serbinenko * grub-core/fs/fat.c (grub_fat_label) [MODE_EXFAT]: Set *label to 0 diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 055f89095..1db2883cd 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -63,7 +63,7 @@ typedef grub_uint16_t grub_minix_ino_t; #define grub_minix_le_to_cpu_ino grub_le_to_cpu16 #endif -#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size)) +#define GRUB_MINIX_INODE_SIZE(data) (grub_le_to_cpu32 (data->inode.size)) #define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) #define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \ (data->inode.dir_zones[blk])) @@ -133,15 +133,14 @@ struct grub_minix_inode grub_uint32_t indir_zone; grub_uint32_t double_indir_zone; grub_uint32_t unused; - }; #else struct grub_minix_inode { grub_uint16_t mode; grub_uint16_t uid; - grub_uint16_t size; - grub_uint32_t ctime; + grub_uint32_t size; + grub_uint32_t mtime; grub_uint8_t gid; grub_uint8_t nlinks; grub_uint16_t dir_zones[7]; @@ -168,15 +167,19 @@ static grub_dl_t my_mod; static grub_err_t grub_minix_find_file (struct grub_minix_data *data, const char *path); -static int +static grub_minix_uintn_t grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { - int indir; + grub_minix_uintn_t indir; + const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ + / GRUB_MINIX_INODE_BLKSZ (data)); - auto int grub_get_indir (int, int); + auto grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t, + grub_minix_uintn_t); /* Read the block pointer in ZONE, on the offset NUM. */ - int grub_get_indir (int zone, int num) + grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t zone, + grub_minix_uintn_t num) { grub_minix_uintn_t indirn; grub_disk_read (data->disk, @@ -192,21 +195,20 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) /* Indirect block. */ blk -= GRUB_MINIX_INODE_DIR_BLOCKS; - if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)) + if (blk < block_per_zone) { indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); return indir; } /* Double indirect block. */ - blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data); - if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)) - * (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))) + blk -= block_per_zone; + if (blk < block_per_zone * block_per_zone) { indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data), - blk / GRUB_MINIX_ZONESZ); + blk / block_per_zone); - indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ); + indir = grub_get_indir (indir, blk % block_per_zone); return indir; } @@ -536,11 +538,7 @@ grub_minix_dir (grub_device_t device, const char *path, info.dir = ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); info.mtimeset = 1; -#ifndef MODE_MINIX2 - info.mtime = grub_le_to_cpu32 (data->inode.ctime); -#else info.mtime = grub_le_to_cpu32 (data->inode.mtime); -#endif if (hook (filename, &info) ? 1 : 0) break; From 6e536dc8ad96e3ca1ae878a4250ec87d6bdccb71 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Oct 2011 16:16:28 +0200 Subject: [PATCH 425/673] Support triple indirect on minix2 and minix3. * grub-core/fs/minix.c (grub_minix_inode) [MODE_MINIX2 || MODE_MINIX3]: Declare triple_indir_zone. (grub_minix_get_file_block) [MODE_MINIX2 || MODE_MINIX3]: Handle triple indirect. --- ChangeLog | 9 +++++++++ grub-core/fs/minix.c | 16 +++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9065162fe..12117d6a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-24 Vladimir Serbinenko + + Support triple indirect on minix2 and minix3. + + * grub-core/fs/minix.c (grub_minix_inode) [MODE_MINIX2 || MODE_MINIX3]: + Declare triple_indir_zone. + (grub_minix_get_file_block) [MODE_MINIX2 || MODE_MINIX3]: Handle triple + indirect. + 2011-10-24 Vladimir Serbinenko Minix FS fixes. diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 1db2883cd..43785b657 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -132,7 +132,7 @@ struct grub_minix_inode grub_uint32_t dir_zones[7]; grub_uint32_t indir_zone; grub_uint32_t double_indir_zone; - grub_uint32_t unused; + grub_uint32_t triple_indir_zone; }; #else struct grub_minix_inode @@ -213,6 +213,20 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) return indir; } +#if defined (MODE_MINIX3) || defined (MODE_MINIX2) + blk -= block_per_zone * block_per_zone; + if (blk < ((grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone + * (grub_uint64_t) block_per_zone)) + { + indir = grub_get_indir (grub_minix_le_to_cpu_n (data->inode.triple_indir_zone), + (blk / block_per_zone) / block_per_zone); + indir = grub_get_indir (indir, (blk / block_per_zone) % block_per_zone); + indir = grub_get_indir (indir, blk % block_per_zone); + + return indir; + } +#endif + /* This should never happen. */ grub_error (GRUB_ERR_OUT_OF_RANGE, "file bigger than maximum size"); From 68c72069d927f5f7c907de32d4d9fa43d453c78c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Oct 2011 17:02:02 +0200 Subject: [PATCH 426/673] * grub-core/fs/jfs.c (grub_jfs_blkno): Use more appropriate types. (grub_jfs_blkno): Fix incorrect shift. (grub_jfs_read_file): Use more appropriate types. --- ChangeLog | 6 ++++++ grub-core/fs/jfs.c | 18 +++++++++--------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 12117d6a0..7d216e1d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-10-24 Vladimir Serbinenko + + * grub-core/fs/jfs.c (grub_jfs_blkno): Use more appropriate types. + (grub_jfs_blkno): Fix incorrect shift. + (grub_jfs_read_file): Use more appropriate types. + 2011-10-24 Vladimir Serbinenko Support triple indirect on minix2 and minix3. diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index ebc2c688a..4a7bb0214 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -253,11 +253,11 @@ static grub_int64_t grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, grub_uint64_t blk) { - auto int getblk (struct grub_jfs_treehead *treehead, - struct grub_jfs_tree_extent *extents); + auto grub_int64_t getblk (struct grub_jfs_treehead *treehead, + struct grub_jfs_tree_extent *extents); - int getblk (struct grub_jfs_treehead *treehead, - struct grub_jfs_tree_extent *extents) + grub_int64_t getblk (struct grub_jfs_treehead *treehead, + struct grub_jfs_tree_extent *extents) { int found = -1; int i; @@ -269,7 +269,7 @@ grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, /* Read the leafnode. */ if (grub_le_to_cpu32 (extents[i].offset2) <= blk && ((grub_le_to_cpu16 (extents[i].extent.length)) - + (extents[i].extent.length2 << 8) + + (extents[i].extent.length2 << 16) + grub_le_to_cpu32 (extents[i].offset2)) > blk) return (blk - grub_le_to_cpu32 (extents[i].offset2) + grub_le_to_cpu32 (extents[i].extent.blk2)); @@ -288,7 +288,7 @@ grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, } tree; if (grub_disk_read (data->disk, - grub_le_to_cpu32 (extents[found].extent.blk2) + ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2)) << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS), 0, sizeof (tree), (char *) &tree)) @@ -558,10 +558,10 @@ static grub_ssize_t grub_jfs_read_file (struct grub_jfs_data *data, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, unsigned offset, unsigned length), - grub_uint64_t pos, grub_size_t len, char *buf) + grub_off_t pos, grub_size_t len, char *buf) { - grub_uint64_t i; - grub_uint64_t blockcnt; + grub_off_t i; + grub_off_t blockcnt; blockcnt = (len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1) >> grub_le_to_cpu16 (data->sblock.log2_blksz); From 5bbd28b8cebbb365faebccf25119a2e6712731ad Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 24 Oct 2011 21:33:35 +0200 Subject: [PATCH 427/673] Fix 2G limit on ZFS. * grub-core/fs/zfs/zfs.c (zio_checksum_verify): Use more appropriate types. (uberblock_verify): Likewise. (dmu_read): Likewise. (grub_zfs_read): Likewise. Remove invalid cast. --- ChangeLog | 10 ++++++++++ grub-core/fs/zfs/zfs.c | 11 ++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7d216e1d7..e8cd7ea77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-10-24 Vladimir Serbinenko + + Fix 2G limit on ZFS. + + * grub-core/fs/zfs/zfs.c (zio_checksum_verify): Use more appropriate + types. + (uberblock_verify): Likewise. + (dmu_read): Likewise. + (grub_zfs_read): Likewise. Remove invalid cast. + 2011-10-24 Vladimir Serbinenko * grub-core/fs/jfs.c (grub_jfs_blkno): Use more appropriate types. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 1eea13b26..9d6ad7055 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -242,7 +242,7 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { */ static grub_err_t zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, - grub_zfs_endian_t endian, char *buf, int size) + grub_zfs_endian_t endian, char *buf, grub_size_t size) { zio_eck_t *zec = (zio_eck_t *) (buf + size) - 1; zio_checksum_info_t *ci = &zio_checksum_table[checksum]; @@ -337,7 +337,7 @@ vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) * */ static grub_err_t -uberblock_verify (uberblock_phys_t * ub, int offset) +uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset) { uberblock_t *uber = &ub->ubp_uberblock; grub_err_t err; @@ -620,7 +620,8 @@ static grub_err_t dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, grub_zfs_endian_t *endian_out, struct grub_zfs_data *data) { - int idx, level; + int level; + grub_off_t idx; blkptr_t *bp_array = dn->dn.dn_blkptr; int epbs = dn->dn.dn_indblkshift - SPA_BLKPTRSHIFT; blkptr_t *bp; @@ -2266,7 +2267,7 @@ static grub_ssize_t grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_zfs_data *data = (struct grub_zfs_data *) file->data; - int blksz, movesize; + grub_size_t blksz, movesize; grub_size_t length; grub_size_t read; grub_err_t err; @@ -2320,7 +2321,7 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) data->file_start = blkid * blksz; data->file_end = data->file_start + blksz; - movesize = MIN (length, data->file_end - (int) file->offset - read); + movesize = MIN (length, data->file_end - file->offset - read); grub_memmove (buf, data->file_buf + file->offset + read - data->file_start, movesize); From f4d9b64bba4e748922056437f0408071376c66b5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 17:38:22 +0200 Subject: [PATCH 428/673] * grub-core/fs/romfs.c (grub_romfs_open): Add missing return. --- ChangeLog | 4 ++++ grub-core/fs/romfs.c | 1 + 2 files changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index e8cd7ea77..1b1975215 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-25 Vladimir Serbinenko + + * grub-core/fs/romfs.c (grub_romfs_open): Add missing return. + 2011-10-24 Vladimir Serbinenko Fix 2G limit on ZFS. diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 58dc98f34..713e8293f 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -367,6 +367,7 @@ grub_romfs_open (struct grub_file *file, const char *name) file->size = grub_be_to_cpu32 (fdiro->file.size); file->data = fdiro; + return GRUB_ERR_NONE; fail: grub_free (data); From 9f326fba96eb04658e7720585e8ad9c643631ced Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 18:01:57 +0200 Subject: [PATCH 429/673] * grub-core/kern/disk.c (grub_disk_read_small): Fix memory leak. --- ChangeLog | 4 ++++ grub-core/kern/disk.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1b1975215..7eef0f796 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-25 Vladimir Serbinenko + + * grub-core/kern/disk.c (grub_disk_read_small): Fix memory leak. + 2011-10-25 Vladimir Serbinenko * grub-core/fs/romfs.c (grub_romfs_open): Add missing return. diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index f296b9d0f..460d8778f 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -442,6 +442,7 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, } } + grub_free (tmp_buf); grub_errno = GRUB_ERR_NONE; { @@ -468,9 +469,11 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, grub_error_push (); grub_dprintf ("disk", "%s read failed\n", disk->name); grub_error_pop (); + grub_free (tmp_buf); return grub_errno; } grub_memcpy (buf, tmp_buf + offset, size); + grub_free (tmp_buf); return GRUB_ERR_NONE; } } From 9f12e664cc1b815cc01000cf87559a3c303de2e6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 18:09:00 +0200 Subject: [PATCH 430/673] Fix handling of uncompressed blocks on squashfs and break 4G limit. * grub-core/fs/squash4.c (grub_squash_super): Add block_size. Remove unused flags. (grub_squash_inode): Add long_file and block_size. (grub_squash_cache_inode): New struct. (grub_squash_dirent): Make types into enum. (SQUASH_TYPE_LONG_REGULAR): New type. (grub_squash_frag_desc): Add field size. (SQUASH_BLOCK_FLAGS): New enum. (grub_squash_data): Use grub_squash_cache_inode. (grub_fshelp_node): Make ino_chunk 64-bit. (read_chunk): Minor argument change. All users updated. (squash_mount): Use correct le_to_cpu. (grub_squash_open): Handle LONG_REGULAR. (direct_read): New function. (grub_squash_read_data): Handle blocks correctly. --- ChangeLog | 20 ++++ grub-core/fs/squash4.c | 254 ++++++++++++++++++++++++++++++++--------- 2 files changed, 223 insertions(+), 51 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7eef0f796..586de218f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2011-10-25 Vladimir Serbinenko + + Fix handling of uncompressed blocks on squashfs and break 4G limit. + + * grub-core/fs/squash4.c (grub_squash_super): Add block_size. Remove + unused flags. + (grub_squash_inode): Add long_file and block_size. + (grub_squash_cache_inode): New struct. + (grub_squash_dirent): Make types into enum. + (SQUASH_TYPE_LONG_REGULAR): New type. + (grub_squash_frag_desc): Add field size. + (SQUASH_BLOCK_FLAGS): New enum. + (grub_squash_data): Use grub_squash_cache_inode. + (grub_fshelp_node): Make ino_chunk 64-bit. + (read_chunk): Minor argument change. All users updated. + (squash_mount): Use correct le_to_cpu. + (grub_squash_open): Handle LONG_REGULAR. + (direct_read): New function. + (grub_squash_read_data): Handle blocks correctly. + 2011-10-25 Vladimir Serbinenko * grub-core/kern/disk.c (grub_disk_read_small): Fix memory leak. diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 4f1265582..d45732c16 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -42,7 +42,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); exttblptr RAW superblock UID/GID table is the array ot uint32_t - unk1 contains pointer to unk3 followed by some chunk. + unk1 contains pointer to fragment table followed by some chunk. unk2 containts one uint64_t */ @@ -52,13 +52,9 @@ struct grub_squash_super #define SQUASH_MAGIC 0x73717368 grub_uint32_t dummy1; grub_uint32_t creation_time; - grub_uint32_t dummy2; + grub_uint32_t block_size; grub_uint64_t dummy3; - grub_uint8_t flags; -#define SQUASH_FLAG_UNCOMPRESSED_INODES 1 -#define SQUASH_FLAG_UNCOMPRESSED_DATA 2 -#define SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS 8 - grub_uint8_t dummy4[7]; + grub_uint64_t dummy4; grub_uint16_t root_ino_offset; grub_uint32_t root_ino_chunk; grub_uint16_t dummy5; @@ -71,7 +67,6 @@ struct grub_squash_super grub_uint64_t unk2offset; } __attribute__ ((packed)); - /* Chunk-based */ struct grub_squash_inode { @@ -87,7 +82,18 @@ struct grub_squash_inode grub_uint32_t fragment; grub_uint32_t offset; grub_uint32_t size; + grub_uint32_t block_size[0]; } __attribute__ ((packed)) file; + struct { + grub_uint32_t dummy; + grub_uint64_t chunk; + grub_uint64_t size; + grub_uint32_t dummy2[3]; + grub_uint32_t fragment; + grub_uint32_t offset; + grub_uint32_t dummy3; + grub_uint32_t block_size[0]; + } __attribute__ ((packed)) long_file; struct { grub_uint32_t dummy1; grub_uint32_t chunk; @@ -104,6 +110,15 @@ struct grub_squash_inode } __attribute__ ((packed)); } __attribute__ ((packed)); +struct grub_squash_cache_inode +{ + struct grub_squash_inode ino; + grub_disk_addr_t ino_chunk; + grub_uint16_t ino_offset; + grub_uint32_t *block_sizes; + grub_disk_addr_t *cumulated_block_sizes; +}; + /* Chunk-based. */ struct grub_squash_dirent_header { @@ -117,29 +132,46 @@ struct grub_squash_dirent grub_uint16_t ino_offset; grub_uint16_t dummy; grub_uint16_t type; -#define SQUASH_TYPE_DIR 1 -#define SQUASH_TYPE_REGULAR 2 -#define SQUASH_TYPE_SYMLINK 3 /* Actually the value is the length of name - 1. */ grub_uint16_t namelen; char name[0]; } __attribute__ ((packed)); +enum + { + SQUASH_TYPE_DIR = 1, + SQUASH_TYPE_REGULAR = 2, + SQUASH_TYPE_SYMLINK = 3, + SQUASH_TYPE_LONG_REGULAR = 9, + }; + + struct grub_squash_frag_desc { grub_uint64_t offset; - grub_uint64_t dummy; + grub_uint32_t size; + grub_uint32_t dummy; } __attribute__ ((packed)); +enum + { + SQUASH_CHUNK_FLAGS = 0x8000, + SQUASH_CHUNK_UNCOMPRESSED = 0x8000 + }; + +enum + { + SQUASH_BLOCK_FLAGS = 0x1000000, + SQUASH_BLOCK_UNCOMPRESSED = 0x1000000 + }; + #define SQUASH_CHUNK_SIZE 0x2000 -#define SQUASH_CHUNK_FLAGS 0x8000 -#define SQUASH_CHUNK_UNCOMPRESSED 0x8000 struct grub_squash_data { grub_disk_t disk; struct grub_squash_super sb; - struct grub_squash_inode ino; + struct grub_squash_cache_inode ino; grub_uint64_t fragments; }; @@ -147,12 +179,12 @@ struct grub_fshelp_node { struct grub_squash_data *data; struct grub_squash_inode ino; - grub_uint32_t ino_chunk; + grub_disk_addr_t ino_chunk; grub_uint16_t ino_offset; }; static grub_err_t -read_chunk (grub_disk_t disk, void *buf, grub_size_t len, +read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, grub_uint64_t chunk, grub_off_t offset) { grub_uint64_t chunk_start; @@ -164,7 +196,8 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len, grub_err_t err; while (1) { - err = grub_disk_read (disk, chunk_start >> GRUB_DISK_SECTOR_BITS, + err = grub_disk_read (data->disk, + chunk_start >> GRUB_DISK_SECTOR_BITS, chunk_start & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (d), &d); if (err) @@ -182,7 +215,7 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len, if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED) { grub_disk_addr_t a = chunk_start + 2 + offset; - err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS), + err = grub_disk_read (data->disk, (a >> GRUB_DISK_SECTOR_BITS), a & (GRUB_DISK_SECTOR_SIZE - 1), csize, buf); if (err) @@ -197,7 +230,7 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len, if (!tmp) return grub_errno; /* FIXME: buffer uncompressed data. */ - err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS), + err = grub_disk_read (data->disk, (a >> GRUB_DISK_SECTOR_BITS), a & (GRUB_DISK_SECTOR_SIZE - 1), bsize, tmp); if (err) @@ -240,9 +273,10 @@ squash_mount (grub_disk_t disk) return NULL; } - err = grub_disk_read (disk, grub_le_to_cpu32 (sb.unk1offset) + err = grub_disk_read (disk, + grub_le_to_cpu64 (sb.unk1offset) >> GRUB_DISK_SECTOR_BITS, - grub_le_to_cpu32 (sb.unk1offset) + grub_le_to_cpu64 (sb.unk1offset) & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag); if (grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_error (GRUB_ERR_BAD_FS, "not a squash4"); @@ -254,7 +288,7 @@ squash_mount (grub_disk_t disk) return NULL; data->sb = sb; data->disk = disk; - data->fragments = frag; + data->fragments = grub_le_to_cpu64 (frag); return data; } @@ -266,7 +300,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node) grub_err_t err; ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1); - err = read_chunk (node->data->disk, ret, + err = read_chunk (node->data, ret, grub_le_to_cpu32 (node->ino.symlink.namelen), grub_le_to_cpu64 (node->data->sb.inodeoffset) + node->ino_chunk, @@ -300,7 +334,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, struct grub_squash_dirent_header dh; grub_err_t err; - err = read_chunk (dir->data->disk, &dh, sizeof (dh), + err = read_chunk (dir->data, &dh, sizeof (dh), grub_le_to_cpu64 (dir->data->sb.diroffset) + grub_le_to_cpu32 (dir->ino.dir.chunk), off); if (err) @@ -315,14 +349,14 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, struct grub_squash_dirent di; struct grub_squash_inode ino; - err = read_chunk (dir->data->disk, &di, sizeof (di), + err = read_chunk (dir->data, &di, sizeof (di), grub_le_to_cpu64 (dir->data->sb.diroffset) + grub_le_to_cpu32 (dir->ino.dir.chunk), off); if (err) return 0; off += sizeof (di); - err = read_chunk (dir->data->disk, &ino, sizeof (ino), + err = read_chunk (dir->data, &ino, sizeof (ino), grub_le_to_cpu64 (dir->data->sb.inodeoffset) + grub_le_to_cpu32 (dh.ino_chunk), grub_cpu_to_le16 (di.ino_offset)); @@ -332,7 +366,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2); if (!buf) return 0; - err = read_chunk (dir->data->disk, buf, + err = read_chunk (dir->data, buf, grub_le_to_cpu16 (di.namelen) + 1, grub_le_to_cpu64 (dir->data->sb.diroffset) + grub_le_to_cpu32 (dir->ino.dir.chunk), off); @@ -370,7 +404,7 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) grub_memset (root, 0, sizeof (*root)); root->data = data; - return read_chunk (data->disk, &root->ino, sizeof (root->ino), + return read_chunk (data, &root->ino, sizeof (root->ino), grub_le_to_cpu64 (data->sb.inodeoffset) + grub_le_to_cpu16 (data->sb.root_ino_chunk), grub_cpu_to_le16 (data->sb.root_ino_offset)); @@ -445,48 +479,166 @@ grub_squash_open (struct grub_file *file, const char *name) } file->data = data; - data->ino = fdiro->ino; - file->size = grub_le_to_cpu32 (fdiro->ino.file.size); + data->ino.ino = fdiro->ino; + data->ino.block_sizes = NULL; + data->ino.cumulated_block_sizes = NULL; + data->ino.ino_chunk = fdiro->ino_chunk; + data->ino.ino_offset = fdiro->ino_offset; + + if (fdiro->ino.type + == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) + file->size = grub_le_to_cpu64 (fdiro->ino.long_file.size); + else + file->size = grub_le_to_cpu32 (fdiro->ino.file.size); return GRUB_ERR_NONE; } +static grub_ssize_t +direct_read (struct grub_squash_data *data, + struct grub_squash_cache_inode *ino, + grub_off_t off, char *buf, grub_size_t len) +{ + grub_err_t err; + grub_off_t cumulated_uncompressed_size = 0; + grub_uint64_t a; + grub_size_t i; + grub_size_t origlen = len; + + if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) + a = grub_le_to_cpu64 (ino->ino.long_file.chunk); + else + a = grub_le_to_cpu32 (ino->ino.file.chunk); + + if (!ino->block_sizes) + { + grub_off_t total_size; + grub_size_t total_blocks; + grub_size_t block_offset; + if (ino->ino.type + == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) + { + total_size = grub_le_to_cpu64 (ino->ino.long_file.size); + block_offset = ((char *) &ino->ino.long_file.block_size + - (char *) &ino->ino); + } + else + { + total_size = grub_le_to_cpu32 (ino->ino.file.size); + block_offset = ((char *) &ino->ino.file.block_size + - (char *) &ino->ino); + } + total_blocks = grub_divmod64 (total_size + + grub_le_to_cpu32 (data->sb.block_size) - 1, + grub_le_to_cpu32 (data->sb.block_size), + 0); + ino->block_sizes = grub_malloc (total_blocks + * sizeof (ino->block_sizes[0])); + ino->cumulated_block_sizes = grub_malloc (total_blocks + * sizeof (ino->cumulated_block_sizes[0])); + if (!ino->block_sizes || !ino->cumulated_block_sizes) + { + grub_free (ino->block_sizes); + grub_free (ino->cumulated_block_sizes); + ino->block_sizes = 0; + ino->cumulated_block_sizes = 0; + return -1; + } + err = read_chunk (data, ino->block_sizes, + total_blocks * sizeof (ino->block_sizes[0]), + grub_le_to_cpu64 (data->sb.inodeoffset) + + ino->ino_chunk, + ino->ino_offset + block_offset); + if (err) + { + grub_free (ino->block_sizes); + grub_free (ino->cumulated_block_sizes); + ino->block_sizes = 0; + ino->cumulated_block_sizes = 0; + return -1; + } + ino->cumulated_block_sizes[0] = 0; + for (i = 1; i < total_blocks; i++) + ino->cumulated_block_sizes[i] = ino->cumulated_block_sizes[i - 1] + + (grub_le_to_cpu32 (ino->block_sizes[i - 1]) & ~SQUASH_BLOCK_FLAGS); + } + + if (a == 0) + a = sizeof (struct grub_squash_super); + i = grub_divmod64 (off, grub_le_to_cpu32 (data->sb.block_size), 0); + cumulated_uncompressed_size = grub_le_to_cpu32 (data->sb.block_size) + * (grub_disk_addr_t) i; + while (cumulated_uncompressed_size < off + len) + { + grub_size_t boff, read; + boff = off - cumulated_uncompressed_size; + read = grub_le_to_cpu32 (data->sb.block_size) - boff; + if (read > len) + read = len; + if (!(ino->block_sizes[i] & SQUASH_BLOCK_UNCOMPRESSED)) + err = grub_zlib_disk_read (data->disk, + ino->cumulated_block_sizes[i] + a, + boff, buf, read); + else + err = grub_disk_read (data->disk, + (ino->cumulated_block_sizes[i] + a + boff) + >> GRUB_DISK_SECTOR_BITS, + (ino->cumulated_block_sizes[i] + a + boff) + & (GRUB_DISK_SECTOR_SIZE - 1), + read, buf); + if (err) + return -1; + off += read; + len -= read; + buf += read; + cumulated_uncompressed_size += grub_le_to_cpu32 (data->sb.block_size); + i++; + } + return origlen; +} + + static grub_ssize_t grub_squash_read_data (struct grub_squash_data *data, - grub_disk_t disk, const struct grub_squash_inode *ino, + struct grub_squash_cache_inode *ino, grub_off_t off, char *buf, grub_size_t len) { grub_err_t err; grub_uint64_t a, b; + grub_uint32_t fragment; int compressed = 0; + struct grub_squash_frag_desc frag; - if (grub_le_to_cpu16 (ino->file.fragment) == 0xffff) + if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) { - if (grub_le_to_cpu32 (ino->file.chunk)) - a = grub_le_to_cpu32 (ino->file.chunk); - else - a = sizeof (struct grub_squash_super); - compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA); + a = grub_le_to_cpu64 (ino->ino.long_file.chunk); + fragment = grub_le_to_cpu32 (ino->ino.long_file.fragment); } else { - struct grub_squash_frag_desc frag; - err = read_chunk (disk, &frag, sizeof (frag), - data->fragments, sizeof (frag) - * grub_le_to_cpu16 (ino->file.fragment)); - if (err) - return -1; - a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (ino->file.chunk); - compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS); + a = grub_le_to_cpu32 (ino->ino.file.chunk); + fragment = grub_le_to_cpu32 (ino->ino.file.fragment); } - b = grub_le_to_cpu32 (data->ino.file.offset) + off; - + if (fragment == 0xffffffff) + return direct_read (data, ino, off, buf, len); + + err = read_chunk (data, &frag, sizeof (frag), + data->fragments, sizeof (frag) * fragment); + if (err) + return -1; + a += grub_le_to_cpu64 (frag.offset); + compressed = !(frag.size & SQUASH_BLOCK_UNCOMPRESSED); + if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) + b = grub_le_to_cpu64 (ino->ino.long_file.offset) + off; + else + b = grub_le_to_cpu32 (ino->ino.file.offset) + off; + /* FIXME: cache uncompressed chunks. */ if (compressed) - err = grub_zlib_disk_read (disk, a, b, buf, len); + err = grub_zlib_disk_read (data->disk, a, b, buf, len); else - err = grub_disk_read (disk, (a + b) >> GRUB_DISK_SECTOR_BITS, + err = grub_disk_read (data->disk, (a + b) >> GRUB_DISK_SECTOR_BITS, (a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); if (err) return -1; @@ -498,7 +650,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_squash_data *data = file->data; - return grub_squash_read_data (data, file->device->disk, &data->ino, + return grub_squash_read_data (data, &data->ino, file->offset, buf, len); } From d4888031f2577c86f354393bf4e2e5f22ea25bd4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 18:12:36 +0200 Subject: [PATCH 431/673] Fix tar 4G limit and handle paths containing dot. * grub-core/fs/cpio.c (grub_cpio_data): Use grub_off_t for offsets. (canonicalize): New function. (grub_cpio_find_file): Use canonicalize. Store offs in grub_disk_addr_t. (grub_cpio_dir): Use grub_disk_addr_t. (grub_cpio_open): Likewise. --- ChangeLog | 11 ++++ grub-core/fs/cpio.c | 134 ++++++++++++++++++++++++++------------------ 2 files changed, 89 insertions(+), 56 deletions(-) diff --git a/ChangeLog b/ChangeLog index 586de218f..19bf1326e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-10-25 Vladimir Serbinenko + + Fix tar 4G limit and handle paths containing dot. + + * grub-core/fs/cpio.c (grub_cpio_data): Use grub_off_t for offsets. + (canonicalize): New function. + (grub_cpio_find_file): Use canonicalize. Store offs in + grub_disk_addr_t. + (grub_cpio_dir): Use grub_disk_addr_t. + (grub_cpio_open): Likewise. + 2011-10-25 Vladimir Serbinenko Fix handling of uncompressed blocks on squashfs and break 4G limit. diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 0d84382ac..92531390e 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -71,80 +71,102 @@ struct head struct grub_cpio_data { grub_disk_t disk; - grub_uint32_t hofs; - grub_uint32_t dofs; - grub_uint32_t size; + grub_off_t hofs; + grub_off_t dofs; + grub_off_t size; }; static grub_dl_t my_mod; +static inline void +canonicalize (char *name) +{ + char *iptr, *optr; + for (iptr = name, optr = name; *iptr; ) + { + while (*iptr == '/') + iptr++; + if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0)) + { + iptr += 2; + continue; + } + while (*iptr && *iptr != '/') + *optr++ = *iptr++; + if (*iptr) + *optr++ = *iptr++; + } + *optr = 0; +} + static grub_err_t grub_cpio_find_file (struct grub_cpio_data *data, char **name, - grub_int32_t *mtime, grub_uint32_t * ofs) + grub_int32_t *mtime, grub_disk_addr_t * ofs) { #ifndef MODE_USTAR - struct head hd; + struct head hd; - if (grub_disk_read - (data->disk, 0, data->hofs, sizeof (hd), &hd)) - return grub_errno; + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; - if (hd.magic != MAGIC_BCPIO) - return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); + if (hd.magic != MAGIC_BCPIO) + return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); - data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; - if (mtime) - *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; + data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; + if (mtime) + *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; - if (hd.namesize & 1) - hd.namesize++; + if (hd.namesize & 1) + hd.namesize++; - if ((*name = grub_malloc (hd.namesize)) == NULL) - return grub_errno; + if ((*name = grub_malloc (hd.namesize)) == NULL) + return grub_errno; - if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), - hd.namesize, *name)) - { - grub_free (*name); - return grub_errno; - } + if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), + hd.namesize, *name)) + { + grub_free (*name); + return grub_errno; + } - if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1 - && ! grub_memcmp(*name, "TRAILER!!!", 11)) - { - *ofs = 0; - return GRUB_ERR_NONE; - } + if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1 + && ! grub_memcmp(*name, "TRAILER!!!", 11)) + { + *ofs = 0; + return GRUB_ERR_NONE; + } - data->dofs = data->hofs + sizeof (hd) + hd.namesize; - *ofs = data->dofs + data->size; - if (data->size & 1) - (*ofs)++; + canonicalize (*name); + + data->dofs = data->hofs + sizeof (hd) + hd.namesize; + *ofs = data->dofs + data->size; + if (data->size & 1) + (*ofs)++; #else - struct head hd; + struct head hd; - if (grub_disk_read - (data->disk, 0, data->hofs, sizeof (hd), &hd)) - return grub_errno; + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; - if (!hd.name[0]) - { - *ofs = 0; - return GRUB_ERR_NONE; - } + if (!hd.name[0]) + { + *ofs = 0; + return GRUB_ERR_NONE; + } - if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) - return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); + if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) + return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); - if ((*name = grub_strdup (hd.name)) == NULL) - return grub_errno; + if ((*name = grub_strdup (hd.name)) == NULL) + return grub_errno; - data->size = grub_strtoul (hd.size, NULL, 8); - data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; - *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - if (mtime) - *mtime = grub_strtoul (hd.mtime, NULL, 8); + data->size = grub_strtoull (hd.size, NULL, 8); + data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; + *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + if (mtime) + *mtime = grub_strtoul (hd.mtime, NULL, 8); + canonicalize (*name); #endif return GRUB_ERR_NONE; } @@ -191,10 +213,10 @@ grub_cpio_dir (grub_device_t device, const char *path, const struct grub_dirhook_info *info)) { struct grub_cpio_data *data; - grub_uint32_t ofs; + grub_disk_addr_t ofs; char *prev, *name; const char *np; - int len; + grub_size_t len; grub_dl_ref (my_mod); @@ -230,7 +252,7 @@ grub_cpio_dir (grub_device_t device, const char *path, if (p) *p = 0; - if ((!prev) || (grub_strcmp (prev, name) != 0)) + if (((!prev) || (grub_strcmp (prev, name) != 0)) && name[len] != 0) { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); @@ -262,7 +284,7 @@ static grub_err_t grub_cpio_open (grub_file_t file, const char *name) { struct grub_cpio_data *data; - grub_uint32_t ofs; + grub_disk_addr_t ofs; char *fn; int i, j; From e12119495df2f7213169985c10889ec46b205b8e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 18:18:58 +0200 Subject: [PATCH 432/673] Support multi-extent iso files. * grub-core/fs/iso9660.c (grub_iso9660_data): Remove first_sector. Add node. (grub_fshelp_node): Revamp. All users updated. (FLAG_*): New enum. (read_node): New function. (grub_iso9660_susp_iterate): Use read_node. Receive a node as argument. All users updated. (grub_iso9660_mount): Don't attempt to read sua when there is none. (get_node_size): New function. (grub_iso9660_iterate_dir): Use read_node. Agglomerate multi-extent entries. Fix memory leak on . and .. (grub_iso9660_read): Use read_node. (grub_iso9660_close): Free node. --- ChangeLog | 19 ++++ grub-core/fs/iso9660.c | 208 +++++++++++++++++++++++++++++------------ 2 files changed, 167 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 19bf1326e..a9b26a313 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-10-25 Vladimir Serbinenko + + Support multi-extent iso files. + + * grub-core/fs/iso9660.c (grub_iso9660_data): Remove first_sector. + Add node. + (grub_fshelp_node): Revamp. All users updated. + (FLAG_*): New enum. + (read_node): New function. + (grub_iso9660_susp_iterate): Use read_node. Receive a node as argument. + All users updated. + (grub_iso9660_mount): Don't attempt to read sua when there is none. + (get_node_size): New function. + (grub_iso9660_iterate_dir): Use read_node. Agglomerate multi-extent + entries. + Fix memory leak on . and .. + (grub_iso9660_read): Use read_node. + (grub_iso9660_close): Free node. + 2011-10-25 Vladimir Serbinenko Fix tar 4G limit and handle paths containing dot. diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 5b53ca597..f6cbbca95 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -149,22 +149,28 @@ struct grub_iso9660_data { struct grub_iso9660_primary_voldesc voldesc; grub_disk_t disk; - unsigned int first_sector; int rockridge; int susp_skip; int joliet; + struct grub_fshelp_node *node; }; struct grub_fshelp_node { struct grub_iso9660_data *data; - struct grub_iso9660_dir dirent; - unsigned int size; - unsigned int blk; - unsigned int dir_blk; - unsigned int dir_off; + grub_size_t have_dirents, alloc_dirents; + grub_off_t dir_off; + struct grub_iso9660_dir dirents[8]; }; +enum + { + FLAG_TYPE_PLAIN = 0, + FLAG_TYPE_DIR = 2, + FLAG_TYPE = 3, + FLAG_MORE_EXTENTS = 0x80 + }; + static grub_dl_t my_mod; @@ -214,30 +220,69 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) return 1; } +static grub_err_t +read_node (grub_fshelp_node_t node, grub_off_t off, grub_size_t len, char *buf) +{ + grub_size_t i = 0; + + while (len > 0) + { + grub_size_t toread; + grub_err_t err; + while (i < node->have_dirents + && off >= grub_le_to_cpu32 (node->dirents[i].size)) + { + off -= grub_le_to_cpu32 (node->dirents[i].size); + i++; + } + if (i == node->have_dirents) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "read out of range"); + toread = grub_le_to_cpu32 (node->dirents[i].size); + if (toread > len) + toread = len; + err = grub_disk_read (node->data->disk, + ((grub_disk_addr_t) grub_le_to_cpu32 (node->dirents[i].first_sector)) << GRUB_ISO9660_LOG2_BLKSZ, + off, toread, buf); + if (err) + return err; + len -= toread; + off += toread; + buf += toread; + } + return GRUB_ERR_NONE; +} + /* Iterate over the susp entries, starting with block SUA_BLOCK on the offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for every entry. */ static grub_err_t -grub_iso9660_susp_iterate (struct grub_iso9660_data *data, - int sua_block, int sua_pos, int sua_size, +grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, + grub_size_t sua_size, grub_err_t (*hook) (struct grub_iso9660_susp_entry *entry)) { char *sua; struct grub_iso9660_susp_entry *entry; + grub_disk_addr_t ce_block; + int is_ce = 0; auto grub_err_t load_sua (void); /* Load a part of the System Usage Area. */ grub_err_t load_sua (void) { + grub_err_t err; sua = grub_malloc (sua_size); if (!sua) return grub_errno; - if (grub_disk_read (data->disk, sua_block, sua_pos, - sua_size, sua)) - return grub_errno; + if (is_ce) + err = grub_disk_read (node->data->disk, ce_block, off, + sua_size, sua); + else + err = read_node (node, off, sua_size, sua); + if (err) + return err; entry = (struct grub_iso9660_susp_entry *) sua; return 0; @@ -259,10 +304,11 @@ grub_iso9660_susp_iterate (struct grub_iso9660_data *data, { struct grub_iso9660_susp_ce *ce; + is_ce = 1; ce = (struct grub_iso9660_susp_ce *) entry; sua_size = grub_le_to_cpu32 (ce->len); - sua_pos = grub_le_to_cpu32 (ce->off); - sua_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ; + off = grub_le_to_cpu32 (ce->off); + ce_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ; grub_free (sua); if (load_sua ()) @@ -383,6 +429,9 @@ grub_iso9660_mount (grub_disk_t disk) + (rootdir.namelen % 2) - 1); sua_size = rootdir.len - sua_pos; + if (!sua_size) + return data; + sua = grub_malloc (sua_size); if (! sua) goto fail; @@ -400,6 +449,14 @@ grub_iso9660_mount (grub_disk_t disk) /* Test if the SUSP protocol is used on this filesystem. */ if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0) { + struct grub_fshelp_node rootnode; + + rootnode.data = data; + rootnode.alloc_dirents = 0; + rootnode.have_dirents = 1; + rootnode.dir_off = 0; + rootnode.dirents[0] = data->voldesc.rootdir; + /* The 2nd data byte stored how many bytes are skipped every time to get to the SUA (System Usage Area). */ data->susp_skip = entry->data[2]; @@ -407,9 +464,7 @@ grub_iso9660_mount (grub_disk_t disk) /* Iterate over the entries in the SUA area to detect extensions. */ - if (grub_iso9660_susp_iterate (data, - (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector) - << GRUB_ISO9660_LOG2_BLKSZ), + if (grub_iso9660_susp_iterate (&rootnode, sua_pos, sua_size, susp_iterate)) goto fail; } @@ -502,10 +557,10 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node) return 0; } - sua_off = (sizeof (node->dirent) + node->dirent.namelen + 1 - - (node->dirent.namelen % 2) + sua_off = (sizeof (node->dirents[0]) + node->dirents[0].namelen + 1 + - (node->dirents[0].namelen % 2) + node->data->susp_skip); - sua_size = node->dirent.len - sua_off; + sua_size = node->dirents[0].len - sua_off; symlink = grub_malloc (1); if (!symlink) @@ -513,8 +568,7 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node) *symlink = '\0'; - if (grub_iso9660_susp_iterate (node->data, node->dir_blk, - node->dir_off + sua_off, + if (grub_iso9660_susp_iterate (node, node->dir_off + sua_off, sua_size, susp_iterate_sl)) { grub_free (symlink); @@ -524,6 +578,16 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node) return symlink; } +static grub_off_t +get_node_size (grub_fshelp_node_t node) +{ + grub_off_t ret = 0; + grub_size_t i; + + for (i = 0; i < node->have_dirents; i++) + ret += grub_le_to_cpu32 (node->dirents[i].size); + return ret; +} static int grub_iso9660_iterate_dir (grub_fshelp_node_t dir, @@ -533,10 +597,11 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_node_t node)) { struct grub_iso9660_dir dirent; - unsigned int offset = 0; + grub_off_t offset = 0; char *filename; int filename_alloc = 0; enum grub_fshelp_filetype type; + grub_off_t len; auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *); @@ -598,13 +663,11 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, return 0; } - for (; offset < dir->size; offset += dirent.len) + len = get_node_size (dir); + + for (; offset < len; offset += dirent.len) { - if (grub_disk_read (dir->data->disk, - (dir->blk << GRUB_ISO9660_LOG2_BLKSZ) - + offset / GRUB_DISK_SECTOR_SIZE, - offset % GRUB_DISK_SECTOR_SIZE, - sizeof (dirent), (char *) &dirent)) + if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; /* The end of the block, skip to the next one. */ @@ -629,39 +692,30 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_UNKNOWN; if (dir->data->rockridge - && grub_iso9660_susp_iterate (dir->data, - (dir->blk << GRUB_ISO9660_LOG2_BLKSZ) - + (sua_off - / GRUB_DISK_SECTOR_SIZE), - sua_off % GRUB_DISK_SECTOR_SIZE, - sua_size, susp_iterate_dir)) + && grub_iso9660_susp_iterate (dir, sua_off, sua_size, + susp_iterate_dir)) return 0; /* Read the name. */ - if (grub_disk_read (dir->data->disk, - (dir->blk << GRUB_ISO9660_LOG2_BLKSZ) - + nameoffset / GRUB_DISK_SECTOR_SIZE, - nameoffset % GRUB_DISK_SECTOR_SIZE, - dirent.namelen, (char *) name)) + if (read_node (dir, nameoffset, dirent.namelen, (char *) name)) return 0; node = grub_malloc (sizeof (struct grub_fshelp_node)); if (!node) return 0; + node->alloc_dirents = ARRAY_SIZE (node->dirents); + node->have_dirents = 1; + /* Setup a new node. */ node->data = dir->data; - node->size = grub_le_to_cpu32 (dirent.size); - node->blk = grub_le_to_cpu32 (dirent.first_sector); - node->dir_blk = ((dir->blk << GRUB_ISO9660_LOG2_BLKSZ) - + offset / GRUB_DISK_SECTOR_SIZE); - node->dir_off = offset % GRUB_DISK_SECTOR_SIZE; + node->dir_off = offset; /* If the filetype was not stored using rockridge, use whatever is stored in the iso9660 filesystem. */ if (type == GRUB_FSHELP_UNKNOWN) { - if ((dirent.flags & 3) == 2) + if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR) type = GRUB_FSHELP_DIR; else type = GRUB_FSHELP_REG; @@ -678,7 +732,10 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, /* . and .. */ if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1)) - continue; + { + grub_free (node); + continue; + } else filename = name; } @@ -701,7 +758,35 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, filename_alloc = 1; } - node->dirent = dirent; + node->dirents[0] = dirent; + while (dirent.flags & FLAG_MORE_EXTENTS) + { + offset += dirent.len; + if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) + { + if (filename_alloc) + grub_free (filename); + grub_free (node); + return 0; + } + if (node->have_dirents >= node->alloc_dirents) + { + struct grub_fshelp_node *new_node; + node->alloc_dirents *= 2; + new_node = grub_malloc (sizeof (struct grub_fshelp_node) + + ((node->alloc_dirents + - ARRAY_SIZE (node->dirents)) + * sizeof (node->dirents[0]))); + if (!new_node) + { + if (filename_alloc) + grub_free (filename); + grub_free (node); + return 0; + } + } + node->dirents[node->have_dirents++] = dirent; + } if (hook (filename, type, node)) { if (filename_alloc) @@ -738,7 +823,7 @@ grub_iso9660_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = !!iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); + info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime); grub_free (node); return hook (filename, &info); @@ -751,8 +836,10 @@ grub_iso9660_dir (grub_device_t device, const char *path, goto fail; rootnode.data = data; - rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector); - rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size); + rootnode.alloc_dirents = 0; + rootnode.have_dirents = 1; + rootnode.dir_off = 0; + rootnode.dirents[0] = data->voldesc.rootdir; /* Use the fshelp function to traverse the path. */ if (grub_fshelp_find_file (path, &rootnode, @@ -792,8 +879,10 @@ grub_iso9660_open (struct grub_file *file, const char *name) goto fail; rootnode.data = data; - rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector); - rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size); + rootnode.alloc_dirents = 0; + rootnode.have_dirents = 1; + rootnode.dir_off = 0; + rootnode.dirents[0] = data->voldesc.rootdir; /* Use the fshelp function to traverse the path. */ if (grub_fshelp_find_file (name, &rootnode, @@ -803,10 +892,9 @@ grub_iso9660_open (struct grub_file *file, const char *name) GRUB_FSHELP_REG)) goto fail; - data->first_sector = foundnode->blk; - + data->node = foundnode; file->data = data; - file->size = foundnode->size; + file->size = get_node_size (foundnode); file->offset = 0; return 0; @@ -828,10 +916,7 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len) /* XXX: The file is stored in as a single extent. */ data->disk->read_hook = file->read_hook; - grub_disk_read (data->disk, - data->first_sector << GRUB_ISO9660_LOG2_BLKSZ, - file->offset, - len, buf); + read_node (data->node, file->offset, len, buf); data->disk->read_hook = NULL; if (grub_errno) @@ -844,7 +929,10 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_iso9660_close (grub_file_t file) { - grub_free (file->data); + struct grub_iso9660_data *data = + (struct grub_iso9660_data *) file->data; + grub_free (data->node); + grub_free (data); grub_dl_unref (my_mod); From db82136381f991edb8fe9bb28406a03ec1d19e2d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 18:20:39 +0200 Subject: [PATCH 433/673] * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): Use union to avoid breaking strict-aliasing rules. --- ChangeLog | 5 +++++ grub-core/loader/i386/bsd.c | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index a9b26a313..8c8af24e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-25 Vladimir Serbinenko + + * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): + Use union to avoid breaking strict-aliasing rules. + 2011-10-25 Vladimir Serbinenko Support multi-extent iso files. diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 18ebeb760..f2d0845f8 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -960,8 +960,10 @@ grub_netbsd_add_boot_disk_and_wedge (void) grub_partition_t part; grub_uint32_t biosdev; grub_uint32_t partmapsector; - struct grub_partition_bsd_disk_label *label; - grub_uint64_t buf[GRUB_DISK_SECTOR_SIZE / 8]; + union { + grub_uint64_t raw[GRUB_DISK_SECTOR_SIZE / 8]; + struct grub_partition_bsd_disk_label label; + } buf; grub_uint8_t *hash; grub_uint64_t ctx[(GRUB_MD_MD5->contextsize + 7) / 8]; @@ -981,7 +983,8 @@ grub_netbsd_add_boot_disk_and_wedge (void) partmapsector = grub_partition_get_start (part->parent) + part->offset; disk->partition = part->parent; - if (grub_disk_read (disk, part->offset, 0, GRUB_DISK_SECTOR_SIZE, buf) != GRUB_ERR_NONE) + if (grub_disk_read (disk, part->offset, 0, GRUB_DISK_SECTOR_SIZE, buf.raw) + != GRUB_ERR_NONE) goto fail; disk->partition = part; @@ -997,7 +1000,7 @@ grub_netbsd_add_boot_disk_and_wedge (void) biw.matchnblks = 1; GRUB_MD_MD5->init (&ctx); - GRUB_MD_MD5->write (&ctx, buf, GRUB_DISK_SECTOR_SIZE); + GRUB_MD_MD5->write (&ctx, buf.raw, GRUB_DISK_SECTOR_SIZE); GRUB_MD_MD5->final (&ctx); hash = GRUB_MD_MD5->read (&ctx); memcpy (biw.matchhash, hash, 16); @@ -1006,18 +1009,17 @@ grub_netbsd_add_boot_disk_and_wedge (void) } /* Fill bootdisk if this a NetBSD disk label. */ - label = (struct grub_partition_bsd_disk_label *) &buf; if (part->partmap != NULL && (grub_strcmp (part->partmap->name, "netbsd") == 0) && - label->magic == grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) + buf.label.magic == grub_cpu_to_le32 (GRUB_PC_PARTITION_BSD_LABEL_MAGIC)) { struct grub_netbsd_btinfo_bootdisk bid; grub_memset (&bid, 0, sizeof (bid)); bid.labelsector = partmapsector; - bid.label.type = label->type; - bid.label.checksum = label->checksum; - memcpy (bid.label.packname, label->packname, 16); + bid.label.type = buf.label.type; + bid.label.checksum = buf.label.checksum; + memcpy (bid.label.packname, buf.label.packname, 16); bid.biosdev = biosdev; bid.partition = part->number; grub_bsd_add_meta (NETBSD_BTINFO_BOOTDISK, &bid, sizeof (bid)); From 66b40850331be5979d85a3d0583c7bd74c704b08 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 21:52:48 +0200 Subject: [PATCH 434/673] Fix symlink handling on iso9660. * grub-core/fs/iso9660.c (grub_fshelp_node): Remove dir_off. Add symlink All users updated. (grub_iso9660_susp_iterate): Accept zero-size iterate. (grub_iso9660_read_symlink): Moved most of code ... (grub_iso9660_iterate_dir): ... here. Fill node->symlink. --- ChangeLog | 10 +++ grub-core/fs/iso9660.c | 182 ++++++++++++++++++----------------------- 2 files changed, 90 insertions(+), 102 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8c8af24e4..d40675db7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-10-25 Vladimir Serbinenko + + Fix symlink handling on iso9660. + + * grub-core/fs/iso9660.c (grub_fshelp_node): Remove dir_off. Add symlink + All users updated. + (grub_iso9660_susp_iterate): Accept zero-size iterate. + (grub_iso9660_read_symlink): Moved most of code ... + (grub_iso9660_iterate_dir): ... here. Fill node->symlink. + 2011-10-25 Vladimir Serbinenko * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index f6cbbca95..f3e828b89 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -159,7 +159,7 @@ struct grub_fshelp_node { struct grub_iso9660_data *data; grub_size_t have_dirents, alloc_dirents; - grub_off_t dir_off; + char *symlink; struct grub_iso9660_dir dirents[8]; }; @@ -257,7 +257,7 @@ read_node (grub_fshelp_node_t node, grub_off_t off, grub_size_t len, char *buf) every entry. */ static grub_err_t grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, - grub_size_t sua_size, + grub_ssize_t sua_size, grub_err_t (*hook) (struct grub_iso9660_susp_entry *entry)) { @@ -288,6 +288,9 @@ grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, return 0; } + if (sua_size <= 0) + return GRUB_ERR_NONE; + if (load_sua ()) return grub_errno; @@ -454,7 +457,7 @@ grub_iso9660_mount (grub_disk_t disk) rootnode.data = data; rootnode.alloc_dirents = 0; rootnode.have_dirents = 1; - rootnode.dir_off = 0; + rootnode.symlink = 0; rootnode.dirents[0] = data->voldesc.rootdir; /* The 2nd data byte stored how many bytes are skipped every time @@ -480,102 +483,7 @@ grub_iso9660_mount (grub_disk_t disk) static char * grub_iso9660_read_symlink (grub_fshelp_node_t node) { - int sua_off; - int sua_size; - char *symlink = 0; - int addslash = 0; - - auto void add_part (const char *part, int len); - auto grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *); - - /* Extend the symlink. */ - void add_part (const char *part, int len) - { - int size = grub_strlen (symlink); - - symlink = grub_realloc (symlink, size + len + 1); - if (! symlink) - return; - - grub_strncat (symlink, part, len); - } - - /* Read in a symlink. */ - grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *entry) - { - if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) - { - unsigned int pos = 1; - - /* The symlink is not stored as a POSIX symlink, translate it. */ - while (pos < grub_le_to_cpu32 (entry->len)) - { - if (addslash) - { - add_part ("/", 1); - addslash = 0; - } - - /* The current position is the `Component Flag'. */ - switch (entry->data[pos] & 30) - { - case 0: - { - /* The data on pos + 2 is the actual data, pos + 1 - is the length. Both are part of the `Component - Record'. */ - add_part ((char *) &entry->data[pos + 2], - entry->data[pos + 1]); - if ((entry->data[pos] & 1)) - addslash = 1; - - break; - } - - case 2: - add_part ("./", 2); - break; - - case 4: - add_part ("../", 3); - break; - - case 8: - add_part ("/", 1); - break; - } - /* In pos + 1 the length of the `Component Record' is - stored. */ - pos += entry->data[pos + 1] + 2; - } - - /* Check if `grub_realloc' failed. */ - if (grub_errno) - return grub_errno; - } - - return 0; - } - - sua_off = (sizeof (node->dirents[0]) + node->dirents[0].namelen + 1 - - (node->dirents[0].namelen % 2) - + node->data->susp_skip); - sua_size = node->dirents[0].len - sua_off; - - symlink = grub_malloc (1); - if (!symlink) - return 0; - - *symlink = '\0'; - - if (grub_iso9660_susp_iterate (node, node->dir_off + sua_off, - sua_size, susp_iterate_sl)) - { - grub_free (symlink); - return 0; - } - - return symlink; + return node->symlink ? grub_strdup (node->symlink) : grub_strdup (""); } static grub_off_t @@ -602,6 +510,23 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, int filename_alloc = 0; enum grub_fshelp_filetype type; grub_off_t len; + char *symlink = 0; + int addslash = 0; + + auto void add_part (const char *part, int len); + + /* Extend the symlink. */ + void add_part (const char *part, int len2) + { + int size = symlink ? grub_strlen (symlink) : 0; + + symlink = grub_realloc (symlink, size + len2 + 1); + if (! symlink) + return; + + symlink[size] = 0; + grub_strncat (symlink, part, len2); + } auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *); @@ -659,6 +584,56 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_UNKNOWN; } } + else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) + { + unsigned int pos = 1; + + /* The symlink is not stored as a POSIX symlink, translate it. */ + while (pos + sizeof (*entry) < grub_le_to_cpu32 (entry->len)) + { + if (addslash) + { + add_part ("/", 1); + addslash = 0; + } + + /* The current position is the `Component Flag'. */ + switch (entry->data[pos] & 30) + { + case 0: + { + /* The data on pos + 2 is the actual data, pos + 1 + is the length. Both are part of the `Component + Record'. */ + add_part ((char *) &entry->data[pos + 2], + entry->data[pos + 1]); + if ((entry->data[pos] & 1)) + addslash = 1; + + break; + } + + case 2: + add_part ("./", 2); + break; + + case 4: + add_part ("../", 3); + break; + + case 8: + add_part ("/", 1); + break; + } + /* In pos + 1 the length of the `Component Record' is + stored. */ + pos += entry->data[pos + 1] + 2; + } + + /* Check if `grub_realloc' failed. */ + if (grub_errno) + return grub_errno; + } return 0; } @@ -667,6 +642,9 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, for (; offset < len; offset += dirent.len) { + symlink = 0; + addslash = 0; + if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; @@ -709,7 +687,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, /* Setup a new node. */ node->data = dir->data; - node->dir_off = offset; + node->symlink = symlink; /* If the filetype was not stored using rockridge, use whatever is stored in the iso9660 filesystem. */ @@ -838,7 +816,7 @@ grub_iso9660_dir (grub_device_t device, const char *path, rootnode.data = data; rootnode.alloc_dirents = 0; rootnode.have_dirents = 1; - rootnode.dir_off = 0; + rootnode.symlink = 0; rootnode.dirents[0] = data->voldesc.rootdir; /* Use the fshelp function to traverse the path. */ @@ -881,7 +859,7 @@ grub_iso9660_open (struct grub_file *file, const char *name) rootnode.data = data; rootnode.alloc_dirents = 0; rootnode.have_dirents = 1; - rootnode.dir_off = 0; + rootnode.symlink = 0; rootnode.dirents[0] = data->voldesc.rootdir; /* Use the fshelp function to traverse the path. */ From 19832ddb37a6e4a034a2501954fd01a8ff935c73 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 25 Oct 2011 21:53:57 +0200 Subject: [PATCH 435/673] * grub-core/fs/fat.c (grub_fat_uuid): Make uppercase to match Linux. --- ChangeLog | 4 ++++ grub-core/fs/fat.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index d40675db7..9f05edaa2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-25 Vladimir Serbinenko + + * grub-core/fs/fat.c (grub_fat_uuid): Make uppercase to match Linux. + 2011-10-25 Vladimir Serbinenko Fix symlink handling on iso9660. diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 36a43fca0..fb1113814 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -1117,9 +1117,12 @@ grub_fat_uuid (grub_device_t device, char **uuid) data = grub_fat_mount (disk); if (data) { + char *ptr; *uuid = grub_xasprintf ("%04x-%04x", (grub_uint16_t) (data->uuid >> 16), (grub_uint16_t) data->uuid); + for (ptr = *uuid; ptr && *ptr; ptr++) + *ptr = grub_toupper (*ptr); } else *uuid = NULL; From e9cc6b7b0e26f38b22a72ecc931273b22a9e1d2a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 26 Oct 2011 00:29:46 +0200 Subject: [PATCH 436/673] * grub-core/fs/ntfs.c (grub_ntfs_uuid): Fix a memory leak. --- ChangeLog | 4 ++++ grub-core/fs/ntfs.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f05edaa2..3b0b4697a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-25 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (grub_ntfs_uuid): Fix a memory leak. + 2011-10-25 Vladimir Serbinenko * grub-core/fs/fat.c (grub_fat_uuid): Make uppercase to match Linux. diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 5d128bcc0..6b8455c34 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -1087,14 +1087,15 @@ grub_ntfs_uuid (grub_device_t device, char **uuid) if (*uuid) for (ptr = *uuid; *ptr; ptr++) *ptr = grub_toupper (*ptr); + free_file (&data->mmft); + free_file (&data->cmft); + grub_free (data); } else *uuid = NULL; grub_dl_unref (my_mod); - grub_free (data); - return grub_errno; } From 67e2bd718e9ddd0571a28358e8928dc320e2d76e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 26 Oct 2011 00:32:17 +0200 Subject: [PATCH 437/673] Read label on HFS+. * grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey_id): New function. (grub_hfsplus_btree_search): Fix types. (grub_hfsplus_label): Implement. --- ChangeLog | 8 ++++ grub-core/fs/hfsplus.c | 87 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3b0b4697a..17e215b62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-10-25 Vladimir Serbinenko + + Read label on HFS+. + + * grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey_id): New function. + (grub_hfsplus_btree_search): Fix types. + (grub_hfsplus_label): Implement. + 2011-10-25 Vladimir Serbinenko * grub-core/fs/ntfs.c (grub_ntfs_uuid): Fix a memory leak. diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 245cd93a5..3d9bc42fa 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -553,6 +553,25 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya, return diff; } +/* Compare the on disk catalog key KEYA with the catalog key we are + looking for (KEYB). */ +static int +grub_hfsplus_cmp_catkey_id (struct grub_hfsplus_key *keya, + struct grub_hfsplus_key_internal *keyb) +{ + struct grub_hfsplus_catkey *catkey_a = &keya->catkey; + struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey; + + /* Safe unsigned comparison */ + grub_uint32_t aparent = grub_be_to_cpu32 (catkey_a->parent); + if (aparent > catkey_b->parent) + return 1; + if (aparent < catkey_b->parent) + return -1; + + return 0; +} + /* Compare the on disk extent overflow key KEYA with the extent overflow key we are looking for (KEYB). */ static int @@ -662,7 +681,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, /* Read a node. */ if (grub_hfsplus_read_file (&btree->file, 0, - (long)currnode * (long)btree->nodesize, + (grub_disk_addr_t) currnode + * (grub_disk_addr_t) btree->nodesize, btree->nodesize, (char *) node) <= 0) { grub_free (node); @@ -961,13 +981,66 @@ grub_hfsplus_dir (grub_device_t device, const char *path, static grub_err_t -grub_hfsplus_label (grub_device_t device __attribute__((unused)) - , char **label __attribute__((unused))) +grub_hfsplus_label (grub_device_t device, char **label) { - /* XXX: It's not documented how to read a label. */ - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "reading the label of a HFS+ " - "partition is not implemented"); + struct grub_hfsplus_data *data; + grub_disk_t disk = device->disk; + struct grub_hfsplus_catkey *catkey; + int i, label_len; + struct grub_hfsplus_key_internal intern; + struct grub_hfsplus_btnode *node; + grub_disk_addr_t ptr; + + *label = 0; + + data = grub_hfsplus_mount (disk); + if (!data) + return grub_errno; + + /* Create a key that points to the label. */ + intern.catkey.parent = 1; + intern.catkey.name = ""; + + /* First lookup the first entry. */ + if (grub_hfsplus_btree_search (&data->catalog_tree, &intern, + grub_hfsplus_cmp_catkey_id, &node, &ptr)) + { + grub_free (data); + return 0; + } + + catkey = (struct grub_hfsplus_catkey *) + grub_hfsplus_btree_recptr (&data->catalog_tree, node, 0); + + label_len = grub_be_to_cpu16 (catkey->namelen); + for (i = 0; i < label_len; i++) + { + catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); + + /* If the name is obviously invalid, skip this node. */ + if (catkey->name[i] == 0) + return 0; + } + + *label = grub_malloc (label_len + 1); + if (! *label) + return grub_errno; + + if (! grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, + label_len)) + { + grub_free (node); + grub_free (*label); + grub_free (data); + *label = 0; + return grub_errno; + } + (*label)[label_len] = '\0'; + + grub_free (node); + grub_free (data); + + return GRUB_ERR_NONE; } /* Get mtime. */ From c0584900ee804a1b8d1a687cfd042321f05f2150 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 26 Oct 2011 00:35:41 +0200 Subject: [PATCH 438/673] * grub-core/fs/jfs.c (grub_jfs_sblock): Fix offset to volname. --- ChangeLog | 4 ++++ grub-core/fs/jfs.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 17e215b62..683fd53f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-25 Vladimir Serbinenko + + * grub-core/fs/jfs.c (grub_jfs_sblock): Fix offset to volname. + 2011-10-25 Vladimir Serbinenko Read label on HFS+. diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 4a7bb0214..c5e82bfec 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -52,9 +52,9 @@ struct grub_jfs_sblock grub_uint32_t blksz; grub_uint16_t log2_blksz; - grub_uint8_t unused[71]; + grub_uint8_t unused[79]; grub_uint8_t volname[11]; - grub_uint8_t unused2[32]; + grub_uint8_t unused2[24]; grub_uint8_t uuid[16]; }; From 5587329c914465659893d484363d919c1fe35c71 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 26 Oct 2011 17:32:21 +0200 Subject: [PATCH 439/673] ZFS fixes. * grub-core/fs/zfs/zfs.c (fzap_iterate): Fix handling of indexes sharing the same block. Iterate over correct number of indices. (dnode_get_path): Handle symlinks correctly. --- ChangeLog | 8 ++++++ grub-core/fs/zfs/zfs.c | 64 +++++++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 683fd53f3..9787d8f9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-10-25 Vladimir Serbinenko + + ZFS fixes. + + * grub-core/fs/zfs/zfs.c (fzap_iterate): Fix handling of indexes + sharing the same block. Iterate over correct number of indices. + (dnode_get_path): Handle symlinks correctly. + 2011-10-25 Vladimir Serbinenko * grub-core/fs/jfs.c (grub_jfs_sblock): Fix offset to volname. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 9d6ad7055..6721cddc1 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -941,7 +941,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, { zap_leaf_phys_t *l; void *l_in; - grub_uint64_t idx, blkid; + grub_uint64_t idx, idx2, blkid; grub_uint16_t chunk; int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << DNODE_SHIFT); @@ -964,10 +964,16 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, grub_error (GRUB_ERR_BAD_FS, "ZAP leaf is too small"); return 0; } - for (idx = 0; idx < zap->zap_ptrtbl.zt_numblks; idx++) + for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++) { blkid = ((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))]; + for (idx2 = 0; idx2 < idx; idx2++) + if (blkid == ((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))]) + break; + if (idx2 != idx) + continue; + err = dmu_read (zap_dnode, blkid, &l_in, &endian, data); l = l_in; if (err) @@ -1093,7 +1099,7 @@ zap_iterate (dnode_end_t * zap_dnode, return 0; block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian); - grub_dprintf ("zfs", "zap read\n"); + grub_dprintf ("zfs", "zap iterate\n"); if (block_type == ZBT_MICRO) { @@ -1310,22 +1316,55 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, break; *path = ch; -#if 0 - if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa && ch) + if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) { + char *sym_value; + grub_size_t avail_in_dnode; + grub_size_t sym_sz; + int free_symval = 0; char *oldpath = path, *oldpathbuf = path_buf; - path = path_buf - = grub_malloc (sizeof (dnode_path->dn.dn.dn_bonus) - - sizeof (znode_phys_t) + grub_strlen (oldpath) + 1); + sym_value = ((char *) DN_BONUS (&dnode_path->dn.dn) + sizeof (struct znode_phys)); + avail_in_dnode = (char *) (&dnode_path->dn + 1) - sym_value; + + sym_sz = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_size, dnode_path->dn.endian); + + if (sym_sz > avail_in_dnode - 8) + { + grub_size_t block; + grub_size_t blksz; + blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, + dnode_path->dn.endian) + << SPA_MINBLOCKSHIFT); + + sym_value = grub_malloc (sym_sz); + if (!sym_value) + return grub_errno; + for (block = 0; block < (sym_sz + blksz - 1) / blksz; block++) + { + void *t; + grub_size_t movesize; + + err = dmu_read (&(dnode_path->dn), block, &t, 0, data); + if (err) + return err; + + movesize = MIN (sym_sz - block * blksz, blksz); + + grub_memcpy (sym_value + block * blksz, t, movesize); + grub_free (t); + } + free_symval = 1; + } + path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); if (!path_buf) { grub_free (oldpathbuf); return grub_errno; } - grub_memcpy (path, - (char *) DN_BONUS(&dnode_path->dn.dn) + sizeof (znode_phys_t), - sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t)); - path [sizeof (dnode_path->dn.dn.dn_bonus) - sizeof (znode_phys_t)] = 0; + grub_memcpy (path, sym_value, sym_sz); + if (free_symval) + grub_free (sym_value); + path [sym_sz] = 0; grub_memcpy (path + grub_strlen (path), oldpath, grub_strlen (oldpath) + 1); @@ -1343,7 +1382,6 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, grub_free (dn_new); } } -#endif } if (!err) From a562fbb48b6934f6dcde9030538a0809016a5acb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 26 Oct 2011 19:11:10 +0200 Subject: [PATCH 440/673] Bump spa version --- include/grub/zfs/zfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index e1759dbbd..374068d06 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -28,7 +28,7 @@ /* * On-disk version number. */ -#define SPA_VERSION 28ULL +#define SPA_VERSION 31ULL /* * The following are configuration names used in the nvlist describing a pool's From 186b402804c37ff3fda5b2a969d071a978194195 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 26 Oct 2011 19:27:36 +0200 Subject: [PATCH 441/673] * include/grub/datetime.h (grub_datetime2unixtime): Fix off-by-one error. --- ChangeLog | 7 ++++++- include/grub/datetime.h | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9787d8f9e..084131202 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ -2011-10-25 Vladimir Serbinenko +2011-10-26 Vladimir Serbinenko + + * include/grub/datetime.h (grub_datetime2unixtime): Fix off-by-one + error. + +2011-10-26 Vladimir Serbinenko ZFS fixes. diff --git a/include/grub/datetime.h b/include/grub/datetime.h index dea0f8ea9..049dbc227 100644 --- a/include/grub/datetime.h +++ b/include/grub/datetime.h @@ -86,13 +86,13 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) are bissextile*/ /* Convenience: let's have 3 consecutive non-bissextile years at the beginning of the epoch. So count from 1971 instead of 1970 */ - ret = SECPERYEAR + SECPERDAY; + ret = 2 * SECPERYEAR + SECPERDAY; /* Transform C divisions and modulos to mathematical ones */ - y4 = (datetime->year - 1971) / 4; - if (datetime->year < 1971) + y4 = (datetime->year - 1972) / 4; + if (datetime->year < 1972) y4--; - ay = datetime->year - 1971 - 4 * y4; + ay = datetime->year - 1972 - 4 * y4; ret += y4 * SECPER4YEARS; ret += ay * SECPERYEAR; From 34c59654519cc13b25b39b8add54e757526e5bed Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 02:04:04 +0200 Subject: [PATCH 442/673] Support version 33 including symlinks --- grub-core/fs/zfs/zfs.c | 149 ++++++++++++++++++++++++++++++++++--- include/grub/zfs/sa_impl.h | 3 + include/grub/zfs/zfs.h | 2 +- 3 files changed, 141 insertions(+), 13 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index e248a1114..454fc4a4a 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1839,19 +1839,18 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, break; *path = ch; - if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + if (dnode_path->dn.dn.dn_bonustype == DMU_OT_ZNODE + && ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) { char *sym_value; - grub_size_t avail_in_dnode; grub_size_t sym_sz; int free_symval = 0; char *oldpath = path, *oldpathbuf = path_buf; sym_value = ((char *) DN_BONUS (&dnode_path->dn.dn) + sizeof (struct znode_phys)); - avail_in_dnode = (char *) (&dnode_path->dn + 1) - sym_value; sym_sz = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_size, dnode_path->dn.endian); - if (sym_sz > avail_in_dnode - 8) + if (dnode_path->dn.dn.dn_flags & 1) { grub_size_t block; grub_size_t blksz; @@ -1905,6 +1904,62 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, grub_free (dn_new); } } + if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA) + { + void *sahdrp; + int hdrsize; + + if (dnode_path->dn.dn.dn_bonuslen != 0) + { + sahdrp = DN_BONUS (&dnode_path->dn.dn); + } + else if (dnode_path->dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + blkptr_t *bp = &dnode_path->dn.dn.dn_spill; + + err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data); + if (err) + return err; + } + else + { + return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); + } + + hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); + + if (((grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_TYPE_OFFSET), dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + { + char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET; + grub_size_t sym_sz = + grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dnode_path->dn.endian); + char *oldpath = path, *oldpathbuf = path_buf; + path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); + if (!path_buf) + { + grub_free (oldpathbuf); + return grub_errno; + } + grub_memcpy (path, sym_value, sym_sz); + path [sym_sz] = 0; + grub_memcpy (path + grub_strlen (path), oldpath, + grub_strlen (oldpath) + 1); + + grub_free (oldpathbuf); + if (path[0] != '/') + { + dn_new = dnode_path; + dnode_path = dn_new->next; + grub_free (dn_new); + } + else while (dnode_path != root) + { + dn_new = dnode_path; + dnode_path = dn_new->next; + grub_free (dn_new); + } + } + } } if (!err) @@ -2666,12 +2721,14 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) } hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - file->size = *(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET); + file->size = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian); } - else + else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE) { file->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, data->dnode.endian); } + else + return grub_error (GRUB_ERR_BAD_FS, "bad bonus type"); file->data = data; file->offset = 0; @@ -2830,8 +2887,39 @@ fill_fs_info (struct grub_dirhook_info *info, return; } - info->mtimeset = 1; - info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); + if (dn.dn.dn_bonustype == DMU_OT_SA) + { + void *sahdrp; + int hdrsize; + + if (dn.dn.dn_bonuslen != 0) + { + sahdrp = (sa_hdr_phys_t *) DN_BONUS (&dn.dn); + } + else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + blkptr_t *bp = &dn.dn.dn_spill; + + err = zio_read (bp, dn.endian, &sahdrp, NULL, data); + if (err) + return; + } + else + { + grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); + return; + } + + hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); + info->mtimeset = 1; + info->mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + } + + if (dn.dn.dn_bonustype == DMU_OT_ZNODE) + { + info->mtimeset = 1; + info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); + } return; } @@ -2855,10 +2943,47 @@ grub_zfs_dir (grub_device_t device, const char *path, grub_memset (&info, 0, sizeof (info)); dnode_get (&(data->mdn), val, 0, &dn, data); - info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); - info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); - grub_dprintf ("zfs", "type=%d, name=%s\n", + + if (dn.dn.dn_bonustype == DMU_OT_SA) + { + void *sahdrp; + int hdrsize; + + if (dn.dn.dn_bonuslen != 0) + { + sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn); + } + else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + blkptr_t *bp = &dn.dn.dn_spill; + + err = zio_read (bp, dn.endian, &sahdrp, NULL, data); + if (err) + { + grub_print_error (); + return 0; + } + } + else + { + grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); + grub_print_error (); + return 0; + } + + hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + } + + if (dn.dn.dn_bonustype == DMU_OT_ZNODE) + { + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], + dn.endian); + } + info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); + grub_dprintf ("zfs", "type=%d, name=%s\n", (int)dn.dn.dn_type, (char *)name); return hook (name, &info); } diff --git a/include/grub/zfs/sa_impl.h b/include/grub/zfs/sa_impl.h index a2b728d37..0845d1290 100644 --- a/include/grub/zfs/sa_impl.h +++ b/include/grub/zfs/sa_impl.h @@ -29,6 +29,9 @@ typedef struct sa_hdr_phys { } sa_hdr_phys_t; #define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0) +#define SA_TYPE_OFFSET 0x0 #define SA_SIZE_OFFSET 0x8 +#define SA_MTIME_OFFSET 0x38 +#define SA_SYMLINK_OFFSET 0xa0 #endif /* _SYS_SA_IMPL_H */ diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index 374068d06..d7029903a 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -28,7 +28,7 @@ /* * On-disk version number. */ -#define SPA_VERSION 31ULL +#define SPA_VERSION 33ULL /* * The following are configuration names used in the nvlist describing a pool's From 8563e2a6707a0a8bed9b36734799a7a3a62e5103 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 02:36:10 +0200 Subject: [PATCH 443/673] Small multidevice fix --- grub-core/fs/zfs/zfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 454fc4a4a..b4deba5c0 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -495,9 +495,9 @@ fill_vdev_info_real (struct grub_zfs_data *data, fill->vdev_phys_sector = insert->vdev_phys_sector; fill->current_uberblock = insert->current_uberblock; fill->original = insert->original; + if (!data->device_original) + data->device_original = fill; } - if (!data->device_original) - data->device_original = fill; return GRUB_ERR_NONE; } From 52a050751b79c3480f8019a789e255df2b546e70 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 02:52:54 +0200 Subject: [PATCH 444/673] * grub-core/fs/nilfs2.c (grub_nilfs2_uuid): Add missing field length. --- ChangeLog | 4 ++++ grub-core/fs/nilfs2.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1abd5daa2..7d2bdd80d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-26 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (grub_nilfs2_uuid): Add missing field length. + 2011-10-26 Vladimir Serbinenko ZFS multi-device and version 33 support. diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 62cf167c7..5986002ef 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -1117,7 +1117,7 @@ grub_nilfs2_uuid (grub_device_t device, char **uuid) { *uuid = grub_xasprintf - ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%0x-%02x%02x%02x%02x%02x%02x", + ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", data->sblock.s_uuid[0], data->sblock.s_uuid[1], data->sblock.s_uuid[2], data->sblock.s_uuid[3], data->sblock.s_uuid[4], data->sblock.s_uuid[5], From 8e32442e804edaf471ffc4156541e089ce2d5374 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 02:55:07 +0200 Subject: [PATCH 445/673] * grub-core/commands/xnu_uuid.c (grub_cmd_xnu_uuid): Support -l argument. Add newline at the end if printing. (GRUB_MOD_INIT): Document -l. --- ChangeLog | 6 ++++++ grub-core/commands/xnu_uuid.c | 20 +++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7d2bdd80d..d2ed9f2ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-10-26 Vladimir Serbinenko + + * grub-core/commands/xnu_uuid.c (grub_cmd_xnu_uuid): Support + -l argument. Add newline at the end if printing. + (GRUB_MOD_INIT): Document -l. + 2011-10-26 Vladimir Serbinenko * grub-core/fs/nilfs2.c (grub_nilfs2_uuid): Add missing field length. diff --git a/grub-core/commands/xnu_uuid.c b/grub-core/commands/xnu_uuid.c index f618b4ec0..3d152a6d6 100644 --- a/grub-core/commands/xnu_uuid.c +++ b/grub-core/commands/xnu_uuid.c @@ -51,10 +51,18 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; char *ptr; grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + int low = 0; if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required"); + if (argc > 1 && grub_strcmp (args[0], "-l") == 0) + { + low = 1; + argc--; + args++; + } + serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16)); GRUB_MD_MD5->init (&ctx); @@ -75,10 +83,11 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), (unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11], (unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13], (unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]); - for (ptr = uuid_string; *ptr; ptr++) - *ptr = grub_toupper (*ptr); + if (!low) + for (ptr = uuid_string; *ptr; ptr++) + *ptr = grub_toupper (*ptr); if (argc == 1) - grub_printf ("%s", uuid_string); + grub_printf ("%s\n", uuid_string); if (argc > 1) grub_env_set (args[1], uuid_string); @@ -91,9 +100,10 @@ static grub_command_t cmd; GRUB_MOD_INIT (xnu_uuid) { cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid, - N_("GRUBUUID [VARNAME]"), + N_("[-l] GRUBUUID [VARNAME]"), N_("Transform 64-bit UUID to format " - "suitable for XNU.")); + "suitable for XNU. If -l is given keep " + "it lowercase as done by blkid.")); } GRUB_MOD_FINI (xnu_uuid) From 3be82e10a9fb1a1d7a7486827f362cb9036f489c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 02:58:32 +0200 Subject: [PATCH 446/673] fstest xnu_uuid subcommand. * grub-core/commands/xnu_uuid.c (libgrubkrn): Add grub-core/commands/xnu_uuid.c. * util/grub-fstest.c (CMD_XNU_UUID): New enum value. (fstest): Handle xnu_uuid. (options): Document xnu_uuid. (argp_parser): Parse xnu_uuid. --- ChangeLog | 11 +++++++++++ Makefile.util.def | 1 + util/grub-fstest.c | 30 +++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d2ed9f2ef..9068bd856 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-10-26 Vladimir Serbinenko + + fstest xnu_uuid subcommand. + + * grub-core/commands/xnu_uuid.c (libgrubkrn): Add + grub-core/commands/xnu_uuid.c. + * util/grub-fstest.c (CMD_XNU_UUID): New enum value. + (fstest): Handle xnu_uuid. + (options): Document xnu_uuid. + (argp_parser): Parse xnu_uuid. + 2011-10-26 Vladimir Serbinenko * grub-core/commands/xnu_uuid.c (grub_cmd_xnu_uuid): Support diff --git a/Makefile.util.def b/Makefile.util.def index e1040c24f..1b66ab961 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -43,6 +43,7 @@ library = { common_nodist = grub_script.tab.h; common = grub-core/commands/blocklist.c; + common = grub-core/commands/xnu_uuid.c; common = grub-core/commands/testload.c; common = grub-core/commands/ls.c; common = grub-core/disk/dmraid_nvidia.c; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index b6ed2ef0c..60889d05e 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -63,7 +63,8 @@ enum { CMD_CRC, CMD_BLOCKLIST, CMD_TESTLOAD, - CMD_ZFSINFO + CMD_ZFSINFO, + CMD_XNU_UUID }; #define BUF_SIZE 32256 @@ -378,6 +379,27 @@ fstest (int n, char **args) case CMD_TESTLOAD: execute_command ("testload", n, args); grub_printf ("\n"); + case CMD_XNU_UUID: + { + grub_device_t dev; + grub_fs_t fs; + char *uuid = 0; + char *argv[3] = { "-l", NULL, NULL}; + dev = grub_device_open (n ? args[0] : 0); + if (!dev) + grub_util_error (grub_errmsg); + fs = grub_fs_probe (dev); + if (!fs) + grub_util_error (grub_errmsg); + if (!fs->uuid) + grub_util_error ("couldn't retrieve UUID"); + if (fs->uuid (dev, &uuid)) + grub_util_error (grub_errmsg); + if (!uuid) + grub_util_error ("couldn't retrieve UUID"); + argv[1] = uuid; + execute_command ("xnu_uuid", 2, argv); + } } for (i = 0; i < num_disks; i++) @@ -406,6 +428,7 @@ static struct argp_option options[] = { {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Hex dump FILE."), 1}, {N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1}, {N_("blocklist FILE"), 0, 0, OPTION_DOC, N_("Display blocklist of FILE."), 1}, + {N_("xnu_uuid"), 0, 0, OPTION_DOC, N_("Compute XNU UUID of the device."), 1}, {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, {"skip", 's', "N", 0, N_("Skip N bytes from output file."), 2}, @@ -558,6 +581,11 @@ argp_parser (int key, char *arg, struct argp_state *state) cmd = CMD_TESTLOAD; nparm = 1; } + else if (grub_strcmp (arg, "xnu_uuid") == 0) + { + cmd = CMD_XNU_UUID; + nparm = 0; + } else { fprintf (stderr, _("Invalid command %s.\n"), arg); From 91c3fdde0deb12db912ca9a3e0436babae634f1e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 02:59:45 +0200 Subject: [PATCH 447/673] * include/grub/ntfs.h: Add GRUB_NTFS_ prefix. All users updated. --- ChangeLog | 4 ++ grub-core/fs/ntfs.c | 124 ++++++++++++++++++-------------- grub-core/fs/ntfscomp.c | 53 +++++++------- include/grub/ntfs.h | 156 +++++++++++++++++++++------------------- 4 files changed, 181 insertions(+), 156 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9068bd856..f8b6a78dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-26 Vladimir Serbinenko + + * include/grub/ntfs.h: Add GRUB_NTFS_ prefix. All users updated. + 2011-10-26 Vladimir Serbinenko fstest xnu_uuid subcommand. diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 6b8455c34..bff760e71 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#define grub_fshelp_node grub_ntfs_file + #include #include #include @@ -30,7 +32,19 @@ GRUB_MOD_LICENSE ("GPLv3+"); static grub_dl_t my_mod; -ntfscomp_func_t grub_ntfscomp_func; +#define grub_fshelp_node grub_ntfs_file + +#define valueat(buf,ofs,type) *((type*)(((char*)buf)+ofs)) + +#define u16at(buf,ofs) grub_le_to_cpu16(valueat(buf,ofs,grub_uint16_t)) +#define u32at(buf,ofs) grub_le_to_cpu32(valueat(buf,ofs,grub_uint32_t)) +#define u64at(buf,ofs) grub_le_to_cpu64(valueat(buf,ofs,grub_uint64_t)) + +#define v16at(buf,ofs) valueat(buf,ofs,grub_uint16_t) +#define v32at(buf,ofs) valueat(buf,ofs,grub_uint32_t) +#define v64at(buf,ofs) valueat(buf,ofs,grub_uint64_t) + +grub_ntfscomp_func_t grub_ntfscomp_func; static grub_err_t fixup (struct grub_ntfs_data *data, char *buf, int len, char *magic) @@ -87,7 +101,7 @@ static void init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft) { at->mft = mft; - at->flags = (mft == &mft->data->mmft) ? AF_MMFT : 0; + at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0; at->attr_nxt = mft->buf + u16at (mft->buf, 0x14); at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL; } @@ -103,7 +117,7 @@ free_attr (struct grub_ntfs_attr *at) static char * find_attr (struct grub_ntfs_attr *at, unsigned char attr) { - if (at->flags & AF_ALST) + if (at->flags & GRUB_NTFS_AF_ALST) { retry: while (at->attr_nxt < at->attr_end) @@ -114,7 +128,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) { char *new_pos; - if (at->flags & AF_MMFT) + if (at->flags & GRUB_NTFS_AF_MMFT) { if ((grub_disk_read (at->mft->data->disk, v32at (at->attr_cur, 0x10), 0, @@ -160,7 +174,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) while ((unsigned char) *at->attr_cur != 0xFF) { at->attr_nxt += u16at (at->attr_cur, 4); - if ((unsigned char) *at->attr_cur == AT_ATTRIBUTE_LIST) + if ((unsigned char) *at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) at->attr_end = at->attr_cur; if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) return at->attr_cur; @@ -170,7 +184,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) { char *pa; - at->emft_buf = grub_malloc (at->mft->data->mft_size << BLK_SHR); + at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); if (at->emft_buf == NULL) return NULL; @@ -199,7 +213,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) at->attr_nxt = at->attr_end + u16at (pa, 0x14); at->attr_end = at->attr_end + u32at (pa, 4); } - at->flags |= AF_ALST; + at->flags |= GRUB_NTFS_AF_ALST; while (at->attr_nxt < at->attr_end) { if (((unsigned char) *at->attr_nxt == attr) || (attr == 0)) @@ -209,9 +223,9 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) if (at->attr_nxt >= at->attr_end) return NULL; - if ((at->flags & AF_MMFT) && (attr == AT_DATA)) + if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA)) { - at->flags |= AF_GPOS; + at->flags |= GRUB_NTFS_AF_GPOS; at->attr_cur = at->attr_nxt; pa = at->attr_cur; v32at (pa, 0x10) = at->mft->data->mft_start; @@ -223,13 +237,13 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) break; if (read_attr (at, pa + 0x10, - u32at (pa, 0x10) * (at->mft->data->mft_size << BLK_SHR), - at->mft->data->mft_size << BLK_SHR, 0, 0)) + u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR), + at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0)) return NULL; pa += u16at (pa, 4); } at->attr_nxt = at->attr_cur; - at->flags &= ~AF_GPOS; + at->flags &= ~GRUB_NTFS_AF_GPOS; } goto retry; } @@ -245,13 +259,13 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, init_attr (at, mft); if ((pa = find_attr (at, attr)) == NULL) return NULL; - if ((at->flags & AF_ALST) == 0) + if ((at->flags & GRUB_NTFS_AF_ALST) == 0) { while (1) { if ((pa = find_attr (at, attr)) == NULL) break; - if (at->flags & AF_ALST) + if (at->flags & GRUB_NTFS_AF_ALST) return pa; } grub_errno = GRUB_ERR_NONE; @@ -296,7 +310,7 @@ retry: c2 = ((unsigned char) (*run) >> 4); if (!c1) { - if ((ctx->attr) && (ctx->attr->flags & AF_ALST)) + if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST)) { void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector, unsigned offset, @@ -325,9 +339,9 @@ retry: run = read_run_data (run, c2, &val, 1); /* offset to previous LCN */ ctx->curr_lcn += val; if (val == 0) - ctx->flags |= RF_BLNK; + ctx->flags |= GRUB_NTFS_RF_BLNK; else - ctx->flags &= ~RF_BLNK; + ctx->flags &= ~GRUB_NTFS_RF_BLNK; ctx->cur_run = run; return 0; } @@ -345,7 +359,7 @@ grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block) return ctx->curr_lcn; } else - return (ctx->flags & RF_BLNK) ? 0 : (block - + return (ctx->flags & GRUB_NTFS_RF_BLNK) ? 0 : (block - ctx->curr_vcn + ctx->curr_lcn); } @@ -376,24 +390,24 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, return 0; } - if (u16at (pa, 0xC) & FLAG_COMPRESSED) - ctx->flags |= RF_COMP; + if (u16at (pa, 0xC) & GRUB_NTFS_FLAG_COMPRESSED) + ctx->flags |= GRUB_NTFS_RF_COMP; else - ctx->flags &= ~RF_COMP; + ctx->flags &= ~GRUB_NTFS_RF_COMP; ctx->cur_run = pa + u16at (pa, 0x20); - if (ctx->flags & RF_COMP) + if (ctx->flags & GRUB_NTFS_RF_COMP) { if (!cached) return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed"); if (at->sbuf) { - if ((ofs & (~(COM_LEN - 1))) == at->save_pos) + if ((ofs & (~(GRUB_NTFS_COM_LEN - 1))) == at->save_pos) { grub_disk_addr_t n; - n = COM_LEN - (ofs - at->save_pos); + n = GRUB_NTFS_COM_LEN - (ofs - at->save_pos); if (n > len) n = len; @@ -408,17 +422,17 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, } else { - at->sbuf = grub_malloc (COM_LEN); + at->sbuf = grub_malloc (GRUB_NTFS_COM_LEN); if (at->sbuf == NULL) return grub_errno; at->save_pos = 1; } - vcn = ctx->target_vcn = (ofs >> COM_LOG_LEN) * (COM_SEC / ctx->comp.spc); + vcn = ctx->target_vcn = (ofs >> GRUB_NTFS_COM_LOG_LEN) * (GRUB_NTFS_COM_SEC / ctx->comp.spc); ctx->target_vcn &= ~0xF; } else - vcn = ctx->target_vcn = grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, 0); + vcn = ctx->target_vcn = grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, 0); ctx->next_vcn = u32at (pa, 0x10); ctx->curr_lcn = 0; @@ -428,12 +442,12 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, return grub_errno; } - if (at->flags & AF_GPOS) + if (at->flags & GRUB_NTFS_AF_GPOS) { grub_disk_addr_t st0, st1; grub_uint64_t m; - grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, &m); + grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, &m); st0 = (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc + m; @@ -450,7 +464,7 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, return 0; } - if (!(ctx->flags & RF_COMP)) + if (!(ctx->flags & GRUB_NTFS_RF_COMP)) { unsigned int pow; @@ -481,12 +495,12 @@ read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, save_cur = at->attr_cur; at->attr_nxt = at->attr_cur; attr = (unsigned char) *at->attr_nxt; - if (at->flags & AF_ALST) + if (at->flags & GRUB_NTFS_AF_ALST) { char *pa; grub_disk_addr_t vcn; - vcn = grub_divmod64 (ofs, at->mft->data->spc << BLK_SHR, 0); + vcn = grub_divmod64 (ofs, at->mft->data->spc << GRUB_NTFS_BLK_SHR, 0); pa = at->attr_nxt + u16at (at->attr_nxt, 4); while (pa < at->attr_end) { @@ -513,8 +527,8 @@ static grub_err_t read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno) { if (read_attr - (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << BLK_SHR), - data->mft_size << BLK_SHR, 0, 0)) + (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR), + data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0)) return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno); return fixup (data, buf, data->mft_size, "FILE"); } @@ -526,7 +540,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) mft->inode_read = 1; - mft->buf = grub_malloc (mft->data->mft_size << BLK_SHR); + mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR); if (mft->buf == NULL) return grub_errno; @@ -541,7 +555,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) { char *pa; - pa = locate_attr (&mft->attr, mft, AT_DATA); + pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_DATA); if (pa == NULL) return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%X", mftno); @@ -550,7 +564,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) else mft->size = u64at (pa, 0x30); - if ((mft->attr.flags & AF_ALST) == 0) + if ((mft->attr.flags & GRUB_NTFS_AF_ALST) == 0) mft->attr.attr_end = 0; /* Don't jump to attribute list */ } else @@ -603,7 +617,7 @@ list_file (struct grub_ntfs_file *diro, char *pos, } type = - (u32at (pos, 0x48) & ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : + (u32at (pos, 0x48) & GRUB_NTFS_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG; fdiro = grub_zalloc (sizeof (struct grub_ntfs_file)); @@ -668,7 +682,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, init_attr (at, mft); while (1) { - if ((cur_pos = find_attr (at, AT_INDEX_ROOT)) == NULL) + if ((cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT)) == NULL) { grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT"); goto done; @@ -694,7 +708,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, bitmap_len = 0; free_attr (at); init_attr (at, mft); - while ((cur_pos = find_attr (at, AT_BITMAP)) != NULL) + while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL) { int ofs; @@ -735,7 +749,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, } free_attr (at); - cur_pos = locate_attr (at, mft, AT_INDEX_ALLOCATION); + cur_pos = locate_attr (at, mft, GRUB_NTFS_AT_INDEX_ALLOCATION); while (cur_pos != NULL) { /* Non-resident, Namelen=4, Offset=0x40, Flags=0, Name="$I30" */ @@ -743,7 +757,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, (u32at (cur_pos, 0x40) == 0x490024) && (u32at (cur_pos, 0x44) == 0x300033)) break; - cur_pos = find_attr (at, AT_INDEX_ALLOCATION); + cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ALLOCATION); } if ((!cur_pos) && (bitmap)) @@ -756,7 +770,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, { grub_disk_addr_t v, i; - indx = grub_malloc (mft->data->idx_size << BLK_SHR); + indx = grub_malloc (mft->data->idx_size << GRUB_NTFS_BLK_SHR); if (indx == NULL) goto done; @@ -766,8 +780,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, if (*bitmap & v) { if ((read_attr - (at, indx, i * (mft->data->idx_size << BLK_SHR), - (mft->data->idx_size << BLK_SHR), 0, 0)) + (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR), + (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0)) || (fixup (mft->data, indx, mft->data->idx_size, "INDX"))) goto done; ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook); @@ -814,32 +828,32 @@ grub_ntfs_mount (grub_disk_t disk) goto fail; data->blocksize = grub_le_to_cpu16 (bpb.bytes_per_sector); - data->spc = bpb.sectors_per_cluster * (data->blocksize >> BLK_SHR); + data->spc = bpb.sectors_per_cluster * (data->blocksize >> GRUB_NTFS_BLK_SHR); if (bpb.clusters_per_mft > 0) data->mft_size = data->spc * bpb.clusters_per_mft; else - data->mft_size = 1 << (-bpb.clusters_per_mft - BLK_SHR); + data->mft_size = 1 << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR); if (bpb.clusters_per_index > 0) data->idx_size = data->spc * bpb.clusters_per_index; else - data->idx_size = 1 << (-bpb.clusters_per_index - BLK_SHR); + data->idx_size = 1 << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR); data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc; - if ((data->mft_size > MAX_MFT) || (data->idx_size > MAX_IDX)) + if ((data->mft_size > GRUB_NTFS_MAX_MFT) || (data->idx_size > GRUB_NTFS_MAX_IDX)) goto fail; data->mmft.data = data; data->cmft.data = data; - data->mmft.buf = grub_malloc (data->mft_size << BLK_SHR); + data->mmft.buf = grub_malloc (data->mft_size << GRUB_NTFS_BLK_SHR); if (!data->mmft.buf) goto fail; if (grub_disk_read - (disk, data->mft_start, 0, data->mft_size << BLK_SHR, data->mmft.buf)) + (disk, data->mft_start, 0, data->mft_size << GRUB_NTFS_BLK_SHR, data->mmft.buf)) goto fail; data->uuid = grub_le_to_cpu64 (bpb.num_serial); @@ -847,10 +861,10 @@ grub_ntfs_mount (grub_disk_t disk) if (fixup (data, data->mmft.buf, data->mft_size, "FILE")) goto fail; - if (!locate_attr (&data->mmft.attr, &data->mmft, AT_DATA)) + if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA)) goto fail; - if (init_file (&data->cmft, FILE_ROOT)) + if (init_file (&data->cmft, GRUB_NTFS_FILE_ROOT)) goto fail; return data; @@ -1030,7 +1044,7 @@ grub_ntfs_label (grub_device_t device, char **label) if (!mft->inode_read) { - mft->buf = grub_malloc (mft->data->mft_size << BLK_SHR); + mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR); if (mft->buf == NULL) goto fail; @@ -1039,7 +1053,7 @@ grub_ntfs_label (grub_device_t device, char **label) } init_attr (&mft->attr, mft); - pa = find_attr (&mft->attr, AT_VOLUME_NAME); + pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME); if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10))) { char *buf; diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c index d2893cb99..890faa3bf 100644 --- a/grub-core/fs/ntfscomp.c +++ b/grub-core/fs/ntfscomp.c @@ -21,7 +21,6 @@ #include #include #include -#include #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -35,7 +34,7 @@ decomp_nextvcn (struct grub_ntfs_comp *cc) (cc->disk, (cc->comp_table[cc->comp_head][1] - (cc->comp_table[cc->comp_head][0] - cc->cbuf_vcn)) * cc->spc, 0, - cc->spc << BLK_SHR, cc->cbuf)) + cc->spc << GRUB_NTFS_BLK_SHR, cc->cbuf)) return grub_errno; cc->cbuf_vcn++; if ((cc->cbuf_vcn >= cc->comp_table[cc->comp_head][0])) @@ -47,7 +46,7 @@ decomp_nextvcn (struct grub_ntfs_comp *cc) static grub_err_t decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res) { - if (cc->cbuf_ofs >= (cc->spc << BLK_SHR)) + if (cc->cbuf_ofs >= (cc->spc << GRUB_NTFS_BLK_SHR)) { if (decomp_nextvcn (cc)) return grub_errno; @@ -87,7 +86,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) bits = copied = tag = 0; while (cnt > 0) { - if (copied > COM_LEN) + if (copied > GRUB_NTFS_COM_LEN) return grub_error (GRUB_ERR_BAD_FS, "compression block too large"); @@ -150,7 +149,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) } else { - if (cnt != COM_LEN) + if (cnt != GRUB_NTFS_COM_LEN) return grub_error (GRUB_ERR_BAD_FS, "invalid compression block size"); } @@ -160,7 +159,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) { int n; - n = (cc->spc << BLK_SHR) - cc->cbuf_ofs; + n = (cc->spc << GRUB_NTFS_BLK_SHR) - cc->cbuf_ofs; if (n > cnt) n = cnt; if ((dest) && (n)) @@ -179,7 +178,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) static grub_err_t read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) { - int cpb = COM_SEC / ctx->comp.spc; + int cpb = GRUB_NTFS_COM_SEC / ctx->comp.spc; while (num) { @@ -192,7 +191,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) return grub_error (GRUB_ERR_BAD_FS, "invalid compression block"); ctx->comp.comp_head = ctx->comp.comp_tail = 0; ctx->comp.cbuf_vcn = ctx->target_vcn; - ctx->comp.cbuf_ofs = (ctx->comp.spc << BLK_SHR); + ctx->comp.cbuf_ofs = (ctx->comp.spc << GRUB_NTFS_BLK_SHR); if (ctx->target_vcn >= ctx->next_vcn) { if (grub_ntfs_read_run_list (ctx)) @@ -200,7 +199,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) } while (ctx->target_vcn + 16 > ctx->next_vcn) { - if (ctx->flags & RF_BLNK) + if (ctx->flags & GRUB_NTFS_RF_BLNK) break; ctx->comp.comp_table[ctx->comp.comp_tail][0] = ctx->next_vcn; ctx->comp.comp_table[ctx->comp.comp_tail][1] = @@ -216,15 +215,15 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) nn = num; num -= nn; - if (ctx->flags & RF_BLNK) + if (ctx->flags & GRUB_NTFS_RF_BLNK) { ctx->target_vcn += nn * cpb; if (ctx->comp.comp_tail == 0) { if (buf) { - grub_memset (buf, 0, nn * COM_LEN); - buf += nn * COM_LEN; + grub_memset (buf, 0, nn * GRUB_NTFS_COM_LEN); + buf += nn * GRUB_NTFS_COM_LEN; } } else @@ -234,7 +233,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) if (decomp_block (&ctx->comp, buf)) return grub_errno; if (buf) - buf += COM_LEN; + buf += GRUB_NTFS_COM_LEN; nn--; } } @@ -259,9 +258,9 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) (ctx->comp.comp_table[ctx->comp.comp_head][1] - (ctx->comp.comp_table[ctx->comp.comp_head][0] - ctx->target_vcn)) * ctx->comp.spc, 0, - tt * (ctx->comp.spc << BLK_SHR), buf)) + tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - buf += tt * (ctx->comp.spc << BLK_SHR); + buf += tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); } nn -= tt; if (ctx->target_vcn >= @@ -276,9 +275,9 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) (ctx->comp.disk, (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc, 0, - nn * (ctx->comp.spc << BLK_SHR), buf)) + nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - buf += nn * (ctx->comp.spc << BLK_SHR); + buf += nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); } ctx->target_vcn += nn; } @@ -294,7 +293,7 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs, grub_err_t ret; ctx->comp.comp_head = ctx->comp.comp_tail = 0; - ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << BLK_SHR); + ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << GRUB_NTFS_BLK_SHR); if (!ctx->comp.cbuf) return 0; @@ -304,17 +303,17 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs, if ((vcn > ctx->target_vcn) && (read_block - (ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / COM_SEC))) + (ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / GRUB_NTFS_COM_SEC))) { ret = grub_errno; goto quit; } - if (ofs % COM_LEN) + if (ofs % GRUB_NTFS_COM_LEN) { grub_uint32_t t, n, o; - t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR); + t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); if (read_block (ctx, at->sbuf, 1)) { ret = grub_errno; @@ -323,8 +322,8 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs, at->save_pos = t; - o = ofs % COM_LEN; - n = COM_LEN - o; + o = ofs % GRUB_NTFS_COM_LEN; + n = GRUB_NTFS_COM_LEN - o; if (n > len) n = len; grub_memcpy (dest, &at->sbuf[o], n); @@ -334,19 +333,19 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs, len -= n; } - if (read_block (ctx, dest, len / COM_LEN)) + if (read_block (ctx, dest, len / GRUB_NTFS_COM_LEN)) { ret = grub_errno; goto quit; } - dest += (len / COM_LEN) * COM_LEN; - len = len % COM_LEN; + dest += (len / GRUB_NTFS_COM_LEN) * GRUB_NTFS_COM_LEN; + len = len % GRUB_NTFS_COM_LEN; if (len) { grub_uint32_t t; - t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR); + t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); if (read_block (ctx, at->sbuf, 1)) { ret = grub_errno; diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h index e220fecf4..cf90ce110 100644 --- a/include/grub/ntfs.h +++ b/include/grub/ntfs.h @@ -20,79 +20,87 @@ #ifndef GRUB_NTFS_H #define GRUB_NTFS_H 1 -#define FILE_MFT 0 -#define FILE_MFTMIRR 1 -#define FILE_LOGFILE 2 -#define FILE_VOLUME 3 -#define FILE_ATTRDEF 4 -#define FILE_ROOT 5 -#define FILE_BITMAP 6 -#define FILE_BOOT 7 -#define FILE_BADCLUS 8 -#define FILE_QUOTA 9 -#define FILE_UPCASE 10 +enum + { + GRUB_NTFS_FILE_MFT = 0, + GRUB_NTFS_FILE_MFTMIRR = 1, + GRUB_NTFS_FILE_LOGFILE = 2, + GRUB_NTFS_FILE_VOLUME = 3, + GRUB_NTFS_FILE_ATTRDEF = 4, + GRUB_NTFS_FILE_ROOT = 5, + GRUB_NTFS_FILE_BITMAP = 6, + GRUB_NTFS_FILE_BOOT = 7, + GRUB_NTFS_FILE_BADCLUS = 8, + GRUB_NTFS_FILE_QUOTA = 9, + GRUB_NTFS_FILE_UPCASE = 10, + }; -#define AT_STANDARD_INFORMATION 0x10 -#define AT_ATTRIBUTE_LIST 0x20 -#define AT_FILENAME 0x30 -#define AT_OBJECT_ID 0x40 -#define AT_SECURITY_DESCRIPTOR 0x50 -#define AT_VOLUME_NAME 0x60 -#define AT_VOLUME_INFORMATION 0x70 -#define AT_DATA 0x80 -#define AT_INDEX_ROOT 0x90 -#define AT_INDEX_ALLOCATION 0xA0 -#define AT_BITMAP 0xB0 -#define AT_SYMLINK 0xC0 -#define AT_EA_INFORMATION 0xD0 -#define AT_EA 0xE0 +enum + { + GRUB_NTFS_AT_STANDARD_INFORMATION = 0x10, + GRUB_NTFS_AT_ATTRIBUTE_LIST = 0x20, + GRUB_NTFS_AT_FILENAME = 0x30, + GRUB_NTFS_AT_OBJECT_ID = 0x40, + GRUB_NTFS_AT_SECURITY_DESCRIPTOR = 0x50, + GRUB_NTFS_AT_VOLUME_NAME = 0x60, + GRUB_NTFS_AT_VOLUME_INFORMATION = 0x70, + GRUB_NTFS_AT_DATA = 0x80, + GRUB_NTFS_AT_INDEX_ROOT = 0x90, + GRUB_NTFS_AT_INDEX_ALLOCATION = 0xA0, + GRUB_NTFS_AT_BITMAP = 0xB0, + GRUB_NTFS_AT_SYMLINK = 0xC0, + GRUB_NTFS_AT_EA_INFORMATION = 0xD0, + GRUB_NTFS_AT_EA = 0xE0, + }; -#define ATTR_READ_ONLY 0x1 -#define ATTR_HIDDEN 0x2 -#define ATTR_SYSTEM 0x4 -#define ATTR_ARCHIVE 0x20 -#define ATTR_DEVICE 0x40 -#define ATTR_NORMAL 0x80 -#define ATTR_TEMPORARY 0x100 -#define ATTR_SPARSE 0x200 -#define ATTR_REPARSE 0x400 -#define ATTR_COMPRESSED 0x800 -#define ATTR_OFFLINE 0x1000 -#define ATTR_NOT_INDEXED 0x2000 -#define ATTR_ENCRYPTED 0x4000 -#define ATTR_DIRECTORY 0x10000000 -#define ATTR_INDEX_VIEW 0x20000000 +enum + { + GRUB_NTFS_ATTR_READ_ONLY = 0x1, + GRUB_NTFS_ATTR_HIDDEN = 0x2, + GRUB_NTFS_ATTR_SYSTEM = 0x4, + GRUB_NTFS_ATTR_ARCHIVE = 0x20, + GRUB_NTFS_ATTR_DEVICE = 0x40, + GRUB_NTFS_ATTR_NORMAL = 0x80, + GRUB_NTFS_ATTR_TEMPORARY = 0x100, + GRUB_NTFS_ATTR_SPARSE = 0x200, + GRUB_NTFS_ATTR_REPARSE = 0x400, + GRUB_NTFS_ATTR_COMPRESSED = 0x800, + GRUB_NTFS_ATTR_OFFLINE = 0x1000, + GRUB_NTFS_ATTR_NOT_INDEXED = 0x2000, + GRUB_NTFS_ATTR_ENCRYPTED = 0x4000, + GRUB_NTFS_ATTR_DIRECTORY = 0x10000000, + GRUB_NTFS_ATTR_INDEX_VIEW = 0x20000000 + }; -#define FLAG_COMPRESSED 1 -#define FLAG_ENCRYPTED 0x4000 -#define FLAG_SPARSE 0x8000 +enum + { + GRUB_NTFS_FLAG_COMPRESSED = 1, + GRUB_NTFS_FLAG_ENCRYPTED = 0x4000, + GRUB_NTFS_FLAG_SPARSE = 0x8000 + }; -#define BLK_SHR GRUB_DISK_SECTOR_BITS +#define GRUB_NTFS_BLK_SHR GRUB_DISK_SECTOR_BITS -#define MAX_MFT (1024 >> BLK_SHR) -#define MAX_IDX (16384 >> BLK_SHR) +#define GRUB_NTFS_MAX_MFT (1024 >> GRUB_NTFS_BLK_SHR) +#define GRUB_NTFS_MAX_IDX (16384 >> GRUB_NTFS_BLK_SHR) -#define COM_LEN 4096 -#define COM_LOG_LEN 12 -#define COM_SEC (COM_LEN >> BLK_SHR) +#define GRUB_NTFS_COM_LEN 4096 +#define GRUB_NTFS_COM_LOG_LEN 12 +#define GRUB_NTFS_COM_SEC (GRUB_NTFS_COM_LEN >> GRUB_NTFS_BLK_SHR) -#define AF_ALST 1 -#define AF_MMFT 2 -#define AF_GPOS 4 +enum + { + GRUB_NTFS_AF_ALST = 1, + GRUB_NTFS_AF_MMFT = 2, + GRUB_NTFS_AF_GPOS = 4, + }; -#define RF_COMP 1 -#define RF_CBLK 2 -#define RF_BLNK 4 - -#define valueat(buf,ofs,type) *((type*)(((char*)buf)+ofs)) - -#define u16at(buf,ofs) grub_le_to_cpu16(valueat(buf,ofs,grub_uint16_t)) -#define u32at(buf,ofs) grub_le_to_cpu32(valueat(buf,ofs,grub_uint32_t)) -#define u64at(buf,ofs) grub_le_to_cpu64(valueat(buf,ofs,grub_uint64_t)) - -#define v16at(buf,ofs) valueat(buf,ofs,grub_uint16_t) -#define v32at(buf,ofs) valueat(buf,ofs,grub_uint32_t) -#define v64at(buf,ofs) valueat(buf,ofs,grub_uint64_t) +enum + { + GRUB_NTFS_RF_COMP = 1, + GRUB_NTFS_RF_CBLK = 2, + GRUB_NTFS_RF_BLNK = 4 + }; struct grub_ntfs_bpb { @@ -120,8 +128,6 @@ struct grub_ntfs_bpb grub_uint32_t checksum; } __attribute__ ((packed)); -#define grub_ntfs_file grub_fshelp_node - struct grub_ntfs_attr { int flags; @@ -132,7 +138,7 @@ struct grub_ntfs_attr struct grub_ntfs_file *mft; }; -struct grub_fshelp_node +struct grub_ntfs_file { struct grub_ntfs_data *data; char *buf; @@ -174,13 +180,15 @@ struct grub_ntfs_rlst struct grub_ntfs_comp comp; }; -typedef grub_err_t (*ntfscomp_func_t) (struct grub_ntfs_attr * at, char *dest, - grub_uint32_t ofs, grub_uint32_t len, - struct grub_ntfs_rlst * ctx, - grub_uint32_t vcn); +typedef grub_err_t (*grub_ntfscomp_func_t) (struct grub_ntfs_attr * at, + char *dest, + grub_uint32_t ofs, + grub_uint32_t len, + struct grub_ntfs_rlst * ctx, + grub_uint32_t vcn); -extern ntfscomp_func_t EXPORT_VAR (grub_ntfscomp_func); +extern grub_ntfscomp_func_t grub_ntfscomp_func; -grub_err_t EXPORT_FUNC(grub_ntfs_read_run_list) (struct grub_ntfs_rlst *ctx); +grub_err_t grub_ntfs_read_run_list (struct grub_ntfs_rlst *ctx); #endif /* ! GRUB_NTFS_H */ From 5773fb64104944b2af0a988183861e88b5579fe6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 03:04:27 +0200 Subject: [PATCH 448/673] Support NTFS reparse points. * grub-core/fs/ntfs.c (list_file): Set symlink type when appropriate. (symlink_descriptor): New struct. (grub_ntfs_read_symlink): New function. (grub_ntfs_iterate_dir): Use grub_ntfs_read_symlink. (grub_ntfs_open): Likewise. --- ChangeLog | 10 ++++ grub-core/fs/ntfs.c | 110 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 115 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index f8b6a78dc..8c3c50434 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-10-26 Vladimir Serbinenko + + Support NTFS reparse points. + + * grub-core/fs/ntfs.c (list_file): Set symlink type when appropriate. + (symlink_descriptor): New struct. + (grub_ntfs_read_symlink): New function. + (grub_ntfs_iterate_dir): Use grub_ntfs_read_symlink. + (grub_ntfs_open): Likewise. + 2011-10-26 Vladimir Serbinenko * include/grub/ntfs.h: Add GRUB_NTFS_ prefix. All users updated. diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index bff760e71..13de52cd8 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -609,6 +609,7 @@ list_file (struct grub_ntfs_file *diro, char *pos, { enum grub_fshelp_filetype type; struct grub_ntfs_file *fdiro; + grub_uint32_t attr; if (u16at (pos, 4)) { @@ -616,9 +617,13 @@ list_file (struct grub_ntfs_file *diro, char *pos, return 0; } - type = - (u32at (pos, 0x48) & GRUB_NTFS_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : - GRUB_FSHELP_REG; + attr = u32at (pos, 0x48); + if (attr & GRUB_NTFS_ATTR_REPARSE) + type = GRUB_FSHELP_SYMLINK; + else if (attr & GRUB_NTFS_ATTR_DIRECTORY) + type = GRUB_FSHELP_DIR; + else + type = GRUB_FSHELP_REG; fdiro = grub_zalloc (sizeof (struct grub_ntfs_file)); if (!fdiro) @@ -653,6 +658,101 @@ list_file (struct grub_ntfs_file *diro, char *pos, return 0; } +struct symlink_descriptor +{ + grub_uint32_t type; + grub_uint32_t total_len; + grub_uint16_t off1; + grub_uint16_t len1; + grub_uint16_t off2; + grub_uint16_t len2; +} __attribute__ ((packed)); + +static char * +grub_ntfs_read_symlink (grub_fshelp_node_t node) +{ + struct grub_ntfs_file *mft; + struct symlink_descriptor symdesc; + grub_err_t err; + grub_uint16_t *buf16; + char *buf, *end; + grub_size_t len; + grub_size_t i; + char *pa; + grub_size_t off; + + mft = (struct grub_ntfs_file *) node; + + mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR); + if (mft->buf == NULL) + return NULL; + + if (read_mft (mft->data, mft->buf, mft->ino)) + return NULL; + + pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_SYMLINK); + if (pa == NULL) + { + grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%X", mft->ino); + return NULL; + } + + err = read_attr (&mft->attr, (char *) &symdesc, 0, + sizeof (struct symlink_descriptor), 1, 0); + if (err) + return NULL; + + switch (grub_cpu_to_le32 (symdesc.type)) + { + case 0xa000000c: + off = sizeof (struct symlink_descriptor) + 4 + grub_cpu_to_le32 (symdesc.off1); + len = grub_cpu_to_le32 (symdesc.len1); + break; + case 0xa0000003: + off = sizeof (struct symlink_descriptor) + grub_cpu_to_le32 (symdesc.off1); + len = grub_cpu_to_le32 (symdesc.len1); + break; + default: + grub_error (GRUB_ERR_BAD_FS, "symlink type invalid (%x)", + grub_cpu_to_le32 (symdesc.type)); + grub_printf ("%d\n", __LINE__); + return NULL; + } + + buf16 = grub_malloc (len); + if (!buf16) + return NULL; + + err = read_attr (&mft->attr, (char *) buf16, off, len, 1, 0); + if (err) + return NULL; + + buf = grub_malloc (len * 2 + 1); + if (!buf) + { + grub_free (buf16); + return NULL; + } + + for (i = 0; i < len / 2; i++) + { + buf16[i] = grub_le_to_cpu16 (buf16[i]); + if (buf16[i] == '\\') + buf16[i] = '/'; + } + + end = (char *) grub_utf16_to_utf8 ((grub_uint8_t *) buf, buf16, len / 2); + *end = '\0'; + /* Split the sequence to avoid GCC thinking that this is a trigraph. */ + if (grub_memcmp (buf, "/?" "?/", 4) == 0 && buf[5] == ':' && buf[6] == '/' + && grub_isalpha (buf[4])) + { + grub_memmove (buf, buf + 6, end - buf + 1 - 6); + end -= 6; + } + return buf; +} + static int grub_ntfs_iterate_dir (grub_fshelp_node_t dir, int NESTED_FUNC_ATTR @@ -915,7 +1015,7 @@ grub_ntfs_dir (grub_device_t device, const char *path, goto fail; grub_fshelp_find_file (path, &data->cmft, &fdiro, grub_ntfs_iterate_dir, - 0, GRUB_FSHELP_DIR); + grub_ntfs_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; @@ -953,7 +1053,7 @@ grub_ntfs_open (grub_file_t file, const char *name) goto fail; grub_fshelp_find_file (name, &data->cmft, &mft, grub_ntfs_iterate_dir, - 0, GRUB_FSHELP_REG); + grub_ntfs_read_symlink, GRUB_FSHELP_REG); if (grub_errno) goto fail; From f8d82408d9f13aa960e2f73317cabb0a66f207e7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 20:55:09 +0200 Subject: [PATCH 449/673] * grub-core/fs/zfs/zfs.c (read_device): Silence spurious warning. (zfs_unmount): Fix memory leak. --- ChangeLog | 5 +++++ grub-core/fs/zfs/zfs.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8c3c50434..980452003 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-27 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (read_device): Silence spurious warning. + (zfs_unmount): Fix memory leak. + 2011-10-26 Vladimir Serbinenko Support NTFS reparse points. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 3253457c7..9bd68222a 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -865,7 +865,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, } case DEVICE_MIRROR: { - grub_err_t err; + grub_err_t err = GRUB_ERR_NONE; unsigned i; if (desc->n_children <= 0) return grub_error (GRUB_ERR_BAD_FS, @@ -2498,6 +2498,7 @@ zfs_unmount (struct grub_zfs_data *data) unsigned i; for (i = 0; i < data->n_devices_attached; i++) unmount_device (&data->devices_attached[i]); + grub_free (data->devices_attached); grub_free (data->dnode_buf); grub_free (data->dnode_mdn); grub_free (data->file_buf); From 5b1ae25f068e405374a8f5b063b1f8a4260274a4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 27 Oct 2011 20:58:52 +0200 Subject: [PATCH 450/673] Support BFS (befs) UUID. * grub-core/fs/afs.c (grub_afs_inode): Make small_data zero-size. (grub_afs_small_data_element_header): New struct. (grub_afs_read_inode): Read complete inode. Fix ino type while on it. (grub_afs_read_attribute) [MODE_BFS]: New function. (grub_afs_iterate_dir): Allocate for complete inode. (grub_afs_mount): Likewise. (grub_afs_uuid) [MODE_BFS]: New function. (grub_afs_fs) [MODE_BFS]: Add .uuid. --- ChangeLog | 13 ++++ grub-core/fs/afs.c | 163 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 162 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 980452003..cfb00531a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-10-27 Vladimir Serbinenko + + Support BFS (befs) UUID. + + * grub-core/fs/afs.c (grub_afs_inode): Make small_data zero-size. + (grub_afs_small_data_element_header): New struct. + (grub_afs_read_inode): Read complete inode. Fix ino type while on it. + (grub_afs_read_attribute) [MODE_BFS]: New function. + (grub_afs_iterate_dir): Allocate for complete inode. + (grub_afs_mount): Likewise. + (grub_afs_uuid) [MODE_BFS]: New function. + (grub_afs_fs) [MODE_BFS]: Add .uuid. + 2011-10-27 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (read_device): Silence spurious warning. diff --git a/grub-core/fs/afs.c b/grub-core/fs/afs.c index b64ebb52c..ea7a9e9ed 100644 --- a/grub-core/fs/afs.c +++ b/grub-core/fs/afs.c @@ -210,7 +210,14 @@ struct grub_afs_inode grub_uint32_t unused; struct grub_afs_datastream stream; grub_uint32_t pad[4]; - grub_uint32_t small_data[1]; + grub_uint8_t small_data[0]; +} __attribute__ ((packed)); + +struct grub_afs_small_data_element_header +{ + grub_uint32_t type; + grub_uint16_t name_len; + grub_uint16_t value_len; } __attribute__ ((packed)); struct grub_fshelp_node @@ -229,6 +236,19 @@ struct grub_afs_data static grub_dl_t my_mod; +static int +grub_afs_iterate_dir (grub_fshelp_node_t dir, + int NESTED_FUNC_ATTR + (*hook) (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node)); +static grub_ssize_t +grub_afs_read_file (grub_fshelp_node_t node, + void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, + unsigned offset, unsigned length), + grub_off_t pos, grub_size_t len, char *buf); + + static grub_afs_off_t grub_afs_run_to_num (struct grub_afs_sblock *sb, struct grub_afs_blockrun *run) @@ -239,15 +259,87 @@ grub_afs_run_to_num (struct grub_afs_sblock *sb, static grub_err_t grub_afs_read_inode (struct grub_afs_data *data, - grub_uint32_t ino, struct grub_afs_inode *inode) + grub_uint64_t ino, struct grub_afs_inode *inode) { return grub_disk_read (data->disk, ino * (data->sblock.block_size >> GRUB_DISK_SECTOR_BITS), - 0, sizeof (struct grub_afs_inode), - inode); + 0, data->sblock.block_size, inode); } +#ifdef MODE_BFS +static grub_ssize_t +grub_afs_read_attribute (grub_fshelp_node_t node, + const char *name, char *buf, grub_size_t len) +{ + grub_ssize_t read = -1; + auto int NESTED_FUNC_ATTR hook (const char *filename, + enum grub_fshelp_filetype filetype + __attribute__ ((unused)), + grub_fshelp_node_t attr_node); + + int NESTED_FUNC_ATTR hook (const char *filename, + enum grub_fshelp_filetype filetype + __attribute__ ((unused)), + grub_fshelp_node_t attr_node) + { + if (grub_strcmp (filename, name) == 0) + { + read = grub_afs_read_file (attr_node, 0, 0, len, buf); + return 1; + } + return 0; + } + grub_uint8_t *ptr = node->inode.small_data; + grub_uint8_t *end = ((grub_uint8_t *) &node->inode + + node->data->sblock.block_size); + + while (ptr + sizeof (struct grub_afs_small_data_element_header) < end) + { + struct grub_afs_small_data_element_header *el; + char *el_name; + grub_uint8_t *data; + el = (struct grub_afs_small_data_element_header *) ptr; + if (el->name_len == 0) + break; + el_name = (char *) (el + 1); + data = (grub_uint8_t *) el_name + grub_afs_to_cpu16 (el->name_len) + 3; + ptr = data + grub_afs_to_cpu16 (el->value_len) + 1; + if (grub_memcmp (name, el_name, grub_afs_to_cpu16 (el->name_len)) == 0 + && name[el->name_len] == 0) + { + grub_size_t copy; + copy = len; + if (grub_afs_to_cpu16 (el->value_len) > copy) + copy = grub_afs_to_cpu16 (el->value_len); + grub_memcpy (buf, data, copy); + return copy; + } + } + + { + struct grub_fshelp_node *fdiro; + + fdiro = grub_malloc (sizeof (struct grub_fshelp_node) + + node->data->sblock.block_size + - sizeof (struct grub_afs_inode)); + if (! fdiro) + return -1; + + fdiro->data = node->data; + if (grub_afs_read_inode (node->data, + grub_afs_run_to_num (&node->data->sblock, + &node->inode.attrib_dir), + &fdiro->inode)) + return -1; + + grub_afs_iterate_dir (fdiro, hook); + } + + return read; +} +#endif + static grub_disk_addr_t grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { @@ -424,7 +516,9 @@ grub_afs_iterate_dir (grub_fshelp_node_t dir, struct grub_fshelp_node *fdiro; int mode, type; - fdiro = grub_malloc (sizeof (struct grub_fshelp_node)); + fdiro = grub_malloc (sizeof (struct grub_fshelp_node) + + dir->data->sblock.block_size + - sizeof (struct grub_afs_inode)); if (! fdiro) return 0; @@ -521,18 +615,31 @@ static struct grub_afs_data * grub_afs_mount (grub_disk_t disk) { struct grub_afs_data *data = 0; - - data = grub_malloc (sizeof (struct grub_afs_data)); - if (!data) - return 0; + struct grub_afs_sblock sb; + grub_err_t err; /* Read the superblock. */ - if (grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0, - sizeof (struct grub_afs_sblock), &data->sblock)) - goto fail; + err = grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0, + sizeof (struct grub_afs_sblock), &sb); + if (err) + { + if (err == GRUB_ERR_OUT_OF_RANGE) + grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem"); + return NULL; + } - if (! grub_afs_validate_sblock (&data->sblock)) - goto fail; + if (! grub_afs_validate_sblock (&sb)) + { + grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem"); + return NULL; + } + + data = grub_malloc (sizeof (struct grub_afs_data) + sb.block_size + - sizeof (struct grub_afs_inode)); + if (!data) + return NULL; + + data->sblock = sb; data->diropen.data = data; data->inode = &data->diropen.inode; @@ -681,6 +788,31 @@ grub_afs_label (grub_device_t device, char **label) return grub_errno; } +#ifdef MODE_BFS +static grub_err_t +grub_afs_uuid (grub_device_t device, char **uuid) +{ + struct grub_afs_data *data; + grub_disk_t disk = device->disk; + grub_uint64_t vid; + grub_ssize_t read; + + *uuid = NULL; + + data = grub_afs_mount (disk); + if (!data) + return grub_errno; + read = grub_afs_read_attribute (&data->diropen, "be:volume_id", + (char *) &vid, + sizeof (vid)); + if (read == sizeof (vid)) + *uuid = grub_xasprintf ("%" PRIxGRUB_UINT64_T, grub_afs_to_cpu64 (vid)); + + grub_free (data); + + return grub_errno; +} +#endif static struct grub_fs grub_afs_fs = { .name = GRUB_AFS_FSNAME, @@ -689,6 +821,9 @@ static struct grub_fs grub_afs_fs = { .read = grub_afs_read, .close = grub_afs_close, .label = grub_afs_label, +#ifdef MODE_BFS + .uuid = grub_afs_uuid, +#endif .next = 0 }; From 6563f63dfd8eb3b3e5db20b774ca3fadb3aac4b5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 28 Oct 2011 15:52:15 +0200 Subject: [PATCH 451/673] * grub-core/disk/raid.c (scan_devices): Check partition. * grub-core/disk/lvm.c (do_lvm_scan): Likewise. --- ChangeLog | 5 +++++ grub-core/disk/lvm.c | 7 ++++++- grub-core/disk/raid.c | 7 ++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index cfb00531a..d2fc4ba84 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-28 Vladimir Serbinenko + + * grub-core/disk/raid.c (scan_devices): Check partition. + * grub-core/disk/lvm.c (do_lvm_scan): Likewise. + 2011-10-27 Vladimir Serbinenko Support BFS (befs) UUID. diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 7c19f08de..7c65db4ab 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include @@ -153,7 +154,11 @@ do_lvm_scan (const char *scan_for) for (vg = vg_list; vg; vg = vg->next) for (pv = vg->pvs; pv; pv = pv->next) if (pv->disk && pv->disk->id == disk->id - && pv->disk->dev->id == disk->dev->id) + && pv->disk->dev->id == disk->dev->id + && grub_partition_get_start (pv->disk->partition) + == grub_partition_get_start (disk->partition) + && grub_partition_get_len (pv->disk->partition) + == grub_partition_get_len (disk->partition)) { grub_disk_close (disk); return 0; diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 5d8326daf..07249eabc 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include #endif @@ -119,7 +120,11 @@ scan_devices (const char *arname) struct grub_raid_member *m; for (m = arr->members; m < arr->members + arr->nr_devs; m++) if (m->device && m->device->id == disk->id - && m->device->dev->id == m->device->dev->id) + && m->device->dev->id == m->device->dev->id + && grub_partition_get_start (m->device->partition) + == grub_partition_get_start (disk->partition) + && grub_partition_get_len (m->device->partition) + == grub_partition_get_len (disk->partition)) { grub_disk_close (disk); return 0; From ad03fe768e8b47cb51612dfa3545fd1a892bbe7f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 28 Oct 2011 15:59:47 +0200 Subject: [PATCH 452/673] Correct befs block counting logic. * grub-core/fs/afs.c (GRUB_AFS_BLOCKS_PER_DI_RUN): Replaced with... (GRUB_AFS_LOG_BLOCKS_PER_DI_RUN): ... this. (GRUB_AFS_BLOCKRUN_LOG_SIZE): New definition. (grub_afs_read_inode): Use block_shift. (RANGE_SHIFT): New definition. (grub_afs_read_block): Account for RANGE_SHIFT, emit errors on unexpected conditions, use shifts and appropriate types. (GRUB_MOD_INIT): Check the value of GRUB_AFS_BLOCKRUN_LOG_SIZE. --- ChangeLog | 13 +++++++++ grub-core/fs/afs.c | 67 ++++++++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index d2fc4ba84..64ae05ef4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-10-28 Vladimir Serbinenko + + Correct befs block counting logic. + + * grub-core/fs/afs.c (GRUB_AFS_BLOCKS_PER_DI_RUN): Replaced with... + (GRUB_AFS_LOG_BLOCKS_PER_DI_RUN): ... this. + (GRUB_AFS_BLOCKRUN_LOG_SIZE): New definition. + (grub_afs_read_inode): Use block_shift. + (RANGE_SHIFT): New definition. + (grub_afs_read_block): Account for RANGE_SHIFT, emit errors on + unexpected conditions, use shifts and appropriate types. + (GRUB_MOD_INIT): Check the value of GRUB_AFS_BLOCKRUN_LOG_SIZE. + 2011-10-28 Vladimir Serbinenko * grub-core/disk/raid.c (scan_devices): Check partition. diff --git a/grub-core/fs/afs.c b/grub-core/fs/afs.c index ea7a9e9ed..9a646ac88 100644 --- a/grub-core/fs/afs.c +++ b/grub-core/fs/afs.c @@ -41,7 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); #endif #define GRUB_AFS_DIRECT_BLOCK_COUNT 12 -#define GRUB_AFS_BLOCKS_PER_DI_RUN 4 +#define GRUB_AFS_LOG_BLOCKS_PER_DI_RUN 2 #ifdef MODE_BFS #define GRUB_AFS_SBLOCK_SECTOR 1 @@ -103,6 +103,7 @@ typedef grub_uint64_t grub_afs_off_t; typedef grub_uint64_t grub_afs_bigtime; typedef grub_uint64_t grub_afs_bvalue_t; +#define GRUB_AFS_BLOCKRUN_LOG_SIZE 3 struct grub_afs_blockrun { grub_uint32_t group; @@ -262,8 +263,7 @@ grub_afs_read_inode (struct grub_afs_data *data, grub_uint64_t ino, struct grub_afs_inode *inode) { return grub_disk_read (data->disk, - ino * - (data->sblock.block_size >> GRUB_DISK_SECTOR_BITS), + ino << (data->sblock.block_shift - GRUB_DISK_SECTOR_BITS), 0, data->sblock.block_size, inode); } @@ -340,13 +340,19 @@ grub_afs_read_attribute (grub_fshelp_node_t node, } #endif +#ifdef MODE_BFS +#define RANGE_SHIFT sb->block_shift +#else +#define RANGE_SHIFT 0 +#endif + static grub_disk_addr_t grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_afs_sblock *sb = &node->data->sblock; struct grub_afs_datastream *ds = &node->inode.stream; - if (fileblock < grub_afs_to_cpu64 (ds->max_direct_range)) + if ((fileblock << RANGE_SHIFT) < grub_afs_to_cpu64 (ds->max_direct_range)) { int i; @@ -356,21 +362,24 @@ grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock; fileblock -= grub_afs_to_cpu16 (ds->direct[i].len); } + grub_error (GRUB_ERR_BAD_FS, "incorrect direct blocks"); + return 0; } - else if (fileblock < grub_afs_to_cpu64 (ds->max_indirect_range)) + else if ((fileblock << RANGE_SHIFT) + < grub_afs_to_cpu64 (ds->max_indirect_range)) { - int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun); + grub_size_t ptrs_per_blk = (1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)); struct grub_afs_blockrun indir[ptrs_per_blk]; grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect); int i; - fileblock -= grub_afs_to_cpu64 (ds->max_direct_range); + fileblock -= grub_afs_to_cpu64 (ds->max_direct_range) >> RANGE_SHIFT; for (i = 0; i < ds->indirect.len; i++, blk++) { - int j; + grub_size_t j; if (grub_disk_read (node->data->disk, - blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS), + blk << (sb->block_shift - GRUB_DISK_SECTOR_BITS), 0, sizeof (indir), indir)) return 0; @@ -383,43 +392,47 @@ grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) fileblock -= grub_afs_to_cpu16 (indir[j].len); } } + grub_error (GRUB_ERR_BAD_FS, "incorrect indirect blocks"); + return 0; } - else + else if ((fileblock << RANGE_SHIFT) < grub_afs_to_cpu64 (ds->max_double_indirect_range)) { - int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun); + grub_size_t ptrs_per_blk = (1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)); struct grub_afs_blockrun indir[ptrs_per_blk]; - + grub_disk_addr_t off, dptr, dblk, idptr, idblk; /* ([idblk][idptr]) ([dblk][dptr]) [blk] */ - int cur_pos = fileblock - grub_afs_to_cpu64 (ds->max_indirect_range); - int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN; - int dblk_size = dptr_size * ptrs_per_blk; - int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN; - int idblk_size = idptr_size * ptrs_per_blk; + fileblock -= grub_afs_to_cpu64 (ds->max_indirect_range) >> RANGE_SHIFT; - int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN; - int dptr = (cur_pos / dptr_size) % ptrs_per_blk; - int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN; - int idptr = (cur_pos / idptr_size) % ptrs_per_blk; - int idblk = (cur_pos / idblk_size); + /* Divisions and modulo fixed number are optimised by compiler. */ + off = fileblock & ((1 << GRUB_AFS_LOG_BLOCKS_PER_DI_RUN) - 1); + dptr = fileblock >> GRUB_AFS_LOG_BLOCKS_PER_DI_RUN; + dblk = dptr >> (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE); + dptr &= ((1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)) - 1); + idptr = dblk >> GRUB_AFS_LOG_BLOCKS_PER_DI_RUN; + dblk &= ((1 << GRUB_AFS_LOG_BLOCKS_PER_DI_RUN) - 1); + idblk = idptr >> (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE); + idptr &= ((1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)) - 1); if (grub_disk_read (node->data->disk, (grub_afs_run_to_num (sb, &ds->double_indirect) - + idblk) * - (sb->block_size >> GRUB_DISK_SECTOR_BITS), + + idblk) << (sb->block_shift - GRUB_DISK_SECTOR_BITS), 0, sizeof (indir), indir)) return 0; if (grub_disk_read (node->data->disk, - (grub_afs_run_to_num (sb, &indir[idptr]) + dblk) * - (sb->block_size >> GRUB_DISK_SECTOR_BITS), + (grub_afs_run_to_num (sb, &indir[idptr]) + dblk) + << (sb->block_shift - GRUB_DISK_SECTOR_BITS), 0, sizeof (indir), indir)) return 0; return grub_afs_run_to_num (sb, &indir[dptr]) + off; } + + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "triple-indirect on " GRUB_AFS_FSNAME " isn't supported"); return 0; } @@ -837,6 +850,8 @@ GRUB_MOD_INIT (afs_be) GRUB_MOD_INIT (afs) #endif { + COMPILE_TIME_ASSERT ((1 << GRUB_AFS_BLOCKRUN_LOG_SIZE) + == sizeof (struct grub_afs_blockrun)); grub_fs_register (&grub_afs_fs); my_mod = mod; } From ed9ba06dd011b1e66bcb757f4cb5e4a4db54ecbc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 28 Oct 2011 16:05:16 +0200 Subject: [PATCH 453/673] Use shifts in squash4. * grub-core/fs/squash4.c (grub_squash_data): New field log2_blksz. (squash_mount): Check block size and take logarithm. (direct_read): Use shifts. --- ChangeLog | 8 ++++++++ grub-core/fs/squash4.c | 19 +++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 64ae05ef4..6d0cfde93 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-10-28 Vladimir Serbinenko + + Use shifts in squash4. + + * grub-core/fs/squash4.c (grub_squash_data): New field log2_blksz. + (squash_mount): Check block size and take logarithm. + (direct_read): Use shifts. + 2011-10-28 Vladimir Serbinenko Correct befs block counting logic. diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index d45732c16..a3832b6be 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -173,6 +173,7 @@ struct grub_squash_data struct grub_squash_super sb; struct grub_squash_cache_inode ino; grub_uint64_t fragments; + int log2_blksz; }; struct grub_fshelp_node @@ -267,7 +268,10 @@ squash_mount (grub_disk_t disk) grub_error (GRUB_ERR_BAD_FS, "not a squash4"); if (err) return NULL; - if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC) + if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC + || grub_le_to_cpu32 (sb.block_size) == 0 + || ((grub_le_to_cpu32 (sb.block_size) - 1) + & grub_le_to_cpu32 (sb.block_size))) { grub_error (GRUB_ERR_BAD_FS, "not squash4"); return NULL; @@ -290,6 +294,10 @@ squash_mount (grub_disk_t disk) data->disk = disk; data->fragments = grub_le_to_cpu64 (frag); + for (data->log2_blksz = 0; + (1U << data->log2_blksz) < grub_le_to_cpu32 (data->sb.block_size); + data->log2_blksz++); + return data; } @@ -528,10 +536,9 @@ direct_read (struct grub_squash_data *data, block_offset = ((char *) &ino->ino.file.block_size - (char *) &ino->ino); } - total_blocks = grub_divmod64 (total_size - + grub_le_to_cpu32 (data->sb.block_size) - 1, - grub_le_to_cpu32 (data->sb.block_size), - 0); + total_blocks = ((total_size + + grub_le_to_cpu32 (data->sb.block_size) - 1) + >> data->log2_blksz); ino->block_sizes = grub_malloc (total_blocks * sizeof (ino->block_sizes[0])); ino->cumulated_block_sizes = grub_malloc (total_blocks @@ -565,7 +572,7 @@ direct_read (struct grub_squash_data *data, if (a == 0) a = sizeof (struct grub_squash_super); - i = grub_divmod64 (off, grub_le_to_cpu32 (data->sb.block_size), 0); + i = off >> data->log2_blksz; cumulated_uncompressed_size = grub_le_to_cpu32 (data->sb.block_size) * (grub_disk_addr_t) i; while (cumulated_uncompressed_size < off + len) From 564dd58c2acf88c5f2a046eae52feb62332dde61 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 28 Oct 2011 16:09:20 +0200 Subject: [PATCH 454/673] Use shifts in minix filesystem. * grub-core/fs/minix.c (GRUB_MINIX_ZONESZ): Use log_block_size. (GRUB_MINIX_ZONE2SECT): Likewise. (grub_minix_data): Replace block_size with log_block_size. (grub_minix_read_file): Use shifts. (grub_minix_mount): Check block size and take a logarithm. --- ChangeLog | 10 ++++++++++ grub-core/fs/minix.c | 32 +++++++++++++++++++------------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6d0cfde93..f73d431d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-10-28 Vladimir Serbinenko + + Use shifts in minix filesystem. + + * grub-core/fs/minix.c (GRUB_MINIX_ZONESZ): Use log_block_size. + (GRUB_MINIX_ZONE2SECT): Likewise. + (grub_minix_data): Replace block_size with log_block_size. + (grub_minix_read_file): Use shifts. + (grub_minix_mount): Check block size and take a logarithm. + 2011-10-28 Vladimir Serbinenko Use shifts in squash4. diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 43785b657..401883e36 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -76,11 +76,11 @@ typedef grub_uint16_t grub_minix_ino_t; #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ + grub_le_to_cpu16 (data->sblock.log2_zone_size)) #endif -#define GRUB_MINIX_ZONESZ (data->block_size \ - << grub_le_to_cpu16 (data->sblock.log2_zone_size)) +#define GRUB_MINIX_ZONESZ (1 << (data->log_block_size \ + + grub_le_to_cpu16 (data->sblock.log2_zone_size))) #ifdef MODE_MINIX3 -#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE)) +#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << (data->log_block_size - GRUB_DISK_SECTOR_BITS)) #else #define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ) #endif @@ -159,7 +159,7 @@ struct grub_minix_data int linknest; grub_disk_t disk; int filename_size; - grub_size_t block_size; + grub_size_t log_block_size; }; static grub_dl_t my_mod; @@ -251,14 +251,15 @@ grub_minix_read_file (struct grub_minix_data *data, if (len + pos > GRUB_MINIX_INODE_SIZE (data)) len = GRUB_MINIX_INODE_SIZE (data) - pos; - blockcnt = grub_divmod64 ((len + pos + data->block_size - 1), - data->block_size, 0); - posblock = grub_divmod64 (pos, data->block_size, &blockoff); + blockcnt = ((len + pos + (1 << data->log_block_size) - 1) + >> data->log_block_size); + posblock = pos >> data->log_block_size; + blockoff = pos & ((1 << data->log_block_size) - 1); for (i = posblock; i < blockcnt; i++) { grub_disk_addr_t blknr; - grub_uint64_t blockend = data->block_size; + grub_uint64_t blockend = 1 << data->log_block_size; grub_off_t skipfirst = 0; blknr = grub_minix_get_file_block (data, i); @@ -268,10 +269,10 @@ grub_minix_read_file (struct grub_minix_data *data, /* Last block. */ if (i == blockcnt - 1) { - grub_divmod64 (len + pos, data->block_size, &blockend); + blockend = (len + pos) & ((1 << data->log_block_size) - 1); if (!blockend) - blockend = data->block_size; + blockend = 1 << data->log_block_size; } /* First block. */ @@ -289,7 +290,7 @@ grub_minix_read_file (struct grub_minix_data *data, if (grub_errno) return -1; - buf += data->block_size - skipfirst; + buf += (1 << data->log_block_size) - skipfirst; } return len; @@ -479,9 +480,14 @@ grub_minix_mount (grub_disk_t disk) data->disk = disk; data->linknest = 0; #ifdef MODE_MINIX3 - data->block_size = grub_le_to_cpu16 (data->sblock.block_size); + if ((grub_le_to_cpu16 (data->sblock.block_size) + & (grub_le_to_cpu16 (data->sblock.block_size) - 1)) + || grub_le_to_cpu16 (data->sblock.block_size) == 0) + goto fail; + for (data->log_block_size = 0; (1 << data->log_block_size) + < grub_le_to_cpu16 (data->sblock.block_size); data->log_block_size++); #else - data->block_size = 1024U; + data->log_block_size = 10; #endif return data; From e551115a26167205995f315881881ddf0db7b722 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 28 Oct 2011 16:21:18 +0200 Subject: [PATCH 455/673] Use shifts in nilfs2. * grub-core/fs/nilfs2.c (LOG_INODE_SIZE): New definition. (LOG_NILFS_DAT_ENTRY_SIZE): Likewise. (grub_nilfs2_palloc_entries_per_group): Replace with ... (grub_nilfs2_log_palloc_entries_per_group): ... this. (grub_nilfs2_palloc_group): Use shifts and bitmasks. (grub_nilfs2_entries_per_block): Replaced with ... (grub_nilfs2_log_entries_per_block_log): ... this. (grub_nilfs2_blocks_per_group): Replaced with ... (grub_nilfs2_blocks_per_group_log): ... this. (grub_nilfs2_blocks_per_desc_block): Replaced with ... (grub_nilfs2_blocks_per_desc_block_log): ... this. (grub_nilfs2_palloc_desc_block_offset): Replaced with ... (grub_nilfs2_palloc_desc_block_offset_log): ... this. (grub_nilfs2_palloc_entry_offset): Replaced ... (grub_nilfs2_palloc_entry_offset_log): ... this. Use shifts. (grub_nilfs2_dat_translate): Use shifts. (grub_nilfs2_read_inode): Likewise. (GRUB_MOD_INIT): Ensure that logs are correct. --- ChangeLog | 23 ++++++++++++ grub-core/fs/nilfs2.c | 87 +++++++++++++++++++++++-------------------- 2 files changed, 70 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index f73d431d2..979b5335a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2011-10-28 Vladimir Serbinenko + + Use shifts in nilfs2. + + * grub-core/fs/nilfs2.c (LOG_INODE_SIZE): New definition. + (LOG_NILFS_DAT_ENTRY_SIZE): Likewise. + (grub_nilfs2_palloc_entries_per_group): Replace with ... + (grub_nilfs2_log_palloc_entries_per_group): ... this. + (grub_nilfs2_palloc_group): Use shifts and bitmasks. + (grub_nilfs2_entries_per_block): Replaced with ... + (grub_nilfs2_log_entries_per_block_log): ... this. + (grub_nilfs2_blocks_per_group): Replaced with ... + (grub_nilfs2_blocks_per_group_log): ... this. + (grub_nilfs2_blocks_per_desc_block): Replaced with ... + (grub_nilfs2_blocks_per_desc_block_log): ... this. + (grub_nilfs2_palloc_desc_block_offset): Replaced with ... + (grub_nilfs2_palloc_desc_block_offset_log): ... this. + (grub_nilfs2_palloc_entry_offset): Replaced ... + (grub_nilfs2_palloc_entry_offset_log): ... this. Use shifts. + (grub_nilfs2_dat_translate): Use shifts. + (grub_nilfs2_read_inode): Likewise. + (GRUB_MOD_INIT): Ensure that logs are correct. + 2011-10-28 Vladimir Serbinenko Use shifts in minix filesystem. diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 5986002ef..a8bbe9566 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -58,6 +58,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); in 512 block size */ #define NILFS_2ND_SUPER_BLOCK(devsize) (((devsize >> 3) - 1) << 3) +#define LOG_INODE_SIZE 7 struct grub_nilfs2_inode { grub_uint64_t i_blocks; @@ -214,6 +215,7 @@ struct grub_nilfs2_palloc_group_desc grub_uint32_t pg_nfrees; }; +#define LOG_NILFS_DAT_ENTRY_SIZE 5 struct grub_nilfs2_dat_entry { grub_uint64_t de_blocknr; @@ -296,17 +298,17 @@ static grub_dl_t my_mod; static inline unsigned long -grub_nilfs2_palloc_entries_per_group (struct grub_nilfs2_data *data) +grub_nilfs2_log_palloc_entries_per_group (struct grub_nilfs2_data *data) { - return 1UL << (LOG2_BLOCK_SIZE (data) + 3); + return LOG2_BLOCK_SIZE (data) + 3; } static inline grub_uint64_t grub_nilfs2_palloc_group (struct grub_nilfs2_data *data, grub_uint64_t nr, grub_uint64_t * offset) { - return grub_divmod64 (nr, grub_nilfs2_palloc_entries_per_group (data), - offset); + *offset = nr & ((1 << grub_nilfs2_log_palloc_entries_per_group (data)) - 1); + return nr >> grub_nilfs2_log_palloc_entries_per_group (data); } static inline grub_uint32_t @@ -317,55 +319,58 @@ grub_nilfs2_palloc_groups_per_desc_block (struct grub_nilfs2_data *data) } static inline grub_uint32_t -grub_nilfs2_entries_per_block (struct grub_nilfs2_data *data, - unsigned long entry_size) +grub_nilfs2_log_entries_per_block_log (struct grub_nilfs2_data *data, + unsigned long log_entry_size) { - return NILFS2_BLOCK_SIZE (data) / entry_size; + return LOG2_BLOCK_SIZE (data) - log_entry_size; } static inline grub_uint32_t -grub_nilfs2_blocks_per_group (struct grub_nilfs2_data *data, - unsigned long entry_size) +grub_nilfs2_blocks_per_group_log (struct grub_nilfs2_data *data, + unsigned long log_entry_size) { - return grub_div_roundup (grub_nilfs2_palloc_entries_per_group (data), - grub_nilfs2_entries_per_block (data, - entry_size)) + 1; + return (1 << (grub_nilfs2_log_palloc_entries_per_group (data) + - grub_nilfs2_log_entries_per_block_log (data, + log_entry_size))) + 1; } static inline grub_uint32_t -grub_nilfs2_blocks_per_desc_block (struct grub_nilfs2_data *data, - unsigned long entry_size) +grub_nilfs2_blocks_per_desc_block_log (struct grub_nilfs2_data *data, + unsigned long log_entry_size) { return grub_nilfs2_palloc_groups_per_desc_block (data) * - grub_nilfs2_blocks_per_group (data, entry_size) + 1; + grub_nilfs2_blocks_per_group_log (data, log_entry_size) + 1; } static inline grub_uint32_t -grub_nilfs2_palloc_desc_block_offset (struct grub_nilfs2_data *data, - unsigned long group, - unsigned long entry_size) +grub_nilfs2_palloc_desc_block_offset_log (struct grub_nilfs2_data *data, + unsigned long group, + unsigned long log_entry_size) { grub_uint32_t desc_block = group / grub_nilfs2_palloc_groups_per_desc_block (data); - return desc_block * grub_nilfs2_blocks_per_desc_block (data, entry_size); + return desc_block * grub_nilfs2_blocks_per_desc_block_log (data, + log_entry_size); } static inline grub_uint32_t grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data *data, unsigned long group, - unsigned long entry_size) + unsigned long log_entry_size) { unsigned long desc_offset = group % grub_nilfs2_palloc_groups_per_desc_block (data); - return grub_nilfs2_palloc_desc_block_offset (data, group, entry_size) + 1 + - desc_offset * grub_nilfs2_blocks_per_group (data, entry_size); + return grub_nilfs2_palloc_desc_block_offset_log (data, group, log_entry_size) + + 1 + + desc_offset * grub_nilfs2_blocks_per_group_log (data, log_entry_size); } static inline grub_uint32_t -grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data, - grub_uint64_t nr, unsigned long entry_size) +grub_nilfs2_palloc_entry_offset_log (struct grub_nilfs2_data *data, + grub_uint64_t nr, + unsigned long log_entry_size) { unsigned long group; grub_uint64_t group_offset; @@ -373,10 +378,9 @@ grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data, group = grub_nilfs2_palloc_group (data, nr, &group_offset); return grub_nilfs2_palloc_bitmap_block_offset (data, group, - entry_size) + 1 + - grub_divmod64 (group_offset, grub_nilfs2_entries_per_block (data, - entry_size), - NULL); + 1 << log_entry_size) + 1 + + (group_offset >> grub_nilfs2_log_entries_per_block_log (data, + log_entry_size)); } @@ -582,12 +586,11 @@ grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key) grub_uint64_t blockno, offset; unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); - blockno = grub_nilfs2_palloc_entry_offset (data, key, - sizeof (struct - grub_nilfs2_dat_entry)); + blockno = grub_nilfs2_palloc_entry_offset_log (data, key, + LOG_NILFS_DAT_ENTRY_SIZE); - grub_divmod64 (key * sizeof (struct grub_nilfs2_dat_entry), - NILFS2_BLOCK_SIZE (data), &offset); + offset = ((key * sizeof (struct grub_nilfs2_dat_entry)) + & ((1 << LOG2_BLOCK_SIZE (data)) - 1)); pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_dat, blockno, 0); if (pptr == (grub_uint64_t) - 1) @@ -652,8 +655,8 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data, sizeof(struct grub_nilfs2_checkpoint). */ blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) / - sizeof (struct grub_nilfs2_checkpoint), &offset); - + sizeof (struct grub_nilfs2_checkpoint), &offset); + pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1); if (pptr == (grub_uint64_t) - 1) { @@ -686,12 +689,11 @@ grub_nilfs2_read_inode (struct grub_nilfs2_data *data, grub_disk_t disk = data->disk; unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); - blockno = grub_nilfs2_palloc_entry_offset (data, ino, - sizeof (struct - grub_nilfs2_inode)); + blockno = grub_nilfs2_palloc_entry_offset_log (data, ino, + LOG_INODE_SIZE); - grub_divmod64 (sizeof (struct grub_nilfs2_inode) * ino, - NILFS2_BLOCK_SIZE (data), &offset); + offset = ((sizeof (struct grub_nilfs2_inode) * ino) + & ((1 << LOG2_BLOCK_SIZE (data)) - 1)); pptr = grub_nilfs2_bmap_lookup (data, &data->ifile, blockno, 1); if (pptr == (grub_uint64_t) - 1) { @@ -1178,6 +1180,11 @@ static struct grub_fs grub_nilfs2_fs = { GRUB_MOD_INIT (nilfs2) { + COMPILE_TIME_ASSERT ((1 << LOG_NILFS_DAT_ENTRY_SIZE) + == sizeof (struct + grub_nilfs2_dat_entry)); + COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE + == sizeof (struct grub_nilfs2_inode)); grub_fs_register (&grub_nilfs2_fs); my_mod = mod; } From c39224b052b2322cc75bca9432fdb29617415c82 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 28 Oct 2011 16:26:17 +0200 Subject: [PATCH 456/673] Prefer rockridge over Joliet. * grub-core/fs/iso9660.c (grub_iso9660_mount): Move rockridge detection to ... (set_rockridge): ... here. (grub_iso9660_mount): Check rockridge on the primary label when discovering. Ignore Joliet if Rockridge is present. --- ChangeLog | 10 +++ grub-core/fs/iso9660.c | 140 ++++++++++++++++++++++------------------- 2 files changed, 85 insertions(+), 65 deletions(-) diff --git a/ChangeLog b/ChangeLog index 979b5335a..deaa6ba68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-10-28 Vladimir Serbinenko + + Prefer rockridge over Joliet. + + * grub-core/fs/iso9660.c (grub_iso9660_mount): Move rockridge detection + to ... + (set_rockridge): ... here. + (grub_iso9660_mount): Check rockridge on the primary label when + discovering. Ignore Joliet if Rockridge is present. + 2011-10-28 Vladimir Serbinenko Use shifts in nilfs2. diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index f3e828b89..a2e731351 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -347,17 +347,14 @@ grub_iso9660_convert_string (grub_uint16_t *us, int len) return p; } -static struct grub_iso9660_data * -grub_iso9660_mount (grub_disk_t disk) +static grub_err_t +set_rockridge (struct grub_iso9660_data *data) { - struct grub_iso9660_data *data = 0; - struct grub_iso9660_dir rootdir; int sua_pos; int sua_size; char *sua; + struct grub_iso9660_dir rootdir; struct grub_iso9660_susp_entry *entry; - struct grub_iso9660_primary_voldesc voldesc; - int block; auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *); @@ -373,6 +370,67 @@ grub_iso9660_mount (grub_disk_t disk) return 0; } + data->rockridge = 0; + + /* Read the system use area and test it to see if SUSP is + supported. */ + if (grub_disk_read (data->disk, + (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector) + << GRUB_ISO9660_LOG2_BLKSZ), 0, + sizeof (rootdir), (char *) &rootdir)) + return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem"); + + sua_pos = (sizeof (rootdir) + rootdir.namelen + + (rootdir.namelen % 2) - 1); + sua_size = rootdir.len - sua_pos; + + if (!sua_size) + return GRUB_ERR_NONE; + + sua = grub_malloc (sua_size); + if (! sua) + return grub_errno; + + if (grub_disk_read (data->disk, + (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector) + << GRUB_ISO9660_LOG2_BLKSZ), sua_pos, + sua_size, sua)) + return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem"); + + entry = (struct grub_iso9660_susp_entry *) sua; + + /* Test if the SUSP protocol is used on this filesystem. */ + if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0) + { + struct grub_fshelp_node rootnode; + + rootnode.data = data; + rootnode.alloc_dirents = 0; + rootnode.have_dirents = 1; + rootnode.symlink = 0; + rootnode.dirents[0] = data->voldesc.rootdir; + + /* The 2nd data byte stored how many bytes are skipped every time + to get to the SUA (System Usage Area). */ + data->susp_skip = entry->data[2]; + entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len); + + /* Iterate over the entries in the SUA area to detect + extensions. */ + if (grub_iso9660_susp_iterate (&rootnode, + sua_pos, sua_size, susp_iterate)) + return grub_errno; + } + return GRUB_ERR_NONE; +} + +static struct grub_iso9660_data * +grub_iso9660_mount (grub_disk_t disk) +{ + struct grub_iso9660_data *data = 0; + struct grub_iso9660_primary_voldesc voldesc; + int block; + data = grub_zalloc (sizeof (struct grub_iso9660_data)); if (! data) return 0; @@ -400,9 +458,11 @@ grub_iso9660_mount (grub_disk_t disk) } if (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_PRIMARY) - copy_voldesc = 1; - else if ((voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP) && - (voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f) && + copy_voldesc = 1; + else if (!data->rockridge + && (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP) + && (voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f) + && ((voldesc.escape[2] == 0x40) || /* UCS-2 Level 1. */ (voldesc.escape[2] == 0x43) || /* UCS-2 Level 2. */ (voldesc.escape[2] == 0x45))) /* UCS-2 Level 3. */ @@ -412,66 +472,16 @@ grub_iso9660_mount (grub_disk_t disk) } if (copy_voldesc) - grub_memcpy((char *) &data->voldesc, (char *) &voldesc, - sizeof (struct grub_iso9660_primary_voldesc)); + { + grub_memcpy((char *) &data->voldesc, (char *) &voldesc, + sizeof (struct grub_iso9660_primary_voldesc)); + if (set_rockridge (data)) + goto fail; + } block++; } while (voldesc.voldesc.type != GRUB_ISO9660_VOLDESC_END); - /* Read the system use area and test it to see if SUSP is - supported. */ - if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector) - << GRUB_ISO9660_LOG2_BLKSZ), 0, - sizeof (rootdir), (char *) &rootdir)) - { - grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem"); - goto fail; - } - - sua_pos = (sizeof (rootdir) + rootdir.namelen - + (rootdir.namelen % 2) - 1); - sua_size = rootdir.len - sua_pos; - - if (!sua_size) - return data; - - sua = grub_malloc (sua_size); - if (! sua) - goto fail; - - if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector) - << GRUB_ISO9660_LOG2_BLKSZ), sua_pos, - sua_size, sua)) - { - grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem"); - goto fail; - } - - entry = (struct grub_iso9660_susp_entry *) sua; - - /* Test if the SUSP protocol is used on this filesystem. */ - if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0) - { - struct grub_fshelp_node rootnode; - - rootnode.data = data; - rootnode.alloc_dirents = 0; - rootnode.have_dirents = 1; - rootnode.symlink = 0; - rootnode.dirents[0] = data->voldesc.rootdir; - - /* The 2nd data byte stored how many bytes are skipped every time - to get to the SUA (System Usage Area). */ - data->susp_skip = entry->data[2]; - entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len); - - /* Iterate over the entries in the SUA area to detect - extensions. */ - if (grub_iso9660_susp_iterate (&rootnode, - sua_pos, sua_size, susp_iterate)) - goto fail; - } - return data; fail: From faba3d163aa2ef77a38e0aebfc0c873fadfdcb35 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 29 Oct 2011 11:29:34 +0200 Subject: [PATCH 457/673] Remove afs and befs because of copyright problem. * grub-core/fs/afs.c: Removed. * grub-core/fs/afs_be.c: Removed. * grub-core/fs/befs.c: Removed. * grub-core/fs/befs_be.c: Removed. * Makefile.util.def (libgrubkern): Remove afs, afs_be, befs and befs_be. * grub-core/Makefile.core.def (afs): Removed. (afs_be): Likewise. (befs): Likewise. (befs_be): Likewise. --- ChangeLog | 14 + Makefile.util.def | 4 - grub-core/Makefile.core.def | 20 - grub-core/fs/afs.c | 870 ------------------------------------ grub-core/fs/afs_be.c | 2 - grub-core/fs/befs.c | 3 - grub-core/fs/befs_be.c | 4 - 7 files changed, 14 insertions(+), 903 deletions(-) delete mode 100644 grub-core/fs/afs.c delete mode 100644 grub-core/fs/afs_be.c delete mode 100644 grub-core/fs/befs.c delete mode 100644 grub-core/fs/befs_be.c diff --git a/ChangeLog b/ChangeLog index deaa6ba68..892357ff3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-10-29 Vladimir Serbinenko + + Remove afs and befs because of copyright problem. + + * grub-core/fs/afs.c: Removed. + * grub-core/fs/afs_be.c: Removed. + * grub-core/fs/befs.c: Removed. + * grub-core/fs/befs_be.c: Removed. + * Makefile.util.def (libgrubkern): Remove afs, afs_be, befs and befs_be. + * grub-core/Makefile.core.def (afs): Removed. + (afs_be): Likewise. + (befs): Likewise. + (befs_be): Likewise. + 2011-10-28 Vladimir Serbinenko Prefer rockridge over Joliet. diff --git a/Makefile.util.def b/Makefile.util.def index 1b66ab961..bc66a51d4 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -55,10 +55,6 @@ library = { common = grub-core/disk/raid6_recover.c; common = grub-core/disk/raid.c; common = grub-core/fs/affs.c; - common = grub-core/fs/afs_be.c; - common = grub-core/fs/afs.c; - common = grub-core/fs/befs_be.c; - common = grub-core/fs/befs.c; common = grub-core/fs/btrfs.c; common = grub-core/fs/cpio.c; common = grub-core/fs/ext2.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 6d3c31ea6..2d91c3b64 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -970,26 +970,6 @@ module = { common = fs/affs.c; }; -module = { - name = afs; - common = fs/afs.c; -}; - -module = { - name = afs_be; - common = fs/afs_be.c; -}; - -module = { - name = befs; - common = fs/befs.c; -}; - -module = { - name = befs_be; - common = fs/befs_be.c; -}; - module = { name = btrfs; common = fs/btrfs.c; diff --git a/grub-core/fs/afs.c b/grub-core/fs/afs.c deleted file mode 100644 index 9a646ac88..000000000 --- a/grub-core/fs/afs.c +++ /dev/null @@ -1,870 +0,0 @@ -/* afs.c - The native AtheOS file-system. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 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 . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -GRUB_MOD_LICENSE ("GPLv3+"); - -#ifdef MODE_BIGENDIAN -#define GRUB_AFS_FSNAME_SUFFIX "_be" -#else -#define GRUB_AFS_FSNAME_SUFFIX "" -#endif - -#ifdef MODE_BFS -#define GRUB_AFS_FSNAME "befs" GRUB_AFS_FSNAME_SUFFIX -#else -#define GRUB_AFS_FSNAME "afs" GRUB_AFS_FSNAME_SUFFIX -#endif - -#define GRUB_AFS_DIRECT_BLOCK_COUNT 12 -#define GRUB_AFS_LOG_BLOCKS_PER_DI_RUN 2 - -#ifdef MODE_BFS -#define GRUB_AFS_SBLOCK_SECTOR 1 -#define GRUB_AFS_SBLOCK_MAGIC1 0x42465331 /* BFS1. */ -#else -#define GRUB_AFS_SBLOCK_SECTOR 2 -#define GRUB_AFS_SBLOCK_MAGIC1 0x41465331 /* AFS1. */ -#endif - -#define GRUB_AFS_SBLOCK_MAGIC2 0xdd121031 -#define GRUB_AFS_SBLOCK_MAGIC3 0x15b6830e - -#define GRUB_AFS_INODE_MAGIC 0x64358428 - -#ifdef MODE_BFS -#define GRUB_AFS_BTREE_MAGIC 0x69f6c2e8 -#else -#define GRUB_AFS_BTREE_MAGIC 0x65768995 -#endif - -#define GRUB_AFS_BNODE_SIZE 1024 - -#define GRUB_AFS_S_IFMT 00170000 -#define GRUB_AFS_S_IFLNK 0120000 - -#define GRUB_AFS_S_IFREG 0100000 -#define GRUB_AFS_S_IFDIR 0040000 -#define GRUB_AFS_S_IFIFO 0010000 - -#define GRUB_AFS_NULL_VAL ((grub_afs_bvalue_t)-1) - -#ifdef MODE_BIGENDIAN -#define grub_afs_to_cpu16(x) grub_be_to_cpu16 (x) -#define grub_afs_to_cpu32(x) grub_be_to_cpu32 (x) -#define grub_afs_to_cpu64(x) grub_be_to_cpu64 (x) -#else -#define grub_afs_to_cpu16(x) grub_le_to_cpu16 (x) -#define grub_afs_to_cpu32(x) grub_le_to_cpu32 (x) -#define grub_afs_to_cpu64(x) grub_le_to_cpu64 (x) -#endif - -#ifdef MODE_BFS -#define B_KEY_INDEX_ALIGN 8 -#else -#define B_KEY_INDEX_ALIGN 4 -#endif - -#define B_KEY_INDEX_OFFSET(node) ((grub_uint16_t *) \ - ((char *) (node) \ - + ALIGN_UP (sizeof (struct grub_afs_bnode) \ - + node->key_size, \ - B_KEY_INDEX_ALIGN))) - -#define B_KEY_VALUE_OFFSET(node) ((grub_afs_bvalue_t *) \ - ((char *) B_KEY_INDEX_OFFSET (node) + \ - node->key_count * 2)) - -typedef grub_uint64_t grub_afs_off_t; -typedef grub_uint64_t grub_afs_bigtime; -typedef grub_uint64_t grub_afs_bvalue_t; - -#define GRUB_AFS_BLOCKRUN_LOG_SIZE 3 -struct grub_afs_blockrun -{ - grub_uint32_t group; - grub_uint16_t start; - grub_uint16_t len; -} __attribute__ ((packed)); - -struct grub_afs_datastream -{ - struct grub_afs_blockrun direct[GRUB_AFS_DIRECT_BLOCK_COUNT]; - grub_afs_off_t max_direct_range; - struct grub_afs_blockrun indirect; - grub_afs_off_t max_indirect_range; - struct grub_afs_blockrun double_indirect; - grub_afs_off_t max_double_indirect_range; - grub_afs_off_t size; -} __attribute__ ((packed)); - -struct grub_afs_bnode -{ - grub_afs_bvalue_t left; - grub_afs_bvalue_t right; - grub_afs_bvalue_t overflow; -#ifdef MODE_BFS - grub_uint16_t key_count; - grub_uint16_t key_size; -#else - grub_uint32_t key_count; - grub_uint32_t key_size; -#endif - char key_data[0]; -} __attribute__ ((packed)); - -#ifdef MODE_BFS -struct grub_afs_btree -{ - grub_uint32_t magic; - grub_uint32_t unused1; - grub_uint32_t tree_depth; - grub_uint32_t unused2; - grub_afs_bvalue_t root; - grub_uint32_t unused3[4]; -} __attribute__ ((packed)); -#else -struct grub_afs_btree -{ - grub_uint32_t magic; - grub_afs_bvalue_t root; - grub_uint32_t tree_depth; - grub_afs_bvalue_t last_node; - grub_afs_bvalue_t first_free; -} __attribute__ ((packed)); -#endif - -/* Beware that following structure describes AtheFS and if you write code - which uses currently unused fields check it with both AtheFS and BeFS. - */ -struct grub_afs_sblock -{ - char name[32]; - grub_uint32_t magic1; - grub_uint32_t byte_order; - grub_uint32_t block_size; - grub_uint32_t block_shift; - grub_afs_off_t num_blocks; - grub_afs_off_t used_blocks; - grub_uint32_t inode_size; - grub_uint32_t magic2; - grub_uint32_t block_per_group; /* Number of blocks per allocation - group. (Max 65536) */ - grub_uint32_t alloc_group_shift; /* Number of bits to shift a group - number to get a byte address. */ - grub_uint32_t alloc_group_count; - grub_uint32_t flags; - struct grub_afs_blockrun log_block; - grub_afs_off_t log_start; - grub_uint32_t valid_log_blocks; - grub_uint32_t log_size; - grub_uint32_t magic3; - struct grub_afs_blockrun root_dir; /* Root dir inode. */ - struct grub_afs_blockrun deleted_files; /* Directory containing files - scheduled for deletion. */ - struct grub_afs_blockrun index_dir; /* Directory of index files. */ - grub_uint32_t boot_loader_size; - grub_uint32_t pad[7]; -} __attribute__ ((packed)); - -struct grub_afs_inode -{ - grub_uint32_t magic1; - struct grub_afs_blockrun inode_num; - grub_uint32_t uid; - grub_uint32_t gid; - grub_uint32_t mode; - grub_uint32_t flags; -#ifndef MODE_BFS - grub_uint32_t link_count; -#endif - grub_afs_bigtime create_time; - grub_afs_bigtime modified_time; - struct grub_afs_blockrun parent; - struct grub_afs_blockrun attrib_dir; - grub_uint32_t index_type; /* Key data-key only used for index files. */ - grub_uint32_t inode_size; - grub_uint32_t unused; - struct grub_afs_datastream stream; - grub_uint32_t pad[4]; - grub_uint8_t small_data[0]; -} __attribute__ ((packed)); - -struct grub_afs_small_data_element_header -{ - grub_uint32_t type; - grub_uint16_t name_len; - grub_uint16_t value_len; -} __attribute__ ((packed)); - -struct grub_fshelp_node -{ - struct grub_afs_data *data; - struct grub_afs_inode inode; -}; - -struct grub_afs_data -{ - grub_disk_t disk; - struct grub_afs_sblock sblock; - struct grub_afs_inode *inode; - struct grub_fshelp_node diropen; -}; - -static grub_dl_t my_mod; - -static int -grub_afs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)); -static grub_ssize_t -grub_afs_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), - grub_off_t pos, grub_size_t len, char *buf); - - -static grub_afs_off_t -grub_afs_run_to_num (struct grub_afs_sblock *sb, - struct grub_afs_blockrun *run) -{ - return ((grub_afs_off_t) grub_afs_to_cpu32 (run->group) - * sb->block_per_group + grub_afs_to_cpu16 (run->start)); -} - -static grub_err_t -grub_afs_read_inode (struct grub_afs_data *data, - grub_uint64_t ino, struct grub_afs_inode *inode) -{ - return grub_disk_read (data->disk, - ino << (data->sblock.block_shift - GRUB_DISK_SECTOR_BITS), - 0, data->sblock.block_size, inode); -} - -#ifdef MODE_BFS -static grub_ssize_t -grub_afs_read_attribute (grub_fshelp_node_t node, - const char *name, char *buf, grub_size_t len) -{ - grub_ssize_t read = -1; - auto int NESTED_FUNC_ATTR hook (const char *filename, - enum grub_fshelp_filetype filetype - __attribute__ ((unused)), - grub_fshelp_node_t attr_node); - - int NESTED_FUNC_ATTR hook (const char *filename, - enum grub_fshelp_filetype filetype - __attribute__ ((unused)), - grub_fshelp_node_t attr_node) - { - if (grub_strcmp (filename, name) == 0) - { - read = grub_afs_read_file (attr_node, 0, 0, len, buf); - return 1; - } - return 0; - } - grub_uint8_t *ptr = node->inode.small_data; - grub_uint8_t *end = ((grub_uint8_t *) &node->inode - + node->data->sblock.block_size); - - while (ptr + sizeof (struct grub_afs_small_data_element_header) < end) - { - struct grub_afs_small_data_element_header *el; - char *el_name; - grub_uint8_t *data; - el = (struct grub_afs_small_data_element_header *) ptr; - if (el->name_len == 0) - break; - el_name = (char *) (el + 1); - data = (grub_uint8_t *) el_name + grub_afs_to_cpu16 (el->name_len) + 3; - ptr = data + grub_afs_to_cpu16 (el->value_len) + 1; - if (grub_memcmp (name, el_name, grub_afs_to_cpu16 (el->name_len)) == 0 - && name[el->name_len] == 0) - { - grub_size_t copy; - copy = len; - if (grub_afs_to_cpu16 (el->value_len) > copy) - copy = grub_afs_to_cpu16 (el->value_len); - grub_memcpy (buf, data, copy); - return copy; - } - } - - { - struct grub_fshelp_node *fdiro; - - fdiro = grub_malloc (sizeof (struct grub_fshelp_node) - + node->data->sblock.block_size - - sizeof (struct grub_afs_inode)); - if (! fdiro) - return -1; - - fdiro->data = node->data; - if (grub_afs_read_inode (node->data, - grub_afs_run_to_num (&node->data->sblock, - &node->inode.attrib_dir), - &fdiro->inode)) - return -1; - - grub_afs_iterate_dir (fdiro, hook); - } - - return read; -} -#endif - -#ifdef MODE_BFS -#define RANGE_SHIFT sb->block_shift -#else -#define RANGE_SHIFT 0 -#endif - -static grub_disk_addr_t -grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) -{ - struct grub_afs_sblock *sb = &node->data->sblock; - struct grub_afs_datastream *ds = &node->inode.stream; - - if ((fileblock << RANGE_SHIFT) < grub_afs_to_cpu64 (ds->max_direct_range)) - { - int i; - - for (i = 0; i < GRUB_AFS_DIRECT_BLOCK_COUNT; i++) - { - if (fileblock < grub_afs_to_cpu16 (ds->direct[i].len)) - return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock; - fileblock -= grub_afs_to_cpu16 (ds->direct[i].len); - } - grub_error (GRUB_ERR_BAD_FS, "incorrect direct blocks"); - return 0; - } - else if ((fileblock << RANGE_SHIFT) - < grub_afs_to_cpu64 (ds->max_indirect_range)) - { - grub_size_t ptrs_per_blk = (1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)); - struct grub_afs_blockrun indir[ptrs_per_blk]; - grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect); - int i; - - fileblock -= grub_afs_to_cpu64 (ds->max_direct_range) >> RANGE_SHIFT; - for (i = 0; i < ds->indirect.len; i++, blk++) - { - grub_size_t j; - - if (grub_disk_read (node->data->disk, - blk << (sb->block_shift - GRUB_DISK_SECTOR_BITS), - 0, sizeof (indir), - indir)) - return 0; - - for (j = 0; j < ptrs_per_blk; j++) - { - if (fileblock < grub_afs_to_cpu16 (indir[j].len)) - return grub_afs_run_to_num (sb, &indir[j]) + fileblock; - - fileblock -= grub_afs_to_cpu16 (indir[j].len); - } - } - grub_error (GRUB_ERR_BAD_FS, "incorrect indirect blocks"); - return 0; - } - else if ((fileblock << RANGE_SHIFT) < grub_afs_to_cpu64 (ds->max_double_indirect_range)) - { - grub_size_t ptrs_per_blk = (1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)); - struct grub_afs_blockrun indir[ptrs_per_blk]; - grub_disk_addr_t off, dptr, dblk, idptr, idblk; - /* ([idblk][idptr]) ([dblk][dptr]) [blk] */ - - fileblock -= grub_afs_to_cpu64 (ds->max_indirect_range) >> RANGE_SHIFT; - - /* Divisions and modulo fixed number are optimised by compiler. */ - off = fileblock & ((1 << GRUB_AFS_LOG_BLOCKS_PER_DI_RUN) - 1); - dptr = fileblock >> GRUB_AFS_LOG_BLOCKS_PER_DI_RUN; - dblk = dptr >> (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE); - dptr &= ((1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)) - 1); - idptr = dblk >> GRUB_AFS_LOG_BLOCKS_PER_DI_RUN; - dblk &= ((1 << GRUB_AFS_LOG_BLOCKS_PER_DI_RUN) - 1); - idblk = idptr >> (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE); - idptr &= ((1 << (sb->block_shift - GRUB_AFS_BLOCKRUN_LOG_SIZE)) - 1); - - if (grub_disk_read (node->data->disk, - (grub_afs_run_to_num (sb, &ds->double_indirect) - + idblk) << (sb->block_shift - GRUB_DISK_SECTOR_BITS), - 0, sizeof (indir), - indir)) - return 0; - - if (grub_disk_read (node->data->disk, - (grub_afs_run_to_num (sb, &indir[idptr]) + dblk) - << (sb->block_shift - GRUB_DISK_SECTOR_BITS), - 0, sizeof (indir), - indir)) - return 0; - - return grub_afs_run_to_num (sb, &indir[dptr]) + off; - } - - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "triple-indirect on " GRUB_AFS_FSNAME " isn't supported"); - - return 0; -} - -static grub_ssize_t -grub_afs_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), - grub_off_t pos, grub_size_t len, char *buf) -{ - return grub_fshelp_read_file (node->data->disk, node, read_hook, - pos, len, buf, grub_afs_read_block, - grub_afs_to_cpu64 (node->inode.stream.size), - node->data->sblock.block_shift - - GRUB_DISK_SECTOR_BITS); -} - -static char * -grub_afs_read_symlink (grub_fshelp_node_t node) -{ - char *ret; - grub_afs_off_t size = grub_afs_to_cpu64 (node->inode.stream.size); - - if (size == 0) - { - size = sizeof (node->inode.stream); - ret = grub_zalloc (size + 1); - if (! ret) - return 0; - grub_memcpy (ret, (char *) &(node->inode.stream), - sizeof (node->inode.stream)); - return ret; - } - ret = grub_zalloc (size + 1); - if (! ret) - return 0; - grub_afs_read_file (node, 0, 0, size, ret); - return ret; -} - -static int -grub_afs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) -{ - struct grub_afs_btree head; - char node_data [GRUB_AFS_BNODE_SIZE]; - struct grub_afs_bnode *node = (struct grub_afs_bnode *) node_data; - int i; - - if ((dir->inode.stream.size == 0) - || ((grub_afs_to_cpu32 (dir->inode.mode) & GRUB_AFS_S_IFMT) - != GRUB_AFS_S_IFDIR)) - return 0; - - grub_afs_read_file (dir, 0, 0, sizeof (head), (char *) &head); - if (grub_errno) - return 0; - - grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (head.root), - GRUB_AFS_BNODE_SIZE, (char *) node); - if (grub_errno) - return 0; - - for (i = 0; i < (int) grub_afs_to_cpu32 (head.tree_depth) - 1; i++) - { - grub_afs_bvalue_t blk; - - blk = grub_afs_to_cpu64(B_KEY_VALUE_OFFSET (node) [0]); - grub_afs_read_file (dir, 0, blk, GRUB_AFS_BNODE_SIZE, (char *) node); - if (grub_errno) - return 0; - } - - if (node->key_count) - { - grub_uint32_t cur_key = 0; - - while (1) - { - int key_start, key_size; - grub_uint16_t *index; - - index = B_KEY_INDEX_OFFSET (node); - - key_start = (cur_key > 0) - ? grub_afs_to_cpu16 (index[cur_key - 1]) : 0; - key_size = grub_afs_to_cpu16 (index[cur_key]) - key_start; - if (key_size > 0) - { - char filename [key_size + 1]; - struct grub_fshelp_node *fdiro; - int mode, type; - - fdiro = grub_malloc (sizeof (struct grub_fshelp_node) - + dir->data->sblock.block_size - - sizeof (struct grub_afs_inode)); - if (! fdiro) - return 0; - - fdiro->data = dir->data; - if (grub_afs_read_inode (dir->data, - grub_afs_to_cpu64 - (B_KEY_VALUE_OFFSET (node) [cur_key]), - &fdiro->inode)) - return 0; - - grub_memcpy (filename, &node->key_data[key_start], key_size); - filename [key_size] = 0; - - mode = (grub_afs_to_cpu32 (fdiro->inode.mode) & GRUB_AFS_S_IFMT); - if (mode == GRUB_AFS_S_IFDIR) - type = GRUB_FSHELP_DIR; - else if (mode == GRUB_AFS_S_IFREG) - type = GRUB_FSHELP_REG; - else if (mode == GRUB_AFS_S_IFLNK) - type = GRUB_FSHELP_SYMLINK; - else - type = GRUB_FSHELP_UNKNOWN; - - if (hook (filename, type, fdiro)) - return 1; - } - - cur_key++; - if (cur_key >= grub_afs_to_cpu32 (node->key_count)) - { - if (node->right == GRUB_AFS_NULL_VAL) - break; - - grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (node->right), - GRUB_AFS_BNODE_SIZE, (char *) node); - if (grub_errno) - return 0; - - cur_key = 0; - } - } - } - - return 0; -} - -static int -grub_afs_validate_sblock (struct grub_afs_sblock *sb) -{ - if (grub_afs_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1) - { - sb->magic2 = grub_afs_to_cpu32 (sb->magic2); - sb->magic3 = grub_afs_to_cpu32 (sb->magic3); - sb->block_shift = grub_afs_to_cpu32 (sb->block_shift); - sb->block_size = grub_afs_to_cpu32 (sb->block_size); - sb->used_blocks = grub_afs_to_cpu64 (sb->used_blocks); - sb->num_blocks = grub_afs_to_cpu64 (sb->num_blocks); - sb->inode_size = grub_afs_to_cpu32 (sb->inode_size); - sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count); - sb->alloc_group_shift = grub_afs_to_cpu32 (sb->alloc_group_shift); - sb->block_per_group = grub_afs_to_cpu32 (sb->block_per_group); - sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count); - sb->log_size = grub_afs_to_cpu32 (sb->log_size); - } - else - return 0; - - if ((sb->magic2 != GRUB_AFS_SBLOCK_MAGIC2) || - (sb->magic3 != GRUB_AFS_SBLOCK_MAGIC3)) - return 0; - -#ifdef MODE_BFS - sb->block_per_group = 1 << (sb->alloc_group_shift); -#endif - - if (((grub_uint32_t) (1 << sb->block_shift) != sb->block_size) - || (sb->used_blocks > sb->num_blocks ) - || (sb->inode_size != sb->block_size) - || (0 == sb->block_size) -#ifndef MODE_BFS - || ((grub_uint32_t) (1 << sb->alloc_group_shift) != - sb->block_per_group * sb->block_size) - || (sb->alloc_group_count * sb->block_per_group < sb->num_blocks) - || (grub_afs_to_cpu16 (sb->log_block.len) != sb->log_size) - || (grub_afs_to_cpu32 (sb->valid_log_blocks) > sb->log_size) -#endif - ) - return 0; - - return 1; -} - -static struct grub_afs_data * -grub_afs_mount (grub_disk_t disk) -{ - struct grub_afs_data *data = 0; - struct grub_afs_sblock sb; - grub_err_t err; - - /* Read the superblock. */ - err = grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0, - sizeof (struct grub_afs_sblock), &sb); - if (err) - { - if (err == GRUB_ERR_OUT_OF_RANGE) - grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem"); - return NULL; - } - - if (! grub_afs_validate_sblock (&sb)) - { - grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem"); - return NULL; - } - - data = grub_malloc (sizeof (struct grub_afs_data) + sb.block_size - - sizeof (struct grub_afs_inode)); - if (!data) - return NULL; - - data->sblock = sb; - - data->diropen.data = data; - data->inode = &data->diropen.inode; - data->disk = disk; - - if (grub_afs_read_inode (data, - grub_afs_run_to_num (&data->sblock, - &data->sblock.root_dir), - data->inode)) - goto fail; - - return data; - -fail: - grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem"); - - grub_free (data); - return 0; -} - -static grub_err_t -grub_afs_open (struct grub_file *file, const char *name) -{ - struct grub_afs_data *data; - struct grub_fshelp_node *fdiro = 0; - - grub_dl_ref (my_mod); - - data = grub_afs_mount (file->device->disk); - if (! data) - goto fail; - - grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_afs_iterate_dir, - grub_afs_read_symlink, GRUB_FSHELP_REG); - if (grub_errno) - goto fail; - - grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_afs_inode)); - grub_free (fdiro); - - file->size = grub_afs_to_cpu64 (data->inode->stream.size); - file->data = data; - file->offset = 0; - - return 0; - -fail: - grub_free (data); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static grub_ssize_t -grub_afs_read (grub_file_t file, char *buf, grub_size_t len) -{ - struct grub_afs_data *data = (struct grub_afs_data *) file->data; - - return grub_afs_read_file (&data->diropen, file->read_hook, - file->offset, len, buf); -} - -static grub_err_t -grub_afs_close (grub_file_t file) -{ - grub_free (file->data); - - grub_dl_unref (my_mod); - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_afs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) -{ - struct grub_afs_data *data = 0; - struct grub_fshelp_node *fdiro = 0; - - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; -#ifdef MODE_BFS - info.mtime = grub_afs_to_cpu64 (node->inode.modified_time) >> 16; -#else - info.mtime = grub_divmod64 (grub_afs_to_cpu64 (node->inode.modified_time), - 1000000, 0); -#endif - grub_free (node); - return hook (filename, &info); - } - - grub_dl_ref (my_mod); - - data = grub_afs_mount (device->disk); - if (! data) - goto fail; - - grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_afs_iterate_dir, - grub_afs_read_symlink, GRUB_FSHELP_DIR); - if (grub_errno) - goto fail; - - grub_afs_iterate_dir (fdiro, iterate); - - if (fdiro != &data->diropen) - grub_free (fdiro); - - fail: - grub_free (data); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static grub_err_t -grub_afs_label (grub_device_t device, char **label) -{ - struct grub_afs_data *data; - grub_disk_t disk = device->disk; - - grub_dl_ref (my_mod); - - data = grub_afs_mount (disk); - if (data) - *label = grub_strndup (data->sblock.name, sizeof (data->sblock.name)); - else - *label = NULL; - - grub_dl_unref (my_mod); - - grub_free (data); - - return grub_errno; -} - -#ifdef MODE_BFS -static grub_err_t -grub_afs_uuid (grub_device_t device, char **uuid) -{ - struct grub_afs_data *data; - grub_disk_t disk = device->disk; - grub_uint64_t vid; - grub_ssize_t read; - - *uuid = NULL; - - data = grub_afs_mount (disk); - if (!data) - return grub_errno; - read = grub_afs_read_attribute (&data->diropen, "be:volume_id", - (char *) &vid, - sizeof (vid)); - if (read == sizeof (vid)) - *uuid = grub_xasprintf ("%" PRIxGRUB_UINT64_T, grub_afs_to_cpu64 (vid)); - - grub_free (data); - - return grub_errno; -} -#endif - -static struct grub_fs grub_afs_fs = { - .name = GRUB_AFS_FSNAME, - .dir = grub_afs_dir, - .open = grub_afs_open, - .read = grub_afs_read, - .close = grub_afs_close, - .label = grub_afs_label, -#ifdef MODE_BFS - .uuid = grub_afs_uuid, -#endif - .next = 0 -}; - -#if defined (MODE_BIGENDIAN) && defined (MODE_BFS) -GRUB_MOD_INIT (befs_be) -#elif defined (MODE_BFS) -GRUB_MOD_INIT (befs) -#elif defined (MODE_BIGENDIAN) -GRUB_MOD_INIT (afs_be) -#else -GRUB_MOD_INIT (afs) -#endif -{ - COMPILE_TIME_ASSERT ((1 << GRUB_AFS_BLOCKRUN_LOG_SIZE) - == sizeof (struct grub_afs_blockrun)); - grub_fs_register (&grub_afs_fs); - my_mod = mod; -} - -#if defined (MODE_BIGENDIAN) && defined (MODE_BFS) -GRUB_MOD_FINI (befs_be) -#elif defined (MODE_BFS) -GRUB_MOD_FINI (befs) -#elif defined (MODE_BIGENDIAN) -GRUB_MOD_FINI (afs_be) -#else -GRUB_MOD_FINI (afs) -#endif -{ - grub_fs_unregister (&grub_afs_fs); -} diff --git a/grub-core/fs/afs_be.c b/grub-core/fs/afs_be.c deleted file mode 100644 index 1f1f48fbb..000000000 --- a/grub-core/fs/afs_be.c +++ /dev/null @@ -1,2 +0,0 @@ -#define MODE_BIGENDIAN 1 -#include "afs.c" diff --git a/grub-core/fs/befs.c b/grub-core/fs/befs.c deleted file mode 100644 index c54d8e1cc..000000000 --- a/grub-core/fs/befs.c +++ /dev/null @@ -1,3 +0,0 @@ -/* befs.c - The native BeOS/Haiku file-system. */ -#define MODE_BFS 1 -#include "afs.c" diff --git a/grub-core/fs/befs_be.c b/grub-core/fs/befs_be.c deleted file mode 100644 index f6e8179f4..000000000 --- a/grub-core/fs/befs_be.c +++ /dev/null @@ -1,4 +0,0 @@ -/* befs.c - The native BeOS/Haiku file-system. */ -#define MODE_BFS 1 -#define MODE_BIGENDIAN 1 -#include "afs.c" From 93f87ec28d1e4bf67883407f80cce15dc094fc2c Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Sun, 30 Oct 2011 10:50:26 +0100 Subject: [PATCH 458/673] * grub-core/net/tcp.c (grub_net_ip_transport_checksum): Silence spurious warning. --- grub-core/net/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c index 579f94e99..d1f329fe2 100644 --- a/grub-core/net/tcp.c +++ b/grub-core/net/tcp.c @@ -410,7 +410,7 @@ grub_net_ip_transport_checksum (struct grub_net_buff *nb, const grub_net_network_level_address_t *src, const grub_net_network_level_address_t *dst) { - grub_uint16_t a, b; + grub_uint16_t a, b = 0; grub_uint32_t c; a = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) nb->data, nb->tail - nb->data)); From 61b99bfc2a2229f352f74eb8349f54b832e0064b Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Sun, 30 Oct 2011 11:16:23 +0100 Subject: [PATCH 459/673] * po/POTFILES.in: Regenerate because of the removal of afs, afs_be, befs and befs_be. --- ChangeLog | 5 +++++ po/POTFILES.in | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 892357ff3..604a427c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-30 Yves Blusseau + + * po/POTFILES.in: Regenerate because of the removal of afs, afs_be, befs + and befs_be. + 2011-10-29 Vladimir Serbinenko Remove afs and befs because of copyright problem. diff --git a/po/POTFILES.in b/po/POTFILES.in index ebb0aadaa..1c718520b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -127,10 +127,6 @@ ./grub-core/font/font.c ./grub-core/font/font_cmd.c ./grub-core/fs/affs.c -./grub-core/fs/afs_be.c -./grub-core/fs/afs.c -./grub-core/fs/befs_be.c -./grub-core/fs/befs.c ./grub-core/fs/btrfs.c ./grub-core/fs/cpio.c ./grub-core/fs/ext2.c From 42b2a706bf071a47d20af08389d1ea3f917f2691 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 13:18:22 +0100 Subject: [PATCH 460/673] * util/grub-fstest.c (cmd_cp): Clarify error message. (cmd_cmp): Likewise. --- ChangeLog | 5 +++++ util/grub-fstest.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 604a427c6..d8c4bf764 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-30 Vladimir Serbinenko + + * util/grub-fstest.c (cmd_cp): Clarify error message. + (cmd_cmp): Likewise. + 2011-10-30 Yves Blusseau * po/POTFILES.in: Regenerate because of the removal of afs, afs_be, befs diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 60889d05e..996d71c3a 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -182,7 +182,8 @@ cmd_cp (char *src, char *dest) ff = fopen (dest, "wb"); if (ff == NULL) { - grub_util_error (_("open error")); + grub_util_error (_("OS file %s open error: %s"), dest, + strerror (errno)); return; } read_file (src, cp_hook); @@ -241,7 +242,8 @@ cmd_cmp (char *src, char *dest) ff = fopen (dest, "rb"); if (ff == NULL) { - grub_util_error (_("open error")); + grub_util_error (_("OS file %s open error: %s"), dest, + strerror (errno)); return; } From 5825b3794be953aa1b5e2ec564e38713ca59418f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 13:25:51 +0100 Subject: [PATCH 461/673] BFS implementation based on the specification. * grub-core/fs/bfs.c: New file. * Makefile.util.def (libgrubmods): Add bfs.c. * grub-core/Makefile.core.def (bfs): New module. --- ChangeLog | 8 + Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/fs/bfs.c | 948 ++++++++++++++++++++++++++++++++++++ 4 files changed, 962 insertions(+) create mode 100644 grub-core/fs/bfs.c diff --git a/ChangeLog b/ChangeLog index d8c4bf764..d8ea7974c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-10-30 Vladimir Serbinenko + + BFS implementation based on the specification. + + * grub-core/fs/bfs.c: New file. + * Makefile.util.def (libgrubmods): Add bfs.c. + * grub-core/Makefile.core.def (bfs): New module. + 2011-10-30 Vladimir Serbinenko * util/grub-fstest.c (cmd_cp): Clarify error message. diff --git a/Makefile.util.def b/Makefile.util.def index bc66a51d4..053ff4340 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -55,6 +55,7 @@ library = { common = grub-core/disk/raid6_recover.c; common = grub-core/disk/raid.c; common = grub-core/fs/affs.c; + common = grub-core/fs/bfs.c; common = grub-core/fs/btrfs.c; common = grub-core/fs/cpio.c; common = grub-core/fs/ext2.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2d91c3b64..c6127b28f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -970,6 +970,11 @@ module = { common = fs/affs.c; }; +module = { + name = bfs; + common = fs/bfs.c; +}; + module = { name = btrfs; common = fs/btrfs.c; diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c new file mode 100644 index 000000000..6f6ebf908 --- /dev/null +++ b/grub-core/fs/bfs.c @@ -0,0 +1,948 @@ +/* bfs.c - The Bee File System. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ +/* + Based on the book "Practical File System Design by Dominic Giampaolo + with corrections and completitions based on Haiku code. +*/ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define grub_bfs_to_cpu16 grub_le_to_cpu16 +#define grub_bfs_to_cpu32 grub_le_to_cpu32 +#define grub_bfs_to_cpu64 grub_le_to_cpu64 + +#define SUPER_BLOCK_MAGIC1 0x42465331 +#define SUPER_BLOCK_MAGIC2 0xdd121031 +#define SUPER_BLOCK_MAGIC3 0x15b6830e +#define POINTER_INVALID 0xffffffffffffffffULL + +#define ATTR_TYPE 0160000 +#define ATTR_REG 0100000 +#define ATTR_DIR 0040000 +#define ATTR_LNK 0120000 + +#define DOUBLE_INDIRECT_SHIFT 2 + +#define LOG_EXTENT_SIZE 3 +struct grub_bfs_extent +{ + grub_uint32_t ag; + grub_uint16_t start; + grub_uint16_t len; +} __attribute__ ((packed)); + +struct grub_bfs_superblock +{ + char label[32]; + grub_uint32_t magic1; + grub_uint32_t unused1; + grub_uint32_t bsize; + grub_uint32_t log2_bsize; + grub_uint8_t unused[20]; + grub_uint32_t magic2; + grub_uint32_t unused2; + grub_uint32_t log2_ag_size; + grub_uint8_t unused3[32]; + grub_uint32_t magic3; + struct grub_bfs_extent root_dir; +} __attribute__ ((packed)); + +struct grub_bfs_inode +{ + grub_uint8_t unused[20]; + grub_uint32_t mode; + grub_uint32_t flags; + grub_uint8_t unused2[8]; + grub_uint64_t mtime; + grub_uint8_t unused3[8]; + struct grub_bfs_extent attr; + grub_uint8_t unused4[12]; + + union + { + struct + { + struct grub_bfs_extent direct[12]; + grub_uint64_t max_direct_range; + struct grub_bfs_extent indirect; + grub_uint64_t max_indirect_range; + struct grub_bfs_extent double_indirect; + grub_uint64_t max_double_indirect_range; + grub_uint64_t size; + grub_uint32_t pad[4]; + } __attribute__ ((packed)); + char inplace_link[144]; + } __attribute__ ((packed)); + grub_uint8_t small_data[0]; +} __attribute__ ((packed)); + +enum +{ + LONG_SYMLINK = 0x40 +}; + +struct grub_bfs_small_data_element_header +{ + grub_uint32_t type; + grub_uint16_t name_len; + grub_uint16_t value_len; +} __attribute__ ((packed)); + +struct grub_bfs_btree_header +{ + grub_uint32_t magic; + grub_uint32_t node_size; + grub_uint32_t level; + grub_uint32_t unused; + grub_uint64_t root; + grub_uint32_t unused2[2]; +} __attribute__ ((packed)); + +struct grub_bfs_btree_node +{ + grub_uint64_t unused; + grub_uint64_t right; + grub_uint64_t overflow; + grub_uint16_t count_keys; + grub_uint16_t total_key_len; +} __attribute__ ((packed)); + +struct grub_bfs_data +{ + struct grub_bfs_superblock sb; + struct grub_bfs_inode ino[0]; +}; + +static grub_err_t +read_extent (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + const struct grub_bfs_extent *in, + grub_off_t off, + grub_off_t byteoff, + void *buf, grub_size_t len) +{ + return grub_disk_read (disk, ((grub_bfs_to_cpu32 (in->ag) + << grub_bfs_to_cpu32 (sb->log2_ag_size)) + + grub_bfs_to_cpu16 (in->start) + off) + << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9) + , byteoff, + len, buf); +} + +static grub_err_t +read_bfs_file (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + const struct grub_bfs_inode *ino, + grub_off_t off, void *buf, grub_size_t len, + void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, + unsigned offset, unsigned length)) +{ + if (len == 0) + return GRUB_ERR_NONE; + + if (off + len > grub_bfs_to_cpu64 (ino->size)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "attempt to read past the end of file"); + + if (off < grub_bfs_to_cpu64 (ino->max_direct_range)) + { + unsigned i; + grub_uint64_t pos = 0; + for (i = 0; i < ARRAY_SIZE (ino->direct); i++) + { + grub_uint64_t newpos; + newpos = pos + (grub_bfs_to_cpu16 (ino->direct[i].len) + << grub_bfs_to_cpu32 (sb->log2_bsize)); + if (newpos > off) + { + grub_size_t read_size; + grub_err_t err; + read_size = newpos - off; + if (read_size > len) + read_size = len; + disk->read_hook = read_hook; + err = read_extent (disk, sb, &ino->direct[i], 0, off - pos, + buf, read_size); + disk->read_hook = 0; + if (err) + return err; + off += read_size; + len -= read_size; + buf = (char *) buf + read_size; + if (len == 0) + return GRUB_ERR_NONE; + } + pos = newpos; + } + } + + if (off < grub_bfs_to_cpu64 (ino->max_direct_range)) + return grub_error (GRUB_ERR_BAD_FS, "incorrect direct blocks"); + + if (off < grub_bfs_to_cpu64 (ino->max_indirect_range)) + { + unsigned i; + struct grub_bfs_extent *entries; + grub_size_t nentries; + grub_err_t err; + grub_uint64_t pos = grub_bfs_to_cpu64 (ino->max_direct_range); + nentries = (grub_bfs_to_cpu16 (ino->indirect.len) + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - LOG_EXTENT_SIZE)); + entries = grub_malloc (nentries << LOG_EXTENT_SIZE); + if (!entries) + return grub_errno; + err = read_extent (disk, sb, &ino->indirect, 0, 0, + entries, nentries << LOG_EXTENT_SIZE); + for (i = 0; i < nentries; i++) + { + grub_uint64_t newpos; + newpos = pos + (grub_bfs_to_cpu16 (entries[i].len) + << grub_bfs_to_cpu32 (sb->log2_bsize)); + if (newpos > off) + { + grub_size_t read_size; + read_size = newpos - off; + if (read_size > len) + read_size = len; + disk->read_hook = read_hook; + err = read_extent (disk, sb, &entries[i], 0, off - pos, + buf, read_size); + disk->read_hook = 0; + if (err) + { + grub_free (entries); + return err; + } + off += read_size; + len -= read_size; + buf = (char *) buf + read_size; + if (len == 0) + { + grub_free (entries); + return GRUB_ERR_NONE; + } + } + pos = newpos; + } + grub_free (entries); + } + + if (off < grub_bfs_to_cpu64 (ino->max_indirect_range)) + return grub_error (GRUB_ERR_BAD_FS, "incorrect indirect blocks"); + + { + struct grub_bfs_extent *l1_entries, *l2_entries; + grub_size_t nl1_entries, nl2_entries; + grub_off_t last_l1n = ~0ULL; + grub_err_t err; + nl1_entries = (grub_bfs_to_cpu16 (ino->double_indirect.len) + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - LOG_EXTENT_SIZE)); + l1_entries = grub_malloc (nl1_entries << LOG_EXTENT_SIZE); + if (!l1_entries) + return grub_errno; + nl2_entries = 0; + l2_entries = grub_malloc (1 << (DOUBLE_INDIRECT_SHIFT + + grub_bfs_to_cpu32 (sb->log2_bsize))); + if (!l2_entries) + { + grub_free (l1_entries); + return grub_errno; + } + err = read_extent (disk, sb, &ino->double_indirect, 0, 0, + l1_entries, nl1_entries << LOG_EXTENT_SIZE); + if (err) + { + grub_free (l1_entries); + grub_free (l2_entries); + return err; + } + + while (len > 0) + { + grub_off_t boff, l2n, l1n; + grub_size_t read_size; + grub_off_t double_indirect_offset; + double_indirect_offset = off + - grub_bfs_to_cpu64 (ino->max_indirect_range); + boff = (double_indirect_offset + & ((1 << (grub_bfs_to_cpu32 (sb->log2_bsize) + + DOUBLE_INDIRECT_SHIFT)) - 1)); + l2n = ((double_indirect_offset >> (grub_bfs_to_cpu32 (sb->log2_bsize) + + DOUBLE_INDIRECT_SHIFT)) + & ((1 << (grub_bfs_to_cpu32 (sb->log2_bsize) - LOG_EXTENT_SIZE + + DOUBLE_INDIRECT_SHIFT)) + - 1)); + l1n = (double_indirect_offset >> (2 * grub_bfs_to_cpu32 (sb->log2_bsize) + - LOG_EXTENT_SIZE + + 2 * DOUBLE_INDIRECT_SHIFT)); + if (l1n > nl1_entries) + { + grub_free (l1_entries); + grub_free (l2_entries); + return grub_error (GRUB_ERR_BAD_FS, + "incorrect double-indirect block"); + } + if (l1n != last_l1n) + { + nl2_entries = (grub_bfs_to_cpu16 (l1_entries[l1n].len) + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - LOG_EXTENT_SIZE)); + if (nl2_entries > (1U << (grub_bfs_to_cpu32 (sb->log2_bsize) + - LOG_EXTENT_SIZE + + DOUBLE_INDIRECT_SHIFT))) + nl2_entries = (1 << (grub_bfs_to_cpu32 (sb->log2_bsize) + - LOG_EXTENT_SIZE + + DOUBLE_INDIRECT_SHIFT)); + err = read_extent (disk, sb, &l1_entries[l1n], 0, 0, + l2_entries, nl2_entries << LOG_EXTENT_SIZE); + if (err) + { + grub_free (l1_entries); + grub_free (l2_entries); + return err; + } + last_l1n = l1n; + } + if (l2n > nl2_entries) + { + grub_free (l1_entries); + grub_free (l2_entries); + return grub_error (GRUB_ERR_BAD_FS, + "incorrect double-indirect block"); + } + + read_size = (1 << (grub_bfs_to_cpu32 (sb->log2_bsize) + + DOUBLE_INDIRECT_SHIFT)) - boff; + if (read_size > len) + read_size = len; + disk->read_hook = read_hook; + err = read_extent (disk, sb, &l2_entries[l2n], 0, boff, + buf, read_size); + disk->read_hook = 0; + if (err) + { + grub_free (l1_entries); + grub_free (l2_entries); + return err; + } + off += read_size; + len -= read_size; + buf = (char *) buf + read_size; + } + return GRUB_ERR_NONE; + } +} + +static int +iterate_in_b_tree (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + const struct grub_bfs_inode *ino, + int (*hook) (const char *name, grub_uint64_t value)) +{ + struct grub_bfs_btree_header head; + grub_err_t err; + int level; + grub_uint64_t node_off; + + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); + if (err) + return 0; + node_off = grub_bfs_to_cpu64 (head.root); + + level = grub_bfs_to_cpu32 (head.level) - 1; + while (level--) + { + struct grub_bfs_btree_node node; + grub_uint64_t key_value; + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + if (err) + return 0; + err = read_bfs_file (disk, sb, ino, node_off + + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), + 8) + + grub_bfs_to_cpu16 (node.count_keys) * 2, + &key_value, sizeof (grub_uint64_t), 0); + if (err) + return 0; + + node_off = grub_bfs_to_cpu64 (key_value); + } + + while (1) + { + struct grub_bfs_btree_node node; + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + if (err) + return 0; + { + char key_data[grub_bfs_to_cpu16 (node.total_key_len) + 1]; + grub_uint16_t keylen_idx[grub_bfs_to_cpu16 (node.count_keys)]; + grub_uint64_t key_values[grub_bfs_to_cpu16 (node.count_keys)]; + unsigned i; + grub_uint16_t start = 0, end = 0; + + err = read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, + grub_bfs_to_cpu16 (node.total_key_len), 0); + if (err) + return 0; + key_data[grub_bfs_to_cpu16 (node.total_key_len)] = 0; + err = read_bfs_file (disk, sb, ino, node_off + + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), + 8), + keylen_idx, grub_bfs_to_cpu16 (node.count_keys) + * 2, 0); + if (err) + return 0; + err = read_bfs_file (disk, sb, ino, node_off + + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), + 8) + + grub_bfs_to_cpu16 (node.count_keys) * 2, + key_values, grub_bfs_to_cpu16 (node.count_keys) + * 8, 0); + if (err) + return 0; + + for (i = 0; i < grub_bfs_to_cpu16 (node.count_keys); i++) + { + char c; + start = end; + end = grub_bfs_to_cpu16 (keylen_idx[i]); + c = key_data[end]; + key_data[end] = 0; + if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]))) + return 1; + key_data[end] = c; + } + node_off = grub_bfs_to_cpu64 (node.right); + if (node_off == POINTER_INVALID) + return 0; + } + } +} + +static grub_err_t +find_in_b_tree (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + const struct grub_bfs_inode *ino, const char *name, + grub_uint64_t *res) +{ + struct grub_bfs_btree_header head; + grub_err_t err; + int level; + grub_uint64_t node_off; + + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); + if (err) + return err; + node_off = grub_bfs_to_cpu64 (head.root); + + level = grub_bfs_to_cpu32 (head.level) - 1; + while (1) + { + struct grub_bfs_btree_node node; + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + if (err) + return err; + if (node.count_keys == 0) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", + name); + { + char key_data[grub_bfs_to_cpu16 (node.total_key_len) + 1]; + grub_uint16_t keylen_idx[grub_bfs_to_cpu16 (node.count_keys)]; + grub_uint64_t key_values[grub_bfs_to_cpu16 (node.count_keys)]; + unsigned i; + grub_uint16_t start = 0, end = 0; + err = read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, + grub_bfs_to_cpu16 (node.total_key_len), 0); + if (err) + return err; + key_data[grub_bfs_to_cpu16 (node.total_key_len)] = 0; + err = read_bfs_file (disk, sb, ino, node_off + + + ALIGN_UP (sizeof (node) +grub_bfs_to_cpu16 (node.total_key_len), + 8), + keylen_idx, grub_bfs_to_cpu16 (node.count_keys) + * 2, 0); + if (err) + return err; + err = read_bfs_file (disk, sb, ino, node_off + + + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), + 8) + + grub_bfs_to_cpu16 (node.count_keys) * 2, + key_values, grub_bfs_to_cpu16 (node.count_keys) + * 8, 0); + if (err) + return err; + + for (i = 0; i < grub_bfs_to_cpu16 (node.count_keys); i++) + { + int cmp; + char c; + start = end; + end = grub_bfs_to_cpu16 (keylen_idx[i]); + if (grub_bfs_to_cpu16 (node.total_key_len) <= end) + end = grub_bfs_to_cpu16 (node.total_key_len); + c = key_data[end]; + key_data[end] = 0; + cmp = grub_strcmp (key_data + start, name); + key_data[end] = c; + if (cmp == 0 && level == 0) + { + *res = grub_bfs_to_cpu64 (key_values[i]); + return GRUB_ERR_NONE; + } + if (cmp >= 0 && level != 0) + { + node_off = grub_bfs_to_cpu64 (key_values[i]); + break; + } + } + if (i < grub_bfs_to_cpu16 (node.count_keys)) + { + level--; + continue; + } + if (node.overflow != POINTER_INVALID) + { + node_off = grub_bfs_to_cpu64 (node.overflow); + /* This level-- isn't specified but is needed. */ + level--; + continue; + } + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", + name); + } + } +} + +static grub_err_t +hop_level (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + struct grub_bfs_inode *ino, + const char *name) +{ + grub_err_t err; + grub_uint64_t res; + + if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + + err = find_in_b_tree (disk, sb, ino, name, &res); + if (err) + return err; + + return grub_disk_read (disk, res + << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9), 0, + grub_bfs_to_cpu32 (sb->bsize), (char *) ino); +} + +static grub_err_t +find_file (const char *path, grub_disk_t disk, + const struct grub_bfs_superblock *sb, + struct grub_bfs_inode *ino) +{ + char *ptr, *ptr2; + char *alloc = NULL; + grub_err_t err; + union { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; + } old_ino; + unsigned symlinks_max = 32; + + err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, + grub_bfs_to_cpu32 (sb->bsize)); + if (err) + return err; + + ptr = (char *) path; + while (1) + { + while (*ptr == '/') + ptr++; + if (*ptr == 0) + { + grub_free (alloc); + return GRUB_ERR_NONE; + } + ptr2 = grub_strchr (ptr, '/'); + grub_memcpy (&old_ino, ino, grub_bfs_to_cpu32 (sb->bsize)); + if (ptr2) + { + char component[ptr2 - ptr + 1]; + grub_memcpy (component, ptr, ptr2 - ptr); + component[ptr2 - ptr] = 0; + err = hop_level (disk, sb, ino, component); + } + else + err = hop_level (disk, sb, ino, ptr); + if (err) + return err; + + if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) == ATTR_LNK)) + { + char *old_alloc = alloc; + if (--symlinks_max == 0) + { + grub_free (alloc); + return grub_error (GRUB_ERR_SYMLINK_LOOP, + "too deep nesting of symlinks"); + } + + if (grub_bfs_to_cpu32 (ino->flags) & LONG_SYMLINK) + { + grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); + alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) + + + symsize + 1); + if (!alloc) + { + grub_free (alloc); + return grub_errno; + } + grub_free (old_alloc); + err = read_bfs_file (disk, sb, ino, + 0, alloc, symsize, 0); + if (err) + { + grub_free (alloc); + return err; + } + alloc[symsize] = 0; + } + else + { + alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) + + sizeof (ino->inplace_link) + 1); + if (!alloc) + { + grub_free (alloc); + return grub_errno; + } + grub_free (old_alloc); + grub_memcpy (alloc, ino->inplace_link, + sizeof (ino->inplace_link)); + alloc[sizeof (ino->inplace_link)] = 0; + } + if (alloc[0] == '/') + { + err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, + grub_bfs_to_cpu32 (sb->bsize)); + if (err) + { + grub_free (alloc); + return err; + } + } + else + grub_memcpy (ino, &old_ino, grub_bfs_to_cpu32 (sb->bsize)); + ptr = alloc + grub_strlen (alloc); + if (ptr2) + ptr = grub_stpcpy (ptr, ptr2); + *ptr = 0; + ptr = ptr2 = alloc; + continue; + } + + if (!ptr2) + { + grub_free (alloc); + return GRUB_ERR_NONE; + } + ptr = ptr2 + 1; + } +} + +static grub_err_t +mount (grub_disk_t disk, struct grub_bfs_superblock *sb) +{ + grub_err_t err; + err = grub_disk_read (disk, 1, 0, + sizeof (*sb), sb); + if (err == GRUB_ERR_OUT_OF_RANGE) + return grub_error (GRUB_ERR_BAD_FS, "not a BFS filesystem"); + if (err) + return err; + if (grub_bfs_to_cpu32 (sb->magic1) != SUPER_BLOCK_MAGIC1 + || grub_bfs_to_cpu32 (sb->magic2) != SUPER_BLOCK_MAGIC2 + || grub_bfs_to_cpu32 (sb->magic3) != SUPER_BLOCK_MAGIC3 + || (grub_bfs_to_cpu32 (sb->bsize) + != (1U << grub_bfs_to_cpu32 (sb->log2_bsize)))) + return grub_error (GRUB_ERR_BAD_FS, "not a BFS filesystem"); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_bfs_dir (grub_device_t device, const char *path, + int (*hook_in) (const char *filename, + const struct grub_dirhook_info *info)) +{ + struct grub_bfs_superblock sb; + grub_err_t err; + auto int hook (const char *name, grub_uint64_t value); + + int hook (const char *name, grub_uint64_t value) + { + grub_err_t err2; + union { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; + } ino; + struct grub_dirhook_info info; + + err2 = grub_disk_read (device->disk, value + << (grub_bfs_to_cpu32 (sb.log2_bsize) - 9) + , 0, + grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw); + if (err2) + { + grub_print_error (); + return 0; + } + + info.mtimeset = 1; + info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; + info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR); + return hook_in (name, &info); + } + err = mount (device->disk, &sb); + if (err) + return err; + + { + union { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; + } ino; + err = find_file (path, device->disk, &sb, &ino.ino); + if (err) + return err; + if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + iterate_in_b_tree (device->disk, &sb, &ino.ino, hook); + } + + return grub_errno; +} + +static grub_err_t +grub_bfs_open (struct grub_file *file, const char *name) +{ + struct grub_bfs_superblock sb; + grub_err_t err; + + err = mount (file->device->disk, &sb); + if (err) + return err; + + { + union { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; + } ino; + struct grub_bfs_data *data; + err = find_file (name, file->device->disk, &sb, &ino.ino); + if (err) + return err; + if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_REG)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + + data = grub_zalloc (sizeof (struct grub_bfs_data) + + grub_bfs_to_cpu32 (sb.bsize)); + if (!data) + return grub_errno; + data->sb = sb; + grub_memcpy (&data->ino, &ino, grub_bfs_to_cpu32 (sb.bsize)); + file->data = data; + file->size = grub_bfs_to_cpu64 (ino.ino.size); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_bfs_close (grub_file_t file) +{ + grub_free (file->data); + + return GRUB_ERR_NONE; +} + +static grub_ssize_t +grub_bfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + grub_err_t err; + struct grub_bfs_data *data = file->data; + + err = read_bfs_file (file->device->disk, &data->sb, + data->ino, + file->offset, buf, len, file->read_hook); + if (err) + return -1; + return len; +} + +static grub_err_t +grub_bfs_label (grub_device_t device, char **label) +{ + struct grub_bfs_superblock sb; + grub_err_t err; + + *label = 0; + + err = mount (device->disk, &sb); + if (err) + return err; + + *label = grub_strndup (sb.label, sizeof (sb.label)); + return GRUB_ERR_NONE; +} + +static grub_ssize_t +read_bfs_attr (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + const struct grub_bfs_inode *ino, + const char *name, + void *buf, grub_size_t len) +{ + grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data; + grub_uint8_t *end = ((grub_uint8_t *) ino + + grub_bfs_to_cpu32 (sb->bsize)); + + while (ptr + sizeof (struct grub_bfs_small_data_element_header) < end) + { + struct grub_bfs_small_data_element_header *el; + char *el_name; + grub_uint8_t *data; + el = (struct grub_bfs_small_data_element_header *) ptr; + if (el->name_len == 0) + break; + el_name = (char *) (el + 1); + data = (grub_uint8_t *) el_name + grub_bfs_to_cpu16 (el->name_len) + 3; + ptr = data + grub_bfs_to_cpu16 (el->value_len) + 1; + if (grub_memcmp (name, el_name, grub_bfs_to_cpu16 (el->name_len)) == 0 + && name[el->name_len] == 0) + { + grub_size_t copy; + copy = len; + if (grub_bfs_to_cpu16 (el->value_len) > copy) + copy = grub_bfs_to_cpu16 (el->value_len); + grub_memcpy (buf, data, copy); + return copy; + } + } + + if (ino->attr.len != 0) + { + union { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; + } ino2; + grub_size_t read; + grub_err_t err; + grub_uint64_t res; + + err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, + grub_bfs_to_cpu32 (sb->bsize)); + if (err) + return -1; + + err = find_in_b_tree (disk, sb, &ino2.ino, name, &res); + if (err) + return -1; + grub_disk_read (disk, res + << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9) + , 0, + grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); + read = grub_bfs_to_cpu64 (ino2.ino.size); + if (read > len) + read = len; + + err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0); + if (err) + return -1; + return read; + } + return -1; +} + +static grub_err_t +grub_bfs_uuid (grub_device_t device, char **uuid) +{ + struct grub_bfs_superblock sb; + grub_err_t err; + + *uuid = 0; + + err = mount (device->disk, &sb); + if (err) + return err; + + { + union { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; + } ino; + grub_uint64_t vid; + + err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, + &ino, grub_bfs_to_cpu32 (sb.bsize)); + if (err) + return err; + if (read_bfs_attr (device->disk, &sb, &ino.ino, "be:volume_id", + &vid, 8) == 8) + *uuid = grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); + } + return GRUB_ERR_NONE; +} + + +static struct grub_fs grub_bfs_fs = { + .name = "bfs", + .dir = grub_bfs_dir, + .open = grub_bfs_open, + .read = grub_bfs_read, + .close = grub_bfs_close, + .label = grub_bfs_label, + .uuid = grub_bfs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, +#endif +}; + +GRUB_MOD_INIT (bfs) +{ + COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE == sizeof (struct grub_bfs_extent)); + grub_fs_register (&grub_bfs_fs); +} + +GRUB_MOD_FINI (bfs) +{ + grub_fs_unregister (&grub_bfs_fs); +} From c4a1628f6765a330f7d1afc40cefc139512b9e6c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 13:27:53 +0100 Subject: [PATCH 462/673] * grub-core/fs/bfs.c: Run indent. --- ChangeLog | 4 + grub-core/fs/bfs.c | 220 +++++++++++++++++++++++---------------------- 2 files changed, 115 insertions(+), 109 deletions(-) diff --git a/ChangeLog b/ChangeLog index d8ea7974c..c52bff5b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-30 Vladimir Serbinenko + + * grub-core/fs/bfs.c: Run indent. + 2011-10-30 Vladimir Serbinenko BFS implementation based on the specification. diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index 6f6ebf908..7b6e359ae 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -141,15 +141,12 @@ static grub_err_t read_extent (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_extent *in, - grub_off_t off, - grub_off_t byteoff, - void *buf, grub_size_t len) + grub_off_t off, grub_off_t byteoff, void *buf, grub_size_t len) { return grub_disk_read (disk, ((grub_bfs_to_cpu32 (in->ag) << grub_bfs_to_cpu32 (sb->log2_ag_size)) + grub_bfs_to_cpu16 (in->start) + off) - << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9) - , byteoff, + << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9), byteoff, len, buf); } @@ -159,13 +156,15 @@ read_bfs_file (grub_disk_t disk, const struct grub_bfs_inode *ino, grub_off_t off, void *buf, grub_size_t len, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length)) + unsigned offset, + unsigned length)) { if (len == 0) return GRUB_ERR_NONE; if (off + len > grub_bfs_to_cpu64 (ino->size)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "attempt to read past the end of file"); + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "attempt to read past the end of file"); if (off < grub_bfs_to_cpu64 (ino->max_direct_range)) { @@ -210,11 +209,10 @@ read_bfs_file (grub_disk_t disk, grub_err_t err; grub_uint64_t pos = grub_bfs_to_cpu64 (ino->max_direct_range); nentries = (grub_bfs_to_cpu16 (ino->indirect.len) - << (grub_bfs_to_cpu32 (sb->log2_bsize) - - LOG_EXTENT_SIZE)); + << (grub_bfs_to_cpu32 (sb->log2_bsize) - LOG_EXTENT_SIZE)); entries = grub_malloc (nentries << LOG_EXTENT_SIZE); if (!entries) - return grub_errno; + return grub_errno; err = read_extent (disk, sb, &ino->indirect, 0, 0, entries, nentries << LOG_EXTENT_SIZE); for (i = 0; i < nentries; i++) @@ -260,8 +258,7 @@ read_bfs_file (grub_disk_t disk, grub_off_t last_l1n = ~0ULL; grub_err_t err; nl1_entries = (grub_bfs_to_cpu16 (ino->double_indirect.len) - << (grub_bfs_to_cpu32 (sb->log2_bsize) - - LOG_EXTENT_SIZE)); + << (grub_bfs_to_cpu32 (sb->log2_bsize) - LOG_EXTENT_SIZE)); l1_entries = grub_malloc (nl1_entries << LOG_EXTENT_SIZE); if (!l1_entries) return grub_errno; @@ -271,7 +268,7 @@ read_bfs_file (grub_disk_t disk, if (!l2_entries) { grub_free (l1_entries); - return grub_errno; + return grub_errno; } err = read_extent (disk, sb, &ino->double_indirect, 0, 0, l1_entries, nl1_entries << LOG_EXTENT_SIZE); @@ -289,17 +286,17 @@ read_bfs_file (grub_disk_t disk, grub_off_t double_indirect_offset; double_indirect_offset = off - grub_bfs_to_cpu64 (ino->max_indirect_range); - boff = (double_indirect_offset + boff = (double_indirect_offset & ((1 << (grub_bfs_to_cpu32 (sb->log2_bsize) + DOUBLE_INDIRECT_SHIFT)) - 1)); l2n = ((double_indirect_offset >> (grub_bfs_to_cpu32 (sb->log2_bsize) + DOUBLE_INDIRECT_SHIFT)) & ((1 << (grub_bfs_to_cpu32 (sb->log2_bsize) - LOG_EXTENT_SIZE - + DOUBLE_INDIRECT_SHIFT)) - - 1)); - l1n = (double_indirect_offset >> (2 * grub_bfs_to_cpu32 (sb->log2_bsize) - - LOG_EXTENT_SIZE - + 2 * DOUBLE_INDIRECT_SHIFT)); + + DOUBLE_INDIRECT_SHIFT)) - 1)); + l1n = + (double_indirect_offset >> + (2 * grub_bfs_to_cpu32 (sb->log2_bsize) - LOG_EXTENT_SIZE + + 2 * DOUBLE_INDIRECT_SHIFT)); if (l1n > nl1_entries) { grub_free (l1_entries); @@ -383,9 +380,10 @@ iterate_in_b_tree (grub_disk_t disk, if (err) return 0; err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), - 8) - + grub_bfs_to_cpu16 (node.count_keys) * 2, + + ALIGN_UP (sizeof (node) + + grub_bfs_to_cpu16 (node.total_key_len), + 8) + + grub_bfs_to_cpu16 (node.count_keys) * 2, &key_value, sizeof (grub_uint64_t), 0); if (err) return 0; @@ -395,7 +393,7 @@ iterate_in_b_tree (grub_disk_t disk, while (1) { - struct grub_bfs_btree_node node; + struct grub_bfs_btree_node node; err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); if (err) return 0; @@ -406,24 +404,28 @@ iterate_in_b_tree (grub_disk_t disk, unsigned i; grub_uint16_t start = 0, end = 0; - err = read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu16 (node.total_key_len), 0); + err = + read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, + grub_bfs_to_cpu16 (node.total_key_len), 0); if (err) return 0; key_data[grub_bfs_to_cpu16 (node.total_key_len)] = 0; - err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), - 8), - keylen_idx, grub_bfs_to_cpu16 (node.count_keys) - * 2, 0); + err = read_bfs_file (disk, sb, ino, node_off + + ALIGN_UP (sizeof (node) + + grub_bfs_to_cpu16 (node. + total_key_len), + 8), keylen_idx, + grub_bfs_to_cpu16 (node.count_keys) * 2, 0); if (err) return 0; err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), - 8) - + grub_bfs_to_cpu16 (node.count_keys) * 2, - key_values, grub_bfs_to_cpu16 (node.count_keys) - * 8, 0); + + ALIGN_UP (sizeof (node) + + grub_bfs_to_cpu16 (node. + total_key_len), + 8) + + grub_bfs_to_cpu16 (node.count_keys) * 2, + key_values, + grub_bfs_to_cpu16 (node.count_keys) * 8, 0); if (err) return 0; @@ -449,7 +451,7 @@ static grub_err_t find_in_b_tree (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, const char *name, - grub_uint64_t *res) + grub_uint64_t * res) { struct grub_bfs_btree_header head; grub_err_t err; @@ -464,7 +466,7 @@ find_in_b_tree (grub_disk_t disk, level = grub_bfs_to_cpu32 (head.level) - 1; while (1) { - struct grub_bfs_btree_node node; + struct grub_bfs_btree_node node; err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); if (err) return err; @@ -477,26 +479,28 @@ find_in_b_tree (grub_disk_t disk, grub_uint64_t key_values[grub_bfs_to_cpu16 (node.count_keys)]; unsigned i; grub_uint16_t start = 0, end = 0; - err = read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu16 (node.total_key_len), 0); + err = + read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, + grub_bfs_to_cpu16 (node.total_key_len), 0); if (err) return err; key_data[grub_bfs_to_cpu16 (node.total_key_len)] = 0; - err = read_bfs_file (disk, sb, ino, node_off - + - ALIGN_UP (sizeof (node) +grub_bfs_to_cpu16 (node.total_key_len), - 8), - keylen_idx, grub_bfs_to_cpu16 (node.count_keys) - * 2, 0); + err = read_bfs_file (disk, sb, ino, node_off + + + ALIGN_UP (sizeof (node) + + grub_bfs_to_cpu16 (node.total_key_len), + 8), keylen_idx, + grub_bfs_to_cpu16 (node.count_keys) * 2, 0); if (err) return err; - err = read_bfs_file (disk, sb, ino, node_off - - + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), - 8) - + grub_bfs_to_cpu16 (node.count_keys) * 2, - key_values, grub_bfs_to_cpu16 (node.count_keys) - * 8, 0); + err = read_bfs_file (disk, sb, ino, node_off + + ALIGN_UP (sizeof (node) + + grub_bfs_to_cpu16 (node. + total_key_len), + 8) + + grub_bfs_to_cpu16 (node.count_keys) * 2, + key_values, + grub_bfs_to_cpu16 (node.count_keys) * 8, 0); if (err) return err; @@ -544,8 +548,7 @@ find_in_b_tree (grub_disk_t disk, static grub_err_t hop_level (grub_disk_t disk, const struct grub_bfs_superblock *sb, - struct grub_bfs_inode *ino, - const char *name) + struct grub_bfs_inode *ino, const char *name) { grub_err_t err; grub_uint64_t res; @@ -564,13 +567,13 @@ hop_level (grub_disk_t disk, static grub_err_t find_file (const char *path, grub_disk_t disk, - const struct grub_bfs_superblock *sb, - struct grub_bfs_inode *ino) + const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) { char *ptr, *ptr2; char *alloc = NULL; grub_err_t err; - union { + union + { struct grub_bfs_inode ino; grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; } old_ino; @@ -619,7 +622,6 @@ find_file (const char *path, grub_disk_t disk, { grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) - + symsize + 1); if (!alloc) { @@ -627,8 +629,7 @@ find_file (const char *path, grub_disk_t disk, return grub_errno; } grub_free (old_alloc); - err = read_bfs_file (disk, sb, ino, - 0, alloc, symsize, 0); + err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0); if (err) { grub_free (alloc); @@ -638,7 +639,7 @@ find_file (const char *path, grub_disk_t disk, } else { - alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) + alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) + sizeof (ino->inplace_link) + 1); if (!alloc) { @@ -653,7 +654,7 @@ find_file (const char *path, grub_disk_t disk, if (alloc[0] == '/') { err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, - grub_bfs_to_cpu32 (sb->bsize)); + grub_bfs_to_cpu32 (sb->bsize)); if (err) { grub_free (alloc); @@ -683,8 +684,7 @@ static grub_err_t mount (grub_disk_t disk, struct grub_bfs_superblock *sb) { grub_err_t err; - err = grub_disk_read (disk, 1, 0, - sizeof (*sb), sb); + err = grub_disk_read (disk, 1, 0, sizeof (*sb), sb); if (err == GRUB_ERR_OUT_OF_RANGE) return grub_error (GRUB_ERR_BAD_FS, "not a BFS filesystem"); if (err) @@ -692,7 +692,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) if (grub_bfs_to_cpu32 (sb->magic1) != SUPER_BLOCK_MAGIC1 || grub_bfs_to_cpu32 (sb->magic2) != SUPER_BLOCK_MAGIC2 || grub_bfs_to_cpu32 (sb->magic3) != SUPER_BLOCK_MAGIC3 - || (grub_bfs_to_cpu32 (sb->bsize) + || (grub_bfs_to_cpu32 (sb->bsize) != (1U << grub_bfs_to_cpu32 (sb->log2_bsize)))) return grub_error (GRUB_ERR_BAD_FS, "not a BFS filesystem"); return GRUB_ERR_NONE; @@ -701,7 +701,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) static grub_err_t grub_bfs_dir (grub_device_t device, const char *path, int (*hook_in) (const char *filename, - const struct grub_dirhook_info *info)) + const struct grub_dirhook_info * info)) { struct grub_bfs_superblock sb; grub_err_t err; @@ -710,21 +710,21 @@ grub_bfs_dir (grub_device_t device, const char *path, int hook (const char *name, grub_uint64_t value) { grub_err_t err2; - union { + union + { struct grub_bfs_inode ino; grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; } ino; struct grub_dirhook_info info; err2 = grub_disk_read (device->disk, value - << (grub_bfs_to_cpu32 (sb.log2_bsize) - 9) - , 0, + << (grub_bfs_to_cpu32 (sb.log2_bsize) - 9), 0, grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw); if (err2) { grub_print_error (); return 0; - } + } info.mtimeset = 1; info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; @@ -736,7 +736,8 @@ grub_bfs_dir (grub_device_t device, const char *path, return err; { - union { + union + { struct grub_bfs_inode ino; grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; } ino; @@ -762,7 +763,8 @@ grub_bfs_open (struct grub_file *file, const char *name) return err; { - union { + union + { struct grub_bfs_inode ino; grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; } ino; @@ -799,10 +801,9 @@ grub_bfs_read (grub_file_t file, char *buf, grub_size_t len) { grub_err_t err; struct grub_bfs_data *data = file->data; - + err = read_bfs_file (file->device->disk, &data->sb, - data->ino, - file->offset, buf, len, file->read_hook); + data->ino, file->offset, buf, len, file->read_hook); if (err) return -1; return len; @@ -828,12 +829,10 @@ static grub_ssize_t read_bfs_attr (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, - const char *name, - void *buf, grub_size_t len) + const char *name, void *buf, grub_size_t len) { grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data; - grub_uint8_t *end = ((grub_uint8_t *) ino - + grub_bfs_to_cpu32 (sb->bsize)); + grub_uint8_t *end = ((grub_uint8_t *) ino + grub_bfs_to_cpu32 (sb->bsize)); while (ptr + sizeof (struct grub_bfs_small_data_element_header) < end) { @@ -859,36 +858,36 @@ read_bfs_attr (grub_disk_t disk, } if (ino->attr.len != 0) - { - union { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; - } ino2; - grub_size_t read; - grub_err_t err; - grub_uint64_t res; + { + union + { + struct grub_bfs_inode ino; + grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; + } ino2; + grub_size_t read; + grub_err_t err; + grub_uint64_t res; - err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, - grub_bfs_to_cpu32 (sb->bsize)); - if (err) - return -1; + err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, + grub_bfs_to_cpu32 (sb->bsize)); + if (err) + return -1; - err = find_in_b_tree (disk, sb, &ino2.ino, name, &res); - if (err) - return -1; - grub_disk_read (disk, res - << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9) - , 0, - grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); - read = grub_bfs_to_cpu64 (ino2.ino.size); - if (read > len) - read = len; + err = find_in_b_tree (disk, sb, &ino2.ino, name, &res); + if (err) + return -1; + grub_disk_read (disk, res + << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9), 0, + grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); + read = grub_bfs_to_cpu64 (ino2.ino.size); + if (read > len) + read = len; - err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0); - if (err) - return -1; - return read; - } + err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0); + if (err) + return -1; + return read; + } return -1; } @@ -905,7 +904,8 @@ grub_bfs_uuid (grub_device_t device, char **uuid) return err; { - union { + union + { struct grub_bfs_inode ino; grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; } ino; @@ -917,7 +917,8 @@ grub_bfs_uuid (grub_device_t device, char **uuid) return err; if (read_bfs_attr (device->disk, &sb, &ino.ino, "be:volume_id", &vid, 8) == 8) - *uuid = grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); + *uuid = + grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); } return GRUB_ERR_NONE; } @@ -938,7 +939,8 @@ static struct grub_fs grub_bfs_fs = { GRUB_MOD_INIT (bfs) { - COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE == sizeof (struct grub_bfs_extent)); + COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE == + sizeof (struct grub_bfs_extent)); grub_fs_register (&grub_bfs_fs); } From 785ab8c76053d18a1b80046d599e0ed7f8680f00 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 14:17:44 +0100 Subject: [PATCH 463/673] * grub-core/fs/bfs.c: MAcroify and add some necessary sanity checks. --- ChangeLog | 4 ++++ grub-core/fs/bfs.c | 37 +++++++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index c52bff5b9..8ff87aebd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-10-30 Vladimir Serbinenko + + * grub-core/fs/bfs.c: MAcroify and add some necessary sanity checks. + 2011-10-30 Vladimir Serbinenko * grub-core/fs/bfs.c: Run indent. diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index 7b6e359ae..c16a50f39 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -146,7 +146,8 @@ read_extent (grub_disk_t disk, return grub_disk_read (disk, ((grub_bfs_to_cpu32 (in->ag) << grub_bfs_to_cpu32 (sb->log2_ag_size)) + grub_bfs_to_cpu16 (in->start) + off) - << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9), byteoff, + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - GRUB_DISK_SECTOR_BITS), byteoff, len, buf); } @@ -383,7 +384,8 @@ iterate_in_b_tree (grub_disk_t disk, + ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), 8) + - grub_bfs_to_cpu16 (node.count_keys) * 2, + grub_bfs_to_cpu16 (node.count_keys) + * sizeof (grub_uint64_t), &key_value, sizeof (grub_uint64_t), 0); if (err) return 0; @@ -415,7 +417,8 @@ iterate_in_b_tree (grub_disk_t disk, grub_bfs_to_cpu16 (node. total_key_len), 8), keylen_idx, - grub_bfs_to_cpu16 (node.count_keys) * 2, 0); + grub_bfs_to_cpu16 (node.count_keys) + * sizeof (grub_uint16_t), 0); if (err) return 0; err = read_bfs_file (disk, sb, ino, node_off @@ -423,9 +426,11 @@ iterate_in_b_tree (grub_disk_t disk, grub_bfs_to_cpu16 (node. total_key_len), 8) + - grub_bfs_to_cpu16 (node.count_keys) * 2, + grub_bfs_to_cpu16 (node.count_keys) + * sizeof (grub_uint16_t), key_values, - grub_bfs_to_cpu16 (node.count_keys) * 8, 0); + grub_bfs_to_cpu16 (node.count_keys) + * sizeof (grub_uint64_t), 0); if (err) return 0; @@ -434,6 +439,8 @@ iterate_in_b_tree (grub_disk_t disk, char c; start = end; end = grub_bfs_to_cpu16 (keylen_idx[i]); + if (grub_bfs_to_cpu16 (node.total_key_len) <= end) + end = grub_bfs_to_cpu16 (node.total_key_len); c = key_data[end]; key_data[end] = 0; if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]))) @@ -490,7 +497,8 @@ find_in_b_tree (grub_disk_t disk, ALIGN_UP (sizeof (node) + grub_bfs_to_cpu16 (node.total_key_len), 8), keylen_idx, - grub_bfs_to_cpu16 (node.count_keys) * 2, 0); + grub_bfs_to_cpu16 (node.count_keys) + * sizeof (grub_uint16_t), 0); if (err) return err; err = read_bfs_file (disk, sb, ino, node_off @@ -498,9 +506,11 @@ find_in_b_tree (grub_disk_t disk, grub_bfs_to_cpu16 (node. total_key_len), 8) + - grub_bfs_to_cpu16 (node.count_keys) * 2, + grub_bfs_to_cpu16 (node.count_keys) + * sizeof (grub_uint16_t), key_values, - grub_bfs_to_cpu16 (node.count_keys) * 8, 0); + grub_bfs_to_cpu16 (node.count_keys) + * sizeof (grub_uint64_t), 0); if (err) return err; @@ -561,7 +571,8 @@ hop_level (grub_disk_t disk, return err; return grub_disk_read (disk, res - << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9), 0, + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - GRUB_DISK_SECTOR_BITS), 0, grub_bfs_to_cpu32 (sb->bsize), (char *) ino); } @@ -718,7 +729,8 @@ grub_bfs_dir (grub_device_t device, const char *path, struct grub_dirhook_info info; err2 = grub_disk_read (device->disk, value - << (grub_bfs_to_cpu32 (sb.log2_bsize) - 9), 0, + << (grub_bfs_to_cpu32 (sb.log2_bsize) + - GRUB_DISK_SECTOR_BITS), 0, grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw); if (err2) { @@ -877,7 +889,8 @@ read_bfs_attr (grub_disk_t disk, if (err) return -1; grub_disk_read (disk, res - << (grub_bfs_to_cpu32 (sb->log2_bsize) - 9), 0, + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - GRUB_DISK_SECTOR_BITS), 0, grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); read = grub_bfs_to_cpu64 (ino2.ino.size); if (read > len) @@ -916,7 +929,7 @@ grub_bfs_uuid (grub_device_t device, char **uuid) if (err) return err; if (read_bfs_attr (device->disk, &sb, &ino.ino, "be:volume_id", - &vid, 8) == 8) + &vid, sizeof (vid)) == sizeof (vid)) *uuid = grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); } From 80f9f81424d72bea0588b48c428bb8d39a276f33 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 14:25:53 +0100 Subject: [PATCH 464/673] Fix a mistake in previous commit --- grub-core/fs/bfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index c16a50f39..a92f3522c 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -385,7 +385,7 @@ iterate_in_b_tree (grub_disk_t disk, grub_bfs_to_cpu16 (node.total_key_len), 8) + grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint64_t), + * sizeof (grub_uint16_t), &key_value, sizeof (grub_uint64_t), 0); if (err) return 0; From eb0b6b45f380ca4831358aa14aa25391f2d9800f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 16:10:18 +0100 Subject: [PATCH 465/673] Leverage BFS implementation to read AFS. * Makefile.util.def (libgrubmods): Add afs.c. * grub-core/Makefile.core.def (afs): New module * grub-core/fs/afs.c: New file. * grub-core/fs/bfs.c [MODE_AFS]: Adapt for AFS. --- ChangeLog | 11 +- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/fs/afs.c | 3 + grub-core/fs/bfs.c | 211 +++++++++++++++++++++++++----------- 5 files changed, 168 insertions(+), 63 deletions(-) create mode 100644 grub-core/fs/afs.c diff --git a/ChangeLog b/ChangeLog index 8ff87aebd..8f44f2080 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,15 @@ 2011-10-30 Vladimir Serbinenko - * grub-core/fs/bfs.c: MAcroify and add some necessary sanity checks. + Leverage BFS implementation to read AFS. + + * Makefile.util.def (libgrubmods): Add afs.c. + * grub-core/Makefile.core.def (afs): New module + * grub-core/fs/afs.c: New file. + * grub-core/fs/bfs.c [MODE_AFS]: Adapt for AFS. + +2011-10-30 Vladimir Serbinenko + + * grub-core/fs/bfs.c: Macroify and add some necessary sanity checks. 2011-10-30 Vladimir Serbinenko diff --git a/Makefile.util.def b/Makefile.util.def index 053ff4340..a839920d5 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -55,6 +55,7 @@ library = { common = grub-core/disk/raid6_recover.c; common = grub-core/disk/raid.c; common = grub-core/fs/affs.c; + common = grub-core/fs/afs.c; common = grub-core/fs/bfs.c; common = grub-core/fs/btrfs.c; common = grub-core/fs/cpio.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index c6127b28f..2b72d8429 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -970,6 +970,11 @@ module = { common = fs/affs.c; }; +module = { + name = afs; + common = fs/afs.c; +}; + module = { name = bfs; common = fs/bfs.c; diff --git a/grub-core/fs/afs.c b/grub-core/fs/afs.c new file mode 100644 index 000000000..00a5e3113 --- /dev/null +++ b/grub-core/fs/afs.c @@ -0,0 +1,3 @@ +#define MODE_AFS 1 +#include "bfs.c" + diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index a92f3522c..fe8f991c4 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -31,11 +31,29 @@ GRUB_MOD_LICENSE ("GPLv3+"); +#ifdef MODE_AFS +#define BTREE_ALIGN 4 +#define SUPERBLOCK 2 +#else +#define BTREE_ALIGN 8 +#define SUPERBLOCK 1 +#endif + #define grub_bfs_to_cpu16 grub_le_to_cpu16 #define grub_bfs_to_cpu32 grub_le_to_cpu32 #define grub_bfs_to_cpu64 grub_le_to_cpu64 +#ifdef MODE_AFS +#define grub_bfs_to_cpu_treehead grub_bfs_to_cpu32 +#else +#define grub_bfs_to_cpu_treehead grub_bfs_to_cpu16 +#endif + +#ifdef MODE_AFS +#define SUPER_BLOCK_MAGIC1 0x41465331 +#else #define SUPER_BLOCK_MAGIC1 0x42465331 +#endif #define SUPER_BLOCK_MAGIC2 0xdd121031 #define SUPER_BLOCK_MAGIC3 0x15b6830e #define POINTER_INVALID 0xffffffffffffffffULL @@ -76,7 +94,11 @@ struct grub_bfs_inode grub_uint8_t unused[20]; grub_uint32_t mode; grub_uint32_t flags; +#ifdef MODE_AFS + grub_uint8_t unused2[12]; +#else grub_uint8_t unused2[8]; +#endif grub_uint64_t mtime; grub_uint8_t unused3[8]; struct grub_bfs_extent attr; @@ -115,10 +137,17 @@ struct grub_bfs_small_data_element_header struct grub_bfs_btree_header { grub_uint32_t magic; +#ifdef MODE_AFS + grub_uint64_t root; + grub_uint32_t level; + grub_uint32_t node_size; + grub_uint32_t unused; +#else grub_uint32_t node_size; grub_uint32_t level; grub_uint32_t unused; grub_uint64_t root; +#endif grub_uint32_t unused2[2]; } __attribute__ ((packed)); @@ -127,8 +156,13 @@ struct grub_bfs_btree_node grub_uint64_t unused; grub_uint64_t right; grub_uint64_t overflow; +#ifdef MODE_AFS + grub_uint32_t count_keys; + grub_uint32_t total_key_len; +#else grub_uint16_t count_keys; grub_uint16_t total_key_len; +#endif } __attribute__ ((packed)); struct grub_bfs_data @@ -143,14 +177,30 @@ read_extent (grub_disk_t disk, const struct grub_bfs_extent *in, grub_off_t off, grub_off_t byteoff, void *buf, grub_size_t len) { +#ifdef MODE_AFS return grub_disk_read (disk, ((grub_bfs_to_cpu32 (in->ag) - << grub_bfs_to_cpu32 (sb->log2_ag_size)) - + grub_bfs_to_cpu16 (in->start) + off) - << (grub_bfs_to_cpu32 (sb->log2_bsize) - - GRUB_DISK_SECTOR_BITS), byteoff, - len, buf); + << (grub_bfs_to_cpu32 (sb->log2_ag_size) + - GRUB_DISK_SECTOR_BITS)) + + ((grub_bfs_to_cpu16 (in->start) + off) + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - GRUB_DISK_SECTOR_BITS))), + byteoff, len, buf); +#else + return grub_disk_read (disk, (((grub_bfs_to_cpu32 (in->ag) + << grub_bfs_to_cpu32 (sb->log2_ag_size)) + + grub_bfs_to_cpu16 (in->start) + off) + << (grub_bfs_to_cpu32 (sb->log2_bsize) + - GRUB_DISK_SECTOR_BITS)), + byteoff, len, buf); +#endif } +#ifdef MODE_AFS +#define RANGE_SHIFT grub_bfs_to_cpu32 (sb->log2_bsize) +#else +#define RANGE_SHIFT 0 +#endif + static grub_err_t read_bfs_file (grub_disk_t disk, const struct grub_bfs_superblock *sb, @@ -167,7 +217,7 @@ read_bfs_file (grub_disk_t disk, return grub_error (GRUB_ERR_OUT_OF_RANGE, "attempt to read past the end of file"); - if (off < grub_bfs_to_cpu64 (ino->max_direct_range)) + if (off < (grub_bfs_to_cpu64 (ino->max_direct_range) << RANGE_SHIFT)) { unsigned i; grub_uint64_t pos = 0; @@ -199,16 +249,17 @@ read_bfs_file (grub_disk_t disk, } } - if (off < grub_bfs_to_cpu64 (ino->max_direct_range)) + if (off < (grub_bfs_to_cpu64 (ino->max_direct_range) << RANGE_SHIFT)) return grub_error (GRUB_ERR_BAD_FS, "incorrect direct blocks"); - if (off < grub_bfs_to_cpu64 (ino->max_indirect_range)) + if (off < (grub_bfs_to_cpu64 (ino->max_indirect_range) << RANGE_SHIFT)) { unsigned i; struct grub_bfs_extent *entries; grub_size_t nentries; grub_err_t err; - grub_uint64_t pos = grub_bfs_to_cpu64 (ino->max_direct_range); + grub_uint64_t pos = (grub_bfs_to_cpu64 (ino->max_direct_range) + << RANGE_SHIFT); nentries = (grub_bfs_to_cpu16 (ino->indirect.len) << (grub_bfs_to_cpu32 (sb->log2_bsize) - LOG_EXTENT_SIZE)); entries = grub_malloc (nentries << LOG_EXTENT_SIZE); @@ -250,7 +301,7 @@ read_bfs_file (grub_disk_t disk, grub_free (entries); } - if (off < grub_bfs_to_cpu64 (ino->max_indirect_range)) + if (off < (grub_bfs_to_cpu64 (ino->max_indirect_range) << RANGE_SHIFT)) return grub_error (GRUB_ERR_BAD_FS, "incorrect indirect blocks"); { @@ -382,11 +433,12 @@ iterate_in_b_tree (grub_disk_t disk, return 0; err = read_bfs_file (disk, sb, ino, node_off + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu16 (node.total_key_len), - 8) + - grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint16_t), - &key_value, sizeof (grub_uint64_t), 0); + grub_bfs_to_cpu_treehead (node. + total_key_len), + BTREE_ALIGN) + + grub_bfs_to_cpu_treehead (node.count_keys) * + sizeof (grub_uint16_t), &key_value, + sizeof (grub_uint64_t), 0); if (err) return 0; @@ -400,47 +452,46 @@ iterate_in_b_tree (grub_disk_t disk, if (err) return 0; { - char key_data[grub_bfs_to_cpu16 (node.total_key_len) + 1]; - grub_uint16_t keylen_idx[grub_bfs_to_cpu16 (node.count_keys)]; - grub_uint64_t key_values[grub_bfs_to_cpu16 (node.count_keys)]; + char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; + grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; + grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; unsigned i; grub_uint16_t start = 0, end = 0; err = read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu16 (node.total_key_len), 0); + grub_bfs_to_cpu_treehead (node.total_key_len), 0); if (err) return 0; - key_data[grub_bfs_to_cpu16 (node.total_key_len)] = 0; + key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; err = read_bfs_file (disk, sb, ino, node_off + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu16 (node. - total_key_len), - 8), keylen_idx, - grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint16_t), 0); + grub_bfs_to_cpu_treehead + (node.total_key_len), BTREE_ALIGN), + keylen_idx, + grub_bfs_to_cpu_treehead (node.count_keys) * + sizeof (grub_uint16_t), 0); if (err) return 0; err = read_bfs_file (disk, sb, ino, node_off + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu16 (node. - total_key_len), - 8) + - grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint16_t), - key_values, - grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint64_t), 0); + grub_bfs_to_cpu_treehead + (node.total_key_len), + BTREE_ALIGN) + + grub_bfs_to_cpu_treehead (node.count_keys) * + sizeof (grub_uint16_t), key_values, + grub_bfs_to_cpu_treehead (node.count_keys) * + sizeof (grub_uint64_t), 0); if (err) return 0; - for (i = 0; i < grub_bfs_to_cpu16 (node.count_keys); i++) + for (i = 0; i < grub_bfs_to_cpu_treehead (node.count_keys); i++) { char c; start = end; end = grub_bfs_to_cpu16 (keylen_idx[i]); - if (grub_bfs_to_cpu16 (node.total_key_len) <= end) - end = grub_bfs_to_cpu16 (node.total_key_len); + if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node.total_key_len); c = key_data[end]; key_data[end] = 0; if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]))) @@ -481,47 +532,47 @@ find_in_b_tree (grub_disk_t disk, return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", name); { - char key_data[grub_bfs_to_cpu16 (node.total_key_len) + 1]; - grub_uint16_t keylen_idx[grub_bfs_to_cpu16 (node.count_keys)]; - grub_uint64_t key_values[grub_bfs_to_cpu16 (node.count_keys)]; + char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; + grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; + grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; unsigned i; grub_uint16_t start = 0, end = 0; err = read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu16 (node.total_key_len), 0); + grub_bfs_to_cpu_treehead (node.total_key_len), 0); if (err) return err; - key_data[grub_bfs_to_cpu16 (node.total_key_len)] = 0; + key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; err = read_bfs_file (disk, sb, ino, node_off + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu16 (node.total_key_len), - 8), keylen_idx, - grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint16_t), 0); + grub_bfs_to_cpu_treehead (node. + total_key_len), + BTREE_ALIGN), keylen_idx, + grub_bfs_to_cpu_treehead (node.count_keys) * + sizeof (grub_uint16_t), 0); if (err) return err; err = read_bfs_file (disk, sb, ino, node_off + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu16 (node. - total_key_len), - 8) + - grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint16_t), - key_values, - grub_bfs_to_cpu16 (node.count_keys) - * sizeof (grub_uint64_t), 0); + grub_bfs_to_cpu_treehead + (node.total_key_len), + BTREE_ALIGN) + + grub_bfs_to_cpu_treehead (node.count_keys) * + sizeof (grub_uint16_t), key_values, + grub_bfs_to_cpu_treehead (node.count_keys) * + sizeof (grub_uint64_t), 0); if (err) return err; - for (i = 0; i < grub_bfs_to_cpu16 (node.count_keys); i++) + for (i = 0; i < grub_bfs_to_cpu_treehead (node.count_keys); i++) { int cmp; char c; start = end; end = grub_bfs_to_cpu16 (keylen_idx[i]); - if (grub_bfs_to_cpu16 (node.total_key_len) <= end) - end = grub_bfs_to_cpu16 (node.total_key_len); + if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node.total_key_len); c = key_data[end]; key_data[end] = 0; cmp = grub_strcmp (key_data + start, name); @@ -537,7 +588,7 @@ find_in_b_tree (grub_disk_t disk, break; } } - if (i < grub_bfs_to_cpu16 (node.count_keys)) + if (i < grub_bfs_to_cpu_treehead (node.count_keys)) { level--; continue; @@ -629,7 +680,9 @@ find_file (const char *path, grub_disk_t disk, "too deep nesting of symlinks"); } +#ifndef MODE_AFS if (grub_bfs_to_cpu32 (ino->flags) & LONG_SYMLINK) +#endif { grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) @@ -648,6 +701,7 @@ find_file (const char *path, grub_disk_t disk, } alloc[symsize] = 0; } +#ifndef MODE_AFS else { alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) @@ -662,6 +716,7 @@ find_file (const char *path, grub_disk_t disk, sizeof (ino->inplace_link)); alloc[sizeof (ino->inplace_link)] = 0; } +#endif if (alloc[0] == '/') { err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, @@ -695,9 +750,15 @@ static grub_err_t mount (grub_disk_t disk, struct grub_bfs_superblock *sb) { grub_err_t err; - err = grub_disk_read (disk, 1, 0, sizeof (*sb), sb); + err = grub_disk_read (disk, SUPERBLOCK, 0, sizeof (*sb), sb); if (err == GRUB_ERR_OUT_OF_RANGE) - return grub_error (GRUB_ERR_BAD_FS, "not a BFS filesystem"); + return grub_error (GRUB_ERR_BAD_FS, +#ifdef MODE_AFS + "not an AFS filesystem" +#else + "not a BFS filesystem" +#endif + ); if (err) return err; if (grub_bfs_to_cpu32 (sb->magic1) != SUPER_BLOCK_MAGIC1 @@ -705,7 +766,13 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) || grub_bfs_to_cpu32 (sb->magic3) != SUPER_BLOCK_MAGIC3 || (grub_bfs_to_cpu32 (sb->bsize) != (1U << grub_bfs_to_cpu32 (sb->log2_bsize)))) - return grub_error (GRUB_ERR_BAD_FS, "not a BFS filesystem"); + return grub_error (GRUB_ERR_BAD_FS, +#ifdef MODE_AFS + "not an AFS filesystem" +#else + "not a BFS filesystem" +#endif + ); return GRUB_ERR_NONE; } @@ -739,7 +806,12 @@ grub_bfs_dir (grub_device_t device, const char *path, } info.mtimeset = 1; +#ifdef MODE_AFS + info.mtime = + grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0); +#else info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; +#endif info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR); return hook_in (name, &info); } @@ -785,7 +857,7 @@ grub_bfs_open (struct grub_file *file, const char *name) if (err) return err; if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_REG)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file"); data = grub_zalloc (sizeof (struct grub_bfs_data) + grub_bfs_to_cpu32 (sb.bsize)); @@ -837,6 +909,7 @@ grub_bfs_label (grub_device_t device, char **label) return GRUB_ERR_NONE; } +#ifndef MODE_AFS static grub_ssize_t read_bfs_attr (grub_disk_t disk, const struct grub_bfs_superblock *sb, @@ -935,29 +1008,43 @@ grub_bfs_uuid (grub_device_t device, char **uuid) } return GRUB_ERR_NONE; } - +#endif static struct grub_fs grub_bfs_fs = { +#ifdef MODE_AFS + .name = "afs", +#else .name = "bfs", +#endif .dir = grub_bfs_dir, .open = grub_bfs_open, .read = grub_bfs_read, .close = grub_bfs_close, .label = grub_bfs_label, +#ifndef MODE_AFS .uuid = grub_bfs_uuid, +#endif #ifdef GRUB_UTIL .reserved_first_sector = 1, #endif }; +#ifdef MODE_AFS +GRUB_MOD_INIT (afs) +#else GRUB_MOD_INIT (bfs) +#endif { COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE == sizeof (struct grub_bfs_extent)); grub_fs_register (&grub_bfs_fs); } +#ifdef MODE_AFS +GRUB_MOD_FINI (afs) +#else GRUB_MOD_FINI (bfs) +#endif { grub_fs_unregister (&grub_bfs_fs); } From 94ef05c2652e78d2b6be32829530efa5eb9d7ac0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 19:30:04 +0100 Subject: [PATCH 466/673] * grub-core/loader/mips/linux.c (loongson_machtypes): Fix fuloong type string. --- ChangeLog | 5 +++++ grub-core/loader/mips/linux.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8f44f2080..3e9f8a640 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-30 Vladimir Serbinenko + + * grub-core/loader/mips/linux.c (loongson_machtypes): Fix fuloong type + string. + 2011-10-30 Vladimir Serbinenko Leverage BFS implementation to read AFS. diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 2b4875983..17c2656e2 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -41,7 +41,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); const char loongson_machtypes[][60] = { [GRUB_ARCH_MACHINE_YEELOONG] = "machtype=lemote-yeeloong-2f-8.9inches", - [GRUB_ARCH_MACHINE_FULOONG2F] = "machtype=lemote-fuloong-2f-unknown", + [GRUB_ARCH_MACHINE_FULOONG2F] = "machtype=lemote-fuloong-2f-box", [GRUB_ARCH_MACHINE_FULOONG2E] = "machtype=lemote-fuloong-2e-unknown" }; #endif From 45cdd3ea372ff15b68b622e2791b61edc6d0ac21 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 20:14:57 +0100 Subject: [PATCH 467/673] Fix JFS file name length limitations. * grub-core/fs/jfs.c (grub_jfs_inode): Fix in-place symlink length. (grub_jfs_diropen): Fix maximum filename length. (grub_jfs_getent): Fix filename length. (grub_jfs_lookup_symlink): Fix size checks. --- ChangeLog | 9 +++++++++ grub-core/fs/jfs.c | 15 +++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3e9f8a640..cfdbfaeda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-30 Vladimir Serbinenko + + Fix JFS file name length limitations. + + * grub-core/fs/jfs.c (grub_jfs_inode): Fix in-place symlink length. + (grub_jfs_diropen): Fix maximum filename length. + (grub_jfs_getent): Fix filename length. + (grub_jfs_lookup_symlink): Fix size checks. + 2011-10-30 Vladimir Serbinenko * grub-core/loader/mips/linux.c (loongson_machtypes): Fix fuloong type diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index c5e82bfec..cf7520bb3 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -205,7 +205,7 @@ struct grub_jfs_inode struct { grub_uint8_t unused[32]; - grub_uint8_t path[128]; + grub_uint8_t path[256]; } symlink; } __attribute__ ((packed)); } __attribute__ ((packed)); @@ -238,7 +238,10 @@ struct grub_jfs_diropen struct grub_jfs_leaf_next_dirent *next_leaf; /* The filename and inode of the last read dirent. */ - char name[255]; + /* On-disk name is at most 255 UTF-16 codepoints. + Every UTF-16 codepoint is at most 4 UTF-8 bytes. + */ + char name[256 * 4 + 1]; grub_uint32_t ino; } __attribute__ ((packed)); @@ -479,7 +482,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) struct grub_jfs_leaf_next_dirent *next_leaf; int len; int nextent; - grub_uint16_t filename[255]; + grub_uint16_t filename[256]; auto void addstr (grub_uint16_t *uname, int ulen); @@ -708,14 +711,14 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path, static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) { - grub_uint64_t size = grub_le_to_cpu64 (data->currinode.size); + grub_size_t size = grub_le_to_cpu64 (data->currinode.size); char symlink[size + 1]; if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); - if (size <= 128) - grub_strncpy (symlink, (char *) (data->currinode.symlink.path), 128); + if (size <= sizeof (data->currinode.symlink.path)) + grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size); else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0) return grub_errno; From c83a08d84ac9e35cfde2e9df2b660010073e9227 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 20:23:05 +0100 Subject: [PATCH 468/673] Fix iso9660 filename limitations and fix memory leaks. * grub-core/fs/iso9660.c (set_rockridge): Free sua at the end. (grub_iso9660_iterate_dir): Fix slash handling in symlinks. --- ChangeLog | 7 +++++++ grub-core/fs/iso9660.c | 46 ++++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index cfdbfaeda..223afb1e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-10-30 Vladimir Serbinenko + + Fix iso9660 filename limitations and fix memory leaks. + + * grub-core/fs/iso9660.c (set_rockridge): Free sua at the end. + (grub_iso9660_iterate_dir): Fix slash handling in symlinks. + 2011-10-30 Vladimir Serbinenko Fix JFS file name length limitations. diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index a2e731351..d4c52bed4 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -395,7 +395,10 @@ set_rockridge (struct grub_iso9660_data *data) (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector) << GRUB_ISO9660_LOG2_BLKSZ), sua_pos, sua_size, sua)) - return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem"); + { + grub_free (sua); + return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem"); + } entry = (struct grub_iso9660_susp_entry *) sua; @@ -419,8 +422,12 @@ set_rockridge (struct grub_iso9660_data *data) extensions. */ if (grub_iso9660_susp_iterate (&rootnode, sua_pos, sua_size, susp_iterate)) - return grub_errno; + { + grub_free (sua); + return grub_errno; + } } + grub_free (sua); return GRUB_ERR_NONE; } @@ -516,12 +523,11 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, { struct grub_iso9660_dir dirent; grub_off_t offset = 0; - char *filename; + char *filename = 0; int filename_alloc = 0; enum grub_fshelp_filetype type; grub_off_t len; char *symlink = 0; - int addslash = 0; auto void add_part (const char *part, int len); @@ -551,23 +557,30 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, filename = "."; else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) filename = ".."; - else + else if (entry->len >= 5) { int size = 1; - if (filename) + char *old; + size = entry->len - 5; + old = filename; + if (filename_alloc) { size += grub_strlen (filename); - grub_realloc (filename, - grub_strlen (filename) - + entry->len); + filename = grub_realloc (filename, size + 1); } else { - size = entry->len - 5; + filename_alloc = 1; filename = grub_zalloc (size + 1); + filename[0] = 0; + } + if (!filename) + { + filename = old; + return grub_errno; } filename_alloc = 1; - grub_strncpy (filename, (char *) &entry->data[1], size); + grub_strncat (filename, (char *) &entry->data[1], size); filename[size] = '\0'; } } @@ -601,12 +614,6 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, /* The symlink is not stored as a POSIX symlink, translate it. */ while (pos + sizeof (*entry) < grub_le_to_cpu32 (entry->len)) { - if (addslash) - { - add_part ("/", 1); - addslash = 0; - } - /* The current position is the `Component Flag'. */ switch (entry->data[pos] & 30) { @@ -615,10 +622,10 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, /* The data on pos + 2 is the actual data, pos + 1 is the length. Both are part of the `Component Record'. */ + if (symlink && (entry->data[pos] & 1)) + add_part ("/", 1); add_part ((char *) &entry->data[pos + 2], entry->data[pos + 1]); - if ((entry->data[pos] & 1)) - addslash = 1; break; } @@ -653,7 +660,6 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, for (; offset < len; offset += dirent.len) { symlink = 0; - addslash = 0; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; From 19ee298767b7780618ea04cb556cd6211fffe780 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 30 Oct 2011 23:06:25 +0100 Subject: [PATCH 469/673] Handle symlinks and long names on tar and cpio. * grub-core/fs/cpio.c (ATTR_TYPE): New definition. (ATTR_FILE): Likewise. (ATTR_DIR): Likewise. (ATTR_LNK): Likewise. (grub_cpio_data) [MODE_USTAR]: New fields linkname and linkname_alloc. (grub_cpio_find_file): Fill mode, handle linkname field as well as L and K entries. (grub_cpio_mount): Zero-fill data. (handle_symlink): New function. --- ChangeLog | 14 ++ grub-core/fs/cpio.c | 351 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 307 insertions(+), 58 deletions(-) diff --git a/ChangeLog b/ChangeLog index 223afb1e6..543823e9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-10-30 Vladimir Serbinenko + + Handle symlinks and long names on tar and cpio. + + * grub-core/fs/cpio.c (ATTR_TYPE): New definition. + (ATTR_FILE): Likewise. + (ATTR_DIR): Likewise. + (ATTR_LNK): Likewise. + (grub_cpio_data) [MODE_USTAR]: New fields linkname and linkname_alloc. + (grub_cpio_find_file): Fill mode, handle linkname field as well as + L and K entries. + (grub_cpio_mount): Zero-fill data. + (handle_symlink): New function. + 2011-10-30 Vladimir Serbinenko Fix iso9660 filename limitations and fix memory leaks. diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 92531390e..b43e54ec9 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -25,6 +25,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); +#define ATTR_TYPE 0160000 +#define ATTR_FILE 0100000 +#define ATTR_DIR 0040000 +#define ATTR_LNK 0120000 + #ifndef MODE_USTAR /* cpio support */ #define MAGIC_BCPIO 070707 @@ -74,6 +79,10 @@ struct grub_cpio_data grub_off_t hofs; grub_off_t dofs; grub_off_t size; +#ifdef MODE_USTAR + char *linkname; + grub_size_t linkname_alloc; +#endif }; static grub_dl_t my_mod; @@ -101,7 +110,8 @@ canonicalize (char *name) static grub_err_t grub_cpio_find_file (struct grub_cpio_data *data, char **name, - grub_int32_t *mtime, grub_disk_addr_t * ofs) + grub_int32_t *mtime, grub_disk_addr_t *ofs, + grub_uint32_t *mode) { #ifndef MODE_USTAR struct head hd; @@ -115,11 +125,14 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; if (mtime) *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; + if (mode) + *mode = hd.mode; if (hd.namesize & 1) hd.namesize++; - if ((*name = grub_malloc (hd.namesize)) == NULL) + *name = grub_malloc (hd.namesize + 1); + if (*name == NULL) return grub_errno; if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), @@ -128,9 +141,10 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, grub_free (*name); return grub_errno; } + (*name)[hd.namesize] = 0; if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1 - && ! grub_memcmp(*name, "TRAILER!!!", 11)) + && grub_memcmp(*name, "TRAILER!!!", 11) == 0) { *ofs = 0; return GRUB_ERR_NONE; @@ -144,29 +158,118 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, (*ofs)++; #else struct head hd; + int reread = 0, have_longname = 0, have_longlink = 0; - if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) - return grub_errno; - - if (!hd.name[0]) + for (reread = 0; reread < 3; reread++) { - *ofs = 0; + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; + + if (!hd.name[0]) + { + *ofs = 0; + return GRUB_ERR_NONE; + } + + if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) + return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); + + if (hd.typeflag == 'L') + { + grub_err_t err; + grub_size_t namesize = grub_strtoull (hd.size, NULL, 8); + *name = grub_malloc (namesize + 1); + if (*name == NULL) + return grub_errno; + err = grub_disk_read (data->disk, 0, + data->hofs + GRUB_DISK_SECTOR_SIZE, namesize, + *name); + (*name)[namesize] = 0; + if (err) + return err; + data->hofs += GRUB_DISK_SECTOR_SIZE + + ((namesize + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + have_longname = 1; + continue; + } + + if (hd.typeflag == 'K') + { + grub_err_t err; + grub_size_t linksize = grub_strtoull (hd.size, NULL, 8); + if (data->linkname_alloc < linksize + 1) + { + char *n; + n = grub_malloc (2 * (linksize + 1)); + if (!n) + return grub_errno; + grub_free (data->linkname); + data->linkname = n; + data->linkname_alloc = 2 * (linksize + 1); + } + + err = grub_disk_read (data->disk, 0, + data->hofs + GRUB_DISK_SECTOR_SIZE, linksize, + data->linkname); + if (err) + return err; + data->linkname[linksize] = 0; + data->hofs += GRUB_DISK_SECTOR_SIZE + + ((linksize + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + have_longlink = 1; + continue; + } + + if (!have_longname) + { + *name = grub_strdup (hd.name); + if (*name == NULL) + return grub_errno; + } + + data->size = grub_strtoull (hd.size, NULL, 8); + data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; + *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + if (mtime) + *mtime = grub_strtoul (hd.mtime, NULL, 8); + if (mode) + { + *mode = grub_strtoul (hd.mode, NULL, 8); + switch (hd.typeflag) + { + case '2': + *mode |= ATTR_LNK; + break; + case '0': + *mode |= ATTR_FILE; + break; + case '5': + *mode |= ATTR_DIR; + break; + } + } + if (!have_longlink) + { + if (data->linkname_alloc < 101) + { + char *n; + n = grub_malloc (101); + if (!n) + return grub_errno; + grub_free (data->linkname); + data->linkname = n; + data->linkname_alloc = 101; + } + grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname)); + data->linkname[100] = 0; + } + + canonicalize (*name); return GRUB_ERR_NONE; } - - if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) - return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); - - if ((*name = grub_strdup (hd.name)) == NULL) - return grub_errno; - - data->size = grub_strtoull (hd.size, NULL, 8); - data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; - *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - if (mtime) - *mtime = grub_strtoul (hd.mtime, NULL, 8); - canonicalize (*name); #endif return GRUB_ERR_NONE; } @@ -188,7 +291,7 @@ grub_cpio_mount (grub_disk_t disk) #endif goto fail; - data = (struct grub_cpio_data *) grub_malloc (sizeof (*data)); + data = (struct grub_cpio_data *) grub_zalloc (sizeof (*data)); if (!data) goto fail; @@ -208,15 +311,105 @@ fail: } static grub_err_t -grub_cpio_dir (grub_device_t device, const char *path, +handle_symlink (struct grub_cpio_data *data, + const char *fn, char **name, + grub_uint32_t mode, int *restart) +{ + grub_size_t flen; + char *target; +#ifndef MODE_USTAR + grub_err_t err; +#endif + char *ptr; + char *lastslash; + grub_size_t prefixlen; + char *rest; + grub_size_t size; + + *restart = 0; + + if ((mode & ATTR_TYPE) != ATTR_LNK) + return GRUB_ERR_NONE; + flen = grub_strlen (fn); + if (grub_memcmp (*name, fn, flen) != 0 + || ((*name)[flen] != 0 && (*name)[flen] != '/')) + return GRUB_ERR_NONE; + rest = *name + flen; + lastslash = rest; + if (*rest) + rest++; + while (lastslash >= *name && *lastslash != '/') + lastslash--; + if (lastslash >= *name) + prefixlen = lastslash - *name; + else + prefixlen = 0; + + if (prefixlen) + prefixlen++; + +#ifdef MODE_USTAR + size = grub_strlen (data->linkname); +#else + size = data->size; +#endif + if (size == 0) + return GRUB_ERR_NONE; + target = grub_malloc (size + grub_strlen (*name) + 2); + if (!target) + return grub_errno; + +#ifdef MODE_USTAR + grub_memcpy (target + prefixlen, data->linkname, size); +#else + err = grub_disk_read (data->disk, 0, data->dofs, data->size, + target + prefixlen); + if (err) + return err; +#endif + if (target[prefixlen] == '/') + { + grub_memmove (target, target + prefixlen, data->size - 1); + ptr = target + data->size - 1; + ptr = grub_stpcpy (ptr, rest); + *ptr = 0; + grub_dprintf ("cpio", "symlink redirected %s to %s\n", + *name, target); + grub_free (*name); + *name = target; + *restart = 1; + return GRUB_ERR_NONE; + } + if (prefixlen) + { + grub_memcpy (target, *name, prefixlen); + target[prefixlen] = '/'; + } + ptr = target + prefixlen + size; + ptr = grub_stpcpy (ptr, rest); + *ptr = 0; + grub_dprintf ("cpio", "symlink redirected %s to %s\n", + *name, target); + grub_free (*name); + *name = target; + *restart = 1; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cpio_dir (grub_device_t device, const char *path_in, int (*hook) (const char *filename, const struct grub_dirhook_info *info)) { struct grub_cpio_data *data; grub_disk_addr_t ofs; - char *prev, *name; - const char *np; + char *prev, *name, *path; grub_size_t len; + int symlinknest = 0; + + path = grub_strdup (path_in + 1); + if (!path) + return grub_errno; grub_dl_ref (my_mod); @@ -224,23 +417,27 @@ grub_cpio_dir (grub_device_t device, const char *path, data = grub_cpio_mount (device->disk); if (!data) - goto fail; - - np = path + 1; - len = grub_strlen (path) - 1; + { + grub_free (path); + return grub_errno; + } + len = grub_strlen (path); data->hofs = 0; while (1) { grub_int32_t mtime; + grub_uint32_t mode; + grub_err_t err; - if (grub_cpio_find_file (data, &name, &mtime, &ofs)) + if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode)) goto fail; if (!ofs) break; - if (grub_memcmp (np, name, len) == 0) + if (grub_memcmp (path, name, len) == 0 + && (name[len] == 0 || name[len] == '/' || len == 0)) { char *p, *n; @@ -265,14 +462,35 @@ grub_cpio_dir (grub_device_t device, const char *path, prev = name; } else - grub_free (name); + { + int restart; + err = handle_symlink (data, name, &path, mode, &restart); + grub_free (name); + if (err) + goto fail; + if (restart) + { + len = grub_strlen (path); + if (++symlinknest == 8) + { + grub_error (GRUB_ERR_SYMLINK_LOOP, + "too deep nesting of symlinks"); + goto fail; + } + ofs = 0; + } + } } data->hofs = ofs; } fail: + grub_free (path); grub_free (prev); +#ifdef MODE_USTAR + grub_free (data->linkname); +#endif grub_free (data); grub_dl_unref (my_mod); @@ -281,23 +499,33 @@ fail: } static grub_err_t -grub_cpio_open (grub_file_t file, const char *name) +grub_cpio_open (grub_file_t file, const char *name_in) { struct grub_cpio_data *data; grub_disk_addr_t ofs; char *fn; - int i, j; + char *name = grub_strdup (name_in + 1); + int symlinknest = 0; + + if (!name) + return grub_errno; grub_dl_ref (my_mod); data = grub_cpio_mount (file->device->disk); if (!data) - goto fail; + { + grub_free (name); + return grub_errno; + } data->hofs = 0; while (1) { - if (grub_cpio_find_file (data, &fn, NULL, &ofs)) + grub_uint32_t mode; + int restart; + + if (grub_cpio_find_file (data, &fn, NULL, &ofs, &mode)) goto fail; if (!ofs) @@ -306,33 +534,31 @@ grub_cpio_open (grub_file_t file, const char *name) break; } - /* Compare NAME and FN by hand in order to cope with duplicate - slashes. */ - i = 0; - j = 0; - while (name[i] == '/') - i++; - while (1) + if (handle_symlink (data, fn, &name, mode, &restart)) { - if (name[i] != fn[j]) - goto no_match; - - if (name[i] == '\0') - break; - - while (name[i] == '/' && name[i+1] == '/') - i++; - - i++; - j++; + grub_free (fn); + goto fail; } - if (name[i] != fn[j]) + if (restart) + { + ofs = 0; + if (++symlinknest == 8) + { + grub_error (GRUB_ERR_SYMLINK_LOOP, + "too deep nesting of symlinks"); + goto fail; + } + goto no_match; + } + + if (grub_strcmp (name, fn) != 0) goto no_match; file->data = data; file->size = data->size; grub_free (fn); + grub_free (name); return GRUB_ERR_NONE; @@ -343,8 +569,11 @@ grub_cpio_open (grub_file_t file, const char *name) } fail: - +#ifdef MODE_USTAR + grub_free (data->linkname); +#endif grub_free (data); + grub_free (name); grub_dl_unref (my_mod); @@ -364,7 +593,13 @@ grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_cpio_close (grub_file_t file) { - grub_free (file->data); + struct grub_cpio_data *data; + + data = file->data; +#ifdef MODE_USTAR + grub_free (data->linkname); +#endif + grub_free (data); grub_dl_unref (my_mod); From 46bc1dc244f7e6461cc2d59f41a2181722c6c384 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 31 Oct 2011 10:40:30 +0100 Subject: [PATCH 470/673] * grub-core/fs/ufs.c (grub_ufs_lookup_symlink): Fix handling of long symlinks. --- ChangeLog | 8 ++++++++ grub-core/fs/ufs.c | 13 ++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 543823e9c..825524c09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-31 Vladimir Serbinenko + + * grub-core/fs/ufs.c (grub_ufs_lookup_symlink): Fix handling of + long symlinks. + 2011-10-30 Vladimir Serbinenko Handle symlinks and long names on tar and cpio. @@ -11,6 +16,9 @@ L and K entries. (grub_cpio_mount): Zero-fill data. (handle_symlink): New function. + (grub_cpio_dir): Handle symlinks. + (grub_cpio_open): Likewise. + (grub_cpio_close) [MODE_USTAR]: Free linkname. 2011-10-30 Vladimir Serbinenko diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index 435fec6a5..ea7a7455f 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -394,21 +394,16 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) static grub_err_t grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) { - char symlink[INODE_SIZE (data)]; + char symlink[INODE_SIZE (data) + 1]; if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); - if (INODE_NBLOCKS (data) == 0) + if (INODE_SIZE (data) <= sizeof (data->inode.symlink)) grub_strcpy (symlink, (char *) INODE (data, symlink)); else - { - grub_disk_read (data->disk, - (INODE_DIRBLOCKS (data, 0) - << grub_le_to_cpu32 (data->sblock.log2_blksz)), - 0, INODE_SIZE (data), symlink); - symlink[INODE_SIZE (data)] = '\0'; - } + grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink); + symlink[INODE_SIZE (data)] = '\0'; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') From 87661123b23d12bed46d90c3d6c11af7780beb88 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 31 Oct 2011 10:50:43 +0100 Subject: [PATCH 471/673] Use shifts in UFS. * grub-core/fs/ufs.c (UFS_LOG_BLKSZ): New macro. (grub_ufs_data): New field log2_blksz. (grub_ufs_read_file): Use shifts. (grub_ufs_mount): Check block size and logarithm it. --- ChangeLog | 9 +++++++++ grub-core/fs/ufs.c | 23 ++++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 825524c09..79b930c1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-10-31 Vladimir Serbinenko + + Use shifts in UFS. + + * grub-core/fs/ufs.c (UFS_LOG_BLKSZ): New macro. + (grub_ufs_data): New field log2_blksz. + (grub_ufs_read_file): Use shifts. + (grub_ufs_mount): Check block size and logarithm it. + 2011-10-31 Vladimir Serbinenko * grub-core/fs/ufs.c (grub_ufs_lookup_symlink): Fix handling of diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index ea7a7455f..bfcb7148f 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -50,6 +50,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* Calculate in which group the inode can be found. */ #define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize)) +#define UFS_LOG_BLKSZ(sblock) (data->log2_blksz) #define INODE(data,field) data->inode. field #ifdef MODE_UFS2 @@ -214,6 +215,7 @@ struct grub_ufs_data struct grub_ufs_inode inode; int ino; int linknest; + int log2_blksz; }; static grub_dl_t my_mod; @@ -295,10 +297,9 @@ grub_ufs_read_file (struct grub_ufs_data *data, if (len + pos > INODE_SIZE (data)) len = INODE_SIZE (data) - pos; - blockcnt = grub_divmod64 ((len + pos + UFS_BLKSZ (sblock) - 1), - UFS_BLKSZ (sblock), 0); + blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) >> UFS_LOG_BLKSZ (sblock); - for (i = grub_divmod64 (pos, UFS_BLKSZ (sblock), 0); i < blockcnt; i++) + for (i = pos >> UFS_LOG_BLKSZ (sblock); i < blockcnt; i++) { grub_disk_addr_t blknr; grub_off_t blockoff; @@ -306,7 +307,7 @@ grub_ufs_read_file (struct grub_ufs_data *data, int skipfirst = 0; - grub_divmod64 (pos, UFS_BLKSZ (sblock), &blockoff); + blockoff = pos & (UFS_BLKSZ (sblock) - 1); blknr = grub_ufs_get_file_block (data, i); if (grub_errno) @@ -315,14 +316,14 @@ grub_ufs_read_file (struct grub_ufs_data *data, /* Last block. */ if (i == blockcnt - 1) { - grub_divmod64 (len + pos, UFS_BLKSZ (sblock), &blockend); + blockend = (len + pos) & (UFS_BLKSZ (sblock) - 1); if (!blockend) blockend = UFS_BLKSZ (sblock); } /* First block. */ - if (i == grub_divmod64 (pos, UFS_BLKSZ (sblock), 0)) + if (i == (pos >> UFS_LOG_BLKSZ (sblock))) { skipfirst = blockoff; blockend -= skipfirst; @@ -536,8 +537,16 @@ grub_ufs_mount (grub_disk_t disk) if (grub_errno) goto fail; - if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC) + /* No need to byteswap bsize in this check. It works the same on both + endiannesses. */ + if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC + && data->sblock.bsize != 0 + && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0)) { + for (data->log2_blksz = 0; + (1U << data->log2_blksz) < grub_le_to_cpu32 (data->sblock.bsize); + data->log2_blksz++); + data->disk = disk; data->linknest = 0; return data; From ce109e843cd605acc2e69a1449b723a8edc6c873 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 31 Oct 2011 10:52:39 +0100 Subject: [PATCH 472/673] Read label on UFS1. * grub-core/fs/ufs.c (grub_ufs_label): Remove MODE_UFS2 condition. (grub_ufs_fs): Always set .label. --- ChangeLog | 7 +++++++ grub-core/fs/ufs.c | 5 ----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 79b930c1e..211a5f9ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-10-31 Vladimir Serbinenko + + Read label on UFS1. + + * grub-core/fs/ufs.c (grub_ufs_label): Remove MODE_UFS2 condition. + (grub_ufs_fs): Always set .label. + 2011-10-31 Vladimir Serbinenko Use shifts in UFS. diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index bfcb7148f..e951d6ce3 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -705,8 +705,6 @@ grub_ufs_close (grub_file_t file) return GRUB_ERR_NONE; } - -#ifdef MODE_UFS2 static grub_err_t grub_ufs_label (grub_device_t device, char **label) { @@ -726,7 +724,6 @@ grub_ufs_label (grub_device_t device, char **label) return grub_errno; } -#endif static grub_err_t grub_ufs_uuid (grub_device_t device, char **uuid) @@ -790,9 +787,7 @@ static struct grub_fs grub_ufs_fs = .open = grub_ufs_open, .read = grub_ufs_read, .close = grub_ufs_close, -#ifdef MODE_UFS2 .label = grub_ufs_label, -#endif .uuid = grub_ufs_uuid, .mtime = grub_ufs_mtime, .next = 0 From 7c01e783dcff1365057ea917e9095a2cb7b9d271 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 31 Oct 2011 13:56:52 +0100 Subject: [PATCH 473/673] * grub-core/fs/btrfs.c (grub_btrfs_extent_read): Add sanity check and don't report potentially unavialiable fields in debug output. (find_path): Fix double-free and memory leak. --- ChangeLog | 6 ++++++ grub-core/fs/btrfs.c | 17 +++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 211a5f9ca..27c18655a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-10-31 Vladimir Serbinenko + + * grub-core/fs/btrfs.c (grub_btrfs_extent_read): Add sanity check and + don't report potentially unavialiable fields in debug output. + (find_path): Fix double-free and memory leak. + 2011-10-31 Vladimir Serbinenko Read label on UFS1. diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 93642f789..16e034661 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -992,6 +992,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, grub_error (GRUB_ERR_BAD_FS, "extent not found"); return -1; } + if ((grub_ssize_t) elemsize < ((char *) &data->extent->inl + - (char *) data->extent)) + { + grub_error (GRUB_ERR_BAD_FS, "extent descriptor is too short"); + return -1; + } data->extstart = grub_le_to_cpu64 (key_out.offset); data->extsize = elemsize; data->extent = grub_malloc (elemsize); @@ -1012,12 +1018,10 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, data->extend = data->extstart + grub_le_to_cpu64 (data->extent->filled); - grub_dprintf ("btrfs", "extent 0x%" PRIxGRUB_UINT64_T "+0x%" - PRIxGRUB_UINT64_T " (0x%" - PRIxGRUB_UINT64_T ")\n", + grub_dprintf ("btrfs", "regular extent 0x%" PRIxGRUB_UINT64_T "+0x%" + PRIxGRUB_UINT64_T "\n", grub_le_to_cpu64 (key_out.offset), - grub_le_to_cpu64 (data->extent->size), - grub_le_to_cpu64 (data->extent->filled)); + grub_le_to_cpu64 (data->extent->size)); if (data->extend <= pos) { grub_error (GRUB_ERR_BAD_FS, "extent not found"); @@ -1309,7 +1313,6 @@ find_path (struct grub_btrfs_data *data, grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path, grub_strlen (path) + 1); grub_free (path_alloc); - grub_free (origpath); path = path_alloc = tmp; if (path[0] == '/') { @@ -1385,6 +1388,8 @@ find_path (struct grub_btrfs_data *data, } grub_free (direl); + grub_free (origpath); + grub_free (path_alloc); return GRUB_ERR_NONE; } From ce8ca56ed996ddeff86141f40a2d09dd8046d5c3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 1 Nov 2011 20:05:28 +0100 Subject: [PATCH 474/673] Fix RAIDZ(2). * grub-core/fs/zfs/zfs.c (grub_zfs_device_desc): New member ashift. (fill_vdev_info_real): Set ashift. (read_device): Rewrite RAIDZ part based on reverse engineering. --- ChangeLog | 8 +++++ grub-core/fs/zfs/zfs.c | 70 +++++++++++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 27c18655a..e112868f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-11-01 Vladimir Serbinenko + + Fix RAIDZ(2). + + * grub-core/fs/zfs/zfs.c (grub_zfs_device_desc): New member ashift. + (fill_vdev_info_real): Set ashift. + (read_device): Rewrite RAIDZ part based on reverse engineering. + 2011-10-31 Vladimir Serbinenko * grub-core/fs/btrfs.c (grub_btrfs_extent_read): Add sanity check and diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 9bd68222a..c7fd13018 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -152,6 +152,7 @@ struct grub_zfs_device_desc /* Valid only for RAIDZ. */ unsigned nparity; + unsigned ashift; /* Valid only for leaf devices. */ grub_device_t dev; @@ -516,6 +517,9 @@ fill_vdev_info_real (struct grub_zfs_data *data, if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "nparity", &par)) return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity"); fill->nparity = par; + if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "ashift", &par)) + return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz ashift"); + fill->ashift = par; } nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, ZPOOL_CONFIG_CHILDREN); @@ -882,38 +886,76 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, } case DEVICE_RAIDZ: { - grub_uint64_t sector; - grub_uint32_t bsize; unsigned c = 0; + grub_uint64_t high; + grub_uint64_t devn; + grub_uint64_t redundancy_strip = 0, m; + grub_uint64_t redundancy_strip2 = 0; + grub_uint32_t s; - bsize = (asize + desc->nparity) / desc->n_children; - sector = offset >> 9; + /* (4,1) -> 2, (3,1) -> 1 */ + if (desc->nparity == 1) + s = asize + desc->n_children - 2; + else + s = asize + desc->n_children - 3; + high = grub_divmod64 ((offset >> desc->ashift), + desc->n_children, &m); + + if (desc->nparity == 1) + { + redundancy_strip = m; + redundancy_strip += ((offset >> (desc->ashift + 11)) & 1); + if (redundancy_strip == desc->n_children) + redundancy_strip = 0; + redundancy_strip2 = redundancy_strip; + } + else + { + redundancy_strip = m; + redundancy_strip2 = m + 1; + if (redundancy_strip2 == desc->n_children) + redundancy_strip2 = 0; + } + grub_dprintf ("zfs", "rs = %x, %llx\n", + (int) redundancy_strip, + (unsigned long long) high); while (len > 0) { grub_size_t csize; - grub_uint64_t high; - grub_uint64_t devn; + grub_uint32_t bsize; grub_err_t err; - high = grub_divmod64 (sector + (asize > 2) + c, desc->n_children, - &devn); - csize = bsize << 9; + bsize = s / desc->n_children; + + while (1) + { + high = grub_divmod64 ((offset >> desc->ashift) + c, + desc->n_children, &devn); + if (devn != redundancy_strip && devn != redundancy_strip2) + break; + c++; + } + csize = bsize << desc->ashift; if (csize > len) csize = len; + grub_dprintf ("zfs", "RAIDZ mapping 0x%" PRIxGRUB_UINT64_T - "+%d+%u -> (0x%" PRIxGRUB_UINT64_T ", 0x%" + "+%u (%d, %d) -> (0x%" PRIxGRUB_UINT64_T ", 0x%" PRIxGRUB_UINT64_T ")\n", - sector,(asize > 2), c, high, devn); - err = read_device (high << 9, &desc->children[devn], + offset >> desc->ashift, c, asize, bsize, high, + devn); + err = read_device ((high << desc->ashift) + | (offset & ((1 << desc->ashift) - 1)), + &desc->children[devn], bsize, csize, buf); if (err) return err; c++; + s--; buf = (char *) buf + csize; len -= csize; } - return GRUB_ERR_NONE; } - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; } return grub_error (GRUB_ERR_BAD_FS, "unsupported device type"); } From aca5aefc7c7d3a1fccfbd49cb98f360af7e69e93 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 2 Nov 2011 20:48:04 +0100 Subject: [PATCH 475/673] Fix RAIDZ(2) for >= 5 devices. * grub-core/fs/zfs/zfs.c (read_device): Fix length formula. Remove asize argument. All users updated. --- ChangeLog | 7 +++++++ grub-core/fs/zfs/zfs.c | 42 ++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index e112868f0..08bad81c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-11-02 Vladimir Serbinenko + + Fix RAIDZ(2) for >= 5 devices. + + * grub-core/fs/zfs/zfs.c (read_device): Fix length formula. Remove + asize argument. All users updated. + 2011-11-01 Vladimir Serbinenko Fix RAIDZ(2). diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index c7fd13018..1c9b240ab 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -852,7 +852,7 @@ scan_devices (struct grub_zfs_data *data) static grub_err_t read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, - grub_uint32_t asize, grub_size_t len, void *buf) + grub_size_t len, void *buf) { switch (desc->type) { @@ -876,7 +876,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, "non-positive number of mirror children"); for (i = 0; i < desc->n_children; i++) { - err = read_device (offset, &desc->children[i], asize, + err = read_device (offset, &desc->children[i], len, buf); if (!err) break; @@ -893,28 +893,32 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_uint64_t redundancy_strip2 = 0; grub_uint32_t s; - /* (4,1) -> 2, (3,1) -> 1 */ - if (desc->nparity == 1) - s = asize + desc->n_children - 2; - else - s = asize + desc->n_children - 3; + if (desc->nparity < 1 || desc->nparity > 2) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "raidz%d is not supported", desc->nparity); + + s = (((len + (1 << desc->ashift) - 1) >> desc->ashift) + + (desc->n_children - desc->nparity) - 1); + high = grub_divmod64 ((offset >> desc->ashift), desc->n_children, &m); - if (desc->nparity == 1) + + switch (desc->nparity) { + case 1: redundancy_strip = m; redundancy_strip += ((offset >> (desc->ashift + 11)) & 1); if (redundancy_strip == desc->n_children) redundancy_strip = 0; redundancy_strip2 = redundancy_strip; - } - else - { + break; + case 2: redundancy_strip = m; redundancy_strip2 = m + 1; if (redundancy_strip2 == desc->n_children) redundancy_strip2 = 0; + break; } grub_dprintf ("zfs", "rs = %x, %llx\n", (int) redundancy_strip, @@ -924,8 +928,8 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_size_t csize; grub_uint32_t bsize; grub_err_t err; - bsize = s / desc->n_children; - + bsize = s / (desc->n_children - desc->nparity); + while (1) { high = grub_divmod64 ((offset >> desc->ashift) + c, @@ -934,21 +938,24 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, break; c++; } + csize = bsize << desc->ashift; if (csize > len) csize = len; grub_dprintf ("zfs", "RAIDZ mapping 0x%" PRIxGRUB_UINT64_T - "+%u (%d, %d) -> (0x%" PRIxGRUB_UINT64_T ", 0x%" + "+%u (%" PRIxGRUB_SIZE ", %" PRIxGRUB_UINT32_T + ") -> (0x%" PRIxGRUB_UINT64_T ", 0x%" PRIxGRUB_UINT64_T ")\n", - offset >> desc->ashift, c, asize, bsize, high, + offset >> desc->ashift, c, len, bsize, high, devn); err = read_device ((high << desc->ashift) | (offset & ((1 << desc->ashift) - 1)), &desc->children[devn], - bsize, csize, buf); + csize, buf); if (err) return err; + c++; s--; buf = (char *) buf + csize; @@ -976,8 +983,7 @@ read_dva (const dva_t *dva, for (i = 0; i < data->n_devices_attached; i++) if (data->devices_attached[i].id == DVA_GET_VDEV (dva)) { - err = read_device (offset, &data->devices_attached[i], - dva->dva_word[0] & 0xffffff, len, buf); + err = read_device (offset, &data->devices_attached[i], len, buf); if (!err) return GRUB_ERR_NONE; break; From 177440046d0f5129dfa2513835a42cfb86fdc2c7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 2 Nov 2011 23:28:25 +0100 Subject: [PATCH 476/673] * grub-core/fs/zfs/zfs.c (read_device): Add ability to sustain a single drive failure on both raidz and raidz2. --- ChangeLog | 5 +++ grub-core/fs/zfs/zfs.c | 100 +++++++++++++++++++++++++++-------------- 2 files changed, 71 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 08bad81c6..047c156c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-02 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (read_device): Add ability to sustain a single + drive failure on both raidz and raidz2. + 2011-11-02 Vladimir Serbinenko Fix RAIDZ(2) for >= 5 devices. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 1c9b240ab..1bfbed72c 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -850,6 +850,14 @@ scan_devices (struct grub_zfs_data *data) return GRUB_ERR_NONE; } +static inline void +xor (grub_uint64_t *a, const grub_uint64_t *b, grub_size_t s) +{ + s /= sizeof (grub_uint64_t); + while (s--) + *a++ ^= *b++; +} + static grub_err_t read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_size_t len, void *buf) @@ -889,40 +897,26 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, unsigned c = 0; grub_uint64_t high; grub_uint64_t devn; - grub_uint64_t redundancy_strip = 0, m; - grub_uint64_t redundancy_strip2 = 0; - grub_uint32_t s; + grub_uint64_t m; + grub_uint32_t s, orig_s; + void *orig_buf = buf; + grub_size_t orig_len = len; + void *recovery_buf = NULL; + grub_size_t recovery_len = 0; if (desc->nparity < 1 || desc->nparity > 2) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "raidz%d is not supported", desc->nparity); - s = (((len + (1 << desc->ashift) - 1) >> desc->ashift) - + (desc->n_children - desc->nparity) - 1); + orig_s = (((len + (1 << desc->ashift) - 1) >> desc->ashift) + + (desc->n_children - desc->nparity) - 1); + s = orig_s; high = grub_divmod64 ((offset >> desc->ashift), desc->n_children, &m); - - switch (desc->nparity) - { - case 1: - redundancy_strip = m; - redundancy_strip += ((offset >> (desc->ashift + 11)) & 1); - if (redundancy_strip == desc->n_children) - redundancy_strip = 0; - redundancy_strip2 = redundancy_strip; - break; - case 2: - redundancy_strip = m; - redundancy_strip2 = m + 1; - if (redundancy_strip2 == desc->n_children) - redundancy_strip2 = 0; - break; - } - grub_dprintf ("zfs", "rs = %x, %llx\n", - (int) redundancy_strip, - (unsigned long long) high); + if (desc->nparity == 2) + c = 2; while (len > 0) { grub_size_t csize; @@ -930,15 +924,12 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_err_t err; bsize = s / (desc->n_children - desc->nparity); - while (1) - { - high = grub_divmod64 ((offset >> desc->ashift) + c, - desc->n_children, &devn); - if (devn != redundancy_strip && devn != redundancy_strip2) - break; - c++; - } + if (desc->nparity == 1 + && ((offset >> (desc->ashift + 11)) & 1) == c) + c++; + high = grub_divmod64 ((offset >> desc->ashift) + c, + desc->n_children, &devn); csize = bsize << desc->ashift; if (csize > len) csize = len; @@ -953,6 +944,13 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, | (offset & ((1 << desc->ashift) - 1)), &desc->children[devn], csize, buf); + /* No raidz2 recovery yet. */ + if (err && recovery_len == 0) + { + recovery_buf = buf; + recovery_len = csize; + grub_errno = err = 0; + } if (err) return err; @@ -961,8 +959,42 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, buf = (char *) buf + csize; len -= csize; } + if (recovery_buf) + { + grub_err_t err; + high = grub_divmod64 ((offset >> desc->ashift) + + + ((desc->nparity == 1) + && ((offset >> (desc->ashift + 11)) & 1)), + desc->n_children, &devn); + err = read_device ((high << desc->ashift) + | (offset & ((1 << desc->ashift) - 1)), + &desc->children[devn], + recovery_len, recovery_buf); + if (err) + return err; + buf = orig_buf; + len = orig_len; + s = orig_s; + while (len > 0) + { + grub_size_t csize; + csize = ((s / (desc->n_children - desc->nparity)) + << desc->ashift); + if (csize > len) + csize = len; + + if (buf != recovery_buf) + xor (recovery_buf, buf, + csize < recovery_len ? csize : recovery_len); + + s--; + buf = (char *) buf + csize; + len -= csize; + } + } + return GRUB_ERR_NONE; } - return GRUB_ERR_NONE; } return grub_error (GRUB_ERR_BAD_FS, "unsupported device type"); } From cf5ba824ea0d09e43b11af0d36e7267ec323c157 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 3 Nov 2011 07:29:35 +0100 Subject: [PATCH 477/673] * grub-core/fs/zfs/zfs.c (read_device): Support raidz3. --- ChangeLog | 4 ++++ grub-core/fs/zfs/zfs.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 047c156c7..f6f5eaeeb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-03 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (read_device): Support raidz3. + 2011-11-02 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (read_device): Add ability to sustain a single diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 1bfbed72c..ef352a770 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -904,7 +904,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, void *recovery_buf = NULL; grub_size_t recovery_len = 0; - if (desc->nparity < 1 || desc->nparity > 2) + if (desc->nparity < 1 || desc->nparity > 3) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "raidz%d is not supported", desc->nparity); @@ -914,9 +914,10 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, high = grub_divmod64 ((offset >> desc->ashift), desc->n_children, &m); - if (desc->nparity == 2) c = 2; + if (desc->nparity == 3) + c = 3; while (len > 0) { grub_size_t csize; From f92ece7d45946f04b5dacda73efe99c2df3888c9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 3 Nov 2011 14:52:59 +0100 Subject: [PATCH 478/673] * grub-core/fs/nilfs2.c (grub_nilfs2_mtime): Use correct superblock field. --- grub-core/fs/nilfs2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index a8bbe9566..35a040b97 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -1152,7 +1152,7 @@ grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm) if (!data) *tm = 0; else - *tm = (grub_int32_t) grub_le_to_cpu64 (data->sblock.s_mtime); + *tm = (grub_int32_t) grub_le_to_cpu64 (data->sblock.s_wtime); grub_dl_unref (my_mod); From 7d0ac9316382378b389c15b0d103296df8e640dd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 3 Nov 2011 14:57:34 +0100 Subject: [PATCH 479/673] Make reiserfs label retrieval similar to other *_label functions. * grub-core/fs/reiserfs.c (grub_reiserfs_superblock): New field label. (REISERFS_MAX_LABEL_LENGTH): Removed. (REISERFS_LABEL_OFFSET): Likewise. (grub_reiserfs_label): Rewritten. --- ChangeLog | 14 ++++++++++++++ grub-core/fs/reiserfs.c | 25 +++++++++++++++++-------- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6f5eaeeb..84ad4f9ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-11-03 Vladimir Serbinenko + + Make reiserfs label retrieval similar to other *_label functions. + + * grub-core/fs/reiserfs.c (grub_reiserfs_superblock): New field label. + (REISERFS_MAX_LABEL_LENGTH): Removed. + (REISERFS_LABEL_OFFSET): Likewise. + (grub_reiserfs_label): Rewritten. + +2011-11-03 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (grub_nilfs2_mtime): Use correct superblock + field. + 2011-11-03 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (read_device): Support raidz3. diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index d5bc52d14..639de8d74 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -57,8 +57,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB" /* If the 3rd bit of an item state is set, then it's visible. */ #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04) -#define REISERFS_MAX_LABEL_LENGTH 16 -#define REISERFS_LABEL_OFFSET 0x64 #define S_IFLNK 0xA000 @@ -109,6 +107,7 @@ struct grub_reiserfs_superblock grub_uint32_t inode_generation; grub_uint8_t unused[4]; grub_uint16_t uuid[8]; + char label[16]; } __attribute__ ((packed)); struct grub_reiserfs_journal_header @@ -1323,14 +1322,24 @@ grub_reiserfs_dir (grub_device_t device, const char *path, static grub_err_t grub_reiserfs_label (grub_device_t device, char **label) { - *label = grub_malloc (REISERFS_MAX_LABEL_LENGTH); - if (*label) + struct grub_reiserfs_data *data; + grub_disk_t disk = device->disk; + + grub_dl_ref (my_mod); + + data = grub_reiserfs_mount (disk); + if (data) { - grub_disk_read (device->disk, - REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE, - REISERFS_LABEL_OFFSET, REISERFS_MAX_LABEL_LENGTH, - *label); + *label = grub_strndup (data->superblock.label, + sizeof (data->superblock.label)); } + else + *label = NULL; + + grub_dl_unref (my_mod); + + grub_free (data); + return grub_errno; } From 9d9b3d2f0260a7782dfe5f91e3240cde4cf132ae Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 3 Nov 2011 15:00:45 +0100 Subject: [PATCH 480/673] * grub-core/fs/ufs.c (grub_ufs_mtime) [MODE_UFS2]: Check mtime field as well. --- ChangeLog | 5 +++++ grub-core/fs/ufs.c | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 84ad4f9ec..9ec293dda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-03 Vladimir Serbinenko + + * grub-core/fs/ufs.c (grub_ufs_mtime) [MODE_UFS2]: Check mtime field + as well. + 2011-11-03 Vladimir Serbinenko Make reiserfs label retrieval similar to other *_label functions. diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index e951d6ce3..cd2994895 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -761,11 +761,13 @@ grub_ufs_mtime (grub_device_t device, grub_int32_t *tm) if (!data) *tm = 0; else + { + *tm = grub_le_to_cpu32 (data->sblock.mtime); #ifdef MODE_UFS2 - *tm = grub_le_to_cpu64 (data->sblock.mtime2); -#else - *tm = grub_le_to_cpu32 (data->sblock.mtime); + if (*tm < (grub_int64_t) grub_le_to_cpu64 (data->sblock.mtime2)) + *tm = grub_le_to_cpu64 (data->sblock.mtime2); #endif + } grub_dl_unref (my_mod); From 158dc1ea2604c8d9f17ec6c59f90c91760756057 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 3 Nov 2011 15:13:30 +0100 Subject: [PATCH 481/673] XZ CRC64 and SHA256 support. * Makefile.util.def (libgrubmods): Add crc64.c. * grub-core/Makefile.core.def (crc64): New module. * grub-core/lib/crc64.c: New file. * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_hash) [!GRUB_EMBED_DECOMPRESSOR]: Rename crc32_context to hash_context. Fix the type. (MAX_HASH_SIZE): New define. (xz_dec) [!GRUB_EMBED_DECOMPRESSOR]: Add generic hash fields. (dec_block) [!GRUB_EMBED_DECOMPRESSOR]: Handle non-crc32 hashes. (index_update) [!GRUB_EMBED_DECOMPRESSOR]: Likewise. (dec_index) [!GRUB_EMBED_DECOMPRESSOR]: Likewise. (crc32_validate) [!GRUB_EMBED_DECOMPRESSOR]: Rename to ... (hash_validate) [!GRUB_EMBED_DECOMPRESSOR]: ... this. Handle non-crc32 hashes. (hashes) [!GRUB_EMBED_DECOMPRESSOR]: New variable. (dec_stream_header): Handle non-crc32 hashes. (dec_stream_footer): Likewise. (dec_block_header): Likewise. (dec_main): Likewise. (xz_dec_init): Likewise. (xz_dec_reset): Likewise. (xz_dec_end): Likewise. * util/import_gcry.py: Add CRC64 line. --- ChangeLog | 28 ++ Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/lib/crc64.c | 111 ++++++++ grub-core/lib/xzembed/xz_dec_stream.c | 355 +++++++++++++++++--------- util/import_gcry.py | 1 + 6 files changed, 387 insertions(+), 114 deletions(-) create mode 100644 grub-core/lib/crc64.c diff --git a/ChangeLog b/ChangeLog index 9ec293dda..983b7e9e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2011-11-03 Vladimir Serbinenko + + XZ CRC64 and SHA256 support. + + * Makefile.util.def (libgrubmods): Add crc64.c. + * grub-core/Makefile.core.def (crc64): New module. + * grub-core/lib/crc64.c: New file. + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_hash) + [!GRUB_EMBED_DECOMPRESSOR]: Rename crc32_context to hash_context. + Fix the type. + (MAX_HASH_SIZE): New define. + (xz_dec) [!GRUB_EMBED_DECOMPRESSOR]: Add generic hash fields. + (dec_block) [!GRUB_EMBED_DECOMPRESSOR]: Handle non-crc32 hashes. + (index_update) [!GRUB_EMBED_DECOMPRESSOR]: Likewise. + (dec_index) [!GRUB_EMBED_DECOMPRESSOR]: Likewise. + (crc32_validate) [!GRUB_EMBED_DECOMPRESSOR]: Rename to ... + (hash_validate) [!GRUB_EMBED_DECOMPRESSOR]: ... this. + Handle non-crc32 hashes. + (hashes) [!GRUB_EMBED_DECOMPRESSOR]: New variable. + (dec_stream_header): Handle non-crc32 hashes. + (dec_stream_footer): Likewise. + (dec_block_header): Likewise. + (dec_main): Likewise. + (xz_dec_init): Likewise. + (xz_dec_reset): Likewise. + (xz_dec_end): Likewise. + * util/import_gcry.py: Add CRC64 line. + 2011-11-03 Vladimir Serbinenko * grub-core/fs/ufs.c (grub_ufs_mtime) [MODE_UFS2]: Check mtime field diff --git a/Makefile.util.def b/Makefile.util.def index a839920d5..17894b1d2 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -93,6 +93,7 @@ library = { common = grub-core/lib/LzmaEnc.c; common = grub-core/lib/crc.c; common = grub-core/lib/adler32.c; + common = grub-core/lib/crc64.c; common = grub-core/normal/datetime.c; common = grub-core/normal/misc.c; common = grub-core/partmap/acorn.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 2b72d8429..b2e8e7aa2 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1698,3 +1698,8 @@ module = { name = adler32; common = lib/adler32.c; }; + +module = { + name = crc64; + common = lib/crc64.c; +}; diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c new file mode 100644 index 000000000..92c398d1e --- /dev/null +++ b/grub-core/lib/crc64.c @@ -0,0 +1,111 @@ +/* crc64.c - crc64 function */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2011 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 . + */ + +#include +#include +#include + +static grub_uint64_t crc64_table [256]; + +static void +init_crc64_table (void) +{ + auto grub_uint64_t reflect (grub_uint64_t ref, int len); + grub_uint64_t reflect (grub_uint64_t ref, int len) + { + grub_uint64_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1ULL << (len - i); + ref >>= 1; + } + + return result; + } + + grub_uint64_t polynomial = 0x42f0e1eba9ea3693ULL; + int i, j; + + for(i = 0; i < 256; i++) + { + crc64_table[i] = reflect(i, 8) << 56; + for (j = 0; j < 8; j++) + { + crc64_table[i] = (crc64_table[i] << 1) ^ + (crc64_table[i] & (1ULL << 63) ? polynomial : 0); + } + crc64_table[i] = reflect(crc64_table[i], 64); + } +} + +static void +crc64_init (void *context) +{ + if (! crc64_table[1]) + init_crc64_table (); + *(grub_uint64_t *) context = 0; +} + +static void +crc64_write (void *context, const void *buf, grub_size_t size) +{ + unsigned i; + const grub_uint8_t *data = buf; + grub_uint64_t crc = ~grub_le_to_cpu64 (*(grub_uint64_t *) context); + + for (i = 0; i < size; i++) + { + crc = (crc >> 8) ^ crc64_table[(crc & 0xFF) ^ *data]; + data++; + } + + *(grub_uint64_t *) context = grub_cpu_to_le64 (~crc); +} + +static grub_uint8_t * +crc64_read (void *context) +{ + return context; +} + +static void +crc64_final (void *context __attribute__ ((unused))) +{ +} + +gcry_md_spec_t _gcry_digest_spec_crc64 = + { + "CRC64", 0, 0, 0, 8, + crc64_init, crc64_write, crc64_final, crc64_read, + sizeof (grub_uint64_t), + .blocksize = 64 + }; + +GRUB_MOD_INIT(crc64) +{ + grub_md_register (&_gcry_digest_spec_crc64); +} + +GRUB_MOD_FINI(crc64) +{ + grub_md_unregister (&_gcry_digest_spec_crc64); +} diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 3bf201d50..383c29a2f 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -32,10 +32,13 @@ struct xz_dec_hash { vli_type unpadded; vli_type uncompressed; #ifndef GRUB_EMBED_DECOMPRESSOR - uint8_t *crc32_context; + uint64_t *hash_context; #endif }; +/* Enough for up to 512 bits. */ +#define MAX_HASH_SIZE 64 + struct xz_dec { /* Position in dec_main() */ enum { @@ -62,11 +65,22 @@ struct xz_dec { size_t out_start; /* CRC32 value in Block or Index */ - uint32_t crc32_temp; /* need for crc32_validate*/ - uint8_t *crc32_context; +#ifndef GRUB_EMBED_DECOMPRESSOR + uint8_t hash_value[MAX_HASH_SIZE]; /* need for crc32_validate*/ +#endif + int have_hash_value; +#ifndef GRUB_EMBED_DECOMPRESSOR + uint64_t *hash_context; + uint64_t *crc32_context; +#endif - /* True if CRC32 is calculated from uncompressed data */ - bool has_crc32; + /* Hash function calculated from uncompressed data */ +#ifndef GRUB_EMBED_DECOMPRESSOR + const gcry_md_spec_t *hash; + const gcry_md_spec_t *crc32; +#endif + grub_size_t hash_size; + grub_uint8_t hash_id; /* True if we are operating in single-call mode. */ bool single_call; @@ -250,9 +264,12 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) return XZ_DATA_ERROR; #ifndef GRUB_EMBED_DECOMPRESSOR - if (s->has_crc32) - GRUB_MD_CRC32->write(s->crc32_context,b->out + s->out_start, - b->out_pos - s->out_start); + if (s->hash) + s->hash->write(s->hash_context,b->out + s->out_start, + b->out_pos - s->out_start); + if (s->crc32) + s->crc32->write(s->crc32_context,b->out + s->out_start, + b->out_pos - s->out_start); #endif if (ret == XZ_STREAM_END) { @@ -268,14 +285,15 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) s->block.hash.unpadded += s->block_header.size + s->block.compressed; - if (s->has_crc32) - s->block.hash.unpadded += 4; + s->block.hash.unpadded += s->hash_size; s->block.hash.uncompressed += s->block.uncompressed; #ifndef GRUB_EMBED_DECOMPRESSOR - GRUB_MD_CRC32->write(s->block.hash.crc32_context, - (const uint8_t *)&s->block.hash, 2 * sizeof(vli_type)); + if (s->hash) + s->hash->write(s->block.hash.hash_context, + (const uint8_t *)&s->block.hash, + 2 * sizeof(vli_type)); #endif ++s->block.count; @@ -290,7 +308,10 @@ static void index_update(struct xz_dec *s, const struct xz_buf *b) size_t in_used = b->in_pos - s->in_start; s->index.size += in_used; #ifndef GRUB_EMBED_DECOMPRESSOR - GRUB_MD_CRC32->write(s->crc32_context,b->in + s->in_start, in_used); + if (s->hash) + s->hash->write(s->hash_context,b->in + s->in_start, in_used); + if (s->crc32) + s->crc32->write(s->crc32_context,b->in + s->in_start, in_used); #endif } @@ -337,8 +358,9 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) s->index.hash.uncompressed += s->vli; #ifndef GRUB_EMBED_DECOMPRESSOR - GRUB_MD_CRC32->write(s->index.hash.crc32_context, - (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type)); + if (s->hash) + s->hash->write(s->index.hash.hash_context, + (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type)); #endif --s->index.count; @@ -354,13 +376,30 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) * Validate that the next four input bytes match the value of s->crc32. * s->pos must be zero when starting to validate the first byte. */ -static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b) +static enum xz_ret hash_validate(struct xz_dec *s, struct xz_buf *b, + int crc32) { #ifndef GRUB_EMBED_DECOMPRESSOR - if(s->crc32_temp == 0) + const gcry_md_spec_t *hash = crc32 ? s->crc32 : s->hash; + grub_uint64_t *hash_context = crc32 ? s->crc32_context + : s->hash_context; + if(!s->have_hash_value && hash + && sizeof (s->hash_value) >= hash->mdlen) { - GRUB_MD_CRC32->final(s->crc32_context); - s->crc32_temp = get_unaligned_be32(GRUB_MD_CRC32->read(s->crc32_context)); + hash->final(hash_context); + grub_memcpy (s->hash_value, hash->read(hash_context), + hash->mdlen); + s->have_hash_value = 1; + if (s->hash_id == 1 || crc32) + { + grub_uint8_t t; + t = s->hash_value[0]; + s->hash_value[0] = s->hash_value[3]; + s->hash_value[3] = t; + t = s->hash_value[1]; + s->hash_value[1] = s->hash_value[2]; + s->hash_value[2] = t; + } } #endif @@ -369,23 +408,38 @@ static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b) return XZ_OK; #ifndef GRUB_EMBED_DECOMPRESSOR - if (((s->crc32_temp >> s->pos) & 0xFF) != b->in[b->in_pos++]) + if (hash && s->hash_value[s->pos / 8] != b->in[b->in_pos++]) return XZ_DATA_ERROR; #endif s->pos += 8; - } while (s->pos < 32); + } while (s->pos < (crc32 ? 32 : s->hash_size * 8)); #ifndef GRUB_EMBED_DECOMPRESSOR - GRUB_MD_CRC32->init(s->crc32_context); + if (s->hash) + s->hash->init(s->hash_context); + if (s->crc32) + s->crc32->init(s->crc32_context); #endif - s->crc32_temp = 0; + s->have_hash_value = 0; s->pos = 0; return XZ_STREAM_END; } +#ifndef GRUB_EMBED_DECOMPRESSOR +static struct +{ + const char *name; + grub_size_t size; +} hashes[] = { + [0x01] = { "CRC32", 4}, + [0x04] = { "CRC64", 8}, + [0x0A] = { "SHA256", 32}, +}; +#endif + /* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ static enum xz_ret dec_stream_header(struct xz_dec *s) { @@ -393,17 +447,27 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) return XZ_FORMAT_ERROR; #ifndef GRUB_EMBED_DECOMPRESSOR - uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + if (s->crc32) + { + uint64_t hash_context[(s->crc32->contextsize + 7) / 8]; + uint8_t resulthash[s->crc32->mdlen]; + uint8_t readhash[4]; - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context,s->temp.buf + HEADER_MAGIC_SIZE, 2); - GRUB_MD_CRC32->final(crc32_context); + s->crc32->init(hash_context); + s->crc32->write(hash_context,s->temp.buf + HEADER_MAGIC_SIZE, 2); + s->crc32->final(hash_context); - uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context)); - uint32_t readcrc = get_unaligned_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2); + grub_memcpy (resulthash, s->crc32->read(hash_context), + s->crc32->mdlen); + readhash[0] = s->temp.buf[HEADER_MAGIC_SIZE + 5]; + readhash[1] = s->temp.buf[HEADER_MAGIC_SIZE + 4]; + readhash[2] = s->temp.buf[HEADER_MAGIC_SIZE + 3]; + readhash[3] = s->temp.buf[HEADER_MAGIC_SIZE + 2]; - if(resultcrc != readcrc) - return XZ_DATA_ERROR; + if(4 != s->crc32->mdlen + || grub_memcmp (readhash, resulthash, s->crc32->mdlen) != 0) + return XZ_DATA_ERROR; + } #endif /* @@ -411,10 +475,77 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) * only none (Check ID = 0) and CRC32 (Check ID = 1). */ if (s->temp.buf[HEADER_MAGIC_SIZE] != 0 - || s->temp.buf[HEADER_MAGIC_SIZE + 1] > 1) + || s->temp.buf[HEADER_MAGIC_SIZE + 1] >= ARRAY_SIZE (hashes) + || (hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].name == 0 + && s->temp.buf[HEADER_MAGIC_SIZE + 1] != 0)) return XZ_OPTIONS_ERROR; - s->has_crc32 = s->temp.buf[HEADER_MAGIC_SIZE + 1]; + s->hash_id = s->temp.buf[HEADER_MAGIC_SIZE + 1]; + +#ifndef GRUB_EMBED_DECOMPRESSOR + if (s->crc32) + { + s->crc32_context = kmalloc(s->crc32->contextsize, GFP_KERNEL); + if (s->crc32_context == NULL) + return XZ_MEMLIMIT_ERROR; + s->crc32->init(s->crc32_context); + } +#endif + + if (s->temp.buf[HEADER_MAGIC_SIZE + 1]) + { + s->hash_size = hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].size; +#ifndef GRUB_EMBED_DECOMPRESSOR + s->hash = grub_crypto_lookup_md_by_name (hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].name); + if (s->hash) + { + if (s->hash->mdlen != s->hash_size) + return XZ_OPTIONS_ERROR; + s->hash_context = kmalloc(s->hash->contextsize, GFP_KERNEL); + if (s->hash_context == NULL) + { + kfree(s->crc32_context); + return XZ_MEMLIMIT_ERROR; + } + + s->index.hash.hash_context = kmalloc(s->hash->contextsize, + GFP_KERNEL); + if (s->index.hash.hash_context == NULL) + { + kfree(s->hash_context); + kfree(s->crc32_context); + return XZ_MEMLIMIT_ERROR; + } + + s->block.hash.hash_context = kmalloc(s->hash->contextsize, GFP_KERNEL); + if (s->block.hash.hash_context == NULL) + { + kfree(s->index.hash.hash_context); + kfree(s->hash_context); + kfree(s->crc32_context); + return XZ_MEMLIMIT_ERROR; + } + + s->hash->init(s->hash_context); + s->hash->init(s->index.hash.hash_context); + s->hash->init(s->block.hash.hash_context); + } +#else + s->hash = 0; +#endif +#if 1 + if (!s->hash) + return XZ_OPTIONS_ERROR; +#endif + } + else + { + s->hash = 0; + s->hash_size = 0; + } + + s->have_hash_value = 0; + return XZ_OK; } @@ -426,19 +557,30 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s) return XZ_DATA_ERROR; #ifndef GRUB_EMBED_DECOMPRESSOR - uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + if (s->crc32) + { + uint64_t hash_context[(s->crc32->contextsize + 7) / 8]; + uint8_t resulthash[s->crc32->mdlen]; + uint8_t readhash[4]; - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, s->temp.buf + 4, 6); - GRUB_MD_CRC32->final(crc32_context); + s->crc32->init(hash_context); + s->crc32->write(hash_context,s->temp.buf + 4, 6); + s->crc32->final(hash_context); - uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context)); - uint32_t readcrc = get_unaligned_le32(s->temp.buf); + grub_memcpy (resulthash, s->crc32->read(hash_context), + s->crc32->mdlen); + readhash[0] = s->temp.buf[3]; + readhash[1] = s->temp.buf[2]; + readhash[2] = s->temp.buf[1]; + readhash[3] = s->temp.buf[0]; - if(resultcrc != readcrc) - return XZ_DATA_ERROR; + if(4 != s->crc32->mdlen + || grub_memcmp (readhash, resulthash, s->crc32->mdlen) != 0) + return XZ_DATA_ERROR; + } #endif + /* * Validate Backward Size. Note that we never added the size of the * Index CRC32 field to s->index.size, thus we use s->index.size / 4 @@ -447,7 +589,7 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s) if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) return XZ_DATA_ERROR; - if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->has_crc32) + if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->hash_id) return XZ_DATA_ERROR; /* @@ -468,17 +610,27 @@ static enum xz_ret dec_block_header(struct xz_dec *s) */ s->temp.size -= 4; #ifndef GRUB_EMBED_DECOMPRESSOR - uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + if (s->crc32) + { + uint64_t hash_context[(s->crc32->contextsize + 7) / 8]; + uint8_t resulthash[s->crc32->mdlen]; + uint8_t readhash[4]; - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, s->temp.buf, s->temp.size); - GRUB_MD_CRC32->final(crc32_context); + s->crc32->init(hash_context); + s->crc32->write(hash_context,s->temp.buf, s->temp.size); + s->crc32->final(hash_context); - uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context)); - uint32_t readcrc = get_unaligned_le32(s->temp.buf + s->temp.size); + grub_memcpy (resulthash, s->crc32->read(hash_context), + s->crc32->mdlen); + readhash[3] = s->temp.buf[s->temp.size]; + readhash[2] = s->temp.buf[s->temp.size + 1]; + readhash[1] = s->temp.buf[s->temp.size + 2]; + readhash[0] = s->temp.buf[s->temp.size + 3]; - if (resultcrc != readcrc) - return XZ_DATA_ERROR; + if(4 != s->crc32->mdlen + || grub_memcmp (readhash, resulthash, s->crc32->mdlen) != 0) + return XZ_DATA_ERROR; + } #endif s->temp.pos = 2; @@ -659,11 +811,9 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_BLOCK_CHECK; case SEQ_BLOCK_CHECK: - if (s->has_crc32) { - ret = crc32_validate(s, b); - if (ret != XZ_STREAM_END) - return ret; - } + ret = hash_validate(s, b, 0); + if (ret != XZ_STREAM_END) + return ret; s->sequence = SEQ_BLOCK_START; break; @@ -691,24 +841,31 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) index_update(s, b); #ifndef GRUB_EMBED_DECOMPRESSOR - /* Compare the hashes to validate the Index field. */ - GRUB_MD_CRC32->final(s->block.hash.crc32_context); - GRUB_MD_CRC32->final(s->index.hash.crc32_context); - uint32_t block_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->block.hash.crc32_context); - uint32_t index_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->index.hash.crc32_context); - - if (s->block.hash.unpadded != s->index.hash.unpadded - || s->block.hash.uncompressed != s->index.hash.uncompressed - || block_crc != index_crc) + if (s->hash) { - return XZ_DATA_ERROR; + uint8_t block_hash[s->hash->mdlen]; + uint8_t index_hash[s->hash->mdlen]; + /* Compare the hashes to validate the Index field. */ + s->hash->final(s->block.hash.hash_context); + s->hash->final(s->index.hash.hash_context); + grub_memcpy (block_hash, + s->hash->read(s->block.hash.hash_context), + s->hash->mdlen); + grub_memcpy (index_hash, + s->hash->read(s->index.hash.hash_context), + s->hash->mdlen); + + if (s->block.hash.unpadded != s->index.hash.unpadded + || s->block.hash.uncompressed != s->index.hash.uncompressed + || grub_memcmp (block_hash, index_hash, s->hash->mdlen) != 0) + return XZ_DATA_ERROR; } #endif s->sequence = SEQ_INDEX_CRC32; case SEQ_INDEX_CRC32: - ret = crc32_validate(s, b); + ret = hash_validate(s, b, 1); if (ret != XZ_STREAM_END) return ret; @@ -802,46 +959,12 @@ struct xz_dec * xz_dec_init(uint32_t dict_max) return NULL; #endif + memset (s, 0, sizeof (*s)); + #ifndef GRUB_EMBED_DECOMPRESSOR - /* prepare CRC32 calculators */ - if(GRUB_MD_CRC32 == NULL) - { - kfree(s); - return NULL; - } - - s->crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL); - if (s->crc32_context == NULL) - { - kfree(s); - return NULL; - } - - s->index.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL); - if (s->index.hash.crc32_context == NULL) - { - kfree(s->crc32_context); - kfree(s); - return NULL; - } - - s->block.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL); - if (s->block.hash.crc32_context == NULL) - { - kfree(s->index.hash.crc32_context); - kfree(s->crc32_context); - kfree(s); - return NULL; - } - - - GRUB_MD_CRC32->init(s->crc32_context); - GRUB_MD_CRC32->init(s->index.hash.crc32_context); - GRUB_MD_CRC32->init(s->block.hash.crc32_context); + s->crc32 = grub_crypto_lookup_md_by_name ("CRC32"); #endif - s->crc32_temp = 0; - s->single_call = dict_max == 0; #ifdef XZ_DEC_BCJ @@ -876,28 +999,31 @@ void xz_dec_reset(struct xz_dec *s) { #ifndef GRUB_EMBED_DECOMPRESSOR - uint8_t *t; - t = s->block.hash.crc32_context; + uint64_t *t; + t = s->block.hash.hash_context; #endif memzero(&s->block, sizeof(s->block)); #ifndef GRUB_EMBED_DECOMPRESSOR - s->block.hash.crc32_context = t; - t = s->index.hash.crc32_context; + s->block.hash.hash_context = t; + t = s->index.hash.hash_context; #endif memzero(&s->index, sizeof(s->index)); #ifndef GRUB_EMBED_DECOMPRESSOR - s->index.hash.crc32_context = t; + s->index.hash.hash_context = t; #endif } s->temp.pos = 0; s->temp.size = STREAM_HEADER_SIZE; #ifndef GRUB_EMBED_DECOMPRESSOR - GRUB_MD_CRC32->init(s->crc32_context); - GRUB_MD_CRC32->init(s->index.hash.crc32_context); - GRUB_MD_CRC32->init(s->block.hash.crc32_context); + if (s->hash) + { + s->hash->init(s->hash_context); + s->hash->init(s->index.hash.hash_context); + s->hash->init(s->block.hash.hash_context); + } #endif - s->crc32_temp = 0; + s->have_hash_value = 0; } void xz_dec_end(struct xz_dec *s) @@ -905,8 +1031,9 @@ void xz_dec_end(struct xz_dec *s) if (s != NULL) { xz_dec_lzma2_end(s->lzma2); #ifndef GRUB_EMBED_DECOMPRESSOR - kfree(s->index.hash.crc32_context); - kfree(s->block.hash.crc32_context); + kfree(s->index.hash.hash_context); + kfree(s->block.hash.hash_context); + kfree(s->hash_context); kfree(s->crc32_context); #endif #ifdef XZ_DEC_BCJ diff --git a/util/import_gcry.py b/util/import_gcry.py index 7591d8f0e..ec34d16b5 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -83,6 +83,7 @@ cryptolist.write ("AES-192: gcry_rijndael\n"); cryptolist.write ("AES-256: gcry_rijndael\n"); cryptolist.write ("ADLER32: adler32\n"); +cryptolist.write ("CRC64: crc64\n"); for cipher_file in cipher_files: infile = os.path.join (cipher_dir_in, cipher_file) From 9cc3581d7d06d3d56a1e1b54316bef66362513f5 Mon Sep 17 00:00:00 2001 From: crocket Date: Thu, 3 Nov 2011 15:21:47 +0100 Subject: [PATCH 482/673] * util/grub.d/10_linux.in: Add Slackware initrd naming. --- ChangeLog | 4 ++++ util/grub.d/10_linux.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 983b7e9e5..81f5d942d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-03 crocket + + * util/grub.d/10_linux.in: Add Slackware initrd naming. + 2011-11-03 Vladimir Serbinenko XZ CRC64 and SHA256 support. diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index c3565096b..fe4f0e730 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -156,7 +156,7 @@ while [ "x$list" != "x" ] ; do linux_root_device_thisversion="${LINUX_ROOT_DEVICE}" initrd= - for i in "initrd.img-${version}" "initrd-${version}.img" \ + for i in "initrd.img-${version}" "initrd-${version}.img" "initrd-${version}.gz" \ "initrd-${version}" "initramfs-${version}.img" \ "initrd.img-${alt_version}" "initrd-${alt_version}.img" \ "initrd-${alt_version}" "initramfs-${alt_version}.img" \ From 1e51cabd7bf407917363d24fbe53c44ee0e925bc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 3 Nov 2011 16:04:26 +0100 Subject: [PATCH 483/673] * grub-core/gettext/gettext.c (grub_gettext_init_ext): Exit if local is NULL. --- ChangeLog | 5 +++++ grub-core/gettext/gettext.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 81f5d942d..ceca3fddb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-03 Vladimir Serbinenko + + * grub-core/gettext/gettext.c (grub_gettext_init_ext): Exit if local is + NULL. + 2011-11-03 crocket * util/grub.d/10_linux.in: Add Slackware initrd naming. diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c index cca8b901f..8581b1ff3 100644 --- a/grub-core/gettext/gettext.c +++ b/grub-core/gettext/gettext.c @@ -296,6 +296,9 @@ grub_gettext_init_ext (const char *locale) { char *locale_dir; + if (!locale) + return; + locale_dir = grub_env_get ("locale_dir"); if (locale_dir == NULL) { @@ -370,8 +373,6 @@ grub_cmd_translate (grub_command_t cmd __attribute__ ((unused)), GRUB_MOD_INIT (gettext) { - (void) mod; /* To stop warning. */ - const char *lang; lang = grub_env_get ("lang"); From 182c872a7bedb2c2c228cbee1e7022616aa8416b Mon Sep 17 00:00:00 2001 From: Philipp Matthias Hahn Date: Thu, 3 Nov 2011 16:49:02 +0100 Subject: [PATCH 484/673] * util/grub-mkrescue.in: Fix handling xorriso option. --- ChangeLog | 4 ++++ util/grub-mkrescue.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ceca3fddb..028bffe5c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-03 Philipp Matthias Hahn + + * util/grub-mkrescue.in: Fix handling xorriso option. + 2011-11-03 Vladimir Serbinenko * grub-core/gettext/gettext.c (grub_gettext_init_ext): Exit if local is diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 4c96dd42b..eff77088f 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -129,7 +129,7 @@ do --xorriso) xorriso=`argument $option "$@"`; shift ;; --xorriso=*) - xorriso=`echo "${option}/" | sed 's/--xorriso=//'` ;; + xorriso=`echo "${option}" | sed 's/--xorriso=//'` ;; *) source="${source} ${option} $@"; break ;; From dbd3a32e4325699e997de191b9c265c301a888bd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 4 Nov 2011 13:15:29 +0100 Subject: [PATCH 485/673] * grub-core/disk/raid.c (scan_devices): Don't derference NULL on whole disk. * grub-core/disk/lvm.c (do_lvm_scan): Likewise. --- ChangeLog | 6 ++++++ grub-core/disk/lvm.c | 4 ++-- grub-core/disk/raid.c | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 028bffe5c..89974cff6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-11-04 Vladimir Serbinenko + + * grub-core/disk/raid.c (scan_devices): Don't derference NULL on whole + disk. + * grub-core/disk/lvm.c (do_lvm_scan): Likewise. + 2011-11-03 Philipp Matthias Hahn * util/grub-mkrescue.in: Fix handling xorriso option. diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 7c65db4ab..4020fc427 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -157,8 +157,8 @@ do_lvm_scan (const char *scan_for) && pv->disk->dev->id == disk->dev->id && grub_partition_get_start (pv->disk->partition) == grub_partition_get_start (disk->partition) - && grub_partition_get_len (pv->disk->partition) - == grub_partition_get_len (disk->partition)) + && grub_disk_get_size (pv->disk) + == grub_disk_get_size (disk)) { grub_disk_close (disk); return 0; diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 07249eabc..e4c53e73b 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -123,8 +123,8 @@ scan_devices (const char *arname) && m->device->dev->id == m->device->dev->id && grub_partition_get_start (m->device->partition) == grub_partition_get_start (disk->partition) - && grub_partition_get_len (m->device->partition) - == grub_partition_get_len (disk->partition)) + && grub_disk_get_size (m->device) + == grub_disk_get_size (disk)) { grub_disk_close (disk); return 0; From 8bec9a284bf2bc3f492fc1ba62b0f199998f81b2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 4 Nov 2011 13:18:30 +0100 Subject: [PATCH 486/673] * include/grub/kernel.h (grub_module_header): Make type into uint32 as expected by grub-mkimage and it's more clear since there is no implicit padding. --- ChangeLog | 6 ++++++ include/grub/kernel.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 89974cff6..52bd2608d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-11-04 Vladimir Serbinenko + + * include/grub/kernel.h (grub_module_header): Make type into uint32 as + expected by grub-mkimage and it's more clear since there is no implicit + padding. + 2011-11-04 Vladimir Serbinenko * grub-core/disk/raid.c (scan_devices): Don't derference NULL on whole diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 2ff6b2469..f9fc817db 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -34,7 +34,7 @@ enum struct grub_module_header { /* The type of object. */ - grub_uint8_t type; + grub_uint32_t type; /* The size of object (including this header). */ grub_uint32_t size; }; From 09e2763fb150684377d0633f0de92591f4dbe93b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 4 Nov 2011 13:22:38 +0100 Subject: [PATCH 487/673] * grub-core/disk/raid6_recover.c (grub_raid6_recover): Get start_sector for the right device. --- ChangeLog | 5 +++++ grub-core/disk/raid6_recover.c | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52bd2608d..f8813f259 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-04 Vladimir Serbinenko + + * grub-core/disk/raid6_recover.c (grub_raid6_recover): Get start_sector + for the right device. + 2011-11-04 Vladimir Serbinenko * include/grub/kernel.h (grub_module_header): Make type into uint32 as diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index 25b50eb6b..54dc612ee 100644 --- a/grub-core/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -122,7 +122,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, { if ((array->members[pos].device) && (! grub_disk_read (array->members[pos].device, - array->members[i].start_sector + sector, + array->members[pos].start_sector + sector, 0, size, buf))) { grub_raid_block_xor (pbuf, buf, size); @@ -154,7 +154,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, /* One bad device */ if ((array->members[p].device) && (! grub_disk_read (array->members[p].device, - array->members[i].start_sector + sector, + array->members[p].start_sector + sector, 0, size, buf))) { grub_raid_block_xor (buf, pbuf, size); @@ -169,7 +169,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, grub_errno = GRUB_ERR_NONE; if (grub_disk_read (array->members[q].device, - array->members[i].start_sector + sector, 0, size, buf)) + array->members[q].start_sector + sector, 0, size, buf)) goto quit; grub_raid_block_xor (buf, qbuf, size); @@ -188,14 +188,14 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, } if (grub_disk_read (array->members[p].device, - array->members[i].start_sector + sector, + array->members[p].start_sector + sector, 0, size, buf)) goto quit; grub_raid_block_xor (pbuf, buf, size); if (grub_disk_read (array->members[q].device, - array->members[i].start_sector + sector, + array->members[q].start_sector + sector, 0, size, buf)) goto quit; From 11ee4389e27c9e776d598bc90f452cd3918982ff Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 4 Nov 2011 13:27:50 +0100 Subject: [PATCH 488/673] Use a power of generator representation of GF(256) multiplication group to save space time and complexity. * grub-core/disk/raid6_recover.c (raid6_table1): Removed. (raid6_table2): Likewise. (powx): New array. (powx_inv): Likewise. (poly): New const. (grub_raid_block_mul): Replace with ... (grub_raid_block_mulx): ...this. (grub_raid6_init_table): Rewritten. (grub_raid6_recover): Use power of generator representation. --- ChangeLog | 15 +++++++ grub-core/disk/raid6_recover.c | 81 ++++++++++++---------------------- 2 files changed, 42 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index f8813f259..b9e32f0e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2011-11-04 Vladimir Serbinenko + + Use a power of generator representation of GF(256) multiplication group + to save space time and complexity. + + * grub-core/disk/raid6_recover.c (raid6_table1): Removed. + (raid6_table2): Likewise. + (powx): New array. + (powx_inv): Likewise. + (poly): New const. + (grub_raid_block_mul): Replace with ... + (grub_raid_block_mulx): ...this. + (grub_raid6_init_table): Rewritten. + (grub_raid6_recover): Use power of generator representation. + 2011-11-04 Vladimir Serbinenko * grub-core/disk/raid6_recover.c (grub_raid6_recover): Get start_sector diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index 54dc612ee..e91992547 100644 --- a/grub-core/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -26,67 +26,40 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_uint8_t raid6_table1[256][256]; -static grub_uint8_t raid6_table2[256][256]; +/* x**y. */ +static grub_uint8_t powx[255 * 2]; +/* Such an s that x**s = y */ +static int powx_inv[256]; +static const grub_uint8_t poly = 0x1d; static void -grub_raid_block_mul (grub_uint8_t mul, char *buf, int size) +grub_raid_block_mulx (int mul, char *buf, int size) { int i; grub_uint8_t *p; p = (grub_uint8_t *) buf; for (i = 0; i < size; i++, p++) - *p = raid6_table1[mul][*p]; + if (*p) + *p = powx[mul + powx_inv[*p]]; } static void grub_raid6_init_table (void) { - int i, j; + int i; - for (i = 0; i < 256; i++) - raid6_table1[i][1] = raid6_table1[1][i] = i; - - for (i = 2; i < 256; i++) - for (j = i; j < 256; j++) - { - int n; - grub_uint8_t c; - - n = i >> 1; - - c = raid6_table1[n][j]; - c = (c << 1) ^ ((c & 0x80) ? 0x1d : 0); - if (i & 1) - c ^= j; - - raid6_table1[j][i] = raid6_table1[i][j] = c; - } - - raid6_table2[0][0] = 1; - for (i = 1; i < 256; i++) - raid6_table2[i][i] = raid6_table1[raid6_table2[i - 1][i - 1]][2]; - - for (i = 0; i < 254; i++) - for (j = 0; j < 254; j++) - { - grub_uint8_t c, n; - int k; - - if (i == j) - continue; - - k = i - j; - if (k < 0) - k += 255; - - c = n = raid6_table2[k][k] ^ 1; - for (k = 0; k < 253; k++) - c = raid6_table1[c][n]; - - raid6_table2[i][j] = raid6_table1[raid6_table2[255 - j][255 - j]][c]; - } + grub_uint8_t cur = 1; + for (i = 0; i < 255; i++) + { + powx[i] = cur; + powx[i + 255] = cur; + powx_inv[cur] = i; + if (cur & 0x80) + cur = (cur << 1) ^ poly; + else + cur <<= 1; + } } static grub_err_t @@ -126,7 +99,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, 0, size, buf))) { grub_raid_block_xor (pbuf, buf, size); - grub_raid_block_mul (raid6_table2[i][i], buf, size); + grub_raid_block_mulx (i, buf, size); grub_raid_block_xor (qbuf, buf, size); } else @@ -173,13 +146,13 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, goto quit; grub_raid_block_xor (buf, qbuf, size); - grub_raid_block_mul (raid6_table2[255 - bad1][255 - bad1], buf, + grub_raid_block_mulx (255 - bad1, buf, size); } else { /* Two bad devices */ - grub_uint8_t c; + int c; if ((! array->members[p].device) || (! array->members[q].device)) { @@ -201,11 +174,11 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, grub_raid_block_xor (qbuf, buf, size); - c = raid6_table2[bad2][bad1]; - grub_raid_block_mul (c, qbuf, size); + c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255; + grub_raid_block_mulx (c, qbuf, size); - c = raid6_table1[raid6_table2[bad2][bad2]][c]; - grub_raid_block_mul (c, pbuf, size); + c = (bad2 + c) % 255; + grub_raid_block_mulx (c, pbuf, size); grub_raid_block_xor (pbuf, qbuf, size); grub_memcpy (buf, pbuf, size); From 95f2e86095d8349af0936a820270ecba972fa636 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 4 Nov 2011 13:36:08 +0100 Subject: [PATCH 489/673] Support second redundancy strip on raidz(2,3). * grub-core/fs/zfs/zfs.c (powx): New array. (powx_inv): Likewise. (poly): New const. (xor_out): New function. (gf_mul): Likewise. (recovery): Likewise. (read_device): Use second redundancy strip. --- ChangeLog | 12 +++ grub-core/fs/zfs/zfs.c | 208 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 197 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index b9e32f0e0..a75ec3705 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-11-04 Vladimir Serbinenko + + Support second redundancy strip on raidz(2,3). + + * grub-core/fs/zfs/zfs.c (powx): New array. + (powx_inv): Likewise. + (poly): New const. + (xor_out): New function. + (gf_mul): Likewise. + (recovery): Likewise. + (read_device): Use second redundancy strip. + 2011-11-04 Vladimir Serbinenko Use a power of generator representation of GF(256) multiplication group diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index ef352a770..4c92425dd 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -858,6 +858,92 @@ xor (grub_uint64_t *a, const grub_uint64_t *b, grub_size_t s) *a++ ^= *b++; } +/* x**y. */ +static grub_uint8_t powx[255 * 2]; +/* Such an s that x**s = y */ +static int powx_inv[256]; +static const grub_uint8_t poly = 0x1d; + +/* perform the operation a ^= b * (x ** (known_idx * recovery_pow) ) */ +static inline void +xor_out (void *a_in, const void *b_in, grub_size_t s, + int known_idx, int recovery_pow) +{ + int add; + grub_uint8_t *a = a_in; + const grub_uint8_t *b = b_in; + + /* Simple xor. */ + if (known_idx == 0 || recovery_pow == 0) + { + xor (a_in, b_in, s); + return; + } + add = (known_idx * recovery_pow) % 255; + for (;s--; b++, a++) + if (*b) + *a ^= powx[powx_inv[*b] + add]; +} + +static inline grub_uint8_t +gf_mul (grub_uint8_t a, grub_uint8_t b) +{ + if (a == 0 || b == 0) + return 0; + return powx[powx_inv[a] + powx_inv[b]]; +} + +static inline void +recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, + const unsigned *powers, + const int *idx) +{ + /* Now we have */ + /* b_i = sum (r_j* (x ** (powers[i] * idx[j])))*/ + /* Since nbufs <= 3 let's be lazy. */ + switch (nbufs) + { + /* Easy: r_0 = bufs[0] / (x << (powers[i] * idx[j])). */ + case 1: + { + int add; + grub_uint8_t *a; + if (powers[0] == 0 || idx[0] == 0) + return; + add = 255 - ((powers[0] * idx[0]) % 255); + for (a = bufs[0]; s--; a++) + if (*a) + *a = powx[powx_inv[*a] + add]; + return; + } + /* b_0 = r_0 * (x ** (powers[0] * idx[0])) + r_1 * (x ** (powers[0] * idx[1])) + b_1 = r_0 * (x ** (powers[1] * idx[0])) + r_1 * (x ** (powers[1] * idx[1])) + */ + case 2: + { + grub_uint8_t det, det_inv; + grub_uint8_t det0, det1; + unsigned i; + /* The determinant is: */ + det = (powx[(powers[0] * idx[0] + powers[1] * idx[1]) % 255] + ^ powx[(powers[0] * idx[1] + powers[1] * idx[0]) % 255]); + det_inv = powx[255 - powx_inv[det]]; + for (i = 0; i < s; i++) + { + det0 = (gf_mul (bufs[0][i], powx[(powers[1] * idx[1]) % 255]) + ^ gf_mul (bufs[1][i], powx[(powers[0] * idx[1]) % 255])); + det1 = (gf_mul (bufs[0][i], powx[(powers[1] * idx[0]) % 255]) + ^ gf_mul (bufs[1][i], powx[(powers[0] * idx[0]) % 255])); + + bufs[0][i] = gf_mul (det0, det_inv); + bufs[1][i] = gf_mul (det1, det_inv); + } + break; + } + } + +} + static grub_err_t read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_size_t len, void *buf) @@ -901,8 +987,11 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_uint32_t s, orig_s; void *orig_buf = buf; grub_size_t orig_len = len; - void *recovery_buf = NULL; - grub_size_t recovery_len = 0; + grub_uint8_t *recovery_buf[4]; + grub_size_t recovery_len[4]; + int recovery_idx[4]; + unsigned failed_devices = 0; + int idx, orig_idx; if (desc->nparity < 1 || desc->nparity > 3) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, @@ -918,6 +1007,12 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, c = 2; if (desc->nparity == 3) c = 3; + if (((len + (1 << desc->ashift) - 1) >> desc->ashift) + >= (desc->n_children - desc->nparity)) + idx = (desc->n_children - desc->nparity - 1); + else + idx = ((len + (1 << desc->ashift) - 1) >> desc->ashift) - 1; + orig_idx = idx; while (len > 0) { grub_size_t csize; @@ -945,38 +1040,84 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, | (offset & ((1 << desc->ashift) - 1)), &desc->children[devn], csize, buf); - /* No raidz2 recovery yet. */ - if (err && recovery_len == 0) + /* No raidz3 recovery yet. */ + if (err + && failed_devices < desc->nparity + && failed_devices < 2) { - recovery_buf = buf; - recovery_len = csize; + recovery_buf[failed_devices] = buf; + recovery_len[failed_devices] = csize; + recovery_idx[failed_devices] = idx; + failed_devices++; grub_errno = err = 0; } if (err) return err; c++; + idx--; s--; buf = (char *) buf + csize; len -= csize; } - if (recovery_buf) + if (failed_devices) { - grub_err_t err; - high = grub_divmod64 ((offset >> desc->ashift) - + - ((desc->nparity == 1) - && ((offset >> (desc->ashift + 11)) & 1)), - desc->n_children, &devn); - err = read_device ((high << desc->ashift) - | (offset & ((1 << desc->ashift) - 1)), - &desc->children[devn], - recovery_len, recovery_buf); - if (err) - return err; + unsigned redundancy_pow[4]; + unsigned cur_redundancy_pow = 0; + unsigned n_redundancy = 0; + unsigned i, j; + + /* Compute mul. x**s has a period of 255. */ + if (powx[0] == 0) + { + grub_uint8_t cur = 1; + for (i = 0; i < 255; i++) + { + powx[i] = cur; + powx[i + 255] = cur; + powx_inv[cur] = i; + if (cur & 0x80) + cur = (cur << 1) ^ poly; + else + cur <<= 1; + } + } + + /* Read redundancy data. */ + for (n_redundancy = 0, cur_redundancy_pow = 0; + n_redundancy < failed_devices; + cur_redundancy_pow++) + { + grub_err_t err; + high = grub_divmod64 ((offset >> desc->ashift) + + cur_redundancy_pow + + ((desc->nparity == 1) + && ((offset >> (desc->ashift + 11)) + & 1)), + desc->n_children, &devn); + err = read_device ((high << desc->ashift) + | (offset & ((1 << desc->ashift) - 1)), + &desc->children[devn], + recovery_len[n_redundancy], + recovery_buf[n_redundancy]); + /* Ignore error if we may still have enough devices. */ + if (err && n_redundancy + desc->nparity - cur_redundancy_pow - 1 + >= failed_devices) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (err) + return err; + redundancy_pow[n_redundancy] = cur_redundancy_pow; + n_redundancy++; + } + /* Now xor-our the parts we already know. */ buf = orig_buf; len = orig_len; s = orig_s; + idx = orig_idx; + while (len > 0) { grub_size_t csize; @@ -985,14 +1126,35 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, if (csize > len) csize = len; - if (buf != recovery_buf) - xor (recovery_buf, buf, - csize < recovery_len ? csize : recovery_len); + for (j = 0; j < failed_devices; j++) + if (buf == recovery_buf[j]) + break; + + if (j == failed_devices) + for (j = 0; j < failed_devices; j++) + xor_out (recovery_buf[j], buf, + csize < recovery_len[j] ? csize : recovery_len[j], + idx, redundancy_pow[j]); s--; buf = (char *) buf + csize; len -= csize; - } + idx--; + } + for (i = 0; i < failed_devices + && recovery_len[i] == recovery_len[0]; + i++); + /* Since the chunks have variable length handle the last block + separately. */ + if (i != failed_devices) + { + grub_uint8_t *tmp_recovery_buf[4]; + for (j = 0; j < i; j++) + tmp_recovery_buf[j] = recovery_buf[j] + recovery_len[j] - 1; + recovery (tmp_recovery_buf, 1, i, redundancy_pow, recovery_idx); + } + recovery (recovery_buf, recovery_len[failed_devices - 1], + failed_devices, redundancy_pow, recovery_idx); } return GRUB_ERR_NONE; } From 8622923b662282f534ee88307065bc9ded80a023 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 4 Nov 2011 13:44:56 +0100 Subject: [PATCH 490/673] Support case-insensitive ZFS subvolumes. * grub-core/fs/zfs/zfs.c (mzap_lookup): New parameter case_insensitive. All users updated. (zap_hash): Likewise. (name_cmp): New function. (zap_leaf_array_equal): New parameter case_insensitive. All users updated. (zap_leaf_lookup): Likewise. (fzap_lookup): Likewise. (zap_lookup): Likewise. (dnode_get_path): New parameter case_insensitive. Retrieve case sensitiviness of a volume. All users updated. (dnode_get_fullpath): New parameter case_insensitive. All users updated. (grub_zfs_dir): Set info.case_insensitiveness. --- ChangeLog | 19 +++++++ grub-core/fs/zfs/zfs.c | 112 ++++++++++++++++++++++++++++++----------- 2 files changed, 101 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index a75ec3705..48c43467b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-11-04 Vladimir Serbinenko + + Support case-insensitive ZFS subvolumes. + + * grub-core/fs/zfs/zfs.c (mzap_lookup): New parameter case_insensitive. + All users updated. + (zap_hash): Likewise. + (name_cmp): New function. + (zap_leaf_array_equal): New parameter case_insensitive. + All users updated. + (zap_leaf_lookup): Likewise. + (fzap_lookup): Likewise. + (zap_lookup): Likewise. + (dnode_get_path): New parameter case_insensitive. Retrieve case + sensitiviness of a volume. All users updated. + (dnode_get_fullpath): New parameter case_insensitive. + All users updated. + (grub_zfs_dir): Set info.case_insensitiveness. + 2011-11-04 Vladimir Serbinenko Support second redundancy strip on raidz(2,3). diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 4c92425dd..9c06574e9 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1448,7 +1448,8 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, */ static grub_err_t mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, - int objsize, char *name, grub_uint64_t * value) + int objsize, char *name, grub_uint64_t * value, + int case_insensitive) { int i, chunks; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; @@ -1456,7 +1457,8 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, chunks = objsize / MZAP_ENT_LEN - 1; for (i = 0; i < chunks; i++) { - if (grub_strcmp (mzap_ent[i].mze_name, name) == 0) + if (case_insensitive ? (grub_strcasecmp (mzap_ent[i].mze_name, name) == 0) + : (grub_strcmp (mzap_ent[i].mze_name, name) == 0)) { *value = grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian); return GRUB_ERR_NONE; @@ -1489,7 +1491,8 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, } static grub_uint64_t -zap_hash (grub_uint64_t salt, const char *name) +zap_hash (grub_uint64_t salt, const char *name, + int case_insensitive) { static grub_uint64_t table[256]; const grub_uint8_t *cp; @@ -1507,8 +1510,12 @@ zap_hash (grub_uint64_t salt, const char *name) } } - for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++) - crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF]; + if (case_insensitive) + for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++) + crc = (crc >> 8) ^ table[(crc ^ grub_toupper (c)) & 0xFF]; + else + for (cp = (const grub_uint8_t *) name; (c = *cp) != '\0'; cp++) + crc = (crc >> 8) ^ table[(crc ^ c) & 0xFF]; /* * Only use 28 bits, since we need 4 bits in the cookie for the @@ -1526,10 +1533,34 @@ zap_hash (grub_uint64_t salt, const char *name) * array_len is actual len in bytes (not encoded le_value_length). * buf is null-terminated. */ + +static inline int +name_cmp (const char *s1, const char *s2, grub_size_t n, + int case_insensitive) +{ + const char *t1 = (const char *) s1; + const char *t2 = (const char *) s2; + + if (!case_insensitive) + return grub_memcmp (t1, t2, n); + + while (n--) + { + if (grub_toupper (*t1) != grub_toupper (*t2)) + return (int) grub_toupper (*t1) - (int) grub_toupper (*t2); + + t1++; + t2++; + } + + return 0; +} + /* XXX */ static int zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, - int blksft, int chunk, int array_len, const char *buf) + int blksft, int chunk, int array_len, const char *buf, + int case_insensitive) { int bseen = 0; @@ -1541,7 +1572,8 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) return (0); - if (grub_memcmp (la->la_array, buf + bseen, toread) != 0) + if (name_cmp ((char *) la->la_array, buf + bseen, toread, + case_insensitive) != 0) break; chunk = grub_zfs_to_cpu16 (la->la_next, endian); bseen += toread; @@ -1582,7 +1614,8 @@ zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, static grub_err_t zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, grub_uint64_t h, - const char *name, grub_uint64_t * value) + const char *name, grub_uint64_t * value, + int case_insensitive) { grub_uint16_t chunk; struct zap_leaf_entry *le; @@ -1614,7 +1647,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, if (zap_leaf_array_equal (l, endian, blksft, grub_zfs_to_cpu16 (le->le_name_chunk,endian), grub_zfs_to_cpu16 (le->le_name_length, endian), - name)) + name, case_insensitive)) { struct zap_leaf_array *la; @@ -1658,7 +1691,8 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) /* XXX */ static grub_err_t fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, - char *name, grub_uint64_t * value, struct grub_zfs_data *data) + char *name, grub_uint64_t * value, struct grub_zfs_data *data, + int case_insensitive) { void *l; grub_uint64_t hash, idx, blkid; @@ -1671,7 +1705,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, if (err) return err; - hash = zap_hash (zap->zap_salt, name); + hash = zap_hash (zap->zap_salt, name, case_insensitive); /* get block id from index */ if (zap->zap_ptrtbl.zt_numblks != 0) @@ -1687,7 +1721,8 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, if (err) return err; - err = zap_leaf_lookup (l, leafendian, blksft, hash, name, value); + err = zap_leaf_lookup (l, leafendian, blksft, hash, name, value, + case_insensitive); grub_free (l); return err; } @@ -1806,7 +1841,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, */ static grub_err_t zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val, - struct grub_zfs_data *data) + struct grub_zfs_data *data, int case_insensitive) { grub_uint64_t block_type; int size; @@ -1829,7 +1864,8 @@ zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val, if (block_type == ZBT_MICRO) { grub_dprintf ("zfs", "micro zap\n"); - err = (mzap_lookup (zapbuf, endian, size, name, val)); + err = mzap_lookup (zapbuf, endian, size, name, val, + case_insensitive); grub_dprintf ("zfs", "returned %d\n", err); grub_free (zapbuf); return err; @@ -1838,7 +1874,8 @@ zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val, { grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - err = (fzap_lookup (zap_dnode, zapbuf, name, val, data)); + err = fzap_lookup (zap_dnode, zapbuf, name, val, data, + case_insensitive); grub_dprintf ("zfs", "returned %d\n", err); grub_free (zapbuf); return err; @@ -1964,9 +2001,9 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, */ static grub_err_t dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, - struct grub_zfs_data *data) + struct grub_zfs_data *data, int *case_insensitive) { - grub_uint64_t objnum, version; + grub_uint64_t objnum, version, insensitivity; char *cname, ch; grub_err_t err = GRUB_ERR_NONE; char *path, *path_buf; @@ -1991,19 +2028,31 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, return err; } - err = zap_lookup (&(dnode_path->dn), ZPL_VERSION_STR, &version, data); + err = zap_lookup (&(dnode_path->dn), ZPL_VERSION_STR, &version, + data, 0); if (err) { grub_free (dn_new); return err; } + if (version > ZPL_VERSION) { grub_free (dn_new); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new ZPL version"); } - - err = zap_lookup (&(dnode_path->dn), ZFS_ROOT_OBJ, &objnum, data); + + err = zap_lookup (&(dnode_path->dn), "casesensitivity", &insensitivity, + data, 0); + if (err == GRUB_ERR_FILE_NOT_FOUND) + { + grub_errno = GRUB_ERR_NONE; + insensitivity = 0; + } + if (case_insensitive) + *case_insensitive = insensitivity; + + err = zap_lookup (&(dnode_path->dn), ZFS_ROOT_OBJ, &objnum, data, 0); if (err) { grub_free (dn_new); @@ -2064,7 +2113,7 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, grub_free (path_buf); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); } - err = zap_lookup (&(dnode_path->dn), cname, &objnum, data); + err = zap_lookup (&(dnode_path->dn), cname, &objnum, data, insensitivity); if (err) break; @@ -2296,7 +2345,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, grub_dprintf ("zfs", "alive\n"); - err = zap_lookup (mdn, DMU_POOL_ROOT_DATASET, &objnum, data); + err = zap_lookup (mdn, DMU_POOL_ROOT_DATASET, &objnum, data, 0); if (err) return err; @@ -2331,7 +2380,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, if (err) return err; - err = zap_lookup (mdn, cname, &objnum, data); + err = zap_lookup (mdn, cname, &objnum, data, 0); if (err) return err; @@ -2374,7 +2423,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) static grub_err_t dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, grub_uint64_t *mdnobj, dnode_end_t * dn, int *isfs, - struct grub_zfs_data *data) + struct grub_zfs_data *data, int *case_insensitive) { char *fsname, *snapname; const char *ptr_at, *filename; @@ -2452,7 +2501,7 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, err = dnode_get (&(data->mos), snapobj, DMU_OT_DSL_DS_SNAP_MAP, mdn, data); if (!err) - err = zap_lookup (mdn, snapname, &headobj, data); + err = zap_lookup (mdn, snapname, &headobj, data, 0); if (!err) err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data); if (err) @@ -2476,7 +2525,7 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, grub_free (snapname); return GRUB_ERR_NONE; } - err = dnode_get_path (mdn, filename, dn, data); + err = dnode_get_path (mdn, filename, dn, data, case_insensitive); grub_free (fsname); grub_free (snapname); return err; @@ -2916,7 +2965,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) return grub_errno; err = dnode_get_fullpath (fsfilename, &(data->mdn), 0, - &(data->dnode), &isfs, data); + &(data->dnode), &isfs, data, NULL); if (err) { zfs_unmount (data); @@ -3080,7 +3129,7 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename, return grub_errno; err = dnode_get_fullpath (fsfilename, &(data->mdn), mdnobj, - &(data->dnode), &isfs, data); + &(data->dnode), &isfs, data, NULL); zfs_unmount (data); return err; } @@ -3118,7 +3167,7 @@ fill_fs_info (struct grub_dirhook_info *info, return; } - err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data); + err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0); if (err) { grub_dprintf ("zfs", "failed here\n"); @@ -3175,6 +3224,7 @@ grub_zfs_dir (grub_device_t device, const char *path, struct grub_zfs_data *data; grub_err_t err; int isfs; + int case_insensitive = 0; auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val); auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val); @@ -3219,6 +3269,7 @@ grub_zfs_dir (grub_device_t device, const char *path, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); info.mtimeset = 1; info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info.case_insensitive = case_insensitive; } if (dn.dn.dn_bonustype == DMU_OT_ZNODE) @@ -3273,7 +3324,8 @@ grub_zfs_dir (grub_device_t device, const char *path, data = zfs_mount (device); if (! data) return grub_errno; - err = dnode_get_fullpath (path, &(data->mdn), 0, &(data->dnode), &isfs, data); + err = dnode_get_fullpath (path, &(data->mdn), 0, &(data->dnode), &isfs, data, + &case_insensitive); if (err) { zfs_unmount (data); From c2fd16cacb3edf41efe3b0ffa266c54c8af9af6f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 4 Nov 2011 15:19:23 +0100 Subject: [PATCH 491/673] Support third redundancy strip on raidz3. * grub-core/fs/zfs/zfs.c (recovery): Add Gauss for general case. Return error on singularity. All users updated. (read_device): Don't stop on 3rd failure on raidz3. --- ChangeLog | 8 +++ grub-core/fs/zfs/zfs.c | 140 +++++++++++++++++++++++++++++++++-------- 2 files changed, 123 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 48c43467b..70dc4e4f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-11-04 Vladimir Serbinenko + + Support third redundancy strip on raidz3. + + * grub-core/fs/zfs/zfs.c (recovery): Add Gauss for general case. + Return error on singularity. All users updated. + (read_device): Don't stop on 3rd failure on raidz3. + 2011-11-04 Vladimir Serbinenko Support case-insensitive ZFS subvolumes. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 9c06574e9..f892290a1 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -893,14 +893,15 @@ gf_mul (grub_uint8_t a, grub_uint8_t b) return powx[powx_inv[a] + powx_inv[b]]; } -static inline void +static inline grub_err_t recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, const unsigned *powers, const int *idx) { + grub_dprintf ("zfs", "recovering %u bufers\n", nbufs); /* Now we have */ /* b_i = sum (r_j* (x ** (powers[i] * idx[j])))*/ - /* Since nbufs <= 3 let's be lazy. */ + /* Let's invert the matrix in question. */ switch (nbufs) { /* Easy: r_0 = bufs[0] / (x << (powers[i] * idx[j])). */ @@ -909,39 +910,126 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, int add; grub_uint8_t *a; if (powers[0] == 0 || idx[0] == 0) - return; + return GRUB_ERR_NONE; add = 255 - ((powers[0] * idx[0]) % 255); for (a = bufs[0]; s--; a++) if (*a) *a = powx[powx_inv[*a] + add]; - return; + return GRUB_ERR_NONE; } - /* b_0 = r_0 * (x ** (powers[0] * idx[0])) + r_1 * (x ** (powers[0] * idx[1])) - b_1 = r_0 * (x ** (powers[1] * idx[0])) + r_1 * (x ** (powers[1] * idx[1])) - */ + /* Case 2x2: Let's use the determinant formula. */ case 2: { grub_uint8_t det, det_inv; - grub_uint8_t det0, det1; + grub_uint8_t matrixinv[2][2]; unsigned i; /* The determinant is: */ det = (powx[(powers[0] * idx[0] + powers[1] * idx[1]) % 255] ^ powx[(powers[0] * idx[1] + powers[1] * idx[0]) % 255]); + if (det == 0) + return grub_error (GRUB_ERR_BAD_FS, "singular recovery matrix"); det_inv = powx[255 - powx_inv[det]]; + matrixinv[0][0] = gf_mul (powx[(powers[1] * idx[1]) % 255], det_inv); + matrixinv[1][1] = gf_mul (powx[(powers[0] * idx[0]) % 255], det_inv); + matrixinv[0][1] = gf_mul (powx[(powers[0] * idx[1]) % 255], det_inv); + matrixinv[1][0] = gf_mul (powx[(powers[1] * idx[0]) % 255], det_inv); for (i = 0; i < s; i++) { - det0 = (gf_mul (bufs[0][i], powx[(powers[1] * idx[1]) % 255]) - ^ gf_mul (bufs[1][i], powx[(powers[0] * idx[1]) % 255])); - det1 = (gf_mul (bufs[0][i], powx[(powers[1] * idx[0]) % 255]) - ^ gf_mul (bufs[1][i], powx[(powers[0] * idx[0]) % 255])); + grub_uint8_t b0, b1; + b0 = bufs[0][i]; + b1 = bufs[1][i]; - bufs[0][i] = gf_mul (det0, det_inv); - bufs[1][i] = gf_mul (det1, det_inv); + bufs[0][i] = (gf_mul (b0, matrixinv[0][0]) + ^ gf_mul (b1, matrixinv[0][1])); + bufs[1][i] = (gf_mul (b0, matrixinv[1][0]) + ^ gf_mul (b1, matrixinv[1][1])); } - break; + return GRUB_ERR_NONE; } - } - + /* Otherwise use Gauss. */ + default: + { + grub_uint8_t matrix1[nbufs][nbufs], matrix2[nbufs][nbufs]; + int i, j, k; + + for (i = 0; i < nbufs; i++) + for (j = 0; j < nbufs; j++) + matrix1[i][j] = powx[(powers[i] * idx[j]) % 255]; + for (i = 0; i < nbufs; i++) + for (j = 0; j < nbufs; j++) + matrix2[i][j] = 0; + for (i = 0; i < nbufs; i++) + matrix2[i][i] = 1; + + for (i = 0; i < nbufs; i++) + { + grub_uint8_t mul; + for (j = i; j < nbufs; j++) + if (matrix1[i][j]) + break; + if (j == nbufs) + return grub_error (GRUB_ERR_BAD_FS, "singular recovery matrix"); + if (j != i) + { + int xchng; + xchng = j; + for (j = 0; j < nbufs; j++) + { + grub_uint8_t t; + t = matrix1[xchng][j]; + matrix1[xchng][j] = matrix1[i][j]; + matrix1[i][j] = t; + } + for (j = 0; j < nbufs; j++) + { + grub_uint8_t t; + t = matrix2[xchng][j]; + matrix2[xchng][j] = matrix2[i][j]; + matrix2[i][j] = t; + } + } + mul = powx[255 - powx_inv[matrix1[i][i]]]; + for (j = 0; j < nbufs; j++) + matrix1[i][j] = gf_mul (matrix1[i][j], mul); + for (j = 0; j < nbufs; j++) + matrix2[i][j] = gf_mul (matrix2[i][j], mul); + for (j = i + 1; j < nbufs; j++) + { + mul = matrix1[j][i]; + for (k = 0; k < nbufs; k++) + matrix1[j][k] ^= gf_mul (matrix1[i][k], mul); + for (k = 0; k < nbufs; k++) + matrix2[j][k] ^= gf_mul (matrix2[i][k], mul); + } + } + for (i = nbufs - 1; i >= 0; i--) + { + for (j = 0; j < i; j++) + { + grub_uint8_t mul; + mul = matrix1[j][i]; + for (k = 0; k < nbufs; k++) + matrix1[j][k] ^= gf_mul (matrix1[i][k], mul); + for (k = 0; k < nbufs; k++) + matrix2[j][k] ^= gf_mul (matrix2[i][k], mul); + } + } + + for (i = 0; i < (int) s; i++) + { + grub_uint8_t b[nbufs]; + for (j = 0; j < nbufs; j++) + b[j] = bufs[j][i]; + for (j = 0; j < nbufs; j++) + { + bufs[j][i] = 0; + for (k = 0; k < nbufs; k++) + bufs[j][i] ^= gf_mul (matrix2[j][k], b[k]); + } + } + return GRUB_ERR_NONE; + } + } } static grub_err_t @@ -1040,10 +1128,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, | (offset & ((1 << desc->ashift) - 1)), &desc->children[devn], csize, buf); - /* No raidz3 recovery yet. */ - if (err - && failed_devices < desc->nparity - && failed_devices < 2) + if (err && failed_devices < desc->nparity) { recovery_buf[failed_devices] = buf; recovery_len[failed_devices] = csize; @@ -1066,6 +1151,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, unsigned cur_redundancy_pow = 0; unsigned n_redundancy = 0; unsigned i, j; + grub_err_t err; /* Compute mul. x**s has a period of 255. */ if (powx[0] == 0) @@ -1088,7 +1174,6 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, n_redundancy < failed_devices; cur_redundancy_pow++) { - grub_err_t err; high = grub_divmod64 ((offset >> desc->ashift) + cur_redundancy_pow + ((desc->nparity == 1) @@ -1151,10 +1236,15 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_uint8_t *tmp_recovery_buf[4]; for (j = 0; j < i; j++) tmp_recovery_buf[j] = recovery_buf[j] + recovery_len[j] - 1; - recovery (tmp_recovery_buf, 1, i, redundancy_pow, recovery_idx); + err = recovery (tmp_recovery_buf, 1, i, redundancy_pow, + recovery_idx); + if (err) + return err; } - recovery (recovery_buf, recovery_len[failed_devices - 1], - failed_devices, redundancy_pow, recovery_idx); + err = recovery (recovery_buf, recovery_len[failed_devices - 1], + failed_devices, redundancy_pow, recovery_idx); + if (err) + return err; } return GRUB_ERR_NONE; } From 455377d93d6feb32f661d48adeea62fa4dfe4143 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 5 Nov 2011 12:15:07 +0100 Subject: [PATCH 492/673] * util/grub-install.in: Fix condition for config_opt. --- ChangeLog | 4 ++++ util/grub-install.in | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70dc4e4f3..75cac6a4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-05 Vladimir Serbinenko + + * util/grub-install.in: Fix condition for config_opt. + 2011-11-04 Vladimir Serbinenko Support third redundancy strip on raidz3. diff --git a/util/grub-install.in b/util/grub-install.in index fdbe10e76..26a2523f8 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -577,10 +577,9 @@ else for uuid in "`"${grub_probe}" --device "${grub_device}" --target=cryptodisk_uuid`"; do echo "cryptomount -u $uuid" >> "${grubdir}/load.cfg" done + config_opt="-c ${grubdir}/load.cfg " fi - config_opt="-c ${grubdir}/load.cfg " - prefix_drive=`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"` || exit 1 fi From c7ba4f6984a646e8d9f5647fe94fef756cd59f42 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 5 Nov 2011 14:47:25 +0100 Subject: [PATCH 493/673] Support BtrFS embedding. * grub-core/fs/btrfs.c (grub_btrfs_embed) [GRUB_UTIL]: New function. (grub_btrfs_fs) [GRUB_UTIL]: Set embed. * include/grub/fs.h (grub_fs) [GRUB_UTIL]: New field embed. * util/grub-setup.c (setup): Use fs embedding if available. Add additional sanity check. --- ChangeLog | 10 ++++++++++ grub-core/fs/btrfs.c | 30 ++++++++++++++++++++++++++++++ include/grub/fs.h | 9 +++++++++ util/grub-setup.c | 32 +++++++++++++++++++++++++------- 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 75cac6a4e..8c125fa97 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-11-05 Vladimir Serbinenko + + Support BtrFS embedding. + + * grub-core/fs/btrfs.c (grub_btrfs_embed) [GRUB_UTIL]: New function. + (grub_btrfs_fs) [GRUB_UTIL]: Set embed. + * include/grub/fs.h (grub_fs) [GRUB_UTIL]: New field embed. + * util/grub-setup.c (setup): Use fs embedding if available. + Add additional sanity check. + 2011-11-05 Vladimir Serbinenko * util/grub-install.in: Fix condition for config_opt. diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 16e034661..3dc680034 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1596,6 +1596,35 @@ grub_btrfs_label (grub_device_t device, char **label) return grub_errno; } +#ifdef GRUB_UTIL +static grub_err_t +grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), + unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) +{ + unsigned i; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "BtrFS curently supports only PC-BIOS embedding"); + + if (64 * 2 - 1 < *nsectors) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your core.img is unusually large. " + "It won't fit in the embedding area."); + + *nsectors = 64 * 2 - 1; + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) + (*sectors)[i] = i + 1; + + return GRUB_ERR_NONE; +} +#endif + static struct grub_fs grub_btrfs_fs = { .name = "btrfs", .dir = grub_btrfs_dir, @@ -1605,6 +1634,7 @@ static struct grub_fs grub_btrfs_fs = { .uuid = grub_btrfs_uuid, .label = grub_btrfs_label, #ifdef GRUB_UTIL + .embed = grub_btrfs_embed, .reserved_first_sector = 1, #endif }; diff --git a/include/grub/fs.h b/include/grub/fs.h index 2c39332a9..dd274e151 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -25,6 +25,10 @@ #include #include +/* For embedding types. */ +#ifdef GRUB_UTIL +#include +#endif /* Forward declaration is required, because of mutual reference. */ struct grub_file; @@ -74,6 +78,11 @@ struct grub_fs grub_err_t (*mtime) (grub_device_t device, grub_int32_t *timebuf); #ifdef GRUB_UTIL + /* Determine sectors available for embedding. */ + grub_err_t (*embed) (grub_device_t device, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors); + /* Whether this filesystem reserves first sector for DOS-style boot. */ int reserved_first_sector; #endif diff --git a/util/grub-setup.c b/util/grub-setup.c index 99de26f76..d3f6fe8b8 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -408,29 +408,44 @@ setup (const char *dir, free (tmp_img); - if (! dest_partmap) + if (! dest_partmap && ! fs) { grub_util_warn (_("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.")); goto unable_to_embed; } - if (multiple_partmaps || fs) + if (multiple_partmaps || (dest_partmap && fs)) { grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); goto unable_to_embed; } - if (!dest_partmap->embed) + if (dest_partmap && !dest_partmap->embed) { grub_util_warn ("Partition style '%s' doesn't support embeding", dest_partmap->name); goto unable_to_embed; } + if (fs && !fs->embed) + { + grub_util_warn ("File system '%s' doesn't support embeding", + fs->name); + goto unable_to_embed; + } + nsec = core_sectors; - err = dest_partmap->embed (dest_dev->disk, &nsec, - GRUB_EMBED_PCBIOS, §ors); - if (nsec > 2 * core_sectors) - nsec = 2 * core_sectors; + if (dest_partmap) + err = dest_partmap->embed (dest_dev->disk, &nsec, + GRUB_EMBED_PCBIOS, §ors); + else + err = fs->embed (dest_dev, &nsec, + GRUB_EMBED_PCBIOS, §ors); + if (!err && nsec < core_sectors) + { + err = grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your embedding area is unusually small. " + "core.img won't fit in it."); + } if (err) { @@ -439,6 +454,9 @@ setup (const char *dir, goto unable_to_embed; } + if (nsec > 2 * core_sectors) + nsec = 2 * core_sectors; + /* Clean out the blocklists. */ block = first_block; while (block->len) From b632b404e08a3b04f5264fd688354934bf7bd3e0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 5 Nov 2011 14:50:53 +0100 Subject: [PATCH 494/673] Support zle compression on ZFS. * grub-core/fs/zfs/zfs.c (zle_decompress): New function. (decomp_table): Add zle. * include/grub/zfs/zio.h (zio_compress): Add zle. --- ChangeLog | 8 ++++++++ grub-core/fs/zfs/zfs.c | 34 ++++++++++++++++++++++++++++++++++ include/grub/zfs/zio.h | 1 + 3 files changed, 43 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8c125fa97..9e9f315f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-11-05 Vladimir Serbinenko + + Support zle compression on ZFS. + + * grub-core/fs/zfs/zfs.c (zle_decompress): New function. + (decomp_table): Add zle. + * include/grub/zfs/zio.h (zio_compress): Add zle. + 2011-11-05 Vladimir Serbinenko Support BtrFS embedding. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index f892290a1..9658dea0d 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -199,6 +199,39 @@ zlib_decompress (void *s, void *d, return GRUB_ERR_NONE; } +static grub_err_t +zle_decompress (void *s, void *d, + grub_size_t slen, grub_size_t dlen) +{ + grub_uint8_t *iptr, *optr; + grub_size_t clen; + for (iptr = s, optr = d; iptr < (grub_uint8_t *) s + slen + && optr < (grub_uint8_t *) d + dlen;) + { + if (*iptr & 0x80) + clen = ((*iptr) & 0x7f) + 0x41; + else + clen = ((*iptr) & 0x3f) + 1; + if ((grub_ssize_t) clen > (grub_uint8_t *) d + dlen - optr) + clen = (grub_uint8_t *) d + dlen - optr; + if (*iptr & 0x40 || *iptr & 0x80) + { + grub_memset (optr, 0, clen); + iptr++; + optr += clen; + continue; + } + if ((grub_ssize_t) clen > (grub_uint8_t *) s + slen - iptr - 1) + clen = (grub_uint8_t *) s + slen - iptr - 1; + grub_memcpy (optr, iptr + 1, clen); + optr += clen; + iptr += clen + 1; + } + if (optr < (grub_uint8_t *) d + dlen) + grub_memset (optr, 0, (grub_uint8_t *) d + dlen - optr); + return GRUB_ERR_NONE; +} + static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"inherit", NULL}, /* ZIO_COMPRESS_INHERIT */ {"on", lzjb_decompress}, /* ZIO_COMPRESS_ON */ @@ -214,6 +247,7 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"gzip-7", zlib_decompress}, /* ZIO_COMPRESS_GZIP7 */ {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ + {"zle", zle_decompress}, /* ZIO_COMPRESS_ZLE */ }; static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h index 3dafb4028..29451593f 100644 --- a/include/grub/zfs/zio.h +++ b/include/grub/zfs/zio.h @@ -86,6 +86,7 @@ enum zio_compress { ZIO_COMPRESS_GZIP7, ZIO_COMPRESS_GZIP8, ZIO_COMPRESS_GZIP9, + ZIO_COMPRESS_ZLE, ZIO_COMPRESS_FUNCTIONS }; From 1bc7cc1b4d850e2ed4d0562798a41f411623c1e1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 6 Nov 2011 13:18:27 +0100 Subject: [PATCH 495/673] First part of zfs-crypto. CCM support with 0-filled keys --- grub-core/fs/zfs/zfs.c | 422 ++++++++++++++++++++++++++++++------- grub-core/lib/crypto.c | 5 +- include/grub/crypto.h | 4 +- include/grub/zfs/dmu.h | 1 + include/grub/zfs/dsl_dir.h | 4 +- include/grub/zfs/zio.h | 1 + 6 files changed, 360 insertions(+), 77 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 9658dea0d..9da4d70e2 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -52,6 +52,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -124,6 +125,23 @@ static grub_dl_t my_mod; #define NBBY 8 #endif +enum grub_zfs_algo + { + GRUB_ZFS_ALGO_CCM, + GRUB_ZFS_ALGO_GCM, + }; + +struct grub_zfs_key +{ + grub_uint64_t algo; + grub_uint8_t enc_nonce[13]; + grub_uint8_t unused[3]; + grub_uint8_t enc_key[48]; + grub_uint8_t unknown_purpose_nonce[13]; + grub_uint8_t unused2[3]; + grub_uint8_t unknown_purpose_key[48]; +}; + extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, @@ -161,6 +179,14 @@ struct grub_zfs_device_desc int original; }; +struct subvolume +{ + dnode_end_t mdn; + grub_uint64_t obj; + grub_uint64_t case_insensitive; + grub_crypto_cipher_handle_t cipher; +}; + struct grub_zfs_data { /* cache for a file block of the currently zfs_open()-ed file */ @@ -176,8 +202,8 @@ struct grub_zfs_data grub_zfs_endian_t dnode_endian; dnode_end_t mos; - dnode_end_t mdn; dnode_end_t dnode; + struct subvolume subvol; struct grub_zfs_device_desc *devices_attached; unsigned n_devices_attached; @@ -292,6 +318,7 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { {fletcher_4, 1, 0, "fletcher4"}, {zio_checksum_SHA256, 1, 0, "SHA256"}, {NULL, 0, 0, "zilog2"}, + {zio_checksum_SHA256, 1, 0, "SHA256+MAC"}, }; /* @@ -302,7 +329,8 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { */ static grub_err_t zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, - grub_zfs_endian_t endian, char *buf, grub_size_t size) + grub_zfs_endian_t endian, + char *buf, grub_size_t size) { zio_eck_t *zec = (zio_eck_t *) (buf + size) - 1; zio_checksum_info_t *ci = &zio_checksum_table[checksum]; @@ -312,7 +340,7 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, { grub_dprintf ("zfs", "unknown checksum function %d\n", checksum); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unknown checksum function %d", checksum); + "unknown checksum function %d", checksum); } if (ci->ci_eck) @@ -326,10 +354,8 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, else ci->ci_func (buf, size, endian, &actual_cksum); - if ((actual_cksum.zc_word[0] != zc.zc_word[0]) - || (actual_cksum.zc_word[1] != zc.zc_word[1]) - || (actual_cksum.zc_word[2] != zc.zc_word[2]) - || (actual_cksum.zc_word[3] != zc.zc_word[3])) + if (grub_memcmp (&actual_cksum, &zc, + checksum != ZIO_CHECKSUM_SHA256_MAC ? 32 : 20) != 0) { grub_dprintf ("zfs", "checksum %s verification failed\n", ci->ci_name); grub_dprintf ("zfs", "actual checksum %016llx %016llx %016llx %016llx\n", @@ -1410,16 +1436,67 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, return err; } +static grub_err_t +grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, + grub_uint8_t *out, const grub_uint8_t *in, + grub_size_t psize, + void *mac_out, const void *nonce, + unsigned l, unsigned m) +{ + grub_uint8_t iv[16]; + grub_uint8_t mul[16]; + grub_uint32_t mac[4]; + unsigned i, j; + grub_err_t err; + + grub_memcpy (iv + 1, nonce, 15 - l); + + iv[0] = (l - 1) | (((m-2) / 2) << 3); + for (j = 0; j < l; j++) + iv[15 - j] = psize >> (8 * j); + err = grub_crypto_ecb_encrypt (cipher, mac, iv, 16); + if (err) + return err; + + iv[0] = l - 1; + + for (i = 0; i < (psize + 15) / 16; i++) + { + grub_size_t csize; + csize = 16; + if (csize > psize - 16 * i) + csize = psize - 16 * i; + for (j = 0; j < l; j++) + iv[15 - j] = (i + 1) >> (8 * j); + err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16); + if (err) + return err; + grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize); + grub_crypto_xor (mac, mac, out + 16 * i, csize); + err = grub_crypto_ecb_encrypt (cipher, mac, mac, 16); + if (err) + return err; + } + for (j = 0; j < l; j++) + iv[15 - j] = 0; + err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16); + if (err) + return err; + if (mac_out) + grub_crypto_xor (mac_out, mac, mul, m); + return GRUB_ERR_NONE; +} + /* * Read in a block of data, verify its checksum, decompress if needed, * and put the uncompressed data in buf. */ static grub_err_t -zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, +zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, grub_size_t *size, struct grub_zfs_data *data) { grub_size_t lsize, psize; - unsigned int comp; + unsigned int comp, encrypted; char *compbuf = NULL; grub_err_t err; zio_cksum_t zc = bp->blk_cksum; @@ -1429,6 +1506,7 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; + encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3); lsize = (BP_IS_HOLE(bp) ? 0 : (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) << SPA_MINBLOCKSHIFT)); @@ -1447,7 +1525,7 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, if (comp != ZIO_COMPRESS_OFF) { - compbuf = grub_malloc (psize); + compbuf = grub_malloc (ALIGN_UP (psize, 16)); if (! compbuf) return grub_errno; } @@ -1462,8 +1540,10 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, *buf = NULL; return err; } + grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize); - err = zio_checksum_verify (zc, checksum, endian, compbuf, psize); + err = zio_checksum_verify (zc, checksum, endian, + compbuf, psize); if (err) { grub_dprintf ("zfs", "incorrect checksum\n"); @@ -1472,6 +1552,45 @@ zio_read (blkptr_t * bp, grub_zfs_endian_t endian, void **buf, return err; } + if (encrypted) + { + grub_uint32_t mac[4]; + unsigned i; + grub_uint32_t sw[4]; + + grub_memcpy (sw, &(bp)->blk_dva[encrypted], 16); + for (i = 0; i < 4; i++) + sw[i] = grub_cpu_to_be32 (grub_zfs_to_cpu32 (sw[i], endian)); + + if (!data->subvol.cipher) + { + grub_free (compbuf); + *buf = NULL; + return grub_error (GRUB_ERR_ACCESS_DENIED, + "no decryption key available");; + } + err = grub_ccm_decrypt (data->subvol.cipher, + (grub_uint8_t *) compbuf, + (grub_uint8_t *) compbuf, + psize, mac, + sw + 1, 3, 12); + if (err) + { + grub_free (compbuf); + *buf = NULL; + return err; + } + + for (i = 0; i < 3; i++) + if (grub_zfs_to_cpu32 (((grub_uint32_t *) &zc + 5)[i], endian) + != grub_be_to_cpu32 (mac[i])) + { + grub_free (compbuf); + *buf = NULL; + return grub_error (GRUB_ERR_BAD_FS, "MAC verification failed"); + } + } + if (comp != ZIO_COMPRESS_OFF) { *buf = grub_malloc (lsize); @@ -1572,7 +1691,7 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, */ static grub_err_t mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, - int objsize, char *name, grub_uint64_t * value, + int objsize, const char *name, grub_uint64_t * value, int case_insensitive) { int i, chunks; @@ -1799,8 +1918,8 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) if (grub_zfs_to_cpu64 (zap->zap_magic, endian) != (grub_uint64_t) ZAP_MAGIC) return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic"); - if (zap->zap_flags != 0) - return grub_error (GRUB_ERR_BAD_FS, "bad ZAP flags"); + /* if (zap->zap_flags != 0) + return grub_error (GRUB_ERR_BAD_FS, "bad ZAP flags");*/ if (zap->zap_salt == 0) return grub_error (GRUB_ERR_BAD_FS, "bad ZAP salt"); @@ -1854,9 +1973,11 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, /* XXX */ static int fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, - int NESTED_FUNC_ATTR (*hook) (const char *name, - grub_uint64_t val), - struct grub_zfs_data *data) + int NESTED_FUNC_ATTR (*hook) (const char *name, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize), + struct grub_zfs_data *data) { zap_leaf_phys_t *l; void *l_in; @@ -1918,9 +2039,9 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++) { char *buf; - struct zap_leaf_array *la; struct zap_leaf_entry *le; - grub_uint64_t val; + char *val; + grub_size_t val_length; le = ZAP_LEAF_ENTRY (l, blksft, chunk); /* Verify the chunk entry */ @@ -1940,24 +2061,28 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, } buf[le->le_name_length] = 0; - if (le->le_int_size != 8 - || grub_zfs_to_cpu16 (le->le_value_length, endian) != 1) - continue; + val_length = ((int) le->le_value_length + * (int) le->le_int_size); + val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian)); + if (zap_leaf_array_get (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_value_chunk, + endian), + val_length, val)) + { + grub_free (buf); + grub_free (val); + continue; + } - /* get the uint64_t property value */ - la = &ZAP_LEAF_CHUNK (l, blksft, - grub_zfs_to_cpu16 (le->le_value_chunk, - endian)).l_array; - val = grub_be_to_cpu64 (la->la_array64); - if (hook (buf, val)) + if (hook (buf, val, le->le_value_length, le->le_int_size)) return 1; grub_free (buf); + grub_free (val); } } return 0; } - /* * Read in the data of a zap object and find the value for a matching * property name. @@ -2008,9 +2133,68 @@ zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val, return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type"); } +static int +zap_iterate_u64 (dnode_end_t * zap_dnode, + int NESTED_FUNC_ATTR (*hook) (const char *name, + grub_uint64_t val), + struct grub_zfs_data *data) +{ + grub_uint64_t block_type; + int size; + void *zapbuf; + grub_err_t err; + int ret; + grub_zfs_endian_t endian; + + auto int NESTED_FUNC_ATTR transform (const char *name, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize); + + int NESTED_FUNC_ATTR transform (const char *name, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize) + { + if (elemsize != sizeof (grub_uint64_t) || nelem != 1) + return 0; + return hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in)); + } + + /* Read in the first block of the zap object data. */ + size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT; + err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); + if (err) + return 0; + block_type = grub_zfs_to_cpu64 (*((grub_uint64_t *) zapbuf), endian); + + grub_dprintf ("zfs", "zap iterate\n"); + + if (block_type == ZBT_MICRO) + { + grub_dprintf ("zfs", "micro zap\n"); + ret = mzap_iterate (zapbuf, endian, size, hook); + grub_free (zapbuf); + return ret; + } + else if (block_type == ZBT_HEADER) + { + grub_dprintf ("zfs", "fat zap\n"); + /* this is a fat zap */ + ret = fzap_iterate (zap_dnode, zapbuf, transform, data); + grub_free (zapbuf); + return ret; + } + grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type"); + return 0; +} + static int zap_iterate (dnode_end_t * zap_dnode, - int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t val), + int NESTED_FUNC_ATTR (*hook) (const char *name, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize), struct grub_zfs_data *data) { grub_uint64_t block_type; @@ -2031,12 +2215,10 @@ zap_iterate (dnode_end_t * zap_dnode, if (block_type == ZBT_MICRO) { - grub_dprintf ("zfs", "micro zap\n"); - ret = mzap_iterate (zapbuf, endian, size, hook); - grub_free (zapbuf); - return ret; + grub_error (GRUB_ERR_BAD_FS, "micro ZAP where FAT ZAP expected"); + return 0; } - else if (block_type == ZBT_HEADER) + if (block_type == ZBT_HEADER) { grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ @@ -2124,10 +2306,10 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, * */ static grub_err_t -dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, - struct grub_zfs_data *data, int *case_insensitive) +dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, + struct grub_zfs_data *data) { - grub_uint64_t objnum, version, insensitivity; + grub_uint64_t objnum, version; char *cname, ch; grub_err_t err = GRUB_ERR_NONE; char *path, *path_buf; @@ -2144,7 +2326,7 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, dn_new->next = 0; dnode_path = root = dn_new; - err = dnode_get (mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, + err = dnode_get (&subvol->mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, &(dnode_path->dn), data); if (err) { @@ -2166,15 +2348,14 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new ZPL version"); } - err = zap_lookup (&(dnode_path->dn), "casesensitivity", &insensitivity, + err = zap_lookup (&(dnode_path->dn), "casesensitivity", + &subvol->case_insensitive, data, 0); if (err == GRUB_ERR_FILE_NOT_FOUND) { grub_errno = GRUB_ERR_NONE; - insensitivity = 0; + subvol->case_insensitive = 0; } - if (case_insensitive) - *case_insensitive = insensitivity; err = zap_lookup (&(dnode_path->dn), ZFS_ROOT_OBJ, &objnum, data, 0); if (err) @@ -2183,7 +2364,7 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, return err; } - err = dnode_get (mdn, objnum, 0, &(dnode_path->dn), data); + err = dnode_get (&subvol->mdn, objnum, 0, &(dnode_path->dn), data); if (err) { grub_free (dn_new); @@ -2237,7 +2418,8 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, grub_free (path_buf); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); } - err = zap_lookup (&(dnode_path->dn), cname, &objnum, data, insensitivity); + err = zap_lookup (&(dnode_path->dn), cname, &objnum, + data, subvol->case_insensitive); if (err) break; @@ -2251,7 +2433,7 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn, dnode_path = dn_new; objnum = ZFS_DIRENT_OBJ (objnum); - err = dnode_get (mdn, objnum, 0, &(dnode_path->dn), data); + err = dnode_get (&subvol->mdn, objnum, 0, &(dnode_path->dn), data); if (err) break; @@ -2545,15 +2727,93 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) } static grub_err_t -dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, - grub_uint64_t *mdnobj, dnode_end_t * dn, int *isfs, - struct grub_zfs_data *data, int *case_insensitive) +dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, + dnode_end_t * dn, int *isfs, + struct grub_zfs_data *data) { char *fsname, *snapname; const char *ptr_at, *filename; grub_uint64_t headobj; + grub_uint64_t keychainobj; grub_err_t err; + auto int NESTED_FUNC_ATTR iterate_zap_key (const char *name, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize); + int NESTED_FUNC_ATTR iterate_zap_key (const char *name __attribute__ ((unused)), + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize) + { + const struct grub_zfs_key *key = val_in; + grub_crypto_cipher_handle_t cipher; + grub_uint8_t wrapping_key[32], decrypted[32], mac[32]; + unsigned keylen; + + if (elemsize != 1 || nelem != sizeof (*key)) + { + grub_dprintf ("zfs", "Unexpected key length %" PRIuGRUB_SIZE + " x %" PRIuGRUB_SIZE "\n", nelem, elemsize); + return 0; + } + + if (grub_memcmp (key->enc_key + 32, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) + == 0) + keylen = 16; + else if (grub_memcmp (key->enc_key + 40, "\0\0\0\0\0\0\0\0", 8) == 0) + keylen = 24; + else + keylen = 32; + + grub_memset (wrapping_key, 0, sizeof (wrapping_key)); + + cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); + if (!cipher) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + err = grub_crypto_cipher_set_key (cipher, wrapping_key, keylen); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + + err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32, + mac, key->unknown_purpose_nonce, 2, 16); + if (err || grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) != 0) + { + grub_dprintf ("zfs", "key loading failed\n"); + grub_errno = GRUB_ERR_NONE; + return 0; + } + + err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac, + key->enc_nonce, 2, 16); + if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0) + { + grub_dprintf ("zfs", "key loading failed\n"); + grub_errno = GRUB_ERR_NONE; + return 0; + } + subvol->cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); + if (!subvol->cipher) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + err = grub_crypto_cipher_set_key (subvol->cipher, decrypted, keylen); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + + return 0; + } + ptr_at = grub_strchr (fullpath, '@'); if (! ptr_at) { @@ -2605,29 +2865,47 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_head_dataset_obj, dn->endian); - grub_dprintf ("zfs", "endian = %d\n", mdn->endian); + grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data); + err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &subvol->mdn, + data); if (err) { grub_free (fsname); grub_free (snapname); return err; } - grub_dprintf ("zfs", "endian = %d\n", mdn->endian); + grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); + + keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian); + if (keychainobj) + { + dnode_end_t keychain_dn; + err = dnode_get (&(data->mos), keychainobj, DMU_OT_DSL_KEYCHAIN, + &keychain_dn, data); + if (err) + { + grub_free (fsname); + grub_free (snapname); + return err; + } + zap_iterate (&keychain_dn, iterate_zap_key, data); + } + if (snapname) { grub_uint64_t snapobj; - snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&mdn->dn))->ds_snapnames_zapobj, mdn->endian); + snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&subvol->mdn.dn))->ds_snapnames_zapobj, subvol->mdn.endian); err = dnode_get (&(data->mos), snapobj, - DMU_OT_DSL_DS_SNAP_MAP, mdn, data); + DMU_OT_DSL_DS_SNAP_MAP, &subvol->mdn, data); if (!err) - err = zap_lookup (mdn, snapname, &headobj, data, 0); + err = zap_lookup (&subvol->mdn, snapname, &headobj, data, 0); if (!err) - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, mdn, data); + err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, + &subvol->mdn, data); if (err) { grub_free (fsname); @@ -2636,12 +2914,11 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, } } - if (mdnobj) - *mdnobj = headobj; + subvol->obj = headobj; - make_mdn (mdn, data); + make_mdn (&subvol->mdn, data); - grub_dprintf ("zfs", "endian = %d\n", mdn->endian); + grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); if (*isfs) { @@ -2649,7 +2926,7 @@ dnode_get_fullpath (const char *fullpath, dnode_end_t * mdn, grub_free (snapname); return GRUB_ERR_NONE; } - err = dnode_get_path (mdn, filename, dn, data, case_insensitive); + err = dnode_get_path (subvol, filename, dn, data); grub_free (fsname); grub_free (snapname); return err; @@ -3088,8 +3365,8 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) if (! data) return grub_errno; - err = dnode_get_fullpath (fsfilename, &(data->mdn), 0, - &(data->dnode), &isfs, data, NULL); + err = dnode_get_fullpath (fsfilename, &(data->subvol), + &(data->dnode), &isfs, data); if (err) { zfs_unmount (data); @@ -3252,8 +3529,9 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename, if (! data) return grub_errno; - err = dnode_get_fullpath (fsfilename, &(data->mdn), mdnobj, - &(data->dnode), &isfs, data, NULL); + err = dnode_get_fullpath (fsfilename, &(data->subvol), + &(data->dnode), &isfs, data); + *mdnobj = data->subvol.obj; zfs_unmount (data); return err; } @@ -3348,7 +3626,6 @@ grub_zfs_dir (grub_device_t device, const char *path, struct grub_zfs_data *data; grub_err_t err; int isfs; - int case_insensitive = 0; auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val); auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val); @@ -3361,7 +3638,7 @@ grub_zfs_dir (grub_device_t device, const char *path, dnode_end_t dn; grub_memset (&info, 0, sizeof (info)); - dnode_get (&(data->mdn), val, 0, &dn, data); + dnode_get (&(data->subvol.mdn), val, 0, &dn, data); if (dn.dn.dn_bonustype == DMU_OT_SA) { @@ -3393,7 +3670,7 @@ grub_zfs_dir (grub_device_t device, const char *path, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); info.mtimeset = 1; info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); - info.case_insensitive = case_insensitive; + info.case_insensitive = data->subvol.case_insensitive; } if (dn.dn.dn_bonustype == DMU_OT_ZNODE) @@ -3448,8 +3725,7 @@ grub_zfs_dir (grub_device_t device, const char *path, data = zfs_mount (device); if (! data) return grub_errno; - err = dnode_get_fullpath (path, &(data->mdn), 0, &(data->dnode), &isfs, data, - &case_insensitive); + err = dnode_get_fullpath (path, &(data->subvol), &(data->dnode), &isfs, data); if (err) { zfs_unmount (data); @@ -3475,7 +3751,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate (&dn, iterate_zap_fs, data); + zap_iterate_u64 (&dn, iterate_zap_fs, data); err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data); if (err) @@ -3494,7 +3770,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate (&dn, iterate_zap_snap, data); + zap_iterate_u64 (&dn, iterate_zap_snap, data); } else { @@ -3503,7 +3779,7 @@ grub_zfs_dir (grub_device_t device, const char *path, zfs_unmount (data); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); } - zap_iterate (&(data->dnode), iterate_zap, data); + zap_iterate_u64 (&(data->dnode), iterate_zap, data); } zfs_unmount (data); return grub_errno; diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index 8876cc326..f858be9c6 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -210,9 +210,10 @@ grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, gcry_err_code_t grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size) + void *out, const void *in, grub_size_t size) { - grub_uint8_t *inptr, *outptr, *end; + const grub_uint8_t *inptr; + grub_uint8_t *outptr, *end; if (!cipher->cipher->encrypt) return GPG_ERR_NOT_SUPPORTED; if (size % cipher->cipher->blocksize != 0) diff --git a/include/grub/crypto.h b/include/grub/crypto.h index 10368d99f..573893a3e 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -203,7 +203,7 @@ grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, gcry_err_code_t grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size); + void *out, const void *in, grub_size_t size); gcry_err_code_t grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher, void *out, void *in, grub_size_t size, @@ -251,11 +251,13 @@ extern gcry_md_spec_t _gcry_digest_spec_sha1; extern gcry_md_spec_t _gcry_digest_spec_sha256; extern gcry_md_spec_t _gcry_digest_spec_sha512; extern gcry_md_spec_t _gcry_digest_spec_crc32; +extern gcry_cipher_spec_t _gcry_cipher_spec_aes; #define GRUB_MD_MD5 ((const gcry_md_spec_t *) &_gcry_digest_spec_md5) #define GRUB_MD_SHA1 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha1) #define GRUB_MD_SHA256 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha256) #define GRUB_MD_SHA512 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha512) #define GRUB_MD_CRC32 ((const gcry_md_spec_t *) &_gcry_digest_spec_crc32) +#define GRUB_CIPHER_AES ((const gcry_cipher_spec_t *) &_gcry_cipher_spec_aes) /* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC variant of digest supplied by MD. Inputs are the password P of length PLEN, diff --git a/include/grub/zfs/dmu.h b/include/grub/zfs/dmu.h index bee317e8a..8fc6dc5b5 100644 --- a/include/grub/zfs/dmu.h +++ b/include/grub/zfs/dmu.h @@ -88,6 +88,7 @@ typedef enum dmu_object_type { DMU_OT_SA_MASTER_NODE, /* ZAP */ DMU_OT_SA_ATTR_REGISTRATION, /* ZAP */ DMU_OT_SA_ATTR_LAYOUTS, /* ZAP */ + DMU_OT_DSL_KEYCHAIN = 54, DMU_OT_NUMTYPES } dmu_object_type_t; diff --git a/include/grub/zfs/dsl_dir.h b/include/grub/zfs/dsl_dir.h index 41d77c790..6542a77fe 100644 --- a/include/grub/zfs/dsl_dir.h +++ b/include/grub/zfs/dsl_dir.h @@ -42,7 +42,9 @@ typedef struct dsl_dir_phys { grub_uint64_t dd_reserved; grub_uint64_t dd_props_zapobj; grub_uint64_t dd_deleg_zapobj; /* dataset permissions */ - grub_uint64_t dd_pad[20]; /* pad out to 256 bytes for good measure */ + grub_uint64_t unused[7]; + grub_uint64_t keychain; + grub_uint64_t unused2[12]; } dsl_dir_phys_t; #endif /* _SYS_DSL_DIR_H */ diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h index 29451593f..8b645c063 100644 --- a/include/grub/zfs/zio.h +++ b/include/grub/zfs/zio.h @@ -65,6 +65,7 @@ enum zio_checksum { ZIO_CHECKSUM_FLETCHER_4, ZIO_CHECKSUM_SHA256, ZIO_CHECKSUM_ZILOG2, + ZIO_CHECKSUM_SHA256_MAC, ZIO_CHECKSUM_FUNCTIONS }; From 2cdc899567c4db45ab0a3a5eae2aa91faa7cff92 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 6 Nov 2011 14:44:29 +0100 Subject: [PATCH 496/673] ZFS crypto key adding --- grub-core/fs/zfs/zfs.c | 114 +++++++++++++++++++++++-------------- grub-core/fs/zfs/zfsinfo.c | 67 ++++++++++++++++++++++ include/grub/zfs/zfs.h | 2 + util/grub-fstest.c | 26 +++++++++ 4 files changed, 165 insertions(+), 44 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 9da4d70e2..4008d17f4 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011 Free Software Foundation, Inc. * Copyright 2010 Sun Microsystems, Inc. * * GRUB is free software; you can redistribute it and/or modify @@ -142,6 +142,12 @@ struct grub_zfs_key grub_uint8_t unknown_purpose_key[48]; }; +struct grub_zfs_wrap_key +{ + struct grub_zfs_wrap_key *next; + grub_uint64_t key[GRUB_ZFS_MAX_KEYLEN / 8]; +}; + extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, @@ -216,6 +222,21 @@ struct grub_zfs_data grub_uint64_t guid; }; +static struct grub_zfs_wrap_key *zfs_wrap_keys; + +grub_err_t +grub_zfs_add_key (grub_uint8_t *key_in) +{ + struct grub_zfs_wrap_key *key; + key = grub_malloc (sizeof (*key)); + if (!key) + return grub_errno; + grub_memcpy (key->key, key_in, GRUB_ZFS_MAX_KEYLEN); + key->next = zfs_wrap_keys; + zfs_wrap_keys = key; + return GRUB_ERR_NONE; +} + static grub_err_t zlib_decompress (void *s, void *d, grub_size_t slen, grub_size_t dlen) @@ -2747,9 +2768,8 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_size_t elemsize) { const struct grub_zfs_key *key = val_in; - grub_crypto_cipher_handle_t cipher; - grub_uint8_t wrapping_key[32], decrypted[32], mac[32]; unsigned keylen; + struct grub_zfs_wrap_key *wrap_key; if (elemsize != 1 || nelem != sizeof (*key)) { @@ -2766,51 +2786,57 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, else keylen = 32; - grub_memset (wrapping_key, 0, sizeof (wrapping_key)); + for (wrap_key = zfs_wrap_keys; wrap_key; wrap_key = wrap_key->next) + { + grub_crypto_cipher_handle_t cipher; + grub_uint8_t decrypted[32], mac[32]; + cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); + if (!cipher) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + err = grub_crypto_cipher_set_key (cipher, + (const grub_uint8_t *) wrap_key->key, + keylen); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } - cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); - if (!cipher) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - err = grub_crypto_cipher_set_key (cipher, wrapping_key, keylen); - if (err) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } + err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32, + mac, key->unknown_purpose_nonce, 2, 16); + if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) + != 0)) + { + grub_dprintf ("zfs", "key loading failed\n"); + grub_errno = GRUB_ERR_NONE; + continue; + } - err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32, - mac, key->unknown_purpose_nonce, 2, 16); - if (err || grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) != 0) - { - grub_dprintf ("zfs", "key loading failed\n"); - grub_errno = GRUB_ERR_NONE; + err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac, + key->enc_nonce, 2, 16); + if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0) + { + grub_dprintf ("zfs", "key loading failed\n"); + grub_errno = GRUB_ERR_NONE; + continue; + } + subvol->cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); + if (!subvol->cipher) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + err = grub_crypto_cipher_set_key (subvol->cipher, decrypted, keylen); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } return 0; } - - err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac, - key->enc_nonce, 2, 16); - if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0) - { - grub_dprintf ("zfs", "key loading failed\n"); - grub_errno = GRUB_ERR_NONE; - return 0; - } - subvol->cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); - if (!subvol->cipher) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - err = grub_crypto_cipher_set_key (subvol->cipher, decrypted, keylen); - if (err) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - return 0; } diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index 8c073fab5..dfc238d11 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -21,10 +21,12 @@ #include #include #include +#include #include #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -389,14 +391,78 @@ grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc, return GRUB_ERR_NONE; } +static const struct grub_arg_option options[] = + { + {"raw", 'r', 0, N_("Assume input is raw."), 0, 0}, + {"hex", 'h', 0, N_("Assume input is hex."), 0, 0}, + {"passphrase", 'p', 0, N_("Assume input is passphrase."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_err_t +grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint8_t buf[1024]; + grub_ssize_t real_size; + + if (argc > 0) + { + grub_file_t file; + file = grub_file_open (args[0]); + if (!file) + return grub_errno; + real_size = grub_file_read (file, buf, 1024); + if (real_size < 0) + return grub_errno; + } + if (ctxt->state[0].set + || (argc > 0 && !ctxt->state[1].set && !ctxt->state[2].set)) + { + grub_err_t err; + if (real_size < GRUB_ZFS_MAX_KEYLEN) + grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size); + err = grub_zfs_add_key (buf); + if (err) + return err; + return GRUB_ERR_NONE; + } + + if (ctxt->state[1].set) + { + int i; + grub_err_t err; + if (real_size < 2 * GRUB_ZFS_MAX_KEYLEN) + grub_memset (buf + real_size, '0', 2 * GRUB_ZFS_MAX_KEYLEN - real_size); + for (i = 0; i < GRUB_ZFS_MAX_KEYLEN; i++) + { + char c1 = grub_tolower (buf[2 * i]) - '0'; + char c2 = grub_tolower (buf[2 * i + 1]) - '0'; + if (c1 > 9) + c1 += '0' - 'a' + 10; + if (c2 > 9) + c2 += '0' - 'a' + 10; + buf[i] = (c1 << 4) | c2; + } + err = grub_zfs_add_key (buf); + if (err) + return err; + return GRUB_ERR_NONE; + } + return GRUB_ERR_NONE; +} static grub_command_t cmd_info, cmd_bootfs; +static grub_extcmd_t cmd_key; GRUB_MOD_INIT (zfsinfo) { cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo, "zfsinfo DEVICE", "Print ZFS info about DEVICE."); + cmd_key = grub_register_extcmd ("zfskey", grub_cmd_zfs_key, 0, + "zfskey [-h|-p|-r] [FILE]", + "Import ZFS wrapping key stored in FILE.", + options); cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs, "zfs-bootfs FILESYSTEM [VARIABLE]", "Print ZFS-BOOTFSOBJ or set it to VARIABLE"); @@ -406,4 +472,5 @@ GRUB_MOD_FINI (zfsinfo) { grub_unregister_command (cmd_info); grub_unregister_command (cmd_bootfs); + grub_unregister_extcmd (cmd_key); } diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index d7029903a..62b72776e 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -121,5 +121,7 @@ char *grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, grub_size_t index); int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (const char *nvlist, const char *name); +grub_err_t grub_zfs_add_key (grub_uint8_t *key_in); +#define GRUB_ZFS_MAX_KEYLEN 32 #endif /* ! GRUB_ZFS_HEADER */ diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 996d71c3a..0d0801187 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -438,6 +439,7 @@ static struct argp_option options[] = { {"diskcount", 'c', "N", 0, N_("N input files."), 2}, {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, + {"zfs-key-file", 'K', N_("KEY_FILENAME"), 0, N_("Load zfs crypto key."), 2}, {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, {"uncompress", 'u', NULL, OPTION_ARG_OPTIONAL, N_("Uncompress data."), 2}, {0, 0, 0, 0, 0, 0} @@ -462,6 +464,30 @@ argp_parser (int key, char *arg, struct argp_state *state) root = arg; return 0; + case 'K': + { + FILE *f; + ssize_t real_size; + grub_uint8_t buf[GRUB_ZFS_MAX_KEYLEN]; + f = fopen (arg, "rb"); + if (!f) + { + printf ("Error loading file %s: %s\n", arg, strerror (errno)); + return 0; + } + real_size = fread (buf, 1, GRUB_ZFS_MAX_KEYLEN, f); + if (real_size < 0) + { + printf ("Error loading file %s: %s\n", arg, strerror (errno)); + fclose (f); + return 0; + } + if (real_size < GRUB_ZFS_MAX_KEYLEN) + grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size); + grub_zfs_add_key (buf); + } + return 0; + case 'C': mount_crypt = 1; return 0; From f003a8c5e75df1c0b01511195e62f2afe317aa58 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 6 Nov 2011 15:18:25 +0100 Subject: [PATCH 497/673] Move ZFS crypto to separate module --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 + grub-core/fs/zfs/zfs.c | 255 ++++++---------------------- grub-core/fs/zfs/zfscrypt.c | 324 ++++++++++++++++++++++++++++++++++++ grub-core/fs/zfs/zfsinfo.c | 67 -------- grub-core/lib/crypto.c | 8 - include/grub/crypto.h | 8 +- include/grub/zfs/spa.h | 24 ++- include/grub/zfs/zfs.h | 21 +++ 9 files changed, 415 insertions(+), 298 deletions(-) create mode 100644 grub-core/fs/zfs/zfscrypt.c diff --git a/Makefile.util.def b/Makefile.util.def index 17894b1d2..15a309367 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -82,6 +82,7 @@ library = { common = grub-core/fs/ufs2.c; common = grub-core/fs/ufs.c; common = grub-core/fs/xfs.c; + common = grub-core/fs/zfs/zfscrypt.c; common = grub-core/fs/zfs/zfs.c; common = grub-core/fs/zfs/zfsinfo.c; common = grub-core/fs/zfs/zfs_lzjb.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index b2e8e7aa2..9590188fb 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1116,6 +1116,11 @@ module = { common = fs/zfs/zfs_fletcher.c; }; +module = { + name = zfscrypt; + common = fs/zfs/zfscrypt.c; +}; + module = { name = zfsinfo; common = fs/zfs/zfsinfo.c; diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 4008d17f4..3558bd8bb 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -125,29 +125,6 @@ static grub_dl_t my_mod; #define NBBY 8 #endif -enum grub_zfs_algo - { - GRUB_ZFS_ALGO_CCM, - GRUB_ZFS_ALGO_GCM, - }; - -struct grub_zfs_key -{ - grub_uint64_t algo; - grub_uint8_t enc_nonce[13]; - grub_uint8_t unused[3]; - grub_uint8_t enc_key[48]; - grub_uint8_t unknown_purpose_nonce[13]; - grub_uint8_t unused2[3]; - grub_uint8_t unknown_purpose_key[48]; -}; - -struct grub_zfs_wrap_key -{ - struct grub_zfs_wrap_key *next; - grub_uint64_t key[GRUB_ZFS_MAX_KEYLEN / 8]; -}; - extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, @@ -222,20 +199,13 @@ struct grub_zfs_data grub_uint64_t guid; }; -static struct grub_zfs_wrap_key *zfs_wrap_keys; - -grub_err_t -grub_zfs_add_key (grub_uint8_t *key_in) -{ - struct grub_zfs_wrap_key *key; - key = grub_malloc (sizeof (*key)); - if (!key) - return grub_errno; - grub_memcpy (key->key, key_in, GRUB_ZFS_MAX_KEYLEN); - key->next = zfs_wrap_keys; - zfs_wrap_keys = key; - return GRUB_ERR_NONE; -} +grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, + void *nonce, + char *buf, grub_size_t size, + const grub_uint32_t *expected_mac, + grub_zfs_endian_t endian) = NULL; +grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key, + grub_size_t keysize) = NULL; static grub_err_t zlib_decompress (void *s, void *d, @@ -409,14 +379,16 @@ static int vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) { grub_zfs_endian_t ub1_endian, ub2_endian; - if (grub_zfs_to_cpu64 (ub1->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC) - ub1_endian = LITTLE_ENDIAN; + if (grub_zfs_to_cpu64 (ub1->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) + == UBERBLOCK_MAGIC) + ub1_endian = GRUB_ZFS_LITTLE_ENDIAN; else - ub1_endian = BIG_ENDIAN; - if (grub_zfs_to_cpu64 (ub2->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC) - ub2_endian = LITTLE_ENDIAN; + ub1_endian = GRUB_ZFS_BIG_ENDIAN; + if (grub_zfs_to_cpu64 (ub2->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) + == UBERBLOCK_MAGIC) + ub2_endian = GRUB_ZFS_LITTLE_ENDIAN; else - ub2_endian = BIG_ENDIAN; + ub2_endian = GRUB_ZFS_BIG_ENDIAN; if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) @@ -448,20 +420,23 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset) { uberblock_t *uber = &ub->ubp_uberblock; grub_err_t err; - grub_zfs_endian_t endian = UNKNOWN_ENDIAN; + grub_zfs_endian_t endian = GRUB_ZFS_UNKNOWN_ENDIAN; zio_cksum_t zc; - if (grub_zfs_to_cpu64 (uber->ub_magic, LITTLE_ENDIAN) == UBERBLOCK_MAGIC - && grub_zfs_to_cpu64 (uber->ub_version, LITTLE_ENDIAN) > 0 - && grub_zfs_to_cpu64 (uber->ub_version, LITTLE_ENDIAN) <= SPA_VERSION) - endian = LITTLE_ENDIAN; + if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) + == UBERBLOCK_MAGIC + && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) > 0 + && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) + <= SPA_VERSION) + endian = GRUB_ZFS_LITTLE_ENDIAN; - if (grub_zfs_to_cpu64 (uber->ub_magic, BIG_ENDIAN) == UBERBLOCK_MAGIC - && grub_zfs_to_cpu64 (uber->ub_version, BIG_ENDIAN) > 0 - && grub_zfs_to_cpu64 (uber->ub_version, BIG_ENDIAN) <= SPA_VERSION) - endian = BIG_ENDIAN; + if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC + && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) > 0 + && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) + <= SPA_VERSION) + endian = GRUB_ZFS_BIG_ENDIAN; - if (endian == UNKNOWN_ENDIAN) + if (endian == GRUB_ZFS_UNKNOWN_ENDIAN) return grub_error (GRUB_ERR_BAD_FS, "invalid uberblock magic"); grub_memset (&zc, 0, sizeof (zc)); @@ -1382,7 +1357,7 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, zio_gb = grub_malloc (SPA_GANGBLOCKSIZE); if (!zio_gb) return grub_errno; - grub_dprintf ("zfs", endian == LITTLE_ENDIAN ? "little-endian gang\n" + grub_dprintf ("zfs", endian == GRUB_ZFS_LITTLE_ENDIAN ? "little-endian gang\n" :"big-endian gang\n"); err = read_dva (dva, endian, data, zio_gb, SPA_GANGBLOCKSIZE); @@ -1457,57 +1432,6 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, return err; } -static grub_err_t -grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, - grub_uint8_t *out, const grub_uint8_t *in, - grub_size_t psize, - void *mac_out, const void *nonce, - unsigned l, unsigned m) -{ - grub_uint8_t iv[16]; - grub_uint8_t mul[16]; - grub_uint32_t mac[4]; - unsigned i, j; - grub_err_t err; - - grub_memcpy (iv + 1, nonce, 15 - l); - - iv[0] = (l - 1) | (((m-2) / 2) << 3); - for (j = 0; j < l; j++) - iv[15 - j] = psize >> (8 * j); - err = grub_crypto_ecb_encrypt (cipher, mac, iv, 16); - if (err) - return err; - - iv[0] = l - 1; - - for (i = 0; i < (psize + 15) / 16; i++) - { - grub_size_t csize; - csize = 16; - if (csize > psize - 16 * i) - csize = psize - 16 * i; - for (j = 0; j < l; j++) - iv[15 - j] = (i + 1) >> (8 * j); - err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16); - if (err) - return err; - grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize); - grub_crypto_xor (mac, mac, out + 16 * i, csize); - err = grub_crypto_ecb_encrypt (cipher, mac, mac, 16); - if (err) - return err; - } - for (j = 0; j < l; j++) - iv[15 - j] = 0; - err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16); - if (err) - return err; - if (mac_out) - grub_crypto_xor (mac_out, mac, mul, m); - return GRUB_ERR_NONE; -} - /* * Read in a block of data, verify its checksum, decompress if needed, * and put the uncompressed data in buf. @@ -1575,41 +1499,18 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, if (encrypted) { - grub_uint32_t mac[4]; - unsigned i; - grub_uint32_t sw[4]; - - grub_memcpy (sw, &(bp)->blk_dva[encrypted], 16); - for (i = 0; i < 4; i++) - sw[i] = grub_cpu_to_be32 (grub_zfs_to_cpu32 (sw[i], endian)); - - if (!data->subvol.cipher) - { - grub_free (compbuf); - *buf = NULL; - return grub_error (GRUB_ERR_ACCESS_DENIED, - "no decryption key available");; - } - err = grub_ccm_decrypt (data->subvol.cipher, - (grub_uint8_t *) compbuf, - (grub_uint8_t *) compbuf, - psize, mac, - sw + 1, 3, 12); + if (!grub_zfs_decrypt) + err = grub_error (GRUB_ERR_BAD_FS, "zfscrypto module not loaded"); + else + err = grub_zfs_decrypt (data->subvol.cipher, &(bp)->blk_dva[encrypted], + compbuf, psize, ((grub_uint32_t *) &zc + 5), + endian); if (err) { grub_free (compbuf); *buf = NULL; return err; } - - for (i = 0; i < 3; i++) - if (grub_zfs_to_cpu32 (((grub_uint32_t *) &zc + 5)[i], endian) - != grub_be_to_cpu32 (mac[i])) - { - grub_free (compbuf); - *buf = NULL; - return grub_error (GRUB_ERR_BAD_FS, "MAC verification failed"); - } } if (comp != ZIO_COMPRESS_OFF) @@ -2767,76 +2668,14 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_size_t nelem, grub_size_t elemsize) { - const struct grub_zfs_key *key = val_in; - unsigned keylen; - struct grub_zfs_wrap_key *wrap_key; - - if (elemsize != 1 || nelem != sizeof (*key)) + if (elemsize != 1) { - grub_dprintf ("zfs", "Unexpected key length %" PRIuGRUB_SIZE - " x %" PRIuGRUB_SIZE "\n", nelem, elemsize); + grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n", + elemsize); return 0; } - if (grub_memcmp (key->enc_key + 32, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) - == 0) - keylen = 16; - else if (grub_memcmp (key->enc_key + 40, "\0\0\0\0\0\0\0\0", 8) == 0) - keylen = 24; - else - keylen = 32; - - for (wrap_key = zfs_wrap_keys; wrap_key; wrap_key = wrap_key->next) - { - grub_crypto_cipher_handle_t cipher; - grub_uint8_t decrypted[32], mac[32]; - cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); - if (!cipher) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - err = grub_crypto_cipher_set_key (cipher, - (const grub_uint8_t *) wrap_key->key, - keylen); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - - err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32, - mac, key->unknown_purpose_nonce, 2, 16); - if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) - != 0)) - { - grub_dprintf ("zfs", "key loading failed\n"); - grub_errno = GRUB_ERR_NONE; - continue; - } - - err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac, - key->enc_nonce, 2, 16); - if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0) - { - grub_dprintf ("zfs", "key loading failed\n"); - grub_errno = GRUB_ERR_NONE; - continue; - } - subvol->cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); - if (!subvol->cipher) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - err = grub_crypto_cipher_set_key (subvol->cipher, decrypted, keylen); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - return 0; - } + subvol->cipher = grub_zfs_load_key (val_in, nelem); return 0; } @@ -2904,7 +2743,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian); - if (keychainobj) + if (grub_zfs_load_key && keychainobj) { dnode_end_t keychain_dn; err = dnode_get (&(data->mos), keychainobj, DMU_OT_DSL_KEYCHAIN, @@ -2918,7 +2757,6 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, zap_iterate (&keychain_dn, iterate_zap_key, data); } - if (snapname) { grub_uint64_t snapobj; @@ -3221,6 +3059,7 @@ zfs_unmount (struct grub_zfs_data *data) grub_free (data->dnode_buf); grub_free (data->dnode_mdn); grub_free (data->file_buf); + grub_crypto_cipher_close (data->subvol.cipher); grub_free (data); } @@ -3236,7 +3075,7 @@ zfs_mount (grub_device_t dev) grub_err_t err; objset_phys_t *osp = 0; grub_size_t ospsize; - grub_zfs_endian_t ub_endian = UNKNOWN_ENDIAN; + grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; uberblock_t *ub; if (! dev->disk) @@ -3267,8 +3106,8 @@ zfs_mount (grub_device_t dev) ub = &(data->current_uberblock); ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, - LITTLE_ENDIAN) == UBERBLOCK_MAGIC - ? LITTLE_ENDIAN : BIG_ENDIAN); + GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); err = zio_read (&ub->ub_rootbp, ub_endian, (void **) &osp, &ospsize, data); @@ -3357,7 +3196,7 @@ static grub_err_t zfs_mtime (grub_device_t device, grub_int32_t *mt) { struct grub_zfs_data *data; - grub_zfs_endian_t ub_endian = UNKNOWN_ENDIAN; + grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; uberblock_t *ub; *mt = 0; @@ -3368,8 +3207,8 @@ zfs_mtime (grub_device_t device, grub_int32_t *mt) ub = &(data->current_uberblock); ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, - LITTLE_ENDIAN) == UBERBLOCK_MAGIC - ? LITTLE_ENDIAN : BIG_ENDIAN); + GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); *mt = grub_zfs_to_cpu64 (ub->ub_timestamp, ub_endian); zfs_unmount (data); diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c new file mode 100644 index 000000000..251538041 --- /dev/null +++ b/grub-core/fs/zfs/zfscrypt.c @@ -0,0 +1,324 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +enum grub_zfs_algo + { + GRUB_ZFS_ALGO_CCM, + GRUB_ZFS_ALGO_GCM, + }; + +struct grub_zfs_key +{ + grub_uint64_t algo; + grub_uint8_t enc_nonce[13]; + grub_uint8_t unused[3]; + grub_uint8_t enc_key[48]; + grub_uint8_t unknown_purpose_nonce[13]; + grub_uint8_t unused2[3]; + grub_uint8_t unknown_purpose_key[48]; +}; + +struct grub_zfs_wrap_key +{ + struct grub_zfs_wrap_key *next; + grub_uint64_t key[GRUB_ZFS_MAX_KEYLEN / 8]; +}; + +static struct grub_zfs_wrap_key *zfs_wrap_keys; + +grub_err_t +grub_zfs_add_key (grub_uint8_t *key_in) +{ + struct grub_zfs_wrap_key *key; + key = grub_malloc (sizeof (*key)); + if (!key) + return grub_errno; + grub_memcpy (key->key, key_in, GRUB_ZFS_MAX_KEYLEN); + key->next = zfs_wrap_keys; + zfs_wrap_keys = key; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, + grub_uint8_t *out, const grub_uint8_t *in, + grub_size_t psize, + void *mac_out, const void *nonce, + unsigned l, unsigned m) +{ + grub_uint8_t iv[16]; + grub_uint8_t mul[16]; + grub_uint32_t mac[4]; + unsigned i, j; + grub_err_t err; + + grub_memcpy (iv + 1, nonce, 15 - l); + + iv[0] = (l - 1) | (((m-2) / 2) << 3); + for (j = 0; j < l; j++) + iv[15 - j] = psize >> (8 * j); + err = grub_crypto_ecb_encrypt (cipher, mac, iv, 16); + if (err) + return err; + + iv[0] = l - 1; + + for (i = 0; i < (psize + 15) / 16; i++) + { + grub_size_t csize; + csize = 16; + if (csize > psize - 16 * i) + csize = psize - 16 * i; + for (j = 0; j < l; j++) + iv[15 - j] = (i + 1) >> (8 * j); + err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16); + if (err) + return err; + grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize); + grub_crypto_xor (mac, mac, out + 16 * i, csize); + err = grub_crypto_ecb_encrypt (cipher, mac, mac, 16); + if (err) + return err; + } + for (j = 0; j < l; j++) + iv[15 - j] = 0; + err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16); + if (err) + return err; + if (mac_out) + grub_crypto_xor (mac_out, mac, mul, m); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, void *nonce, + char *buf, grub_size_t size, + const grub_uint32_t *expected_mac, + grub_zfs_endian_t endian) +{ + grub_uint32_t mac[4]; + unsigned i; + grub_uint32_t sw[4]; + grub_err_t err; + + grub_memcpy (sw, nonce, 16); + for (i = 0; i < 4; i++) + sw[i] = grub_cpu_to_be32 (grub_zfs_to_cpu32 (sw[i], endian)); + + if (!cipher) + return grub_error (GRUB_ERR_ACCESS_DENIED, + "no decryption key available");; + err = grub_ccm_decrypt (cipher, + (grub_uint8_t *) buf, + (grub_uint8_t *) buf, + size, mac, + sw + 1, 3, 12); + if (err) + return err; + + for (i = 0; i < 3; i++) + if (grub_zfs_to_cpu32 (expected_mac[i], endian) + != grub_be_to_cpu32 (mac[i])) + return grub_error (GRUB_ERR_BAD_FS, "MAC verification failed"); + return GRUB_ERR_NONE; +} + +static grub_crypto_cipher_handle_t +grub_zfs_load_key_real (const struct grub_zfs_key *key, + grub_size_t keysize) +{ + unsigned keylen; + struct grub_zfs_wrap_key *wrap_key; + grub_crypto_cipher_handle_t ret = NULL; + grub_err_t err; + + if (keysize != sizeof (*key)) + { + grub_dprintf ("zfs", "Unexpected key size %" PRIuGRUB_SIZE "\n", keysize); + return 0; + } + + if (grub_memcmp (key->enc_key + 32, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) + == 0) + keylen = 16; + else if (grub_memcmp (key->enc_key + 40, "\0\0\0\0\0\0\0\0", 8) == 0) + keylen = 24; + else + keylen = 32; + + for (wrap_key = zfs_wrap_keys; wrap_key; wrap_key = wrap_key->next) + { + grub_crypto_cipher_handle_t cipher; + grub_uint8_t decrypted[32], mac[32]; + cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); + if (!cipher) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + err = grub_crypto_cipher_set_key (cipher, + (const grub_uint8_t *) wrap_key->key, + keylen); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + + err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32, + mac, key->unknown_purpose_nonce, 2, 16); + if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) + != 0)) + { + grub_dprintf ("zfs", "key loading failed\n"); + grub_errno = GRUB_ERR_NONE; + continue; + } + + err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac, + key->enc_nonce, 2, 16); + if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0) + { + grub_dprintf ("zfs", "key loading failed\n"); + grub_errno = GRUB_ERR_NONE; + continue; + } + ret = grub_crypto_cipher_open (GRUB_CIPHER_AES); + if (!ret) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + err = grub_crypto_cipher_set_key (ret, decrypted, keylen); + if (err) + { + grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (ret); + continue; + } + return ret; + } + return NULL; +} + +static const struct grub_arg_option options[] = + { + {"raw", 'r', 0, N_("Assume input is raw."), 0, 0}, + {"hex", 'h', 0, N_("Assume input is hex."), 0, 0}, + {"passphrase", 'p', 0, N_("Assume input is passphrase."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_err_t +grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_uint8_t buf[1024]; + grub_ssize_t real_size; + + if (argc > 0) + { + grub_file_t file; + file = grub_file_open (args[0]); + if (!file) + return grub_errno; + real_size = grub_file_read (file, buf, 1024); + if (real_size < 0) + return grub_errno; + } + if (ctxt->state[0].set + || (argc > 0 && !ctxt->state[1].set && !ctxt->state[2].set)) + { + grub_err_t err; + if (real_size < GRUB_ZFS_MAX_KEYLEN) + grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size); + err = grub_zfs_add_key (buf); + if (err) + return err; + return GRUB_ERR_NONE; + } + + if (ctxt->state[1].set) + { + int i; + grub_err_t err; + if (real_size < 2 * GRUB_ZFS_MAX_KEYLEN) + grub_memset (buf + real_size, '0', 2 * GRUB_ZFS_MAX_KEYLEN - real_size); + for (i = 0; i < GRUB_ZFS_MAX_KEYLEN; i++) + { + char c1 = grub_tolower (buf[2 * i]) - '0'; + char c2 = grub_tolower (buf[2 * i + 1]) - '0'; + if (c1 > 9) + c1 += '0' - 'a' + 10; + if (c2 > 9) + c2 += '0' - 'a' + 10; + buf[i] = (c1 << 4) | c2; + } + err = grub_zfs_add_key (buf); + if (err) + return err; + return GRUB_ERR_NONE; + } + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd_key; + +GRUB_MOD_INIT(zfscrypto) +{ + grub_zfs_decrypt = grub_zfs_decrypt_real; + grub_zfs_load_key = grub_zfs_load_key_real; + cmd_key = grub_register_extcmd ("zfskey", grub_cmd_zfs_key, 0, + "zfskey [-h|-p|-r] [FILE]", + "Import ZFS wrapping key stored in FILE.", + options); +} + +GRUB_MOD_FINI(zfscrypto) +{ + grub_zfs_decrypt = 0; + grub_zfs_load_key = 0; + grub_unregister_extcmd (cmd_key); +} diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index dfc238d11..3ed2448b0 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -391,78 +390,13 @@ grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc, return GRUB_ERR_NONE; } -static const struct grub_arg_option options[] = - { - {"raw", 'r', 0, N_("Assume input is raw."), 0, 0}, - {"hex", 'h', 0, N_("Assume input is hex."), 0, 0}, - {"passphrase", 'p', 0, N_("Assume input is passphrase."), 0, 0}, - {0, 0, 0, 0, 0, 0} - }; - -static grub_err_t -grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) -{ - grub_uint8_t buf[1024]; - grub_ssize_t real_size; - - if (argc > 0) - { - grub_file_t file; - file = grub_file_open (args[0]); - if (!file) - return grub_errno; - real_size = grub_file_read (file, buf, 1024); - if (real_size < 0) - return grub_errno; - } - if (ctxt->state[0].set - || (argc > 0 && !ctxt->state[1].set && !ctxt->state[2].set)) - { - grub_err_t err; - if (real_size < GRUB_ZFS_MAX_KEYLEN) - grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size); - err = grub_zfs_add_key (buf); - if (err) - return err; - return GRUB_ERR_NONE; - } - - if (ctxt->state[1].set) - { - int i; - grub_err_t err; - if (real_size < 2 * GRUB_ZFS_MAX_KEYLEN) - grub_memset (buf + real_size, '0', 2 * GRUB_ZFS_MAX_KEYLEN - real_size); - for (i = 0; i < GRUB_ZFS_MAX_KEYLEN; i++) - { - char c1 = grub_tolower (buf[2 * i]) - '0'; - char c2 = grub_tolower (buf[2 * i + 1]) - '0'; - if (c1 > 9) - c1 += '0' - 'a' + 10; - if (c2 > 9) - c2 += '0' - 'a' + 10; - buf[i] = (c1 << 4) | c2; - } - err = grub_zfs_add_key (buf); - if (err) - return err; - return GRUB_ERR_NONE; - } - return GRUB_ERR_NONE; -} - static grub_command_t cmd_info, cmd_bootfs; -static grub_extcmd_t cmd_key; GRUB_MOD_INIT (zfsinfo) { cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo, "zfsinfo DEVICE", "Print ZFS info about DEVICE."); - cmd_key = grub_register_extcmd ("zfskey", grub_cmd_zfs_key, 0, - "zfskey [-h|-p|-r] [FILE]", - "Import ZFS wrapping key stored in FILE.", - options); cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs, "zfs-bootfs FILESYSTEM [VARIABLE]", "Print ZFS-BOOTFSOBJ or set it to VARIABLE"); @@ -472,5 +406,4 @@ GRUB_MOD_FINI (zfsinfo) { grub_unregister_command (cmd_info); grub_unregister_command (cmd_bootfs); - grub_unregister_extcmd (cmd_key); } diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index f858be9c6..4dec5c694 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -169,14 +169,6 @@ grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher, return cipher->cipher->setkey (cipher->ctx, key, keylen); } - -void -grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher) -{ - grub_free (cipher); -} - - void grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size) { diff --git a/include/grub/crypto.h b/include/grub/crypto.h index 573893a3e..b8a5b3a22 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -26,6 +26,7 @@ #include #include #include +#include typedef enum { @@ -191,8 +192,11 @@ grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher, const unsigned char *key, unsigned keylen); -void -grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher); +static inline void +grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher) +{ + grub_free (cipher); +} void grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size); diff --git a/include/grub/zfs/spa.h b/include/grub/zfs/spa.h index 22ee03b15..0e29fa44a 100644 --- a/include/grub/zfs/spa.h +++ b/include/grub/zfs/spa.h @@ -20,26 +20,24 @@ #ifndef GRUB_ZFS_SPA_HEADER #define GRUB_ZFS_SPA_HEADER 1 -typedef enum grub_zfs_endian - { - UNKNOWN_ENDIAN = -2, - LITTLE_ENDIAN = -1, - BIG_ENDIAN = 0 - } grub_zfs_endian_t; - -#define grub_zfs_to_cpu16(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu16(x) \ +#define grub_zfs_to_cpu16(x,a) (((a) == GRUB_ZFS_BIG_ENDIAN) ? \ + grub_be_to_cpu16(x) \ : grub_le_to_cpu16(x)) -#define grub_cpu_to_zfs16(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be16(x) \ +#define grub_cpu_to_zfs16(x,a) (((a) == GRUB_ZFS_BIG_ENDIAN) ? \ + grub_cpu_to_be16(x) \ : grub_cpu_to_le16(x)) -#define grub_zfs_to_cpu32(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu32(x) \ +#define grub_zfs_to_cpu32(x,a) (((a) == GRUB_ZFS_BIG_ENDIAN) ? \ + grub_be_to_cpu32(x) \ : grub_le_to_cpu32(x)) -#define grub_cpu_to_zfs32(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be32(x) \ +#define grub_cpu_to_zfs32(x,a) (((a) == GRUB_ZFS_BIG_ENDIAN) ? \ + grub_cpu_to_be32(x) \ : grub_cpu_to_le32(x)) -#define grub_zfs_to_cpu64(x,a) (((a) == BIG_ENDIAN) ? grub_be_to_cpu64(x) \ +#define grub_zfs_to_cpu64(x,a) (((a) == GRUB_ZFS_BIG_ENDIAN) \ + ? grub_be_to_cpu64(x) \ : grub_le_to_cpu64(x)) -#define grub_cpu_to_zfs64(x,a) (((a) == BIG_ENDIAN) ? grub_cpu_to_be64(x) \ +#define grub_cpu_to_zfs64(x,a) (((a) == GRUB_ZFS_BIG_ENDIAN) ? grub_cpu_to_be64(x) \ : grub_cpu_to_le64(x)) /* diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index 62b72776e..6c280bfe2 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -24,6 +24,14 @@ #include #include +#include + +typedef enum grub_zfs_endian + { + GRUB_ZFS_UNKNOWN_ENDIAN = -2, + GRUB_ZFS_LITTLE_ENDIAN = -1, + GRUB_ZFS_BIG_ENDIAN = 0 + } grub_zfs_endian_t; /* * On-disk version number. @@ -124,4 +132,17 @@ int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (const char *nvlist, grub_err_t grub_zfs_add_key (grub_uint8_t *key_in); #define GRUB_ZFS_MAX_KEYLEN 32 +extern grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, + void *nonce, + char *buf, grub_size_t size, + const grub_uint32_t *expected_mac, + grub_zfs_endian_t endian); + +struct grub_zfs_key; + +extern grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key, + grub_size_t keysize); + + + #endif /* ! GRUB_ZFS_HEADER */ From ed746949afec9a9ab8c231e3ed4e49cefbe7c4f6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 6 Nov 2011 16:30:52 +0100 Subject: [PATCH 498/673] ZFS passphrase support --- grub-core/fs/zfs/zfs.c | 36 +++++++++++++++++++--- grub-core/fs/zfs/zfscrypt.c | 61 ++++++++++++++++++++++++------------- include/grub/zfs/zfs.h | 9 ++++-- util/grub-fstest.c | 20 ++++++++---- 4 files changed, 91 insertions(+), 35 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 3558bd8bb..0e9869d3f 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -205,7 +205,8 @@ grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, const grub_uint32_t *expected_mac, grub_zfs_endian_t endian) = NULL; grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key, - grub_size_t keysize) = NULL; + grub_size_t keysize, + grub_uint64_t salt) = NULL; static grub_err_t zlib_decompress (void *s, void *d, @@ -1500,7 +1501,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, if (encrypted) { if (!grub_zfs_decrypt) - err = grub_error (GRUB_ERR_BAD_FS, "zfscrypto module not loaded"); + err = grub_error (GRUB_ERR_BAD_FS, "zfscrypt module not loaded"); else err = grub_zfs_decrypt (data->subvol.cipher, &(bp)->blk_dva[encrypted], compbuf, psize, ((grub_uint32_t *) &zc + 5), @@ -2657,8 +2658,10 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, const char *ptr_at, *filename; grub_uint64_t headobj; grub_uint64_t keychainobj; + grub_uint64_t salt; grub_err_t err; + auto int NESTED_FUNC_ATTR iterate_zap_key (const char *name, const void *val_in, grub_size_t nelem, @@ -2675,7 +2678,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return 0; } - subvol->cipher = grub_zfs_load_key (val_in, nelem); + subvol->cipher = grub_zfs_load_key (val_in, nelem, salt); return 0; } @@ -2745,7 +2748,32 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian); if (grub_zfs_load_key && keychainobj) { - dnode_end_t keychain_dn; + dnode_end_t keychain_dn, props_dn; + grub_uint64_t propsobj; + propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian); + + err = dnode_get (&(data->mos), propsobj, DMU_OT_DSL_PROPS, + &props_dn, data); + if (err) + { + grub_free (fsname); + grub_free (snapname); + return err; + } + + err = zap_lookup (&props_dn, "salt", &salt, data, 0); + if (err == GRUB_ERR_FILE_NOT_FOUND) + { + err = 0; + grub_errno = 0; + salt = 0; + } + if (err) + { + grub_dprintf ("zfs", "failed here\n"); + return err; + } + err = dnode_get (&(data->mos), keychainobj, DMU_OT_DSL_KEYCHAIN, &keychain_dn, data); if (err) diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 251538041..d8c7181f0 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -64,19 +64,27 @@ struct grub_zfs_key struct grub_zfs_wrap_key { struct grub_zfs_wrap_key *next; - grub_uint64_t key[GRUB_ZFS_MAX_KEYLEN / 8]; + grub_size_t keylen; + int is_passphrase; + grub_uint64_t key[0]; }; static struct grub_zfs_wrap_key *zfs_wrap_keys; grub_err_t -grub_zfs_add_key (grub_uint8_t *key_in) +grub_zfs_add_key (grub_uint8_t *key_in, + grub_size_t keylen, + int passphrase) { struct grub_zfs_wrap_key *key; - key = grub_malloc (sizeof (*key)); + if (!passphrase && keylen > 32) + keylen = 32; + key = grub_malloc (sizeof (*key) + keylen); if (!key) return grub_errno; - grub_memcpy (key->key, key_in, GRUB_ZFS_MAX_KEYLEN); + key->is_passphrase = passphrase; + key->keylen = keylen; + grub_memcpy (key->key, key_in, keylen); key->next = zfs_wrap_keys; zfs_wrap_keys = key; return GRUB_ERR_NONE; @@ -168,7 +176,8 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, void *nonce, static grub_crypto_cipher_handle_t grub_zfs_load_key_real (const struct grub_zfs_key *key, - grub_size_t keysize) + grub_size_t keysize, + grub_uint64_t salt) { unsigned keylen; struct grub_zfs_wrap_key *wrap_key; @@ -192,15 +201,25 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, for (wrap_key = zfs_wrap_keys; wrap_key; wrap_key = wrap_key->next) { grub_crypto_cipher_handle_t cipher; - grub_uint8_t decrypted[32], mac[32]; + grub_uint8_t decrypted[32], mac[32], wrap_key_real[32]; cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); if (!cipher) { grub_errno = GRUB_ERR_NONE; return 0; } - err = grub_crypto_cipher_set_key (cipher, - (const grub_uint8_t *) wrap_key->key, + grub_memset (wrap_key_real, 0, sizeof (wrap_key_real)); + if (!wrap_key->is_passphrase) + grub_memcpy(wrap_key_real, wrap_key->key, + wrap_key->keylen < keylen ? wrap_key->keylen : keylen); + else + grub_crypto_pbkdf2 (GRUB_MD_SHA1, + (const grub_uint8_t *) wrap_key->key, + wrap_key->keylen, + (const grub_uint8_t *) &salt, sizeof (salt), + 1000, wrap_key_real, keylen); + + err = grub_crypto_cipher_set_key (cipher, wrap_key_real, keylen); if (err) { @@ -268,25 +287,19 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) if (real_size < 0) return grub_errno; } - if (ctxt->state[0].set - || (argc > 0 && !ctxt->state[1].set && !ctxt->state[2].set)) + else { - grub_err_t err; - if (real_size < GRUB_ZFS_MAX_KEYLEN) - grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size); - err = grub_zfs_add_key (buf); - if (err) - return err; - return GRUB_ERR_NONE; + grub_printf ("Enter ZFS password: "); + if (!grub_password_get ((char *) buf, 1023)) + return grub_errno; + real_size = grub_strlen ((char *) buf); } if (ctxt->state[1].set) { int i; grub_err_t err; - if (real_size < 2 * GRUB_ZFS_MAX_KEYLEN) - grub_memset (buf + real_size, '0', 2 * GRUB_ZFS_MAX_KEYLEN - real_size); - for (i = 0; i < GRUB_ZFS_MAX_KEYLEN; i++) + for (i = 0; i < real_size / 2; i++) { char c1 = grub_tolower (buf[2 * i]) - '0'; char c2 = grub_tolower (buf[2 * i + 1]) - '0'; @@ -296,12 +309,16 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) c2 += '0' - 'a' + 10; buf[i] = (c1 << 4) | c2; } - err = grub_zfs_add_key (buf); + err = grub_zfs_add_key (buf, real_size / 2, 0); if (err) return err; return GRUB_ERR_NONE; } - return GRUB_ERR_NONE; + + return grub_zfs_add_key (buf, real_size, + ctxt->state[2].set + || (argc == 0 && !ctxt->state[0].set + && !ctxt->state[1].set)); } static grub_extcmd_t cmd_key; diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index 6c280bfe2..db8e915bf 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -129,8 +129,10 @@ char *grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, grub_size_t index); int grub_zfs_nvlist_lookup_nvlist_array_get_nelm (const char *nvlist, const char *name); -grub_err_t grub_zfs_add_key (grub_uint8_t *key_in); -#define GRUB_ZFS_MAX_KEYLEN 32 +grub_err_t +grub_zfs_add_key (grub_uint8_t *key_in, + grub_size_t keylen, + int passphrase); extern grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, void *nonce, @@ -141,7 +143,8 @@ extern grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, struct grub_zfs_key; extern grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key, - grub_size_t keysize); + grub_size_t keysize, + grub_uint64_t salt); diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 0d0801187..f90755e86 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -439,7 +439,7 @@ static struct argp_option options[] = { {"diskcount", 'c', "N", 0, N_("N input files."), 2}, {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, - {"zfs-key-file", 'K', N_("KEY_FILENAME"), 0, N_("Load zfs crypto key."), 2}, + {"zfs-key", 'K', N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2}, {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, {"uncompress", 'u', NULL, OPTION_ARG_OPTIONAL, N_("Uncompress data."), 2}, {0, 0, 0, 0, 0, 0} @@ -465,26 +465,34 @@ argp_parser (int key, char *arg, struct argp_state *state) return 0; case 'K': + if (strcmp (arg, "prompt") == 0) + { + char buf[1024]; + grub_printf ("Enter ZFS password: "); + if (grub_password_get (buf, 1023)) + { + grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1); + } + } + else { FILE *f; ssize_t real_size; - grub_uint8_t buf[GRUB_ZFS_MAX_KEYLEN]; + grub_uint8_t buf[1024]; f = fopen (arg, "rb"); if (!f) { printf ("Error loading file %s: %s\n", arg, strerror (errno)); return 0; } - real_size = fread (buf, 1, GRUB_ZFS_MAX_KEYLEN, f); + real_size = fread (buf, 1, 1024, f); if (real_size < 0) { printf ("Error loading file %s: %s\n", arg, strerror (errno)); fclose (f); return 0; } - if (real_size < GRUB_ZFS_MAX_KEYLEN) - grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size); - grub_zfs_add_key (buf); + grub_zfs_add_key (buf, real_size, 0); } return 0; From d99b3726e591f125220fba02725bfe9fcbfb424b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 6 Nov 2011 17:13:38 +0100 Subject: [PATCH 499/673] Support ZFS subvolumes with multiple keys --- grub-core/fs/zfs/zfs.c | 132 ++++++++++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 27 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 0e9869d3f..6ab1f61a7 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -167,7 +167,12 @@ struct subvolume dnode_end_t mdn; grub_uint64_t obj; grub_uint64_t case_insensitive; - grub_crypto_cipher_handle_t cipher; + grub_size_t nkeys; + struct + { + grub_crypto_cipher_handle_t cipher; + grub_uint64_t txg; + } *keyring; }; struct grub_zfs_data @@ -1503,9 +1508,37 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, if (!grub_zfs_decrypt) err = grub_error (GRUB_ERR_BAD_FS, "zfscrypt module not loaded"); else - err = grub_zfs_decrypt (data->subvol.cipher, &(bp)->blk_dva[encrypted], - compbuf, psize, ((grub_uint32_t *) &zc + 5), - endian); + { + unsigned i, besti = 0; + grub_uint64_t bestval = 0; + for (i = 0; i < data->subvol.nkeys; i++) + if (data->subvol.keyring[i].txg <= grub_zfs_to_cpu64 (bp->blk_birth, + endian) + && data->subvol.keyring[i].txg > bestval) + { + besti = i; + bestval = data->subvol.keyring[i].txg; + } + if (bestval == 0) + { + grub_free (compbuf); + *buf = NULL; + grub_dprintf ("zfs", "no key for txg %" PRIxGRUB_UINT64_T "\n", + grub_zfs_to_cpu64 (bp->blk_birth, + endian)); + return grub_error (GRUB_ERR_BAD_FS, "no key found in keychain"); + } + grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T + ", %p) for txg %" PRIxGRUB_UINT64_T "\n", + besti, data->subvol.keyring[besti].txg, + data->subvol.keyring[besti].cipher, + grub_zfs_to_cpu64 (bp->blk_birth, + endian)); + err = grub_zfs_decrypt (data->subvol.keyring[besti].cipher, + &(bp)->blk_dva[encrypted], + compbuf, psize, ((grub_uint32_t *) &zc + 5), + endian); + } if (err) { grub_free (compbuf); @@ -1896,7 +1929,9 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, /* XXX */ static int fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, - int NESTED_FUNC_ATTR (*hook) (const char *name, + grub_size_t name_elem_length, + int NESTED_FUNC_ATTR (*hook) (const void *name, + grub_size_t name_length, const void *val_in, grub_size_t nelem, grub_size_t elemsize), @@ -1971,18 +2006,19 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, if (le->le_type != ZAP_CHUNK_ENTRY) continue; - buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) - + 1); + buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) + * name_elem_length + 1); if (zap_leaf_array_get (l, endian, blksft, grub_zfs_to_cpu16 (le->le_name_chunk, endian), grub_zfs_to_cpu16 (le->le_name_length, - endian), buf)) + endian) + * name_elem_length, buf)) { grub_free (buf); continue; } - buf[le->le_name_length] = 0; + buf[le->le_name_length * name_elem_length] = 0; val_length = ((int) le->le_value_length * (int) le->le_int_size); @@ -1997,7 +2033,8 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, continue; } - if (hook (buf, val, le->le_value_length, le->le_int_size)) + if (hook (buf, le->le_name_length, + val, le->le_value_length, le->le_int_size)) return 1; grub_free (buf); grub_free (val); @@ -2069,12 +2106,14 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, int ret; grub_zfs_endian_t endian; - auto int NESTED_FUNC_ATTR transform (const char *name, + auto int NESTED_FUNC_ATTR transform (const void *name, + grub_size_t namelen, const void *val_in, grub_size_t nelem, grub_size_t elemsize); - int NESTED_FUNC_ATTR transform (const char *name, + int NESTED_FUNC_ATTR transform (const void *name, + grub_size_t namelen __attribute__ ((unused)), const void *val_in, grub_size_t nelem, grub_size_t elemsize) @@ -2104,7 +2143,7 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, { grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - ret = fzap_iterate (zap_dnode, zapbuf, transform, data); + ret = fzap_iterate (zap_dnode, zapbuf, 1, transform, data); grub_free (zapbuf); return ret; } @@ -2114,7 +2153,9 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, static int zap_iterate (dnode_end_t * zap_dnode, - int NESTED_FUNC_ATTR (*hook) (const char *name, + grub_size_t nameelemlen, + int NESTED_FUNC_ATTR (*hook) (const void *name, + grub_size_t namelen, const void *val_in, grub_size_t nelem, grub_size_t elemsize), @@ -2145,7 +2186,7 @@ zap_iterate (dnode_end_t * zap_dnode, { grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - ret = fzap_iterate (zap_dnode, zapbuf, hook, data); + ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, data); grub_free (zapbuf); return ret; } @@ -2660,17 +2701,41 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_uint64_t keychainobj; grub_uint64_t salt; grub_err_t err; + int keyn = 0; - - auto int NESTED_FUNC_ATTR iterate_zap_key (const char *name, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize); - int NESTED_FUNC_ATTR iterate_zap_key (const char *name __attribute__ ((unused)), - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize) + auto int NESTED_FUNC_ATTR count_zap_keys (const void *name, + grub_size_t namelen, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize); + int NESTED_FUNC_ATTR count_zap_keys (const void *name __attribute__ ((unused)), + grub_size_t namelen __attribute__ ((unused)), + const void *val_in __attribute__ ((unused)), + grub_size_t nelem __attribute__ ((unused)), + grub_size_t elemsize __attribute__ ((unused))) { + subvol->nkeys++; + return 0; + } + + auto int NESTED_FUNC_ATTR load_zap_key (const void *name, + grub_size_t namelen, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize); + int NESTED_FUNC_ATTR load_zap_key (const void *name, + grub_size_t namelen, + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize) + { + if (namelen != 1) + { + grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n", + namelen); + return 0; + } + if (elemsize != 1) { grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n", @@ -2678,7 +2743,9 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return 0; } - subvol->cipher = grub_zfs_load_key (val_in, nelem, salt); + subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name); + subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt); + keyn++; return 0; } @@ -2782,7 +2849,16 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_free (snapname); return err; } - zap_iterate (&keychain_dn, iterate_zap_key, data); + subvol->nkeys = 0; + zap_iterate (&keychain_dn, 8, count_zap_keys, data); + subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0])); + if (!subvol->keyring) + { + grub_free (fsname); + grub_free (snapname); + return err; + } + zap_iterate (&keychain_dn, 8, load_zap_key, data); } if (snapname) @@ -3087,7 +3163,9 @@ zfs_unmount (struct grub_zfs_data *data) grub_free (data->dnode_buf); grub_free (data->dnode_mdn); grub_free (data->file_buf); - grub_crypto_cipher_close (data->subvol.cipher); + for (i = 0; i < data->subvol.nkeys; i++) + grub_crypto_cipher_close (data->subvol.keyring[i].cipher); + grub_free (data->subvol.keyring); grub_free (data); } From bc1de0bc26ad95dd81b968fa75eaae92023bcb18 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 6 Nov 2011 21:05:25 +0100 Subject: [PATCH 500/673] GCM support --- grub-core/fs/zfs/zfs.c | 10 ++- grub-core/fs/zfs/zfscrypt.c | 147 +++++++++++++++++++++++++++++++++--- include/grub/zfs/zfs.h | 4 +- 3 files changed, 147 insertions(+), 14 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 6ab1f61a7..fcf32d9db 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -172,6 +172,7 @@ struct subvolume { grub_crypto_cipher_handle_t cipher; grub_uint64_t txg; + grub_uint64_t algo; } *keyring; }; @@ -205,13 +206,15 @@ struct grub_zfs_data }; grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, + grub_uint64_t algo, void *nonce, char *buf, grub_size_t size, const grub_uint32_t *expected_mac, grub_zfs_endian_t endian) = NULL; grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key, grub_size_t keysize, - grub_uint64_t salt) = NULL; + grub_uint64_t salt, + grub_uint64_t algo) = NULL; static grub_err_t zlib_decompress (void *s, void *d, @@ -1535,6 +1538,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, grub_zfs_to_cpu64 (bp->blk_birth, endian)); err = grub_zfs_decrypt (data->subvol.keyring[besti].cipher, + data->subvol.keyring[besti].algo, &(bp)->blk_dva[encrypted], compbuf, psize, ((grub_uint32_t *) &zc + 5), endian); @@ -2744,7 +2748,9 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, } subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name); - subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt); + subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in); + subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt, + subvol->keyring[keyn].algo); keyn++; return 0; } diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index d8c7181f0..39335a728 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -141,8 +141,132 @@ grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, return GRUB_ERR_NONE; } +static void +grub_gcm_mul_x (grub_uint8_t *a) +{ + int i; + int c = 0, d = 0; + for (i = 0; i < 16; i++) + { + c = a[i] & 0x1; + a[i] = (a[i] >> 1) | (d << 7); + d = c; + } + if (d) + a[0] ^= 0xe1; +} + +static void +grub_gcm_mul (grub_uint8_t *a, const grub_uint8_t *b) +{ + grub_uint8_t res[16], bs[16]; + int i; + grub_memcpy (bs, b, 16); + grub_memset (res, 0, 16); + for (i = 0; i < 128; i++) + { + if ((a[i / 8] << (i % 8)) & 0x80) + grub_crypto_xor (res, res, bs, 16); + grub_gcm_mul_x (bs); + } + + grub_memcpy (a, res, 16); +} + static grub_err_t -grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, void *nonce, +grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher, + grub_uint8_t *out, const grub_uint8_t *in, + grub_size_t psize, + void *mac_out, const void *nonce, + unsigned nonce_len, unsigned m) +{ + grub_uint8_t iv[16]; + grub_uint8_t mul[16]; + grub_uint8_t mac[16], h[16], mac_xor[16]; + unsigned i, j; + grub_err_t err; + + grub_memset (mac, 0, sizeof (mac)); + + err = grub_crypto_ecb_encrypt (cipher, h, mac, 16); + if (err) + return err; + + if (nonce_len == 12) + { + grub_memcpy (iv, nonce, 12); + iv[12] = 0; + iv[13] = 0; + iv[14] = 0; + iv[15] = 1; + } + else + { + grub_memset (iv, 0, sizeof (iv)); + grub_memcpy (iv, nonce, nonce_len); + grub_gcm_mul (iv, h); + iv[15] ^= nonce_len * 8; + grub_gcm_mul (iv, h); + } + + err = grub_crypto_ecb_encrypt (cipher, mac_xor, iv, 16); + if (err) + return err; + + for (i = 0; i < (psize + 15) / 16; i++) + { + grub_size_t csize; + csize = 16; + if (csize > psize - 16 * i) + csize = psize - 16 * i; + for (j = 0; j < 4; j++) + { + iv[15 - j]++; + if (iv[15 - j] != 0) + break; + } + grub_crypto_xor (mac, mac, in + 16 * i, csize); + grub_gcm_mul (mac, h); + err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16); + if (err) + return err; + grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize); + } + for (j = 0; j < 8; j++) + mac[15 - j] ^= ((psize * 8) >> (8 * j)); + grub_gcm_mul (mac, h); + + if (mac_out) + grub_crypto_xor (mac_out, mac, mac_xor, m); + + return GRUB_ERR_NONE; +} + + +static grub_err_t +algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, + grub_uint8_t *out, const grub_uint8_t *in, + grub_size_t psize, + void *mac_out, const void *nonce, + unsigned l, unsigned m) +{ + switch (algo) + { + case 0: + return grub_ccm_decrypt (cipher, out, in, psize, mac_out, nonce, l, m); + case 1: + return grub_gcm_decrypt (cipher, out, in, psize, mac_out, nonce, + 15 - l, m); + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "algorithm %" + PRIuGRUB_UINT64_T " is not supported yet", algo); + } +} + +static grub_err_t +grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, + grub_uint64_t algo, + void *nonce, char *buf, grub_size_t size, const grub_uint32_t *expected_mac, grub_zfs_endian_t endian) @@ -159,11 +283,11 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, void *nonce, if (!cipher) return grub_error (GRUB_ERR_ACCESS_DENIED, "no decryption key available");; - err = grub_ccm_decrypt (cipher, - (grub_uint8_t *) buf, - (grub_uint8_t *) buf, - size, mac, - sw + 1, 3, 12); + err = algo_decrypt (cipher, algo, + (grub_uint8_t *) buf, + (grub_uint8_t *) buf, + size, mac, + sw + 1, 3, 12); if (err) return err; @@ -177,7 +301,8 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, void *nonce, static grub_crypto_cipher_handle_t grub_zfs_load_key_real (const struct grub_zfs_key *key, grub_size_t keysize, - grub_uint64_t salt) + grub_uint64_t salt, + grub_uint64_t algo) { unsigned keylen; struct grub_zfs_wrap_key *wrap_key; @@ -227,8 +352,8 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, continue; } - err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32, - mac, key->unknown_purpose_nonce, 2, 16); + err = algo_decrypt (cipher, algo, decrypted, key->unknown_purpose_key, 32, + mac, key->unknown_purpose_nonce, 2, 16); if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) != 0)) { @@ -237,8 +362,8 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, continue; } - err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac, - key->enc_nonce, 2, 16); + err = algo_decrypt (cipher, algo, decrypted, key->enc_key, keylen, mac, + key->enc_nonce, 2, 16); if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0) { grub_dprintf ("zfs", "key loading failed\n"); diff --git a/include/grub/zfs/zfs.h b/include/grub/zfs/zfs.h index db8e915bf..e326c8b2f 100644 --- a/include/grub/zfs/zfs.h +++ b/include/grub/zfs/zfs.h @@ -135,6 +135,7 @@ grub_zfs_add_key (grub_uint8_t *key_in, int passphrase); extern grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, + grub_uint64_t algo, void *nonce, char *buf, grub_size_t size, const grub_uint32_t *expected_mac, @@ -144,7 +145,8 @@ struct grub_zfs_key; extern grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key, grub_size_t keysize, - grub_uint64_t salt); + grub_uint64_t salt, + grub_uint64_t algo); From ae9a20d973284a143e798e06d292c63a1b3a793e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 6 Nov 2011 21:08:32 +0100 Subject: [PATCH 501/673] Small cleanup --- grub-core/fs/zfs/zfs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index fcf32d9db..4d9a474fb 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1479,6 +1479,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, if (comp != ZIO_COMPRESS_OFF) { + /* It's not really necessary to align to 16, just for safety. */ compbuf = grub_malloc (ALIGN_UP (psize, 16)); if (! compbuf) return grub_errno; @@ -1878,9 +1879,6 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) if (grub_zfs_to_cpu64 (zap->zap_magic, endian) != (grub_uint64_t) ZAP_MAGIC) return grub_error (GRUB_ERR_BAD_FS, "bad ZAP magic"); - /* if (zap->zap_flags != 0) - return grub_error (GRUB_ERR_BAD_FS, "bad ZAP flags");*/ - if (zap->zap_salt == 0) return grub_error (GRUB_ERR_BAD_FS, "bad ZAP salt"); From ed64e9e27954718192e598d1f4bfaf0caba38152 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 11:23:56 +0100 Subject: [PATCH 502/673] Support trampoline jumps on powerpc. * grub-core/kern/dl.c (grub_dl_load_segments) [__powerpc__]: Follow __ia64__ path. (grub_dl_load_segments): Set mod->sz. (grub_dl_flush_cache): Flush whole space occupied by module, not just segments. * grub-core/kern/ia64/dl.c (nopm): Make const while on it. (jump): Likewise. * grub-core/kern/powerpc/dl.c (grub_arch_dl_get_tramp_got_size): New function. (trampoline): New struct. (trampoline_template): New const. (grub_arch_dl_relocate_symbols): Create trampolines on overflow. * include/grub/dl.h (grub_dl): Add sz element. [__powerpc__]: Follow __ia64__. (GRUB_ARCH_DL_TRAMP_ALIGN): Define on ppc. (GRUB_ARCH_DL_GOT_ALIGN): Likewise. (GRUB_ARCH_DL_TRAMP_SIZE): Likewise. (grub_arch_dl_get_tramp_got_size) [__powerpc__]: New proto. --- ChangeLog | 23 ++++++++++++ grub-core/kern/dl.c | 21 ++++------- grub-core/kern/ia64/dl.c | 4 +- grub-core/kern/powerpc/dl.c | 75 ++++++++++++++++++++++++++++++++++++- include/grub/dl.h | 15 +++++++- 5 files changed, 120 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 891126792..48799984d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2011-11-08 Vladimir Serbinenko + + Support trampoline jumps on powerpc. + + * grub-core/kern/dl.c (grub_dl_load_segments) [__powerpc__]: Follow + __ia64__ path. + (grub_dl_load_segments): Set mod->sz. + (grub_dl_flush_cache): Flush whole space occupied by module, not just + segments. + * grub-core/kern/ia64/dl.c (nopm): Make const while on it. + (jump): Likewise. + * grub-core/kern/powerpc/dl.c (grub_arch_dl_get_tramp_got_size): New + function. + (trampoline): New struct. + (trampoline_template): New const. + (grub_arch_dl_relocate_symbols): Create trampolines on overflow. + * include/grub/dl.h (grub_dl): Add sz element. + [__powerpc__]: Follow __ia64__. + (GRUB_ARCH_DL_TRAMP_ALIGN): Define on ppc. + (GRUB_ARCH_DL_GOT_ALIGN): Likewise. + (GRUB_ARCH_DL_TRAMP_SIZE): Likewise. + (grub_arch_dl_get_tramp_got_size) [__powerpc__]: New proto. + 2011-11-06 Vladimir Serbinenko ZFS crypto support. diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 1841bf1f5..b6fb537e8 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -233,7 +233,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) unsigned i; Elf_Shdr *s; grub_size_t tsize = 0, talign = 1; -#ifdef __ia64__ +#if defined (__ia64__) || defined (__powerpc__) grub_size_t tramp; grub_size_t got; #endif @@ -248,9 +248,9 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) talign = s->sh_addralign; } -#ifdef __ia64__ +#if defined (__ia64__) || defined (__powerpc__) grub_arch_dl_get_tramp_got_size (e, &tramp, &got); - tramp *= GRUB_IA64_DL_TRAMP_SIZE; + tramp *= GRUB_ARCH_DL_TRAMP_SIZE; got *= sizeof (grub_uint64_t); tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN); if (talign < GRUB_ARCH_DL_TRAMP_ALIGN) @@ -269,6 +269,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) mod->base = grub_memalign (talign, tsize); if (!mod->base) return grub_errno; + mod->sz = tsize; ptr = mod->base; #ifdef GRUB_MACHINE_EMU @@ -316,7 +317,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) mod->segment = seg; } } -#ifdef __ia64__ +#if defined (__ia64__) || defined (__powerpc__) ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN); mod->tramp = ptr; ptr += tramp; @@ -575,15 +576,9 @@ grub_dl_unref (grub_dl_t mod) static void grub_dl_flush_cache (grub_dl_t mod) { - grub_dl_segment_t seg; - - for (seg = mod->segment; seg; seg = seg->next) { - if (seg->size) { - grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n", - (unsigned long) seg->size, seg->addr); - grub_arch_sync_caches (seg->addr, seg->size); - } - } + grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n", + (unsigned long) mod->sz, mod->base); + grub_arch_sync_caches (mod->base, mod->sz); } /* Load a module from core memory. */ diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 3904f73b7..31b5f94cf 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -104,13 +104,13 @@ add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) } } -static grub_uint8_t nopm[5] = +static const grub_uint8_t nopm[5] = { /* [MLX] nop.m 0x0 */ 0x05, 0x00, 0x00, 0x00, 0x01 }; -static grub_uint8_t jump[0x20] = +static const grub_uint8_t jump[0x20] = { /* ld8 r16=[r15],8 */ 0x02, 0x80, 0x20, 0x1e, 0x18, 0x14, diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c index ad19e5600..34e780a45 100644 --- a/grub-core/kern/powerpc/dl.c +++ b/grub-core/kern/powerpc/dl.c @@ -37,6 +37,65 @@ grub_arch_dl_check_header (void *ehdr) return GRUB_ERR_NONE; } +void +grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got) +{ + const Elf_Ehdr *e = ehdr; + const Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + + *tramp = 0; + *got = 0; + + /* Find a symbol table. */ + for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + + if (i == e->e_shnum) + return; + + entsize = s->sh_entsize; + + for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) + if (s->sh_type == SHT_RELA) + { + const Elf_Rela *rel, *max; + + for (rel = (const Elf_Rela *) ((const char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel++) + if (ELF_R_TYPE (rel->r_info) == R_PPC_REL24) + (*tramp)++; + + } + + return; +} + +/* For low-endian reverse lis and addr_high as well as ori and addr_low. */ +struct trampoline +{ + grub_uint32_t lis; + grub_uint32_t ori; + grub_uint32_t mtctr; + grub_uint32_t bctr; +}; + +static const struct trampoline trampoline_template = + { + 0x3c000000, + 0x60000000, + 0x7c0903a6, + 0x4e800420, + }; /* Relocate symbols. */ grub_err_t @@ -46,6 +105,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) Elf_Shdr *s; Elf_Word entsize; unsigned i; + struct trampoline *tptr = mod->tramp; /* Find a symbol table. */ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); @@ -106,7 +166,20 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) Elf_Sword delta = value - (Elf_Word) addr; if (delta << 6 >> 6 != delta) - return grub_error (GRUB_ERR_BAD_MODULE, "relocation overflow"); + { + COMPILE_TIME_ASSERT (sizeof (struct trampoline) + == GRUB_ARCH_DL_TRAMP_SIZE); + grub_memcpy (tptr, &trampoline_template, + sizeof (*tptr)); + delta = (grub_uint8_t *) tptr - (grub_uint8_t *) addr; + tptr->lis |= (((value) >> 16) & 0xffff); + tptr->ori |= ((value) & 0xffff); + tptr++; + } + + if (delta << 6 >> 6 != delta) + return grub_error (GRUB_ERR_BAD_MODULE, + "relocation overflow"); *addr = (*addr & 0xfc000003) | (delta & 0x3fffffc); break; } diff --git a/include/grub/dl.h b/include/grub/dl.h index 75cd71758..886e966cc 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -136,11 +136,12 @@ struct grub_dl Elf_Sym *symtab; void (*init) (struct grub_dl *mod); void (*fini) (void); -#ifdef __ia64__ +#if defined (__ia64__) || defined (__powerpc__) void *got; void *tramp; #endif void *base; + grub_size_t sz; struct grub_dl *next; }; typedef struct grub_dl *grub_dl_t; @@ -176,10 +177,20 @@ void grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got); -#ifdef __ia64__ +#if defined (__ia64__) #define GRUB_ARCH_DL_TRAMP_ALIGN 16 #define GRUB_ARCH_DL_GOT_ALIGN 16 #define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size +#else +void +grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got); +#endif + +#ifdef __powerpc__ +#define GRUB_ARCH_DL_TRAMP_SIZE 16 +#define GRUB_ARCH_DL_TRAMP_ALIGN 4 +#define GRUB_ARCH_DL_GOT_ALIGN 4 #endif #endif From 9f421dd1f07e7be1b6dfbad162d44bcd5c57916a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 11:32:19 +0100 Subject: [PATCH 503/673] * grub-core/fs/zfs/zfs.c (zap_iterate): Remove set but not used variable. --- ChangeLog | 5 +++++ grub-core/fs/zfs/zfs.c | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 48799984d..dd8a9858d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-08 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (zap_iterate): Remove set but not used + variable. + 2011-11-08 Vladimir Serbinenko Support trampoline jumps on powerpc. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 4d9a474fb..fb16a009b 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2164,14 +2164,12 @@ zap_iterate (dnode_end_t * zap_dnode, struct grub_zfs_data *data) { grub_uint64_t block_type; - int size; void *zapbuf; grub_err_t err; int ret; grub_zfs_endian_t endian; /* Read in the first block of the zap object data. */ - size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT; err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); if (err) return 0; From 78e08dc3cb36e163b2a1e96bf828c1ed0ae9f323 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 12:06:27 +0100 Subject: [PATCH 504/673] * util/grub.d/10_kfreebsd.in: Use ${grub_mkrelpath} not grub-mkrelpath. --- ChangeLog | 4 ++++ util/grub.d/10_kfreebsd.in | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index dd8a9858d..02af51ea8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-08 Vladimir Serbinenko + + * util/grub.d/10_kfreebsd.in: Use ${grub_mkrelpath} not grub-mkrelpath. + 2011-11-08 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (zap_iterate): Remove set but not used diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index e668f3fd9..a1b86b82b 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -160,7 +160,7 @@ while [ "x$list" != "x" ] ; do # zpool name kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE}) # filesystem name (empty string for the main filesystem) - kfreebsd_device="${kfreebsd_device}$(grub-mkrelpath / | sed -e "s,/*@$,,")" + kfreebsd_device="${kfreebsd_device}$(${grub_mkrelpath} / | sed -e "s,/*@$,,")" ;; *) kfreebsd_device=${kfreebsd_fs}id/${GRUB_DEVICE_UUID} From cac14fb663e637f8bb944cb3aab16ce9040840b5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 12:15:57 +0100 Subject: [PATCH 505/673] Support escaped commas in hostdisk. * grub-core/kern/emu/hostdisk.c (unescape_cmp): New function. (find_grub_drive): Use unescape_cmp. (make_device_name): Escape commas. --- ChangeLog | 8 +++++ grub-core/kern/emu/hostdisk.c | 58 +++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02af51ea8..c7f8d3c7b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-11-08 Vladimir Serbinenko + + Support escaped commas in hostdisk. + + * grub-core/kern/emu/hostdisk.c (unescape_cmp): New function. + (find_grub_drive): Use unescape_cmp. + (make_device_name): Escape commas. + 2011-11-08 Vladimir Serbinenko * util/grub.d/10_kfreebsd.in: Use ${grub_mkrelpath} not grub-mkrelpath. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 23417a64d..4d5c28631 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -184,6 +184,27 @@ configure_device_driver (int fd) } #endif /* defined(__NetBSD__) */ +static int +unescape_cmp (const char *a, const char *b_escaped) +{ + while (*a || *b_escaped) + { + if (*b_escaped == '\\' && b_escaped[1] != 0) + b_escaped++; + if (*a < *b_escaped) + return -1; + if (*a > *b_escaped) + return +1; + a++; + b_escaped++; + } + if (*a) + return +1; + if (*b_escaped) + return -1; + return 0; +} + static int find_grub_drive (const char *name) { @@ -192,7 +213,7 @@ find_grub_drive (const char *name) if (name) { for (i = 0; i < ARRAY_SIZE (map); i++) - if (map[i].drive && ! strcmp (map[i].drive, name)) + if (map[i].drive && unescape_cmp (map[i].drive, name) == 0) return i; } @@ -1140,25 +1161,28 @@ grub_util_biosdisk_fini (void) static char * make_device_name (int drive, int dos_part, int bsd_part) { - char *ret; - char *dos_part_str = NULL; - char *bsd_part_str = NULL; + char *ret, *ptr, *end; + const char *iptr; + ret = xmalloc (strlen (map[drive].drive) * 2 + + sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX" + ",XXXXXXXXXXXXXXXXXXXXXXXXXX")); + end = (ret + strlen (map[drive].drive) * 2 + + sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX" + ",XXXXXXXXXXXXXXXXXXXXXXXXXX")); + ptr = ret; + for (iptr = map[drive].drive; *iptr; iptr++) + { + if (*iptr == ',') + *ptr++ = '\\'; + *ptr++ = *iptr; + } + *ptr = 0; if (dos_part >= 0) - dos_part_str = xasprintf (",%d", dos_part + 1); - + snprintf (ptr, end - ptr, ",%d", dos_part + 1); + ptr += strlen (ptr); if (bsd_part >= 0) - bsd_part_str = xasprintf (",%d", bsd_part + 1); - - ret = xasprintf ("%s%s%s", map[drive].drive, - dos_part_str ? : "", - bsd_part_str ? : ""); - - if (dos_part_str) - free (dos_part_str); - - if (bsd_part_str) - free (bsd_part_str); + snprintf (ptr, end - ptr, ",%d", bsd_part + 1); return ret; } From 958ee2216874b6587ff0534fa7030e06a58167ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 12:38:30 +0100 Subject: [PATCH 506/673] Illumos support. * Makefile.util.def (10_illumos): New script. * configure.ac: Set COND_HOST_ILLUMOS. * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__sun__]: Support Illumos calls. (find_partition_start) [__sun__]: Likewise. (convert_system_partition_to_system_disk) [__sun__]: Likewise. (device_is_wholedisk) [__sun__]: Handle Illumos naming scheme. (grub_util_biosdisk_get_grub_dev) [__sun__]: Handle Illumos. * util/getroot.c (find_root_device_from_libzfs) [__sun__]: Return raw device. * util/grub-probe.c (probe) [__sun__]: Do character check. * util/grub.d/10_illumos.in: New file. --- ChangeLog | 17 +++++++++ Makefile.util.def | 7 ++++ configure.ac | 2 + grub-core/kern/emu/hostdisk.c | 72 +++++++++++++++++++++++++++++------ util/getroot.c | 19 ++++++++- util/grub-probe.c | 2 +- util/grub.d/10_illumos.in | 54 ++++++++++++++++++++++++++ 7 files changed, 159 insertions(+), 14 deletions(-) create mode 100644 util/grub.d/10_illumos.in diff --git a/ChangeLog b/ChangeLog index c7f8d3c7b..edb0b2c10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-11-08 Vladimir Serbinenko + + Illumos support. + + * Makefile.util.def (10_illumos): New script. + * configure.ac: Set COND_HOST_ILLUMOS. + * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__sun__]: + Support Illumos calls. + (find_partition_start) [__sun__]: Likewise. + (convert_system_partition_to_system_disk) [__sun__]: Likewise. + (device_is_wholedisk) [__sun__]: Handle Illumos naming scheme. + (grub_util_biosdisk_get_grub_dev) [__sun__]: Handle Illumos. + * util/getroot.c (find_root_device_from_libzfs) [__sun__]: Return raw + device. + * util/grub-probe.c (probe) [__sun__]: Do character check. + * util/grub.d/10_illumos.in: New file. + 2011-11-08 Vladimir Serbinenko Support escaped commas in hostdisk. diff --git a/Makefile.util.def b/Makefile.util.def index 15a309367..8742d1583 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -367,6 +367,13 @@ script = { condition = COND_HOST_KFREEBSD; }; +script = { + name = '10_illumos'; + common = util/grub.d/10_illumos.in; + installdir = grubconf; + condition = COND_HOST_ILLUMOS; +}; + script = { name = '10_netbsd'; common = util/grub.d/10_netbsd.in; diff --git a/configure.ac b/configure.ac index 6aafdf13d..e707081a7 100644 --- a/configure.ac +++ b/configure.ac @@ -154,6 +154,7 @@ case "$host_os" in linux*) host_kernel=linux ;; freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;; netbsd*) host_kernel=netbsd ;; + solaris*) host_kernel=illumos ;; cygwin) host_kernel=windows ;; esac @@ -974,6 +975,7 @@ AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd]) AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows]) AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd]) +AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos]) AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x]) AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 4d5c28631..7074fa8c1 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -98,6 +98,10 @@ struct hd_geometry # define FLOPPY_MAJOR 2 #endif +#if defined (__sun__) +# include +#endif + #if defined(__APPLE__) # include #endif @@ -252,11 +256,11 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), grub_uint64_t grub_util_get_fd_sectors (int fd, unsigned *log_secsize) { -#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) # if defined(__NetBSD__) struct disklabel label; -# else +# elif defined (__sun__) + struct dk_minfo minfo; +#else unsigned long long nr; # endif unsigned sector_size, log_sector_size; @@ -265,7 +269,11 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) if (fstat (fd, &st) < 0) grub_util_error ("fstat failed"); -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) \ + || defined (__sun__) + +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__) if (! S_ISCHR (st.st_mode)) # else if (! S_ISBLK (st.st_mode)) @@ -279,6 +287,8 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) # elif defined(__NetBSD__) configure_device_driver (fd); if (ioctl (fd, DIOCGDINFO, &label) == -1) +# elif defined (__sun__) + if (!ioctl (fd, DKIOCGMEDIAINFO, &minfo)) # else if (ioctl (fd, BLKGETSIZE64, &nr)) # endif @@ -287,13 +297,14 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (ioctl (fd, DIOCGSECTORSIZE, §or_size)) goto fail; +# elif defined(__sun__) + sector_size = minfo.dki_lbsize; # elif defined(__NetBSD__) sector_size = label.d_secsize; # else if (ioctl (fd, BLKSSZGET, §or_size)) goto fail; # endif - if (sector_size & (sector_size - 1) || !sector_size) goto fail; for (log_sector_size = 0; @@ -307,6 +318,8 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) return nr; # elif defined(__NetBSD__) return label.d_secperunit; +# elif defined (__sun__) + return minfo.dki_capacity; # else if (nr & ((1 << log_sector_size) - 1)) grub_util_error ("unaligned device size"); @@ -315,11 +328,15 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) # endif fail: + /* In GNU/Hurd, stat() will return the right size. */ #elif !defined (__GNU__) # warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." #endif + sector_size = 512; + log_sector_size = 9; + if (log_secsize) *log_secsize = 9; @@ -419,12 +436,14 @@ find_partition_start (const char *dev) return out; } -#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) +#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined (__sun__) static grub_disk_addr_t find_partition_start (const char *dev) { int fd; -# if !defined(HAVE_DIOCGDINFO) +#ifdef __sun__ + struct extpart_info pinfo; +# elif !defined(HAVE_DIOCGDINFO) struct hd_geometry hdg; # else /* defined(HAVE_DIOCGDINFO) */ struct disklabel label; @@ -511,7 +530,9 @@ devmapper_fail: return 0; } -# if !defined(HAVE_DIOCGDINFO) +#if defined(__sun__) + if (ioctl (fd, DKIOCEXTPARTINFO, &pinfo)) +# elif !defined(HAVE_DIOCGDINFO) if (ioctl (fd, HDIO_GETGEO, &hdg)) # else /* defined(HAVE_DIOCGDINFO) */ # if defined(__NetBSD__) @@ -532,7 +553,9 @@ devmapper_fail: close (fd); -# if !defined(HAVE_DIOCGDINFO) +#ifdef __sun__ + return pinfo.p_start; +# elif !defined(HAVE_DIOCGDINFO) return hdg.start; # else /* defined(HAVE_DIOCGDINFO) */ if (dev[0]) @@ -1568,12 +1591,37 @@ devmapper_out: } return path; +#elif defined (__sun__) + char *colon = grub_strrchr (os_dev, ':'); + if (grub_memcmp (os_dev, "/devices", sizeof ("/devices") - 1) == 0 + && colon) + { + char *ret = xmalloc (colon - os_dev + sizeof (":q,raw")); + grub_memcpy (ret, os_dev, colon - os_dev); + grub_memcpy (ret + (colon - os_dev), ":q,raw", sizeof (":q,raw")); + return ret; + } + else + return xstrdup (os_dev); #else # warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly." return xstrdup (os_dev); #endif } +#if defined(__sun__) +static int +device_is_wholedisk (const char *os_dev) +{ + if (grub_memcmp (os_dev, "/devices/", sizeof ("/devices/") - 1) != 0) + return 1; + if (grub_memcmp (os_dev + strlen (os_dev) - (sizeof (":q,raw") - 1), + ":q,raw", (sizeof (":q,raw") - 1)) == 0) + return 1; + return 0; +} +#endif + #if defined(__linux__) || defined(__CYGWIN__) static int device_is_wholedisk (const char *os_dev) @@ -1700,14 +1748,14 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) convert_system_partition_to_system_disk (os_dev, &st)) == 0) return make_device_name (drive, -1, -1); -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__) if (! S_ISCHR (st.st_mode)) #else if (! S_ISBLK (st.st_mode)) #endif return make_device_name (drive, -1, -1); -#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__) /* Linux counts partitions uniformly, whether a BSD partition or a DOS partition, so mapping them to GRUB devices is not trivial. @@ -1747,7 +1795,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) name = make_device_name (drive, -1, -1); -# if !defined(HAVE_DIOCGDINFO) +# if !defined(HAVE_DIOCGDINFO) && !defined(__sun__) if (MAJOR (st.st_rdev) == FLOPPY_MAJOR) return name; # else /* defined(HAVE_DIOCGDINFO) */ diff --git a/util/getroot.c b/util/getroot.c index 3d6f9370c..8fce283bc 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -61,6 +61,11 @@ # include #endif +#ifdef __sun__ +# include +# include +#endif + #include #include #include @@ -289,7 +294,19 @@ find_root_device_from_libzfs (const char *dir) struct stat st; if (stat (device, &st) == 0) { - device = xstrdup (device); +#ifdef __sun__ + if (grub_memcmp (device, "/dev/dsk/", sizeof ("/dev/dsk/") - 1) + == 0) + device = xasprintf ("/dev/rdsk/%s", + device + sizeof ("/dev/dsk/") - 1); + else if (grub_memcmp (device, "/devices", sizeof ("/devices") - 1) + == 0 + && grub_memcmp (device + strlen (device) - 4, + ",raw", 4) != 0) + device = xasprintf ("%s,raw", device); + else +#endif + device = xstrdup (device); break; } diff --git a/util/grub-probe.c b/util/grub-probe.c index ae58c89f3..54b9d03c6 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -171,7 +171,7 @@ probe (const char *path, char *device_name) if (path == NULL) { -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__sun__) if (! grub_util_check_char_device (device_name)) grub_util_error ("%s is not a character device", device_name); #else diff --git a/util/grub.d/10_illumos.in b/util/grub.d/10_illumos.in new file mode 100644 index 000000000..2b87dfa4f --- /dev/null +++ b/util/grub.d/10_illumos.in @@ -0,0 +1,54 @@ +#! /bin/sh +set -e + +# grub-mkconfig helper script. +# Copyright (C) 2006,2007,2008,2009,2010,2011 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 . + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libdir=@libdir@ +datarootdir=@datarootdir@ +. ${libdir}/@PACKAGE@/grub-mkconfig_lib + +export TEXTDOMAIN=@PACKAGE@ +export TEXTDOMAINDIR=@localedir@ + +CLASS="--class os" + +case "${GRUB_DISTRIBUTOR}" in + *) + OS="Illumos" + CLASS="--class illumos ${CLASS}" + ;; +esac + +echo "menuentry '${OS}' ${CLASS} {" +save_default_entry | sed -e "s/^/\t/" +prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" +message="$(gettext_printf "Loading kernel of Illumos ...")" + cat << EOF + insmod gzio + if cpuid -l ; then + ISADIR=amd64 + else + ISADIR= + fi + zfs-bootfs $($grub_mkrelpath /) ZFS_BOOTFS + multiboot $($grub_mkrelpath /platform/i86pc/kernel)/\$ISADIR/unix /platform/i86pc/kernel/\$ISADIR/unix -B \$ZFS_BOOTFS,console=text + module $($grub_mkrelpath /platform/i86pc)/\$ISADIR/boot_archive /platform/i86pc/\$ISADIR/boot_archive +} +EOF From 4a19b6017d989c076b06861d3bfd6ba6d3fa9c75 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 16:07:27 +0100 Subject: [PATCH 507/673] Fix ZFS crypto error types. * grub-core/fs/zfs/zfscrypt.c (grub_ccm_decrypt): Fix return type. (grub_gcm_decrypt): Likewise. (grub_zfs_load_key_real): Fix error code type. Handle possible error from PBKDF2. --- ChangeLog | 9 +++++++++ grub-core/fs/zfs/zfscrypt.c | 28 +++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index edb0b2c10..194bd13fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-11-08 Vladimir Serbinenko + + Fix ZFS crypto error types. + + * grub-core/fs/zfs/zfscrypt.c (grub_ccm_decrypt): Fix return type. + (grub_gcm_decrypt): Likewise. + (grub_zfs_load_key_real): Fix error code type. Handle possible error + from PBKDF2. + 2011-11-08 Vladimir Serbinenko Illumos support. diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 39335a728..14babd29f 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -90,7 +90,7 @@ grub_zfs_add_key (grub_uint8_t *key_in, return GRUB_ERR_NONE; } -static grub_err_t +static gcry_err_code_t grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint8_t *out, const grub_uint8_t *in, grub_size_t psize, @@ -101,7 +101,7 @@ grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint8_t mul[16]; grub_uint32_t mac[4]; unsigned i, j; - grub_err_t err; + gcry_err_code_t err; grub_memcpy (iv + 1, nonce, 15 - l); @@ -173,7 +173,7 @@ grub_gcm_mul (grub_uint8_t *a, const grub_uint8_t *b) grub_memcpy (a, res, 16); } -static grub_err_t +static gcry_err_code_t grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint8_t *out, const grub_uint8_t *in, grub_size_t psize, @@ -184,7 +184,7 @@ grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint8_t mul[16]; grub_uint8_t mac[16], h[16], mac_xor[16]; unsigned i, j; - grub_err_t err; + gcry_err_code_t err; grub_memset (mac, 0, sizeof (mac)); @@ -243,7 +243,7 @@ grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher, } -static grub_err_t +static gcry_err_code_t algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, grub_uint8_t *out, const grub_uint8_t *in, grub_size_t psize, @@ -307,7 +307,6 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, unsigned keylen; struct grub_zfs_wrap_key *wrap_key; grub_crypto_cipher_handle_t ret = NULL; - grub_err_t err; if (keysize != sizeof (*key)) { @@ -327,6 +326,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, { grub_crypto_cipher_handle_t cipher; grub_uint8_t decrypted[32], mac[32], wrap_key_real[32]; + gcry_err_code_t err; cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); if (!cipher) { @@ -334,15 +334,21 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, return 0; } grub_memset (wrap_key_real, 0, sizeof (wrap_key_real)); + err = 0; if (!wrap_key->is_passphrase) grub_memcpy(wrap_key_real, wrap_key->key, wrap_key->keylen < keylen ? wrap_key->keylen : keylen); else - grub_crypto_pbkdf2 (GRUB_MD_SHA1, - (const grub_uint8_t *) wrap_key->key, - wrap_key->keylen, - (const grub_uint8_t *) &salt, sizeof (salt), - 1000, wrap_key_real, keylen); + err = grub_crypto_pbkdf2 (GRUB_MD_SHA1, + (const grub_uint8_t *) wrap_key->key, + wrap_key->keylen, + (const grub_uint8_t *) &salt, sizeof (salt), + 1000, wrap_key_real, keylen); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } err = grub_crypto_cipher_set_key (cipher, wrap_key_real, keylen); From 27610c3836e79f8c8d8838b8f3121924a9e60500 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 19:34:19 +0100 Subject: [PATCH 508/673] Fix FreeBSD compilation. * grub-core/disk/geli.c (GRUB_MD_SHA256) [GRUB_UTIL]: Redefine in a way to avoid circular dependency. (GRUB_MD_SHA512) [GRUB_UTIL]: Likewise. * util/getroot.c (grub_util_follow_gpart_up): Move from here... * grub-core/kern/emu/hostdisk.c (+grub_util_follow_gpart_up): ... here. --- ChangeLog | 10 +++++++ grub-core/disk/geli.c | 32 +++++++++++++++++++++ grub-core/kern/emu/hostdisk.c | 53 +++++++++++++++++++++++++++++++++++ util/getroot.c | 50 --------------------------------- 4 files changed, 95 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 194bd13fa..925b798bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-11-08 Vladimir Serbinenko + + Fix FreeBSD compilation. + + * grub-core/disk/geli.c (GRUB_MD_SHA256) [GRUB_UTIL]: Redefine in a way + to avoid circular dependency. + (GRUB_MD_SHA512) [GRUB_UTIL]: Likewise. + * util/getroot.c (grub_util_follow_gpart_up): Move from here... + * grub-core/kern/emu/hostdisk.c (+grub_util_follow_gpart_up): ... here. + 2011-11-08 Vladimir Serbinenko Fix ZFS crypto error types. diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index d2ae5da56..ab94b4131 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -58,6 +58,38 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Dirty trick to solve circular dependency. */ +#ifdef GRUB_UTIL + +#include + +#undef GRUB_MD_SHA256 +#undef GRUB_MD_SHA512 + +static const gcry_md_spec_t * +grub_md_sha256_real (void) +{ + const gcry_md_spec_t *ret; + ret = grub_crypto_lookup_md_by_name ("sha256"); + if (!ret) + grub_util_error ("Coulnd't load sha256"); + return ret; +} + +static const gcry_md_spec_t * +grub_md_sha512_real (void) +{ + const gcry_md_spec_t *ret; + ret = grub_crypto_lookup_md_by_name ("sha512"); + if (!ret) + grub_util_error ("Coulnd't load sha512"); + return ret; +} + +#define GRUB_MD_SHA256 grub_md_sha256_real() +#define GRUB_MD_SHA512 grub_md_sha512_real() +#endif + struct grub_geli_key { grub_uint8_t iv_key[64]; diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 7074fa8c1..7bfc66fef 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -94,6 +94,8 @@ struct hd_geometry # include /* DIOCGMEDIASIZE */ # include # include +# include +#include # define MAJOR(dev) major(dev) # define FLOPPY_MAJOR 2 #endif @@ -423,8 +425,59 @@ grub_util_device_is_mapped (const char *dev) #endif /* HAVE_DEVICE_MAPPER */ } + #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) +/* FIXME: geom actually gives us the whole container hierarchy. + It can be used more efficiently than this. */ +void +grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out) +{ + struct gmesh mesh; + struct gclass *class; + int error; + struct ggeom *geom; + + grub_util_info ("following geom '%s'", name); + + error = geom_gettree (&mesh); + if (error != 0) + grub_util_error ("couldn't open geom"); + + LIST_FOREACH (class, &mesh.lg_class, lg_class) + if (strcasecmp (class->lg_name, "part") == 0) + break; + if (!class) + grub_util_error ("couldn't open geom part"); + + LIST_FOREACH (geom, &class->lg_geom, lg_geom) + { + struct gprovider *provider; + LIST_FOREACH (provider, &geom->lg_provider, lg_provider) + if (strcmp (provider->lg_name, name) == 0) + { + char *name_tmp = xstrdup (geom->lg_name); + grub_disk_addr_t off = 0; + struct gconfig *config; + grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name); + + grub_util_follow_gpart_up (name_tmp, &off, name_out); + free (name_tmp); + LIST_FOREACH (config, &provider->lg_config, lg_config) + if (strcasecmp (config->lg_name, "start") == 0) + off += strtoull (config->lg_val, 0, 10); + if (off_out) + *off_out = off; + return; + } + } + grub_util_info ("geom '%s' has no parent", name); + if (name_out) + *name_out = xstrdup (name); + if (off_out) + *off_out = 0; +} + static grub_disk_addr_t find_partition_start (const char *dev) { diff --git a/util/getroot.c b/util/getroot.c index 8fce283bc..41fbdec10 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -790,56 +790,6 @@ grub_util_get_dm_abstraction (const char *os_dev) #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) #include -/* FIXME: geom actually gives us the whole container hierarchy. - It can be used more efficiently than this. */ -void -grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out) -{ - struct gmesh mesh; - struct gclass *class; - int error; - struct ggeom *geom; - - grub_util_info ("following geom '%s'", name); - - error = geom_gettree (&mesh); - if (error != 0) - grub_util_error ("couldn't open geom"); - - LIST_FOREACH (class, &mesh.lg_class, lg_class) - if (strcasecmp (class->lg_name, "part") == 0) - break; - if (!class) - grub_util_error ("couldn't open geom part"); - - LIST_FOREACH (geom, &class->lg_geom, lg_geom) - { - struct gprovider *provider; - LIST_FOREACH (provider, &geom->lg_provider, lg_provider) - if (strcmp (provider->lg_name, name) == 0) - { - char *name_tmp = xstrdup (geom->lg_name); - grub_disk_addr_t off = 0; - struct gconfig *config; - grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name); - - grub_util_follow_gpart_up (name_tmp, &off, name_out); - free (name_tmp); - LIST_FOREACH (config, &provider->lg_config, lg_config) - if (strcasecmp (config->lg_name, "start") == 0) - off += strtoull (config->lg_val, 0, 10); - if (off_out) - *off_out = off; - return; - } - } - grub_util_info ("geom '%s' has no parent", name); - if (name_out) - *name_out = xstrdup (name); - if (off_out) - *off_out = 0; -} - static const char * grub_util_get_geom_abstraction (const char *dev) { From 3ae17eb83c25cd9b82a8e49a3235168661d8cdbe Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 19:44:18 +0100 Subject: [PATCH 509/673] Fix potential problem with calling zfs_to_cpu and cpu_to_be in a row. * grub-core/fs/zfs/zfscrypt.c (grub_zfs_decrypt_real): Use explicit byteswap when needed. --- ChangeLog | 7 +++++++ grub-core/fs/zfs/zfscrypt.c | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 925b798bc..b23f5156d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-11-08 Vladimir Serbinenko + + Fix potential problem with calling zfs_to_cpu and cpu_to_be in a row. + + * grub-core/fs/zfs/zfscrypt.c (grub_zfs_decrypt_real): Use explicit + byteswap when needed. + 2011-11-08 Vladimir Serbinenko Fix FreeBSD compilation. diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 14babd29f..13f62b25a 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -277,8 +277,9 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, grub_err_t err; grub_memcpy (sw, nonce, 16); - for (i = 0; i < 4; i++) - sw[i] = grub_cpu_to_be32 (grub_zfs_to_cpu32 (sw[i], endian)); + if (endian != GRUB_ZFS_BIG_ENDIAN) + for (i = 0; i < 4; i++) + sw[i] = grub_swap_bytes32 (sw[i]); if (!cipher) return grub_error (GRUB_ERR_ACCESS_DENIED, From 49a45021c1430b481ef4c0be95912e065aa9402f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 19:46:41 +0100 Subject: [PATCH 510/673] * grub-core/lib/LzmaEnc.c (LzmaEnc_CodeOneBlock): Remove set but not used variable. * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): Likewise. --- ChangeLog | 7 +++++++ grub-core/kern/ia64/dl_helper.c | 3 --- grub-core/lib/LzmaEnc.c | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b23f5156d..b7bd30183 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-11-08 Vladimir Serbinenko + + * grub-core/lib/LzmaEnc.c (LzmaEnc_CodeOneBlock): Remove set but not + used variable. + * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): + Likewise. + 2011-11-08 Vladimir Serbinenko Fix potential problem with calling zfs_to_cpu and cpu_to_be in a row. diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index 91f28026e..958cdb25e 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -30,7 +30,6 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, const Elf64_Ehdr *e = ehdr; grub_size_t cntt = 0, cntg = 0;; const Elf64_Shdr *s; - Elf64_Word entsize; unsigned i; /* Find a symbol table. */ @@ -43,8 +42,6 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, if (i == grub_le_to_cpu16 (e->e_shnum)) return; - entsize = s->sh_entsize; - for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); i < grub_le_to_cpu16 (e->e_shnum); i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c index 01ffa91f9..258ed9c91 100644 --- a/grub-core/lib/LzmaEnc.c +++ b/grub-core/lib/LzmaEnc.c @@ -1994,13 +1994,15 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) { UInt32 beforeSize = kNumOpts; +#ifdef COMPRESS_MF_MT Bool btMode; +#endif if (!RangeEnc_Alloc(&p->rc, alloc)) return SZ_ERROR_MEM; +#ifdef COMPRESS_MF_MT btMode = (p->matchFinderBase.btMode != 0); - #ifdef COMPRESS_MF_MT p->mtMode = (p->multiThread && !p->fastMode && btMode); - #endif +#endif { unsigned lclp = p->lc + p->lp; From 438a746a3ff63ed0428818a4f03b181431199747 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 20:03:06 +0100 Subject: [PATCH 511/673] * grub-core/fs/zfs/zfs.c (read_dva): Issue an error if read failed with no error set. --- ChangeLog | 5 +++++ grub-core/fs/zfs/zfs.c | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b7bd30183..f8f424176 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-08 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (read_dva): Issue an error if read failed + with no error set. + 2011-11-08 Vladimir Serbinenko * grub-core/lib/LzmaEnc.c (LzmaEnc_CodeOneBlock): Remove set but not diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index fb16a009b..f85d56e99 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1324,7 +1324,7 @@ read_dva (const dva_t *dva, { grub_uint64_t offset; unsigned i; - grub_err_t err; + grub_err_t err = 0; int try = 0; offset = dva_get_offset (dva, endian); @@ -1344,6 +1344,9 @@ read_dva (const dva_t *dva, if (err) return err; } + if (!err) + return grub_error (GRUB_ERR_BAD_FS, "unknown device %d", + (int) DVA_GET_VDEV (dva)); return err; } From 52b656c037a679c74e9c49dd2c92f289a18b2d4c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 9 Nov 2011 11:43:39 +0100 Subject: [PATCH 512/673] Several AFFS fixes. * grub-core/fs/affs.c (grub_affs_bblock): Replace flags with version. (GRUB_AFFS_FLAG_FFS): Removed. (GRUB_AFFS_SYMLINK_SIZE): Likewise. (GRUB_AFFS_FILETYPE_DIR): Make positive and unsigned. (GRUB_AFFS_FILETYPE_DIR), (GRUB_AFFS_FILETYPE_REG): Fix a mix-up. (grub_fshelp_node): Make block 32-bit. Add block_cache and last_block_cache. (grub_affs_read_block): Fill and use block cache. (grub_affs_read_file): Removed. (grub_affs_mount): Zero-fill node. Fix version check. Don't reread boot block. (grub_affs_read_symlink): Fix symlink size. Add a \0 at the end for safety. (grub_affs_iterate_dir): Use more appropriate types. Zero-fill allocated space. (grub_affs_close): Free block cache. (grub_affs_read): Use grub_fshelp_read_file directly. --- ChangeLog | 22 +++++++++ grub-core/fs/affs.c | 111 +++++++++++++++++++++----------------------- 2 files changed, 74 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index f8f424176..035f18194 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2011-11-09 Vladimir Serbinenko + + Several AFFS fixes. + + * grub-core/fs/affs.c (grub_affs_bblock): Replace flags with version. + (GRUB_AFFS_FLAG_FFS): Removed. + (GRUB_AFFS_SYMLINK_SIZE): Likewise. + (GRUB_AFFS_FILETYPE_DIR): Make positive and unsigned. + (GRUB_AFFS_FILETYPE_DIR), (GRUB_AFFS_FILETYPE_REG): Fix a mix-up. + (grub_fshelp_node): Make block 32-bit. + Add block_cache and last_block_cache. + (grub_affs_read_block): Fill and use block cache. + (grub_affs_read_file): Removed. + (grub_affs_mount): Zero-fill node. Fix version check. Don't reread + boot block. + (grub_affs_read_symlink): Fix symlink size. Add a \0 at the end for + safety. + (grub_affs_iterate_dir): Use more appropriate types. Zero-fill allocated + space. + (grub_affs_close): Free block cache. + (grub_affs_read): Use grub_fshelp_read_file directly. + 2011-11-08 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (read_dva): Issue an error if read failed diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index adf2932bd..06f41c4c3 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -32,15 +32,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct grub_affs_bblock { grub_uint8_t type[3]; - grub_uint8_t flags; + grub_uint8_t version; grub_uint32_t checksum; grub_uint32_t rootblock; } __attribute__ ((packed)); -/* Set if the filesystem is a AFFS filesystem. Otherwise this is an - OFS filesystem. */ -#define GRUB_AFFS_FLAG_FFS 1 - /* The affs rootblock. */ struct grub_affs_rblock { @@ -85,19 +81,19 @@ struct grub_affs_file #define GRUB_AFFS_BLOCKPTR_OFFSET 24 #define GRUB_AFFS_SYMLINK_OFFSET 24 -#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225) - -#define GRUB_AFFS_FILETYPE_DIR -3 -#define GRUB_AFFS_FILETYPE_REG 2 +#define GRUB_AFFS_FILETYPE_REG 0xfffffffd +#define GRUB_AFFS_FILETYPE_DIR 2 #define GRUB_AFFS_FILETYPE_SYMLINK 3 struct grub_fshelp_node { struct grub_affs_data *data; - grub_disk_addr_t block; + grub_uint32_t block; struct grub_fshelp_node *parent; struct grub_affs_file di; + grub_uint32_t *block_cache; + grub_uint32_t last_block_cache; }; /* Information about a "mounted" affs filesystem. */ @@ -120,32 +116,46 @@ static grub_dl_t my_mod; static grub_disk_addr_t grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { - int links; + grub_uint32_t target, curblock; grub_uint32_t pos; - int block = node->block; struct grub_affs_file file; struct grub_affs_data *data = node->data; grub_uint64_t mod; + if (!node->block_cache) + { + node->block_cache = grub_malloc ((((grub_be_to_cpu32 (node->di.size) + + 511) >> 9) / data->htsize + 1) + * sizeof (node->block_cache[0])); + if (!node->block_cache) + return -1; + node->last_block_cache = 0; + node->block_cache[0] = node->block; + } + + /* Files are at most 2G on AFFS, so no need for 64-bit division. */ + target = (grub_uint32_t) fileblock / data->htsize; + mod = (grub_uint32_t) fileblock % data->htsize; /* Find the block that points to the fileblock we are looking up by following the chain until the right table is reached. */ - for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--) + for (curblock = node->last_block_cache + 1; curblock <= target; curblock++) { - grub_disk_read (data->disk, block + data->blocksize - 1, + grub_disk_read (data->disk, + node->block_cache[curblock - 1] + data->blocksize - 1, data->blocksize * (GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION), sizeof (file), &file); if (grub_errno) return 0; - block = grub_be_to_cpu32 (file.extension); + node->block_cache[curblock] = grub_be_to_cpu32 (file.extension); + node->last_block_cache = curblock; } /* Translate the fileblock to the block within the right table. */ - fileblock = mod; - grub_disk_read (data->disk, block, + grub_disk_read (data->disk, node->block_cache[target], GRUB_AFFS_BLOCKPTR_OFFSET - + (data->htsize - fileblock - 1) * sizeof (pos), + + (data->htsize - mod - 1) * sizeof (pos), sizeof (pos), &pos); if (grub_errno) return 0; @@ -153,21 +163,6 @@ grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) return grub_be_to_cpu32 (pos); } - -/* Read LEN bytes from the file described by DATA starting with byte - POS. Return the amount of read bytes in READ. */ -static grub_ssize_t -grub_affs_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), - grub_off_t pos, grub_size_t len, char *buf) -{ - return grub_fshelp_read_file (node->data->disk, node, read_hook, - pos, len, buf, grub_affs_read_block, - grub_be_to_cpu32 (node->di.size), 0); -} - - static struct grub_affs_data * grub_affs_mount (grub_disk_t disk) { @@ -178,7 +173,7 @@ grub_affs_mount (grub_disk_t disk) int checksum = 0; int blocksize = 0; - data = grub_malloc (sizeof (struct grub_affs_data)); + data = grub_zalloc (sizeof (struct grub_affs_data)); if (!data) return 0; @@ -196,18 +191,12 @@ grub_affs_mount (grub_disk_t disk) } /* Test if the filesystem is a OFS filesystem. */ - if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS)) + if (data->bblock.version < 1) { grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported"); goto fail; } - /* Read the bootblock. */ - grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock), - &data->bblock); - if (grub_errno) - goto fail; - /* No sane person uses more than 8KB for a block. At least I hope for that person because in that case this won't work. */ rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16); @@ -270,18 +259,21 @@ grub_affs_read_symlink (grub_fshelp_node_t node) { struct grub_affs_data *data = node->data; char *symlink; + const grub_size_t symlink_size = (data->blocksize * GRUB_DISK_SECTOR_SIZE + - 225); - symlink = grub_malloc (GRUB_AFFS_SYMLINK_SIZE (data->blocksize)); + symlink = grub_malloc (symlink_size + 1); if (!symlink) return 0; grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET, - GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink); + symlink_size, symlink); if (grub_errno) { grub_free (symlink); return 0; } + symlink[symlink_size] = 1; grub_dprintf ("affs", "Symlink: `%s'\n", symlink); return symlink; } @@ -301,24 +293,24 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, grub_uint32_t *hashtable; auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, - grub_disk_addr_t block, + grub_uint32_t block, const struct grub_affs_file *fil); int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, - grub_disk_addr_t block, + grub_uint32_t block, const struct grub_affs_file *fil) { int type; - node = grub_malloc (sizeof (*node)); + node = grub_zalloc (sizeof (*node)); if (!node) { grub_free (hashtable); return 1; } - if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR) + if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG) type = GRUB_FSHELP_REG; - else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG) + else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR) type = GRUB_FSHELP_DIR; else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK) type = GRUB_FSHELP_SYMLINK; @@ -339,7 +331,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, } /* Create the directory entries for `.' and `..'. */ - node = grub_malloc (sizeof (*node)); + node = grub_zalloc (sizeof (*node)); if (!node) return 1; @@ -348,7 +340,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, return 1; if (dir->parent) { - node = grub_malloc (sizeof (*node)); + node = grub_zalloc (sizeof (*node)); if (!node) return 1; *node = *dir->parent; @@ -356,7 +348,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, return 1; } - hashtable = grub_malloc (data->htsize * sizeof (*hashtable)); + hashtable = grub_zalloc (data->htsize * sizeof (*hashtable)); if (!hashtable) return 1; @@ -367,7 +359,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, for (i = 0; i < data->htsize; i++) { - grub_uint64_t next; + grub_uint32_t next; if (!hashtable[i]) continue; @@ -441,10 +433,13 @@ grub_affs_open (struct grub_file *file, const char *name) return grub_errno; } - static grub_err_t grub_affs_close (grub_file_t file) { + struct grub_affs_data *data = + (struct grub_affs_data *) file->data; + + grub_free (data->diropen.block_cache); grub_free (file->data); grub_dl_unref (my_mod); @@ -452,7 +447,6 @@ grub_affs_close (grub_file_t file) return GRUB_ERR_NONE; } - /* Read LEN bytes data from FILE into BUF. */ static grub_ssize_t grub_affs_read (grub_file_t file, char *buf, grub_size_t len) @@ -460,13 +454,12 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_affs_data *data = (struct grub_affs_data *) file->data; - int size = grub_affs_read_file (&data->diropen, file->read_hook, - file->offset, len, buf); - - return size; + return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen, + file->read_hook, + file->offset, len, buf, grub_affs_read_block, + grub_be_to_cpu32 (data->diropen.di.size), 0); } - static grub_err_t grub_affs_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, From 19e81ba7a0b67bb1bd3d427c9c7cc1147a78ec8d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 9 Nov 2011 14:44:21 +0100 Subject: [PATCH 513/673] * configure.ac: Add missing -mXX to TARGET_CPPFLAGS. --- ChangeLog | 4 ++++ configure.ac | 2 ++ 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 035f18194..1b7fd4411 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-09 Vladimir Serbinenko + + * configure.ac: Add missing -mXX to TARGET_CPPFLAGS. + 2011-11-09 Vladimir Serbinenko Several AFFS fixes. diff --git a/configure.ac b/configure.ac index e707081a7..1b3288c8a 100644 --- a/configure.ac +++ b/configure.ac @@ -464,6 +464,7 @@ if test "x$target_m32" = x1; then # Force 32-bit mode. TARGET_CFLAGS="$TARGET_CFLAGS -m32" TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m32" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m32" TARGET_LDFLAGS="$TARGET_LDFLAGS -m32" TARGET_MODULE_FORMAT="elf32" fi @@ -472,6 +473,7 @@ if test "x$target_m64" = x1; then # Force 64-bit mode. TARGET_CFLAGS="$TARGET_CFLAGS -m64" TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m64" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m64" TARGET_LDFLAGS="$TARGET_LDFLAGS -m64" TARGET_MODULE_FORMAT="elf64" fi From 57b01250046a33900d3e4b7434967aacb343bc7e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 9 Nov 2011 14:47:45 +0100 Subject: [PATCH 514/673] * include/grub/misc.h (grub_strncat): Fix the order of conditionals to avoid accessing beyond the array. --- ChangeLog | 5 +++++ include/grub/misc.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1b7fd4411..352c69c4f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-09 Vladimir Serbinenko + + * include/grub/misc.h (grub_strncat): Fix the order of conditionals to + avoid accessing beyond the array. + 2011-11-09 Vladimir Serbinenko * configure.ac: Add missing -mXX to TARGET_CPPFLAGS. diff --git a/include/grub/misc.h b/include/grub/misc.h index 5bc159e7d..4e7d9077c 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -87,7 +87,7 @@ grub_strncat (char *dest, const char *src, int c) while (*p) p++; - while ((*p = *src) != '\0' && c--) + while (c-- && (*p = *src) != '\0') { p++; src++; From 8a5a3a5b5a3f53520f8dd63808e5715558d0d326 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 9 Nov 2011 15:01:58 +0100 Subject: [PATCH 515/673] Fix several memory leaks. * grub-core/fs/btrfs.c (grub_btrfs_dir): Fix memory leak. * grub-core/fs/cpio.c (grub_cpio_find_file): Likewise. (grub_cpio_dir): Likewise. * grub-core/fs/fat.c (grub_fat_label): Likewise. * grub-core/fs/jfs.c (grub_jfs_label): Likewise. * grub-core/fs/romfs.c (grub_romfs_close): Likewise. (grub_romfs_label): Likewise. * grub-core/fs/squash4.c (squash_mount): Use zalloc for safety. (squash_unmount): New function. (grub_squash_dir): Fix memory leak. (grub_squash_open): Likewise. (grub_squash_read): Likewise. (grub_squash_mtime): Likewise. * grub-core/fs/xfs.c (grub_xfs_open): Likewise. * grub-core/fs/zfs/zfs.c (check_pool_label): Likewise. * util/grub-fstest.c (fstest): Likewise. --- ChangeLog | 21 +++++++++++++++++++++ grub-core/fs/btrfs.c | 29 +++++++++++++++++++---------- grub-core/fs/cpio.c | 3 +++ grub-core/fs/fat.c | 6 +++++- grub-core/fs/jfs.c | 2 ++ grub-core/fs/romfs.c | 6 +++++- grub-core/fs/squash4.c | 22 +++++++++++++++++----- grub-core/fs/xfs.c | 11 +++++++---- grub-core/fs/zfs/zfs.c | 2 ++ util/grub-fstest.c | 4 +++- 10 files changed, 84 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 352c69c4f..c367bb134 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2011-11-09 Vladimir Serbinenko + + Fix several memory leaks. + + * grub-core/fs/btrfs.c (grub_btrfs_dir): Fix memory leak. + * grub-core/fs/cpio.c (grub_cpio_find_file): Likewise. + (grub_cpio_dir): Likewise. + * grub-core/fs/fat.c (grub_fat_label): Likewise. + * grub-core/fs/jfs.c (grub_jfs_label): Likewise. + * grub-core/fs/romfs.c (grub_romfs_close): Likewise. + (grub_romfs_label): Likewise. + * grub-core/fs/squash4.c (squash_mount): Use zalloc for safety. + (squash_unmount): New function. + (grub_squash_dir): Fix memory leak. + (grub_squash_open): Likewise. + (grub_squash_read): Likewise. + (grub_squash_mtime): Likewise. + * grub-core/fs/xfs.c (grub_xfs_open): Likewise. + * grub-core/fs/zfs/zfs.c (check_pool_label): Likewise. + * util/grub-fstest.c (fstest): Likewise. + 2011-11-09 Vladimir Serbinenko * include/grub/misc.h (grub_strncat): Fix the order of conditionals to diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 3dc680034..e5aa3084c 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1415,22 +1415,28 @@ grub_btrfs_dir (grub_device_t device, const char *path, err = find_path (data, path, &key_in, &tree, &type); if (err) - return err; + { + grub_btrfs_unmount (data); + return err; + } if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + { + grub_btrfs_unmount (data); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + } err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, &desc); if (err) - return err; + { + grub_btrfs_unmount (data); + return err; + } if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM || key_out.object_id != key_in.object_id) { r = next (data, &desc, &elemaddr, &elemsize, &key_out); if (r <= 0) - { - free_iterator (&desc); - return -r; - } + goto out; } do { @@ -1448,14 +1454,17 @@ grub_btrfs_dir (grub_device_t device, const char *path, direl = grub_malloc (allocated + 1); if (!direl) { - free_iterator (&desc); - return grub_errno; + r = -grub_errno; + break; } } err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize); if (err) - return err; + { + r = -err; + break; + } for (cdirel = direl; (grub_uint8_t *) cdirel - (grub_uint8_t *) direl diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index b43e54ec9..39b35b335 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -147,6 +147,7 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, && grub_memcmp(*name, "TRAILER!!!", 11) == 0) { *ofs = 0; + grub_free (*name); return GRUB_ERR_NONE; } @@ -481,6 +482,8 @@ grub_cpio_dir (grub_device_t device, const char *path_in, } } } + else + grub_free (name); data->hofs = ofs; } diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index fb1113814..0d32e229d 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -1048,7 +1048,10 @@ grub_fat_label (grub_device_t device, char **label) grub_size_t chc; *label = grub_malloc (11 * 4 + 1); if (!*label) - return grub_errno; + { + grub_free (data); + return grub_errno; + } chc = dir.type_specific.volume_label.character_count; if (chc > ARRAY_SIZE (dir.type_specific.volume_label.str)) chc = ARRAY_SIZE (dir.type_specific.volume_label.str); @@ -1057,6 +1060,7 @@ grub_fat_label (grub_device_t device, char **label) } } + grub_free (data); return grub_errno; } diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index cf7520bb3..91497f143 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -891,6 +891,8 @@ grub_jfs_label (grub_device_t device, char **label) else *label = 0; + grub_free (data); + return grub_errno; } diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 713e8293f..202ca102e 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -397,7 +397,10 @@ grub_romfs_read (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_romfs_close (grub_file_t file) { - grub_free (file->data); + struct grub_fshelp_node *data = file->data; + + grub_free (data->data); + grub_free (data); return GRUB_ERR_NONE; } @@ -432,6 +435,7 @@ grub_romfs_label (grub_device_t device, char **label) return err; } (*label)[data->first_file - sizeof (struct grub_romfs_superblock)] = 0; + grub_free (data); return GRUB_ERR_NONE; } diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index a3832b6be..0728287b7 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -287,7 +287,7 @@ squash_mount (grub_disk_t disk) if (err) return NULL; - data = grub_malloc (sizeof (*data)); + data = grub_zalloc (sizeof (*data)); if (!data) return NULL; data->sb = sb; @@ -418,6 +418,15 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) grub_cpu_to_le16 (data->sb.root_ino_offset)); } +static void +squash_unmount (struct grub_squash_data *data) +{ + grub_free (data->ino.cumulated_block_sizes); + grub_free (data->ino.block_sizes); + grub_free (data); +} + + static grub_err_t grub_squash_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, @@ -436,6 +445,7 @@ grub_squash_dir (grub_device_t device, const char *path, info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.mtimeset = 1; info.mtime = grub_le_to_cpu32 (node->ino.mtime); + grub_free (node); return hook (filename, &info); } @@ -457,7 +467,7 @@ grub_squash_dir (grub_device_t device, const char *path, if (!grub_errno) grub_squash_iterate_dir (fdiro, iterate); - grub_free (data); + squash_unmount (data); return grub_errno; } @@ -482,7 +492,7 @@ grub_squash_open (struct grub_file *file, const char *name) grub_squash_read_symlink, GRUB_FSHELP_REG); if (grub_errno) { - grub_free (data); + squash_unmount (data); return grub_errno; } @@ -499,6 +509,8 @@ grub_squash_open (struct grub_file *file, const char *name) else file->size = grub_le_to_cpu32 (fdiro->ino.file.size); + grub_free (fdiro); + return GRUB_ERR_NONE; } @@ -664,7 +676,7 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_squash_close (grub_file_t file) { - grub_free (file->data); + squash_unmount (file->data); return GRUB_ERR_NONE; } @@ -677,7 +689,7 @@ grub_squash_mtime (grub_device_t dev, grub_int32_t *tm) if (! data) return grub_errno; *tm = grub_le_to_cpu32 (data->sb.creation_time); - grub_free (data); + squash_unmount (data); return GRUB_ERR_NONE; } diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 3dc5e0af0..c4d47a099 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -771,10 +771,13 @@ grub_xfs_open (struct grub_file *file, const char *name) } if (fdiro != &data->diropen) - grub_memcpy (&data->diropen, fdiro, - sizeof (struct grub_fshelp_node) - - sizeof (struct grub_xfs_inode) - + (1 << data->sblock.log2_inode)); + { + grub_memcpy (&data->diropen, fdiro, + sizeof (struct grub_fshelp_node) + - sizeof (struct grub_xfs_inode) + + (1 << data->sblock.log2_inode)); + grub_free (fdiro); + } file->size = grub_be_to_cpu64 (data->diropen.inode.size); file->data = data; diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index f85d56e99..7ceb16db2 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -781,9 +781,11 @@ check_pool_label (struct grub_zfs_data *data, err = fill_vdev_info (data, nv, diskdesc); if (err) { + grub_free (nv); grub_free (nvlist); return err; } + grub_free (nv); } grub_dprintf ("zfs", "check 10 passed\n"); diff --git a/util/grub-fstest.c b/util/grub-fstest.c index f90755e86..47b536771 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -401,7 +401,9 @@ fstest (int n, char **args) if (!uuid) grub_util_error ("couldn't retrieve UUID"); argv[1] = uuid; - execute_command ("xnu_uuid", 2, argv); + execute_command ("xnu_uuid", 2, argv); + grub_free (uuid); + grub_device_close (dev); } } From 28840fdaae146999e51d5741a6434b4f3ffaf54c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 10 Nov 2011 08:07:51 +0100 Subject: [PATCH 516/673] * include/grub/i386/netbsd_bootinfo.h (grub_netbsd_btinfo_bootwedge): Fix declaration. --- ChangeLog | 5 +++++ include/grub/i386/netbsd_bootinfo.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c367bb134..7cd370c1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-10 Vladimir Serbinenko + + * include/grub/i386/netbsd_bootinfo.h (grub_netbsd_btinfo_bootwedge): + Fix declaration. + 2011-11-09 Vladimir Serbinenko Fix several memory leaks. diff --git a/include/grub/i386/netbsd_bootinfo.h b/include/grub/i386/netbsd_bootinfo.h index 228f26aaa..24e145b01 100644 --- a/include/grub/i386/netbsd_bootinfo.h +++ b/include/grub/i386/netbsd_bootinfo.h @@ -92,7 +92,7 @@ struct grub_netbsd_btinfo_bootwedge { grub_disk_addr_t matchblk; grub_uint64_t matchnblks; grub_uint8_t matchhash[16]; /* MD5 hash */ -} __packed; +} __attribute__ ((packed)); struct grub_netbsd_btinfo_symtab { From 6b68db81fc42ed6a4b9aa7f15f5578136c383980 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 10 Nov 2011 08:09:33 +0100 Subject: [PATCH 517/673] * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Fix RAID10 logic for >= 6 drives. --- ChangeLog | 5 +++++ grub-core/fs/btrfs.c | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7cd370c1b..506036d5a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-10 Vladimir Serbinenko + + * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Fix RAID10 logic for + >= 6 drives. + 2011-11-10 Vladimir Serbinenko * include/grub/i386/netbsd_bootinfo.h (grub_netbsd_btinfo_bootwedge): diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index e5aa3084c..fae9199a4 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -734,12 +734,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, &low); high = grub_divmod64 (middle, - grub_le_to_cpu16 (chunk->nsubstripes), + grub_le_to_cpu16 (chunk->nstripes) + / grub_le_to_cpu16 (chunk->nsubstripes), &stripen); - stripen *= grub_le_to_cpu16 (chunk->nstripes) - / grub_le_to_cpu16 (chunk->nsubstripes); - redundancy = grub_le_to_cpu16 (chunk->nstripes) - / grub_le_to_cpu16 (chunk->nsubstripes); + stripen *= grub_le_to_cpu16 (chunk->nsubstripes); + redundancy = grub_le_to_cpu16 (chunk->nsubstripes); stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) * high; csize = grub_le_to_cpu64 (chunk->stripe_length) - low; From ad9a2f44b4cbf8e22a65f9f019b7914f1a60d169 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 10 Nov 2011 08:16:27 +0100 Subject: [PATCH 518/673] * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix grub_strncat argument (access out of bounds). --- ChangeLog | 5 +++++ grub-core/fs/iso9660.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 506036d5a..ef82df3af 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-10 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix grub_strncat + argument (access out of bounds). + 2011-11-10 Vladimir Serbinenko * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Fix RAID10 logic for diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index d4c52bed4..5e2f7824a 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -559,9 +559,9 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, filename = ".."; else if (entry->len >= 5) { - int size = 1; + grub_size_t size = 1, csize = 1; char *old; - size = entry->len - 5; + csize = size = entry->len - 5; old = filename; if (filename_alloc) { @@ -580,7 +580,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, return grub_errno; } filename_alloc = 1; - grub_strncat (filename, (char *) &entry->data[1], size); + grub_strncat (filename, (char *) &entry->data[1], csize); filename[size] = '\0'; } } From 45bd824d2eed877eef2c55c96063eefbc4a3c5d5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 10 Nov 2011 08:38:06 +0100 Subject: [PATCH 519/673] Fix ZFS memory and resource leaks. * grub-core/fs/zfs/zfs.c (fill_vdev_info_real): New paramter inserted. All users updated. Free type on exit. (fill_vdev_info): New parameter inserted. All users updated. (check_pool_label): Likewise. (scan_disk): Likewise. (scan_devices): Close non-inserted disks. (fzap_iterate): Free l. (unmount_device): Free children descripto memory. --- ChangeLog | 14 +++++++ grub-core/fs/zfs/zfs.c | 84 +++++++++++++++++++++++++++++++----------- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index ef82df3af..24a2b783b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-11-10 Vladimir Serbinenko + + Fix ZFS memory and resource leaks. + + * grub-core/fs/zfs/zfs.c (fill_vdev_info_real): New paramter inserted. + All users updated. + Free type on exit. + (fill_vdev_info): New parameter inserted. All users updated. + (check_pool_label): Likewise. + (scan_disk): Likewise. + (scan_devices): Close non-inserted disks. + (fzap_iterate): Free l. + (unmount_device): Free children descripto memory. + 2011-11-10 Vladimir Serbinenko * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix grub_strncat diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 7ceb16db2..760668940 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -535,7 +535,8 @@ static grub_err_t fill_vdev_info_real (struct grub_zfs_data *data, const char *nvlist, struct grub_zfs_device_desc *fill, - struct grub_zfs_device_desc *insert) + struct grub_zfs_device_desc *insert, + int *inserted) { char *type; @@ -545,10 +546,16 @@ fill_vdev_info_real (struct grub_zfs_data *data, return grub_errno; if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &(fill->id))) - return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + { + grub_free (type); + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + } if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "guid", &(fill->guid))) - return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + { + grub_free (type); + return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); + } if (grub_strcmp (type, VDEV_TYPE_DISK) == 0 || grub_strcmp (type, VDEV_TYPE_FILE) == 0) @@ -563,8 +570,11 @@ fill_vdev_info_real (struct grub_zfs_data *data, fill->original = insert->original; if (!data->device_original) data->device_original = fill; + *inserted = 1; } + grub_free (type); + return GRUB_ERR_NONE; } @@ -580,17 +590,27 @@ fill_vdev_info_real (struct grub_zfs_data *data, grub_uint64_t par; fill->type = DEVICE_RAIDZ; if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "nparity", &par)) - return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity"); + { + grub_free (type); + return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity"); + } fill->nparity = par; if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "ashift", &par)) - return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz ashift"); + { + grub_free (type); + return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz ashift"); + } fill->ashift = par; } - nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, ZPOOL_CONFIG_CHILDREN); + nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, + ZPOOL_CONFIG_CHILDREN); if (nelm <= 0) - return grub_error (GRUB_ERR_BAD_FS, "incorrect mirror VDEV"); + { + grub_free (type); + return grub_error (GRUB_ERR_BAD_FS, "incorrect mirror VDEV"); + } if (!fill->children) { @@ -608,34 +628,43 @@ fill_vdev_info_real (struct grub_zfs_data *data, child = grub_zfs_nvlist_lookup_nvlist_array (nvlist, ZPOOL_CONFIG_CHILDREN, i); - err = fill_vdev_info_real (data, child, &fill->children[i], insert); + err = fill_vdev_info_real (data, child, &fill->children[i], insert, + inserted); grub_free (child); if (err) - return err; + { + grub_free (type); + return err; + } } + grub_free (type); return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported", - type); + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "vdev %s isn't supported", type); + grub_free (type); + return grub_errno; } static grub_err_t fill_vdev_info (struct grub_zfs_data *data, - char *nvlist, struct grub_zfs_device_desc *diskdesc) + char *nvlist, struct grub_zfs_device_desc *diskdesc, + int *inserted) { grub_uint64_t id; unsigned i; + *inserted = 0; + if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "id", &id)) return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); for (i = 0; i < data->n_devices_attached; i++) if (data->devices_attached[i].id == id) return fill_vdev_info_real (data, nvlist, &data->devices_attached[i], - diskdesc); + diskdesc, inserted); data->n_devices_attached++; if (data->n_devices_attached > data->n_devices_allocated) @@ -658,7 +687,7 @@ fill_vdev_info (struct grub_zfs_data *data, return fill_vdev_info_real (data, nvlist, &data->devices_attached[data->n_devices_attached - 1], - diskdesc); + diskdesc, inserted); } /* @@ -667,7 +696,8 @@ fill_vdev_info (struct grub_zfs_data *data, */ static grub_err_t check_pool_label (struct grub_zfs_data *data, - struct grub_zfs_device_desc *diskdesc) + struct grub_zfs_device_desc *diskdesc, + int *inserted) { grub_uint64_t pool_state, txg = 0; char *nvlist; @@ -679,6 +709,8 @@ check_pool_label (struct grub_zfs_data *data, int found; grub_err_t err; + *inserted = 0; + err = zfs_fetch_nvlist (diskdesc, &nvlist); if (err) return err; @@ -778,7 +810,7 @@ check_pool_label (struct grub_zfs_data *data, grub_free (nvlist); return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev tree"); } - err = fill_vdev_info (data, nv, diskdesc); + err = fill_vdev_info (data, nv, diskdesc, inserted); if (err) { grub_free (nv); @@ -796,7 +828,7 @@ check_pool_label (struct grub_zfs_data *data, static grub_err_t scan_disk (grub_device_t dev, struct grub_zfs_data *data, - int original) + int original, int *inserted) { int label = 0; uberblock_phys_t *ub_array, *ubbest = NULL; @@ -858,7 +890,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, grub_memmove (&(data->current_uberblock), &ubbest->ubp_uberblock, sizeof (uberblock_t)); - err = check_pool_label (data, &desc); + err = check_pool_label (data, &desc, inserted); if (err) { grub_errno = GRUB_ERR_NONE; @@ -889,6 +921,7 @@ scan_devices (struct grub_zfs_data *data) { grub_device_t dev; grub_err_t err; + int inserted; dev = grub_device_open (name); if (!dev) return 0; @@ -897,7 +930,7 @@ scan_devices (struct grub_zfs_data *data) grub_device_close (dev); return 0; } - err = scan_disk (dev, data, 0); + err = scan_disk (dev, data, 0, &inserted); if (err == GRUB_ERR_BAD_FS) { grub_device_close (dev); @@ -910,6 +943,9 @@ scan_devices (struct grub_zfs_data *data) grub_print_error (); return 0; } + + if (!inserted) + grub_device_close (dev); return 0; } @@ -2042,10 +2078,14 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, if (hook (buf, le->le_name_length, val, le->le_value_length, le->le_int_size)) - return 1; + { + grub_free (l); + return 1; + } grub_free (buf); grub_free (val); } + grub_free (l); } return 0; } @@ -3156,6 +3196,7 @@ unmount_device (struct grub_zfs_device_desc *desc) case DEVICE_MIRROR: for (i = 0; i < desc->n_children; i++) unmount_device (&desc->children[i]); + grub_free (desc->children); return; } } @@ -3190,6 +3231,7 @@ zfs_mount (grub_device_t dev) grub_size_t ospsize; grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; uberblock_t *ub; + int inserted; if (! dev->disk) { @@ -3210,7 +3252,7 @@ zfs_mount (grub_device_t dev) data->devices_attached = grub_malloc (sizeof (data->devices_attached[0]) * data->n_devices_allocated); data->n_devices_attached = 0; - err = scan_disk (dev, data, 1); + err = scan_disk (dev, data, 1, &inserted); if (err) { zfs_unmount (data); From cb544caa2ecd10367cd05d5ebbcdc019fdab255a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 10 Nov 2011 08:43:08 +0100 Subject: [PATCH 520/673] * grub-core/fs/zfs/zfs.c (zfs_mount): Fix spurious warning. --- ChangeLog | 4 ++++ grub-core/fs/zfs/zfs.c | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 24a2b783b..2687b65be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-10 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (zfs_mount): Fix spurious warning. + 2011-11-10 Vladimir Serbinenko Fix ZFS memory and resource leaks. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 760668940..20cba3509 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -3227,7 +3227,7 @@ zfs_mount (grub_device_t dev) { struct grub_zfs_data *data = 0; grub_err_t err; - objset_phys_t *osp = 0; + void *osp = 0; grub_size_t ospsize; grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; uberblock_t *ub; @@ -3265,7 +3265,7 @@ zfs_mount (grub_device_t dev) ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); err = zio_read (&ub->ub_rootbp, ub_endian, - (void **) &osp, &ospsize, data); + &osp, &ospsize, data); if (err) { zfs_unmount (data); @@ -3281,7 +3281,8 @@ zfs_mount (grub_device_t dev) } /* Got the MOS. Save it at the memory addr MOS. */ - grub_memmove (&(data->mos.dn), &osp->os_meta_dnode, DNODE_SIZE); + grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode, + DNODE_SIZE); data->mos.endian = (grub_zfs_to_cpu64 (ub->ub_rootbp.blk_prop, ub_endian) >> 63) & 1; grub_free (osp); From c3591189b82421a8eaeebc97c118d81bba1931cd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 10 Nov 2011 08:46:09 +0100 Subject: [PATCH 521/673] Remove local keyword. * util/grub-mkconfig_lib.in (version_test_numeric): Remove local. (version_test_gt): Likewise. (version_find_latest): Likewise. (gettext_printf): Likewise. * util/grub.d/10_windows.in (get_os_name_from_boot_ini): Likewise. --- ChangeLog | 10 ++++++++ util/grub-mkconfig_lib.in | 48 +++++++++++++++++++-------------------- util/grub.d/10_windows.in | 10 ++++---- 3 files changed, 39 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2687b65be..e60b4da9c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-11-10 Vladimir Serbinenko + + Remove local keyword. + + * util/grub-mkconfig_lib.in (version_test_numeric): Remove local. + (version_test_gt): Likewise. + (version_find_latest): Likewise. + (gettext_printf): Likewise. + * util/grub.d/10_windows.in (get_os_name_from_boot_ini): Likewise. + 2011-11-10 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (zfs_mount): Fix spurious warning. diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index a453a6bb5..5a9bf90c0 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -167,21 +167,21 @@ grub_file_is_not_garbage () version_test_numeric () { - local a="$1" - local cmp="$2" - local b="$3" - if [ "$a" = "$b" ] ; then - case "$cmp" in + version_test_numeric_a="$1" + version_test_numeric_cmp="$2" + version_test_numeric_b="$3" + if [ "$version_test_numeric_a" = "$version_test_numeric_b" ] ; then + case "$version_test_numeric_cmp" in ge|eq|le) return 0 ;; gt|lt) return 1 ;; esac fi - if [ "$cmp" = "lt" ] ; then - c="$a" - a="$b" - b="$c" + if [ "$version_test_numeric_cmp" = "lt" ] ; then + version_test_numeric_c="$version_test_numeric_a" + version_test_numeric_a="$version_test_numeric_b" + version_test_numeric_b="$version_test_numeric_c" fi - if (echo "$a" ; echo "$b") | sort -n | head -n 1 | grep -qx "$b" ; then + if (echo "$version_test_numeric_a" ; echo "$version_test_numeric_b") | sort -n | head -n 1 | grep -qx "$version_test_numeric_b" ; then return 0 else return 1 @@ -190,30 +190,30 @@ version_test_numeric () version_test_gt () { - local a="`echo "$1" | sed -e "s/[^-]*-//"`" - local b="`echo "$2" | sed -e "s/[^-]*-//"`" - local cmp=gt - if [ "x$b" = "x" ] ; then + version_test_gt_a="`echo "$1" | sed -e "s/[^-]*-//"`" + version_test_gt_b="`echo "$2" | sed -e "s/[^-]*-//"`" + version_test_gt_cmp=gt + if [ "x$version_test_gt_b" = "x" ] ; then return 0 fi - case "$a:$b" in + case "$version_test_gt_a:$version_test_gt_b" in *.old:*.old) ;; - *.old:*) a="`echo -n "$a" | sed -e 's/\.old$//'`" ; cmp=gt ;; - *:*.old) b="`echo -n "$b" | sed -e 's/\.old$//'`" ; cmp=ge ;; + *.old:*) version_test_gt_a="`echo -n "$version_test_gt_a" | sed -e 's/\.old$//'`" ; cmp=gt ;; + *:*.old) version_test_gt_b="`echo -n "$version_test_gt_b" | sed -e 's/\.old$//'`" ; cmp=ge ;; esac - version_test_numeric "$a" "$cmp" "$b" + version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b" return "$?" } version_find_latest () { - local a="" + version_find_latest_a="" for i in "$@" ; do - if version_test_gt "$i" "$a" ; then - a="$i" + if version_test_gt "$i" "$version_find_latest_a" ; then + version_find_latest_a="$i" fi done - echo "$a" + echo "$version_find_latest_a" } # One layer of quotation is eaten by "", the second by sed, and the third by @@ -227,9 +227,9 @@ gettext_quoted () { # remaining arguments to printf. This is a useful abbreviation and tends to # be easier to type. gettext_printf () { - local format="$1" + gettext_printf_format="$1" shift - printf "$(gettext_quoted "$format")" "$@" + printf "$(gettext_quoted "$gettext_printf_format")" "$@" } uses_abstraction () { diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index 0a848880d..20fd4e044 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -42,14 +42,14 @@ get_os_name_from_boot_ini () sort | uniq | wc -l`" = 1 || return 1 # Search 'default=PARTITION' - local part=`sed -n 's,^default=,,p' "$1" | sed 's,\\\\,/,g;s,[ \t\r]*$,,;1q'` - test -n "$part" || return 1 + get_os_name_from_boot_ini_part=`sed -n 's,^default=,,p' "$1" | sed 's,\\\\,/,g;s,[ \t\r]*$,,;1q'` + test -n "$get_os_name_from_boot_ini_part" || return 1 # Search 'PARTITION="NAME" ...' - local name=`sed -n 's,\\\\,/,g;s,^'"$part"'="\([^"]*\)".*$,\1,p' "$1" | sed 1q` - test -n "$name" || return 1 + get_os_name_from_boot_ini_name=`sed -n 's,\\\\,/,g;s,^'"$get_os_name_from_boot_ini_part"'="\([^"]*\)".*$,\1,p' "$1" | sed 1q` + test -n "$get_os_name_from_boot_ini_name" || return 1 - echo "$name" + echo "$get_os_name_from_boot_ini_name" } From f627652531ee17d729e024858d529c9b05657593 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 10 Nov 2011 09:31:06 +0100 Subject: [PATCH 522/673] Put symlink at the end of the node and fix a potential memory corruption. * grub-core/fs/iso9660.c (grub_fshelp_node): New field have_symlink. Make symlink into an array. (set_rockridge): Set have_symlink and alloc_dirents. (grub_iso9660_read_symlink): Use new layout. (grub_iso9660_iterate_dir): Fix memory corruption. Use new layout. (grub_iso9660_dir): Set have_symlink. (grub_iso9660_open): Likewise. --- ChangeLog | 14 +++++++++++ grub-core/fs/iso9660.c | 55 +++++++++++++++++++++++++++++++++--------- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index e60b4da9c..f293e0773 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-11-10 Vladimir Serbinenko + + Put symlink at the end of the node and fix a potential + memory corruption. + + * grub-core/fs/iso9660.c (grub_fshelp_node): New field have_symlink. + Make symlink into an array. + (set_rockridge): Set have_symlink and alloc_dirents. + (grub_iso9660_read_symlink): Use new layout. + (grub_iso9660_iterate_dir): Fix memory corruption. + Use new layout. + (grub_iso9660_dir): Set have_symlink. + (grub_iso9660_open): Likewise. + 2011-11-10 Vladimir Serbinenko Remove local keyword. diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 5e2f7824a..7b1e32f7c 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -159,8 +159,9 @@ struct grub_fshelp_node { struct grub_iso9660_data *data; grub_size_t have_dirents, alloc_dirents; - char *symlink; + int have_symlink; struct grub_iso9660_dir dirents[8]; + char symlink[0]; }; enum @@ -408,9 +409,9 @@ set_rockridge (struct grub_iso9660_data *data) struct grub_fshelp_node rootnode; rootnode.data = data; - rootnode.alloc_dirents = 0; + rootnode.alloc_dirents = ARRAY_SIZE (rootnode.dirents); rootnode.have_dirents = 1; - rootnode.symlink = 0; + rootnode.have_symlink = 0; rootnode.dirents[0] = data->voldesc.rootdir; /* The 2nd data byte stored how many bytes are skipped every time @@ -500,7 +501,10 @@ grub_iso9660_mount (grub_disk_t disk) static char * grub_iso9660_read_symlink (grub_fshelp_node_t node) { - return node->symlink ? grub_strdup (node->symlink) : grub_strdup (""); + return node->have_symlink + ? grub_strdup (node->symlink + + (node->have_dirents) * sizeof (node->dirents[0]) + - sizeof (node->dirents)) : grub_strdup (""); } static grub_off_t @@ -703,7 +707,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, /* Setup a new node. */ node->data = dir->data; - node->symlink = symlink; + node->have_symlink = 0; /* If the filetype was not stored using rockridge, use whatever is stored in the iso9660 filesystem. */ @@ -767,10 +771,11 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, { struct grub_fshelp_node *new_node; node->alloc_dirents *= 2; - new_node = grub_malloc (sizeof (struct grub_fshelp_node) - + ((node->alloc_dirents - - ARRAY_SIZE (node->dirents)) - * sizeof (node->dirents[0]))); + new_node = grub_realloc (node, + sizeof (struct grub_fshelp_node) + + ((node->alloc_dirents + - ARRAY_SIZE (node->dirents)) + * sizeof (node->dirents[0]))); if (!new_node) { if (filename_alloc) @@ -778,9 +783,37 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, grub_free (node); return 0; } + node = new_node; } node->dirents[node->have_dirents++] = dirent; } + if (symlink) + { + if ((node->alloc_dirents - node->have_dirents) + * sizeof (node->dirents[0]) < grub_strlen (symlink) + 1) + { + struct grub_fshelp_node *new_node; + new_node = grub_realloc (node, + sizeof (struct grub_fshelp_node) + + ((node->alloc_dirents + - ARRAY_SIZE (node->dirents)) + * sizeof (node->dirents[0])) + + grub_strlen (symlink) + 1); + if (!new_node) + { + if (filename_alloc) + grub_free (filename); + grub_free (node); + return 0; + } + node = new_node; + } + node->have_symlink = 1; + grub_strcpy (node->symlink + + node->have_dirents * sizeof (node->dirents[0]) + - sizeof (node->dirents), symlink); + grub_free (symlink); + } if (hook (filename, type, node)) { if (filename_alloc) @@ -832,7 +865,7 @@ grub_iso9660_dir (grub_device_t device, const char *path, rootnode.data = data; rootnode.alloc_dirents = 0; rootnode.have_dirents = 1; - rootnode.symlink = 0; + rootnode.have_symlink = 0; rootnode.dirents[0] = data->voldesc.rootdir; /* Use the fshelp function to traverse the path. */ @@ -875,7 +908,7 @@ grub_iso9660_open (struct grub_file *file, const char *name) rootnode.data = data; rootnode.alloc_dirents = 0; rootnode.have_dirents = 1; - rootnode.symlink = 0; + rootnode.have_symlink = 0; rootnode.dirents[0] = data->voldesc.rootdir; /* Use the fshelp function to traverse the path. */ From 33f784e88175d449eab915d74020cb6cd581b333 Mon Sep 17 00:00:00 2001 From: Shea Levy Date: Thu, 10 Nov 2011 09:41:07 +0100 Subject: [PATCH 523/673] Allow all modules to perform serial IO * grub-core/term-serial.c (grub_serial_find): Remove static qualifier * include/grub/serial.h (grub_serial_port_configure): New inline function. (grub_serial_port_fetch): Likewise. (grub_serial_port_put): Likewise. (grub_serial_port_fini): Likewise. (grub_serial_find): New proto. --- ChangeLog | 12 ++++++++++++ grub-core/term/serial.c | 2 +- include/grub/serial.h | 27 +++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f293e0773..6c7304387 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-11-10 Shea Levy + + Allow all modules to perform serial IO + + * grub-core/term-serial.c (grub_serial_find): Remove static qualifier + * include/grub/serial.h (grub_serial_port_configure): New inline + function. + (grub_serial_port_fetch): Likewise. + (grub_serial_port_put): Likewise. + (grub_serial_port_fini): Likewise. + (grub_serial_find): New proto. + 2011-11-10 Vladimir Serbinenko Put symlink at the end of the node and fix a potential diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index 306694192..86935626c 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -125,7 +125,7 @@ static struct grub_term_output grub_serial_term_output = -static struct grub_serial_port * +struct grub_serial_port * grub_serial_find (char *name) { struct grub_serial_port *port; diff --git a/include/grub/serial.h b/include/grub/serial.h index 41b720891..49ac0623a 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -96,6 +96,32 @@ grub_err_t EXPORT_FUNC(grub_serial_register) (struct grub_serial_port *port); void EXPORT_FUNC(grub_serial_unregister) (struct grub_serial_port *port); + /* Convenience functions to perform primitive operations on a port. */ +static inline grub_err_t +grub_serial_port_configure (struct grub_serial_port *port, + struct grub_serial_config *config) +{ + return port->driver->configure (port, config); +} + +static inline int +grub_serial_port_fetch (struct grub_serial_port *port) +{ + return port->driver->fetch (port); +} + +static inline void +grub_serial_port_put (struct grub_serial_port *port, const int c) +{ + port->driver->put (port, c); +} + +static inline void +grub_serial_port_fini (struct grub_serial_port *port) +{ + port->driver->fini (port); +} + /* Set default settings. */ static inline grub_err_t grub_serial_config_defaults (struct grub_serial_port *port) @@ -117,6 +143,7 @@ grub_serial_config_defaults (struct grub_serial_port *port) void grub_ns8250_init (void); char *grub_serial_ns8250_add_port (grub_port_t port); +struct grub_serial_port *grub_serial_find (char *name); extern struct grub_serial_driver grub_ns8250_driver; void EXPORT_FUNC(grub_serial_unregister_driver) (struct grub_serial_driver *driver); From 11a775a3ad55e6de651edcd71d344ea41e64d2eb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 17:08:29 +0100 Subject: [PATCH 524/673] * grub-core/commands/probe.c (grub_cmd_probe): Fix error message. --- ChangeLog | 4 ++++ grub-core/commands/probe.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6c7304387..4e2d18c11 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/commands/probe.c (grub_cmd_probe): Fix error message. + 2011-11-10 Shea Levy Allow all modules to perform serial IO diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index ce1e9aac0..a1d68cdeb 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -136,7 +136,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) return err; if (! label) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "uuid for this FS isn't supported yet"); + "label for this FS isn't supported yet"); if (state[0].set) grub_env_set (state[0].arg, label); From f768836950b038dbc67dabafb2a6086148edab82 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 17:10:50 +0100 Subject: [PATCH 525/673] * grub-core/efiemu/main.c (grub_efiemu_register_configuration_table): A stylistic fix. --- ChangeLog | 5 +++++ grub-core/efiemu/main.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4e2d18c11..fcbfe0c9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/efiemu/main.c (grub_efiemu_register_configuration_table): + A stylistic fix. + 2011-11-11 Vladimir Serbinenko * grub-core/commands/probe.c (grub_cmd_probe): Fix error message. diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c index 7ad3abb0d..126ecf9e7 100644 --- a/grub-core/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -149,7 +149,8 @@ grub_efiemu_register_configuration_table (grub_efi_guid_t guid, if (! get_table && ! data) return grub_error (GRUB_ERR_BAD_ARGUMENT, "you must set at least get_table or data"); - if ((err = grub_efiemu_unregister_configuration_table (guid))) + err = grub_efiemu_unregister_configuration_table (guid); + if (err) return err; tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl)); From 6c1892942da03b61e5bfe74f670d3b5c33053152 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 17:13:23 +0100 Subject: [PATCH 526/673] * grub-core/fs/btrfs.c (grub_btrfs_embed): Spelling fix. --- ChangeLog | 4 ++++ grub-core/fs/btrfs.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index fcbfe0c9d..e37326afa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/fs/btrfs.c (grub_btrfs_embed): Spelling fix. + 2011-11-11 Vladimir Serbinenko * grub-core/efiemu/main.c (grub_efiemu_register_configuration_table): diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index fae9199a4..db251ffd7 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1615,7 +1615,7 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), if (embed_type != GRUB_EMBED_PCBIOS) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "BtrFS curently supports only PC-BIOS embedding"); + "BtrFS currently supports only PC-BIOS embedding"); if (64 * 2 - 1 < *nsectors) return grub_error (GRUB_ERR_OUT_OF_RANGE, From 53dc85906500ef6a23a37562c5619bf25ca6d7a2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 17:18:34 +0100 Subject: [PATCH 527/673] * grub-core/fs/ntfs.c (grub_ntfs_read_symlink): Stylistic fix. Remove leftover debug printf. --- ChangeLog | 5 +++++ grub-core/fs/ntfs.c | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e37326afa..2b2920b79 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (grub_ntfs_read_symlink): Stylistic fix. Remove + leftover debug printf. + 2011-11-11 Vladimir Serbinenko * grub-core/fs/btrfs.c (grub_btrfs_embed): Spelling fix. diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index 13de52cd8..ac695a29f 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -705,17 +705,18 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) switch (grub_cpu_to_le32 (symdesc.type)) { case 0xa000000c: - off = sizeof (struct symlink_descriptor) + 4 + grub_cpu_to_le32 (symdesc.off1); + off = (sizeof (struct symlink_descriptor) + 4 + + grub_cpu_to_le32 (symdesc.off1)); len = grub_cpu_to_le32 (symdesc.len1); break; case 0xa0000003: - off = sizeof (struct symlink_descriptor) + grub_cpu_to_le32 (symdesc.off1); + off = (sizeof (struct symlink_descriptor) + + grub_cpu_to_le32 (symdesc.off1)); len = grub_cpu_to_le32 (symdesc.len1); break; default: grub_error (GRUB_ERR_BAD_FS, "symlink type invalid (%x)", grub_cpu_to_le32 (symdesc.type)); - grub_printf ("%d\n", __LINE__); return NULL; } From e2d22baf41ecd6252d9c7ca718d4906f37338cd9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 17:21:33 +0100 Subject: [PATCH 528/673] * grub-core/fs/zfs/zfscrypt.c (GRUB_MOD_INIT), (GRUB_MOD_FINI): Fix module name. --- ChangeLog | 5 +++++ grub-core/fs/zfs/zfscrypt.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2b2920b79..0864781d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/fs/zfs/zfscrypt.c (GRUB_MOD_INIT), (GRUB_MOD_FINI): + Fix module name. + 2011-11-11 Vladimir Serbinenko * grub-core/fs/ntfs.c (grub_ntfs_read_symlink): Stylistic fix. Remove diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 13f62b25a..619878243 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -455,7 +455,7 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) static grub_extcmd_t cmd_key; -GRUB_MOD_INIT(zfscrypto) +GRUB_MOD_INIT(zfscrypt) { grub_zfs_decrypt = grub_zfs_decrypt_real; grub_zfs_load_key = grub_zfs_load_key_real; @@ -465,7 +465,7 @@ GRUB_MOD_INIT(zfscrypto) options); } -GRUB_MOD_FINI(zfscrypto) +GRUB_MOD_FINI(zfscrypt) { grub_zfs_decrypt = 0; grub_zfs_load_key = 0; From 4c458569a7f1a7ac71c0d4f91820d45a227b3326 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 17:34:38 +0100 Subject: [PATCH 529/673] * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_set_property): Make buf a const. --- ChangeLog | 5 +++++ grub-core/kern/ieee1275/ieee1275.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0864781d7..f011fdef5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_set_property): + Make buf a const. + 2011-11-11 Vladimir Serbinenko * grub-core/fs/zfs/zfscrypt.c (GRUB_MOD_INIT), (GRUB_MOD_FINI): diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c index 9e2919172..b32fd2d8b 100644 --- a/grub-core/kern/ieee1275/ieee1275.c +++ b/grub-core/kern/ieee1275/ieee1275.c @@ -532,7 +532,7 @@ grub_ieee1275_release (grub_addr_t addr, grub_size_t size) int grub_ieee1275_set_property (grub_ieee1275_phandle_t phandle, - const char *propname, void *buf, + const char *propname, const void *buf, grub_size_t size, grub_ssize_t *actual) { struct set_property_args From 63a9e6f6a07bc07ae1df3c6917428cccfbf1fb71 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 17:44:47 +0100 Subject: [PATCH 530/673] * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Issue error rather than printf on unknown arguments. --- ChangeLog | 5 +++++ grub-core/kern/ieee1275/openfw.c | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index f011fdef5..7c2b55e3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): + Issue error rather than printf on unknown arguments. + 2011-11-11 Vladimir Serbinenko * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_set_property): diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 57252d96b..3568ffe64 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -403,7 +403,8 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) break; default: unknown: - grub_printf ("Unsupported type %s for device %s\n", type, device); + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported type %s for device %s", type, device); } fail: From 9bb182f3716cc9f850f5e64edb61a6da09748d7e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 18:05:16 +0100 Subject: [PATCH 531/673] * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Issue an error and not a fatal on unrecognised relocation types. --- ChangeLog | 5 +++++ grub-core/kern/x86_64/dl.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7c2b55e3b..b0a790c10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Issue + an error and not a fatal on unrecognised relocation types. + 2011-11-11 Vladimir Serbinenko * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c index 090ad78b8..9b63b30f8 100644 --- a/grub-core/kern/x86_64/dl.c +++ b/grub-core/kern/x86_64/dl.c @@ -109,7 +109,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; default: - grub_fatal ("Unrecognized relocation: %d\n", ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "this relocation (%d) is not implemented yet", + ELF_R_TYPE (rel->r_info)); } } } From f7ce5bafb56ebeb2121c2d35eb98293f3e98acd0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 18:30:34 +0100 Subject: [PATCH 532/673] Fix mips compilation. * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec): Restrict hash_id to normal decoder. (hashes): Use in embed decoder as well (for sizes). (dec_stream_header): Fix embed decompressor logic. (dec_stream_footer): Likewise. --- ChangeLog | 10 ++++++++++ grub-core/lib/xzembed/xz_dec_stream.c | 19 ++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index b0a790c10..ca07d5cab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-11-11 Vladimir Serbinenko + + Fix mips compilation. + + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec): Restrict hash_id to + normal decoder. + (hashes): Use in embed decoder as well (for sizes). + (dec_stream_header): Fix embed decompressor logic. + (dec_stream_footer): Likewise. + 2011-11-11 Vladimir Serbinenko * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Issue diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 383c29a2f..09e5e513a 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -78,9 +78,9 @@ struct xz_dec { #ifndef GRUB_EMBED_DECOMPRESSOR const gcry_md_spec_t *hash; const gcry_md_spec_t *crc32; + grub_uint8_t hash_id; #endif grub_size_t hash_size; - grub_uint8_t hash_id; /* True if we are operating in single-call mode. */ bool single_call; @@ -428,8 +428,7 @@ static enum xz_ret hash_validate(struct xz_dec *s, struct xz_buf *b, return XZ_STREAM_END; } -#ifndef GRUB_EMBED_DECOMPRESSOR -static struct +static const struct { const char *name; grub_size_t size; @@ -438,7 +437,6 @@ static struct [0x04] = { "CRC64", 8}, [0x0A] = { "SHA256", 32}, }; -#endif /* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ static enum xz_ret dec_stream_header(struct xz_dec *s) @@ -470,9 +468,9 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) } #endif +#ifndef GRUB_EMBED_DECOMPRESSOR /* - * Decode the Stream Flags field. Of integrity checks, we support - * only none (Check ID = 0) and CRC32 (Check ID = 1). + * Decode the Stream Flags field. */ if (s->temp.buf[HEADER_MAGIC_SIZE] != 0 || s->temp.buf[HEADER_MAGIC_SIZE + 1] >= ARRAY_SIZE (hashes) @@ -482,7 +480,6 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) s->hash_id = s->temp.buf[HEADER_MAGIC_SIZE + 1]; -#ifndef GRUB_EMBED_DECOMPRESSOR if (s->crc32) { s->crc32_context = kmalloc(s->crc32->contextsize, GFP_KERNEL); @@ -530,17 +527,15 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) s->hash->init(s->index.hash.hash_context); s->hash->init(s->block.hash.hash_context); } -#else - s->hash = 0; -#endif -#if 1 if (!s->hash) return XZ_OPTIONS_ERROR; #endif } else { +#ifndef GRUB_EMBED_DECOMPRESSOR s->hash = 0; +#endif s->hash_size = 0; } @@ -589,8 +584,10 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s) if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) return XZ_DATA_ERROR; +#ifndef GRUB_EMBED_DECOMPRESSOR if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->hash_id) return XZ_DATA_ERROR; +#endif /* * Use XZ_STREAM_END instead of XZ_OK to be more convenient From a8bd9d39d6fa19ee6672db9732a6f9f1a6d2502e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 18:32:06 +0100 Subject: [PATCH 533/673] * include/grub/ieee1275/ieee1275.h (grub_ieee1275_set_property): Fix prototype. --- ChangeLog | 5 +++++ include/grub/ieee1275/ieee1275.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ca07d5cab..4838d9566 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_set_property): + Fix prototype. + 2011-11-11 Vladimir Serbinenko Fix mips compilation. diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 81590ee4b..be3835a42 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -173,7 +173,8 @@ int EXPORT_FUNC(grub_ieee1275_claim) (grub_addr_t addr, grub_size_t size, unsigned int align, grub_addr_t *result); int EXPORT_FUNC(grub_ieee1275_release) (grub_addr_t addr, grub_size_t size); int EXPORT_FUNC(grub_ieee1275_set_property) (grub_ieee1275_phandle_t phandle, - const char *propname, void *buf, + const char *propname, + const void *buf, grub_size_t size, grub_ssize_t *actual); int EXPORT_FUNC(grub_ieee1275_set_color) (grub_ieee1275_ihandle_t ihandle, From 067fdf005573500c6998402affe1723cd51efaf9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 20:02:51 +0100 Subject: [PATCH 534/673] * grub-core/kern/misc.c (grub_strstr): Moved from here ... * include/grub/misc.h (grub_strstr): ... here. Make static and inline. --- ChangeLog | 5 +++++ grub-core/kern/misc.c | 46 ----------------------------------------- include/grub/misc.h | 48 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4838d9566..6d740545a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_strstr): Moved from here ... + * include/grub/misc.h (grub_strstr): ... here. Make static and inline. + 2011-11-11 Vladimir Serbinenko * include/grub/ieee1275/ieee1275.h (grub_ieee1275_set_property): diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index ebf80f100..34c9b3b0c 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -312,52 +312,6 @@ grub_strrchr (const char *s, int c) return p; } -/* Copied from gnulib. - Written by Bruno Haible , 2005. */ -char * -grub_strstr (const char *haystack, const char *needle) -{ - /* Be careful not to look at the entire extent of haystack or needle - until needed. This is useful because of these two cases: - - haystack may be very long, and a match of needle found early, - - needle may be very long, and not even a short initial segment of - needle may be found in haystack. */ - if (*needle != '\0') - { - /* Speed up the following searches of needle by caching its first - character. */ - char b = *needle++; - - for (;; haystack++) - { - if (*haystack == '\0') - /* No match. */ - return NULL; - if (*haystack == b) - /* The first character matches. */ - { - const char *rhaystack = haystack + 1; - const char *rneedle = needle; - - for (;; rhaystack++, rneedle++) - { - if (*rneedle == '\0') - /* Found a match. */ - return (char *) haystack; - if (*rhaystack == '\0') - /* No match. */ - return NULL; - if (*rhaystack != *rneedle) - /* Nothing in this round. */ - break; - } - } - } - } - else - return (char *) haystack; -} - int grub_strword (const char *haystack, const char *needle) { diff --git a/include/grub/misc.h b/include/grub/misc.h index 4e7d9077c..358f73258 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -113,7 +113,53 @@ int EXPORT_FUNC(grub_strncmp) (const char *s1, const char *s2, grub_size_t n); char *EXPORT_FUNC(grub_strchr) (const char *s, int c); char *EXPORT_FUNC(grub_strrchr) (const char *s, int c); int EXPORT_FUNC(grub_strword) (const char *s, const char *w); -char *EXPORT_FUNC(grub_strstr) (const char *haystack, const char *needle); + +/* Copied from gnulib. + Written by Bruno Haible , 2005. */ +static inline char * +grub_strstr (const char *haystack, const char *needle) +{ + /* Be careful not to look at the entire extent of haystack or needle + until needed. This is useful because of these two cases: + - haystack may be very long, and a match of needle found early, + - needle may be very long, and not even a short initial segment of + needle may be found in haystack. */ + if (*needle != '\0') + { + /* Speed up the following searches of needle by caching its first + character. */ + char b = *needle++; + + for (;; haystack++) + { + if (*haystack == '\0') + /* No match. */ + return 0; + if (*haystack == b) + /* The first character matches. */ + { + const char *rhaystack = haystack + 1; + const char *rneedle = needle; + + for (;; rhaystack++, rneedle++) + { + if (*rneedle == '\0') + /* Found a match. */ + return (char *) haystack; + if (*rhaystack == '\0') + /* No match. */ + return 0; + if (*rhaystack != *rneedle) + /* Nothing in this round. */ + break; + } + } + } + } + else + return (char *) haystack; +} + int EXPORT_FUNC(grub_isspace) (int c); int EXPORT_FUNC(grub_isprint) (int c); From 9aed8a7178adb8c959fde3c3c3318478c8eab9ec Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 20:09:14 +0100 Subject: [PATCH 535/673] * grub-core/normal/main.c (grub_normal_execute): Remove leftover call. --- ChangeLog | 4 ++++ grub-core/normal/main.c | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6d740545a..abf4dce28 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/normal/main.c (grub_normal_execute): Remove leftover call. + 2011-11-11 Vladimir Serbinenko * grub-core/kern/misc.c (grub_strstr): Moved from here ... diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index f372b6798..281b1f4bc 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -274,7 +274,6 @@ grub_normal_execute (const char *config, int nested, int batch) prefix = grub_env_get ("prefix"); read_lists (prefix); grub_register_variable_hook ("prefix", NULL, read_lists_hook); - grub_command_execute ("parser.grub", 0, 0); } if (config) From d35d0d3753cef291ed141d891f6c5e98dee929f7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 20:34:37 +0100 Subject: [PATCH 536/673] Add const keyword to grub_env_get and gettextize week days. * grub-core/hook/datehook.c (grub_datetime_names): Make const. (grub_read_hook_datetime): Return const char *. * grub-core/kern/env.c (grub_env_get): Return const char *. All users updated. * grub-core/normal/datetime.c (grub_weekday_names): Make const. Mark for gettext. (grub_get_weekday_name): Return const char *. Call gettext. * grub-core/script/argv.c (grub_script_argv_append): Receive const char * and len as the argument. All users updated. (grub_script_argv_split_append): Receive const char *. * include/grub/datetime.h (grub_get_weekday_name): Update proto. * include/grub/env.h (grub_env_get): Likewise. (grub_env_read_hook_t): Return const char *. * include/grub/script_sh.h (grub_script_argv_append): Update proto. (grub_script_argv_split_append): Likewise. --- ChangeLog | 20 ++++++++++++++ grub-core/commands/i386/pc/drivemap.c | 2 +- grub-core/commands/legacycfg.c | 2 +- grub-core/commands/loadenv.c | 4 +-- grub-core/commands/wildcard.c | 2 +- grub-core/gettext/gettext.c | 2 +- grub-core/hook/datehook.c | 4 +-- grub-core/kern/dl.c | 2 +- grub-core/kern/env.c | 2 +- grub-core/kern/parser.c | 2 +- grub-core/lib/i386/pc/biosnum.c | 2 +- grub-core/loader/i386/linux.c | 7 ++--- grub-core/loader/i386/xnu.c | 2 +- grub-core/normal/datetime.c | 21 ++++++++------- grub-core/normal/menu.c | 4 +-- grub-core/script/argv.c | 25 ++++++++--------- grub-core/script/execute.c | 39 ++++++++++++++++----------- include/grub/datetime.h | 2 +- include/grub/env.h | 6 ++--- include/grub/script_sh.h | 5 ++-- 20 files changed, 91 insertions(+), 64 deletions(-) diff --git a/ChangeLog b/ChangeLog index abf4dce28..f98fd8e75 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2011-11-11 Vladimir Serbinenko + + Add const keyword to grub_env_get and gettextize week days. + + * grub-core/hook/datehook.c (grub_datetime_names): Make const. + (grub_read_hook_datetime): Return const char *. + * grub-core/kern/env.c (grub_env_get): Return const char *. All users + updated. + * grub-core/normal/datetime.c (grub_weekday_names): Make const. + Mark for gettext. + (grub_get_weekday_name): Return const char *. Call gettext. + * grub-core/script/argv.c (grub_script_argv_append): Receive const + char * and len as the argument. All users updated. + (grub_script_argv_split_append): Receive const char *. + * include/grub/datetime.h (grub_get_weekday_name): Update proto. + * include/grub/env.h (grub_env_get): Likewise. + (grub_env_read_hook_t): Return const char *. + * include/grub/script_sh.h (grub_script_argv_append): Update proto. + (grub_script_argv_split_append): Likewise. + 2011-11-11 Vladimir Serbinenko * grub-core/normal/main.c (grub_normal_execute): Remove leftover call. diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index c9c8881b4..9a89f968c 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -363,7 +363,7 @@ uninstall_int13_handler (void) static int grub_get_root_biosnumber_drivemap (void) { - char *biosnum; + const char *biosnum; int ret = -1; grub_device_t dev; diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index e68b3315a..4e87adafc 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -344,7 +344,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), int bsd_part = -1; { grub_device_t dev; - char *hdbiasstr; + const char *hdbiasstr; int hdbias = 0; hdbiasstr = grub_env_get ("legacy_hdbias"); if (hdbiasstr) diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 5d53a8e66..1073712d5 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -43,7 +43,7 @@ open_envblk_file (char *filename) if (! filename) { - char *prefix; + const char *prefix; prefix = grub_env_get ("prefix"); if (prefix) @@ -346,7 +346,7 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) while (argc) { - char *value; + const char *value; value = grub_env_get (args[0]); if (value) diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 256c07e51..d991b2010 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -436,7 +436,7 @@ wildcard_expand (const char *s, char ***strs) else if (*start == '/') /* no device part */ { - char *root; + const char *root; char *prefix; root = grub_env_get ("root"); diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c index 8581b1ff3..682754421 100644 --- a/grub-core/gettext/gettext.c +++ b/grub-core/gettext/gettext.c @@ -294,7 +294,7 @@ grub_mofile_open_lang (const char *locale_dir, const char *locale) static void grub_gettext_init_ext (const char *locale) { - char *locale_dir; + const char *locale_dir; if (!locale) return; diff --git a/grub-core/hook/datehook.c b/grub-core/hook/datehook.c index f64fac074..d7ceb85c8 100644 --- a/grub-core/hook/datehook.c +++ b/grub-core/hook/datehook.c @@ -26,7 +26,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static char *grub_datetime_names[] = +static const char *grub_datetime_names[] = { "YEAR", "MONTH", @@ -37,7 +37,7 @@ static char *grub_datetime_names[] = "WEEKDAY", }; -static char * +static const char * grub_read_hook_datetime (struct grub_env_var *var, const char *val __attribute__ ((unused))) { diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index b6fb537e8..26cf0d21d 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -697,7 +697,7 @@ grub_dl_load (const char *name) { char *filename; grub_dl_t mod; - char *grub_dl_dir = grub_env_get ("prefix"); + const char *grub_dl_dir = grub_env_get ("prefix"); mod = grub_dl_get (name); if (mod) diff --git a/grub-core/kern/env.c b/grub-core/kern/env.c index 8f843a872..96b730d35 100644 --- a/grub-core/kern/env.c +++ b/grub-core/kern/env.c @@ -132,7 +132,7 @@ grub_env_set (const char *name, const char *val) return grub_errno; } -char * +const char * grub_env_get (const char *name) { struct grub_env_var *var; diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c index 6370a7b3a..5b449586c 100644 --- a/grub-core/kern/parser.c +++ b/grub-core/kern/parser.c @@ -123,7 +123,7 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, void add_var (grub_parser_state_t newstate) { - char *val; + const char *val; /* Check if a variable was being read in and the end of the name was reached. */ diff --git a/grub-core/lib/i386/pc/biosnum.c b/grub-core/lib/i386/pc/biosnum.c index 12771085a..0f0e743c4 100644 --- a/grub-core/lib/i386/pc/biosnum.c +++ b/grub-core/lib/i386/pc/biosnum.c @@ -24,7 +24,7 @@ static int grub_get_root_biosnumber_default (void) { - char *biosnum; + const char *biosnum; int ret = -1; grub_device_t dev; diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index fded7bb0a..a6eb95028 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -320,7 +320,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) void *framebuffer; grub_err_t err; grub_video_driver_id_t driver_id; - char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb"); + const char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb"); driver_id = grub_video_get_driver_id (); @@ -418,14 +418,15 @@ grub_linux_boot (void) struct linux_kernel_params *params; int e820_num; grub_err_t err = 0; - char *modevar, *tmp; + const char *modevar; + char *tmp; struct grub_relocator32_state state; params = real_mode_mem; #ifdef GRUB_MACHINE_IEEE1275 { - char *bootpath; + const char *bootpath; grub_ssize_t len; bootpath = grub_env_get ("root"); diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index 6128ec384..fa7af514b 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -700,7 +700,7 @@ grub_cpu_xnu_fill_devicetree (void) return grub_errno; /* First see if user supplies the value. */ - char *fsbvar = grub_env_get ("fsb"); + const char *fsbvar = grub_env_get ("fsb"); if (! fsbvar) *((grub_uint64_t *) curval->data) = 0; else diff --git a/grub-core/normal/datetime.c b/grub-core/normal/datetime.c index 44791e18c..8183601ba 100644 --- a/grub-core/normal/datetime.c +++ b/grub-core/normal/datetime.c @@ -18,16 +18,17 @@ */ #include +#include -static char *grub_weekday_names[] = +static const char *grub_weekday_names[] = { - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", + N_("Sunday"), + N_("Monday"), + N_("Tuesday"), + N_("Wednesday"), + N_("Thursday"), + N_("Friday"), + N_("Saturday"), }; int @@ -42,10 +43,10 @@ grub_get_weekday (struct grub_datetime *datetime) return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7; } -char * +const char * grub_get_weekday_name (struct grub_datetime *datetime) { - return grub_weekday_names[grub_get_weekday (datetime)]; + return _ (grub_weekday_names[grub_get_weekday (datetime)]); } #define SECPERMIN 60 diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index 2c127794b..b75e9f523 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -79,7 +79,7 @@ grub_menu_get_entry (grub_menu_t menu, int no) int grub_menu_get_timeout (void) { - char *val; + const char *val; int timeout; val = grub_env_get ("timeout"); @@ -124,7 +124,7 @@ grub_menu_set_timeout (int timeout) static int get_and_remove_first_entry_number (const char *name) { - char *val; + const char *val; char *tail; int entry; diff --git a/grub-core/script/argv.c b/grub-core/script/argv.c index 856828d7b..b58d3e658 100644 --- a/grub-core/script/argv.c +++ b/grub-core/script/argv.c @@ -66,7 +66,8 @@ grub_script_argv_make (struct grub_script_argv *argv, int argc, char **args) struct grub_script_argv r = { 0, 0, 0 }; for (i = 0; i < argc; i++) - if (grub_script_argv_next (&r) || grub_script_argv_append (&r, args[i])) + if (grub_script_argv_next (&r) + || grub_script_argv_append (&r, args[i], grub_strlen (args[i]))) { grub_script_argv_free (&r); return 1; @@ -99,23 +100,23 @@ grub_script_argv_next (struct grub_script_argv *argv) /* Append `s' to the last argument. */ int -grub_script_argv_append (struct grub_script_argv *argv, const char *s) +grub_script_argv_append (struct grub_script_argv *argv, const char *s, + grub_size_t slen) { - int a; - int b; + grub_size_t a; char *p = argv->args[argv->argc - 1]; if (! s) return 0; a = p ? grub_strlen (p) : 0; - b = grub_strlen (s); - p = grub_realloc (p, round_up_exp ((a + b + 1) * sizeof (char))); + p = grub_realloc (p, round_up_exp ((a + slen + 1) * sizeof (char))); if (! p) return 1; - grub_strcpy (p + a, s); + grub_memcpy (p + a, s, slen); + p[a+slen] = 0; argv->args[argv->argc - 1] = p; return 0; @@ -123,10 +124,9 @@ grub_script_argv_append (struct grub_script_argv *argv, const char *s) /* Split `s' and append words as multiple arguments. */ int -grub_script_argv_split_append (struct grub_script_argv *argv, char *s) +grub_script_argv_split_append (struct grub_script_argv *argv, const char *s) { - char ch; - char *p; + const char *p; int errors = 0; if (! s) @@ -138,10 +138,7 @@ grub_script_argv_split_append (struct grub_script_argv *argv, char *s) while (*s && ! grub_isspace (*s)) s++; - ch = *s; - *s = '\0'; - errors += grub_script_argv_append (argv, p); - *s = ch; + errors += grub_script_argv_append (argv, p, s - p); while (*s && grub_isspace (*s)) s++; diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index 72d199760..1fb5de6a3 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -193,7 +193,7 @@ grub_script_env_get (const char *name, grub_script_arg_type_t type) if (! grub_env_special (name)) { - char *v = grub_env_get (name); + const char *v = grub_env_get (name); if (v && v[0]) { if (type == GRUB_SCRIPT_ARG_TYPE_VAR) @@ -202,20 +202,20 @@ grub_script_env_get (const char *name, grub_script_arg_type_t type) goto fail; } else - if (grub_script_argv_append (&result, v)) + if (grub_script_argv_append (&result, v, grub_strlen (v))) goto fail; } } else if (! scope) { - if (grub_script_argv_append (&result, 0)) + if (grub_script_argv_append (&result, 0, 0)) goto fail; } else if (grub_strcmp (name, "#") == 0) { char buffer[ERRNO_DIGITS_MAX + 1]; grub_snprintf (buffer, sizeof (buffer), "%u", scope->argv.argc); - if (grub_script_argv_append (&result, buffer)) + if (grub_script_argv_append (&result, buffer, grub_strlen (buffer))) goto fail; } else if (grub_strcmp (name, "*") == 0) @@ -231,10 +231,11 @@ grub_script_env_get (const char *name, grub_script_arg_type_t type) } else { - if (i != 0 && grub_script_argv_append (&result, " ")) + if (i != 0 && grub_script_argv_append (&result, " ", 1)) goto fail; - if (grub_script_argv_append (&result, scope->argv.args[i])) + if (grub_script_argv_append (&result, scope->argv.args[i], + grub_strlen (scope->argv.args[i]))) goto fail; } } @@ -251,7 +252,8 @@ grub_script_env_get (const char *name, grub_script_arg_type_t type) goto fail; } else - if (grub_script_argv_append (&result, scope->argv.args[i])) + if (grub_script_argv_append (&result, scope->argv.args[i], + grub_strlen (scope->argv.args[i]))) goto fail; } } @@ -270,7 +272,9 @@ grub_script_env_get (const char *name, grub_script_arg_type_t type) goto fail; } else - if (grub_script_argv_append (&result, scope->argv.args[num - 1])) + if (grub_script_argv_append (&result, scope->argv.args[num - 1], + grub_strlen (scope->argv.args[num - 1]) + )) goto fail; } } @@ -309,7 +313,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, char *p = 0; if (! grub_wildcard_translator || escape_type == 0) - return grub_script_argv_append (&result, s); + return grub_script_argv_append (&result, s, grub_strlen (s)); if (escape_type > 0) p = grub_wildcard_translator->escape (s); @@ -319,7 +323,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, if (! p) return 1; - r = grub_script_argv_append (&result, p); + r = grub_script_argv_append (&result, p, grub_strlen (p)); grub_free (p); return r; } @@ -344,7 +348,8 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, if (arg->type == GRUB_SCRIPT_ARG_TYPE_VAR) { - if (grub_script_argv_append (&result, values[i])) + if (grub_script_argv_append (&result, values[i], + grub_strlen (values[i]))) goto fail; } else @@ -359,16 +364,18 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, break; case GRUB_SCRIPT_ARG_TYPE_BLOCK: - if (grub_script_argv_append (&result, "{") || - grub_script_argv_append (&result, arg->str) || - grub_script_argv_append (&result, "}")) + if (grub_script_argv_append (&result, "{", 1) + || grub_script_argv_append (&result, arg->str, + grub_strlen (arg->str)) + || grub_script_argv_append (&result, "}", 1)) goto fail; result.script = arg->script; break; case GRUB_SCRIPT_ARG_TYPE_TEXT: if (grub_strlen (arg->str) && - grub_script_argv_append (&result, arg->str)) + grub_script_argv_append (&result, arg->str, + grub_strlen (arg->str))) goto fail; break; @@ -680,7 +687,7 @@ grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd) { int ret; - char *result; + const char *result; struct grub_script_cmdif *cmdif = (struct grub_script_cmdif *) cmd; /* Check if the commands results in a true or a false. The value is diff --git a/include/grub/datetime.h b/include/grub/datetime.h index 049dbc227..a7154fa1a 100644 --- a/include/grub/datetime.h +++ b/include/grub/datetime.h @@ -46,7 +46,7 @@ grub_err_t grub_set_datetime (struct grub_datetime *datetime); #endif int grub_get_weekday (struct grub_datetime *datetime); -char *grub_get_weekday_name (struct grub_datetime *datetime); +const char *grub_get_weekday_name (struct grub_datetime *datetime); void grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime); diff --git a/include/grub/env.h b/include/grub/env.h index c0107f16a..1ef11ecad 100644 --- a/include/grub/env.h +++ b/include/grub/env.h @@ -26,8 +26,8 @@ struct grub_env_var; -typedef char *(*grub_env_read_hook_t) (struct grub_env_var *var, - const char *val); +typedef const char *(*grub_env_read_hook_t) (struct grub_env_var *var, + const char *val); typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var, const char *val); @@ -43,7 +43,7 @@ struct grub_env_var }; grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char *val); -char *EXPORT_FUNC(grub_env_get) (const char *name); +const char *EXPORT_FUNC(grub_env_get) (const char *name); void EXPORT_FUNC(grub_env_unset) (const char *name); void EXPORT_FUNC(grub_env_iterate) (int (*func) (struct grub_env_var *var)); struct grub_env_var *EXPORT_FUNC(grub_env_find) (const char *name); diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index 6d31fca5a..fdccaca8d 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -245,8 +245,9 @@ void grub_script_mem_free (struct grub_script_mem *mem); void grub_script_argv_free (struct grub_script_argv *argv); int grub_script_argv_make (struct grub_script_argv *argv, int argc, char **args); int grub_script_argv_next (struct grub_script_argv *argv); -int grub_script_argv_append (struct grub_script_argv *argv, const char *s); -int grub_script_argv_split_append (struct grub_script_argv *argv, char *s); +int grub_script_argv_append (struct grub_script_argv *argv, const char *s, + grub_size_t slen); +int grub_script_argv_split_append (struct grub_script_argv *argv, const char *s); struct grub_script_arglist * grub_script_create_arglist (struct grub_parser_param *state); From c1860f878be376b2778dc0590a94f8f8494a7c87 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 20:45:31 +0100 Subject: [PATCH 537/673] * grub-core/kern/misc.c (grub_vprintf): Add missing va_end. (grub_xvasprintf): Likewise. --- ChangeLog | 5 +++++ grub-core/kern/misc.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index f98fd8e75..bdab31591 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vprintf): Add missing va_end. + (grub_xvasprintf): Likewise. + 2011-11-11 Vladimir Serbinenko Add const keyword to grub_env_get and gettextize week days. diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 34c9b3b0c..8dd7f453f 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -216,6 +216,8 @@ grub_vprintf (const char *fmt, va_list args) s = grub_vsnprintf_real (curbuf, s, fmt, ap2); } + va_end (ap2); + grub_xputs (curbuf); if (curbuf != buf) @@ -911,6 +913,9 @@ grub_xvasprintf (const char *fmt, va_list ap) return NULL; s = grub_vsnprintf_real (ret, as, fmt, ap2); + + va_end (ap2); + if (s <= as) return ret; From 5b289bc5f6b48bdfb12a9a78779b4fef66d91d6e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 20:52:41 +0100 Subject: [PATCH 538/673] * util/grub-macho2img.c: Add comment concerning gettext. * grub-core/lib/legacy_parse.c: Likewise. --- ChangeLog | 5 +++++ grub-core/lib/legacy_parse.c | 3 +++ util/grub-macho2img.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index bdab31591..aaec2066b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * util/grub-macho2img.c: Add comment concerning gettext. + * grub-core/lib/legacy_parse.c: Likewise. + 2011-11-11 Vladimir Serbinenko * grub-core/kern/misc.c (grub_vprintf): Add missing va_end. diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 659fa7061..43fca51dc 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -58,6 +58,9 @@ struct legacy_command const char *longdesc; }; +/* Help texts are kept here mostly for reference. They are never shown. So + no need to gettextize. + */ static struct legacy_command legacy_commands[] = { {"blocklist", "blocklist '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", diff --git a/util/grub-macho2img.c b/util/grub-macho2img.c index bce0a06d1..6dfb5fcbe 100644 --- a/util/grub-macho2img.c +++ b/util/grub-macho2img.c @@ -25,6 +25,8 @@ #include #include +/* Please don't internationalise this file. It's pointless. */ + /* XXX: this file assumes particular Mach-O layout and does no checks. */ /* However as build system ensures correct usage of this tool this shouldn't be a problem. */ From df067ad13af3c5722a0d7370d429415342d446a0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 20:59:25 +0100 Subject: [PATCH 539/673] * grub-core/efiemu/mm.c (grub_efiemu_mmap_fill): Change printf into dprintf. * grub-core/font/font.c (grub_font_load): Likewise. --- ChangeLog | 6 ++++++ grub-core/efiemu/mm.c | 3 ++- grub-core/font/font.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index aaec2066b..e645709ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/efiemu/mm.c (grub_efiemu_mmap_fill): Change printf into + dprintf. + * grub-core/font/font.c (grub_font_load): Likewise. + 2011-11-11 Vladimir Serbinenko * util/grub-macho2img.c: Add comment concerning gettext. diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index 3c1dc2946..7bb7cc080 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -404,7 +404,8 @@ grub_efiemu_mmap_fill (void) GRUB_EFI_ACPI_MEMORY_NVS); default: - grub_printf ("Unknown memory type %d. Assuming unusable\n", type); + grub_dprintf ("efiemu", + "Unknown memory type %d. Assuming unusable\n", type); case GRUB_MEMORY_RESERVED: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_UNUSABLE_MEMORY); diff --git a/grub-core/font/font.c b/grub-core/font/font.c index 26eac4c05..3737480cf 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -608,7 +608,7 @@ grub_font_load (const char *filename) if (!font->name) { - grub_printf ("Note: Font has no name.\n"); + grub_dprintf ("font", "Font has no name.\n"); font->name = grub_strdup ("Unknown"); } From c76b54176213bb705badc31a434ec0229a45751e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 21:03:49 +0100 Subject: [PATCH 540/673] * grub-core/hook/datehook.c (grub_read_hook_datetime): Small stylistic fix. --- ChangeLog | 5 +++++ grub-core/hook/datehook.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e645709ef..be33b7660 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/hook/datehook.c (grub_read_hook_datetime): Small stylistic + fix. + 2011-11-11 Vladimir Serbinenko * grub-core/efiemu/mm.c (grub_efiemu_mmap_fill): Change printf into diff --git a/grub-core/hook/datehook.c b/grub-core/hook/datehook.c index d7ceb85c8..ac75908ef 100644 --- a/grub-core/hook/datehook.c +++ b/grub-core/hook/datehook.c @@ -50,7 +50,7 @@ grub_read_hook_datetime (struct grub_env_var *var, int i; for (i = 0; i < 7; i++) - if (! grub_strcmp (var->name, grub_datetime_names[i])) + if (grub_strcmp (var->name, grub_datetime_names[i]) == 0) { int n; From 12d4f965cddb0625d2c6ada654463adefdef8bce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 21:14:41 +0100 Subject: [PATCH 541/673] Support %1$d syntax. * tests/printf_unit_test.c: New file. * Makefile.util.def (printf_test): New test. * grub-core/kern/misc.c (grub_vsnprintf_real): Support %1$d syntax. --- Makefile.util.def | 15 ++ grub-core/kern/misc.c | 484 ++++++++++++++++++++++++++------------- tests/printf_unit_test.c | 43 ++++ 3 files changed, 378 insertions(+), 164 deletions(-) create mode 100644 tests/printf_unit_test.c diff --git a/Makefile.util.def b/Makefile.util.def index 8742d1583..89e614468 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -660,6 +660,21 @@ program = { ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; +program = { + testcase; + name = printf_test; + common = tests/printf_unit_test.c; + common = tests/lib/unit_test.c; + common = grub-core/kern/list.c; + common = grub-core/kern/misc.c; + common = grub-core/tests/lib/test.c; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/gnulib/libgnu.a; + ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + program = { name = grub-menulst2cfg; mansection = 1; diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 8dd7f453f..128139dc8 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -637,10 +637,13 @@ grub_lltoa (char *str, int c, unsigned long long n) } static int -grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list args) +grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list args_in) { char c; + grub_size_t n = 0; grub_size_t count = 0; + grub_size_t count_args = 0; + const char *fmt; auto void write_char (unsigned char ch); auto void write_str (const char *s); auto void write_fill (const char ch, int n); @@ -659,209 +662,362 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list ar write_char (*s++); } - void write_fill (const char ch, int n) + void write_fill (const char ch, int count_fill) { int i; - for (i = 0; i < n; i++) + for (i = 0; i < count_fill; i++) write_char (ch); } + fmt = fmt0; while ((c = *fmt++) != 0) { if (c != '%') - write_char (c); - else + continue; + + if (*fmt && *fmt =='-') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + + if (*fmt && *fmt == '$') + fmt++; + + if (*fmt && *fmt =='-') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + + if (*fmt && *fmt =='.') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + + c = *fmt++; + if (c == 'l') { - char tmp[32]; - char *p; - unsigned int format1 = 0; - unsigned int format2 = ~ 0U; - char zerofill = ' '; - int rightfill = 0; - int n; - int longfmt = 0; - int longlongfmt = 0; - int unsig = 0; + c = *fmt++; + if (c == 'l') + c = *fmt++; + } + switch (c) + { + case 'p': + case 'x': + case 'u': + case 'd': + case 'c': + case 'C': + case 's': + count_args++; + break; + } + } - if (*fmt && *fmt =='-') + enum { INT, WCHAR, LONG, LONGLONG, POINTER } types[count_args]; + union + { + int i; + grub_uint32_t w; + long l; + long long ll; + void *p; + } args[count_args]; + + grub_memset (types, 0, sizeof (types)); + + fmt = fmt0; + n = 0; + while ((c = *fmt++) != 0) + { + int longfmt = 0; + int longlongfmt = 0; + grub_size_t curn; + const char *p; + + if (c != '%') + continue; + + curn = n++; + + if (*fmt && *fmt =='-') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + + p = fmt; + + if (*fmt && *fmt == '$') + { + curn = grub_strtoull (p, 0, 10) - 1; + fmt++; + } + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + + c = *fmt++; + if (c == 'l') + { + c = *fmt++; + longfmt = 1; + if (c == 'l') { - rightfill = 1; - fmt++; + c = *fmt++; + longlongfmt = 1; } + } + if (curn >= count_args) + continue; + switch (c) + { + case 'x': + case 'u': + case 'd': + if (longlongfmt) + types[curn] = LONGLONG; + else if (longfmt) + types[curn] = LONG; + else + types[curn] = INT; + break; + case 'p': + case 's': + types[curn] = POINTER; + break; + case 'c': + types[curn] = INT; + break; + case 'C': + types[curn] = WCHAR; + break; + } + } - p = (char *) fmt; - /* Read formatting parameters. */ + for (n = 0; n < count_args; n++) + switch (types[n]) + { + case WCHAR: + args[n].w = va_arg (args_in, grub_uint32_t); + break; + case POINTER: + args[n].p = va_arg (args_in, void *); + break; + case INT: + args[n].i = va_arg (args_in, int); + break; + case LONG: + args[n].l = va_arg (args_in, long); + break; + case LONGLONG: + args[n].ll = va_arg (args_in, long long); + break; + } + + fmt = fmt0; + + n = 0; + while ((c = *fmt++) != 0) + { + char tmp[32]; + char *p; + unsigned int format1 = 0; + unsigned int format2 = ~ 0U; + char zerofill = ' '; + int rightfill = 0; + int longfmt = 0; + int longlongfmt = 0; + int unsig = 0; + grub_size_t curn; + + if (c != '%') + { + write_char (c); + continue; + } + + curn = n++; + + rescan:; + + if (*fmt && *fmt =='-') + { + rightfill = 1; + fmt++; + } + + p = (char *) fmt; + /* Read formatting parameters. */ + while (*p && grub_isdigit (*p)) + p++; + + if (p > fmt) + { + char s[p - fmt + 1]; + grub_strncpy (s, fmt, p - fmt); + s[p - fmt] = 0; + if (s[0] == '0') + zerofill = '0'; + format1 = grub_strtoul (s, 0, 10); + fmt = p; + } + + if (*p && *p == '.') + { + p++; + fmt++; while (*p && grub_isdigit (*p)) p++; if (p > fmt) { - char s[p - fmt + 1]; - grub_strncpy (s, fmt, p - fmt); - s[p - fmt] = 0; - if (s[0] == '0') - zerofill = '0'; - format1 = grub_strtoul (s, 0, 10); + char fstr[p - fmt + 1]; + grub_strncpy (fstr, fmt, p - fmt); + fstr[p - fmt] = 0; + format2 = grub_strtoul (fstr, 0, 10); fmt = p; } + } + if (*fmt == '$') + { + curn = format1 - 1; + fmt++; + format1 = 0; + format2 = ~ 0U; + zerofill = ' '; + rightfill = 0; - if (*p && *p == '.') - { - p++; - fmt++; - while (*p && grub_isdigit (*p)) - p++; - - if (p > fmt) - { - char fstr[p - fmt + 1]; - grub_strncpy (fstr, fmt, p - fmt); - fstr[p - fmt] = 0; - format2 = grub_strtoul (fstr, 0, 10); - fmt = p; - } - } + goto rescan; + } + c = *fmt++; + if (c == 'l') + { + longfmt = 1; c = *fmt++; if (c == 'l') { - longfmt = 1; + longlongfmt = 1; c = *fmt++; - if (c == 'l') - { - longlongfmt = 1; - c = *fmt++; - } } + } - switch (c) - { - case 'p': - write_str ("0x"); - c = 'x'; - longlongfmt |= (sizeof (void *) == sizeof (long long)); - /* Fall through. */ - case 'x': - case 'u': - unsig = 1; - /* Fall through. */ - case 'd': - if (longlongfmt) - { - long long ll; + if (curn >= count_args) + continue; - ll = va_arg (args, long long); - grub_lltoa (tmp, c, ll); - } - else if (longfmt && unsig) - { - unsigned long l = va_arg (args, unsigned long); - grub_lltoa (tmp, c, l); - } - else if (longfmt) - { - long l = va_arg (args, long); - grub_lltoa (tmp, c, l); - } - else if (unsig) - { - unsigned u = va_arg (args, unsigned); - grub_lltoa (tmp, c, u); - } - else - { - n = va_arg (args, int); - grub_lltoa (tmp, c, n); - } - if (! rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); - write_str (tmp); - if (rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); - break; + switch (c) + { + case 'p': + write_str ("0x"); + c = 'x'; + longlongfmt |= (sizeof (void *) == sizeof (long long)); + /* Fall through. */ + case 'x': + case 'u': + unsig = 1; + /* Fall through. */ + case 'd': + if (longlongfmt) + grub_lltoa (tmp, c, args[curn].ll); + else if (longfmt && unsig) + grub_lltoa (tmp, c, (unsigned long) args[curn].l); + else if (longfmt) + grub_lltoa (tmp, c, args[curn].l); + else if (unsig) + grub_lltoa (tmp, c, (unsigned) args[curn].i); + else + grub_lltoa (tmp, c, args[curn].i); + if (! rightfill && grub_strlen (tmp) < format1) + write_fill (zerofill, format1 - grub_strlen (tmp)); + write_str (tmp); + if (rightfill && grub_strlen (tmp) < format1) + write_fill (zerofill, format1 - grub_strlen (tmp)); + break; - case 'c': - n = va_arg (args, int); - write_char (n & 0xff); - break; + case 'c': + write_char (args[curn].i & 0xff); + break; - case 'C': + case 'C': + { + grub_uint32_t code = args[curn].w; + int shift; + unsigned mask; + + if (code <= 0x7f) { - grub_uint32_t code = va_arg (args, grub_uint32_t); - int shift; - unsigned mask; - - if (code <= 0x7f) - { - shift = 0; - mask = 0; - } - else if (code <= 0x7ff) - { - shift = 6; - mask = 0xc0; - } - else if (code <= 0xffff) - { - shift = 12; - mask = 0xe0; - } - else if (code <= 0x1fffff) - { - shift = 18; - mask = 0xf0; - } - else if (code <= 0x3ffffff) - { - shift = 24; - mask = 0xf8; - } - else if (code <= 0x7fffffff) - { - shift = 30; - mask = 0xfc; - } - else - { - code = '?'; - shift = 0; - mask = 0; - } - - write_char (mask | (code >> shift)); - - for (shift -= 6; shift >= 0; shift -= 6) - write_char (0x80 | (0x3f & (code >> shift))); + shift = 0; + mask = 0; + } + else if (code <= 0x7ff) + { + shift = 6; + mask = 0xc0; + } + else if (code <= 0xffff) + { + shift = 12; + mask = 0xe0; + } + else if (code <= 0x1fffff) + { + shift = 18; + mask = 0xf0; + } + else if (code <= 0x3ffffff) + { + shift = 24; + mask = 0xf8; + } + else if (code <= 0x7fffffff) + { + shift = 30; + mask = 0xfc; + } + else + { + code = '?'; + shift = 0; + mask = 0; } - break; - case 's': - p = va_arg (args, char *); - if (p) - { - grub_size_t len = 0; - while (len < format2 && p[len]) - len++; + write_char (mask | (code >> shift)); - if (!rightfill && len < format1) - write_fill (zerofill, format1 - len); + for (shift -= 6; shift >= 0; shift -= 6) + write_char (0x80 | (0x3f & (code >> shift))); + } + break; - grub_size_t i; - for (i = 0; i < len; i++) - write_char (*p++); + case 's': + p = args[curn].p; + if (p) + { + grub_size_t len = 0; + while (len < format2 && p[len]) + len++; - if (rightfill && len < format1) - write_fill (zerofill, format1 - len); - } - else - write_str ("(null)"); + if (!rightfill && len < format1) + write_fill (zerofill, format1 - len); - break; + grub_size_t i; + for (i = 0; i < len; i++) + write_char (*p++); - default: - write_char (c); - break; + if (rightfill && len < format1) + write_fill (zerofill, format1 - len); } + else + write_str ("(null)"); + + break; + + default: + write_char (c); + break; } } diff --git a/tests/printf_unit_test.c b/tests/printf_unit_test.c new file mode 100644 index 000000000..6e601b401 --- /dev/null +++ b/tests/printf_unit_test.c @@ -0,0 +1,43 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 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 . + */ + +#include +#include +#include +#include + +static void +printf_test (void) +{ + char real[512]; + char expected[512]; + grub_snprintf (real, sizeof (real), "%d %d %d", 1, 2, 3); + snprintf (expected, sizeof (expected), "%d %d %d", 1, 2, 3); + grub_test_assert (strcmp (real, expected) == 0); + grub_snprintf (real, sizeof (real), "%3$d %2$d %1$d", 1, 2, 3); + snprintf (expected, sizeof (expected), "%3$d %2$d %1$d", 1, 2, 3); + grub_test_assert (strcmp (real, expected) == 0); + grub_snprintf (real, sizeof (real), "%d %lld %d", 1, 2LL, 3); + snprintf (expected, sizeof (expected), "%d %lld %d", 1, 2LL, 3); + grub_test_assert (strcmp (real, expected) == 0); + grub_snprintf (real, sizeof (real), "%3$d %2$lld %1$d", 1, 2LL, 3); + snprintf (expected, sizeof (expected), "%3$d %2$lld %1$d", 1, 2LL, 3); + grub_test_assert (strcmp (real, expected) == 0); +} + +GRUB_UNIT_TEST ("printf_unit_test", printf_test); From 073aa7a9bf07d988b6337850f48599901089b9d7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 21:22:02 +0100 Subject: [PATCH 542/673] Forgotten ChangeLog entry --- ChangeLog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index be33b7660..725415cd0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-11-11 Vladimir Serbinenko + + Support %1$d syntax. + + * tests/printf_unit_test.c: New file. + * Makefile.util.def (printf_test): New test. + * grub-core/kern/misc.c (grub_vsnprintf_real): Support %1$d syntax. + 2011-11-11 Vladimir Serbinenko * grub-core/hook/datehook.c (grub_read_hook_datetime): Small stylistic From 6e0632e28cd692faae2b026bb987e69906d6326a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 21:44:56 +0100 Subject: [PATCH 543/673] * grub-core/commands/acpihalt.c: Gettextized. * grub-core/commands/cacheinfo.c: Likewise. * grub-core/commands/cmp.c: Likewise. * grub-core/commands/efi/loadbios.c: Likewise. * grub-core/commands/gptsync.c: Likewise. * grub-core/commands/ieee1275/suspend.c: Likewise. * grub-core/commands/legacycfg.c: Likewise. * grub-core/commands/memrw.c: Likewise. * grub-core/commands/minicmd.c: Likewise. * grub-core/commands/parttool.c: Likewise. * grub-core/commands/time.c: Likewise. * grub-core/commands/videoinfo.c: Likewise. * grub-core/disk/geli.c: Likewise. * grub-core/disk/i386/pc/biosdisk.c: Likewise. * grub-core/disk/luks.c: Likewise. * grub-core/disk/lvm.c: Likewise. * grub-core/font/font_cmd.c: Likewise. * grub-core/fs/zfs/zfscrypt.c: Likewise. * grub-core/fs/zfs/zfsinfo.c: Likewise. * grub-core/gfxmenu/view.c: Likewise. * grub-core/kern/emu/hostdisk.c: Likewise. * grub-core/kern/emu/main.c: Likewise. * grub-core/kern/emu/misc.c: Likewise. * grub-core/kern/emu/mm.c: Likewise. * grub-core/kern/mips/arc/init.c: Likewise. * grub-core/kern/mips/loongson/init.c: Likewise. * grub-core/kern/partition.c: Likewise. * grub-core/lib/i386/halt.c: Likewise. * grub-core/lib/mips/arc/reboot.c: Likewise. * grub-core/lib/mips/loongson/reboot.c: Likewise. * grub-core/loader/i386/pc/chainloader.c: Likewise. * grub-core/loader/i386/xnu.c: Likewise. * grub-core/loader/multiboot.c: Likewise. * grub-core/net/bootp.c: Likewise. * grub-core/net/net.c: Likewise. * grub-core/normal/term.c: Likewise. * grub-core/partmap/bsdlabel.c: Likewise. * grub-core/parttool/msdospart.c: Likewise. * grub-core/term/gfxterm.c: Likewise. * grub-core/term/terminfo.c: Likewise. * grub-core/video/i386/pc/vbe.c: Likewise. * util/grub-menulst2cfg.c: Likewise. * util/grub-mkdevicemap.c: Likewise. * util/grub-mklayout.c: Likewise. * util/grub-mkrelpath.c: Likewise. * util/grub-script-check.c: Likewise. * util/ieee1275/grub-ofpathname.c: Likewise. * util/resolve.c: Likewise. --- ChangeLog | 51 ++++++++++++++++ grub-core/commands/acpihalt.c | 3 +- grub-core/commands/cacheinfo.c | 4 +- grub-core/commands/cmp.c | 19 +++--- grub-core/commands/efi/loadbios.c | 6 +- grub-core/commands/gptsync.c | 2 +- grub-core/commands/ieee1275/suspend.c | 2 +- grub-core/commands/legacycfg.c | 2 +- grub-core/commands/memrw.c | 2 +- grub-core/commands/minicmd.c | 2 +- grub-core/commands/parttool.c | 14 ++--- grub-core/commands/time.c | 4 +- grub-core/commands/videoinfo.c | 65 ++++++++++---------- grub-core/disk/geli.c | 14 ++--- grub-core/disk/i386/pc/biosdisk.c | 3 +- grub-core/disk/luks.c | 6 +- grub-core/disk/lvm.c | 3 +- grub-core/font/font_cmd.c | 2 +- grub-core/fs/zfs/zfscrypt.c | 6 +- grub-core/fs/zfs/zfsinfo.c | 83 +++++++++++++------------- grub-core/gfxmenu/view.c | 3 +- grub-core/kern/emu/hostdisk.c | 20 +++---- grub-core/kern/emu/main.c | 10 ++-- grub-core/kern/emu/misc.c | 6 +- grub-core/kern/emu/mm.c | 2 +- grub-core/kern/mips/arc/init.c | 5 +- grub-core/kern/mips/loongson/init.c | 3 +- grub-core/kern/partition.c | 3 +- grub-core/lib/i386/halt.c | 3 +- grub-core/lib/mips/arc/reboot.c | 3 +- grub-core/lib/mips/loongson/reboot.c | 3 +- grub-core/loader/i386/pc/chainloader.c | 2 +- grub-core/loader/i386/xnu.c | 2 +- grub-core/loader/multiboot.c | 2 +- grub-core/net/bootp.c | 4 +- grub-core/net/net.c | 8 +-- grub-core/normal/term.c | 5 +- grub-core/partmap/bsdlabel.c | 3 +- grub-core/parttool/msdospart.c | 13 ++-- grub-core/term/gfxterm.c | 5 +- grub-core/term/terminfo.c | 2 +- grub-core/video/i386/pc/vbe.c | 17 +++--- util/grub-menulst2cfg.c | 7 ++- util/grub-mkdevicemap.c | 8 +-- util/grub-mklayout.c | 16 ++--- util/grub-mkrelpath.c | 10 ++-- util/grub-script-check.c | 10 ++-- util/ieee1275/grub-ofpathname.c | 2 +- util/resolve.c | 5 +- 49 files changed, 275 insertions(+), 200 deletions(-) diff --git a/ChangeLog b/ChangeLog index 725415cd0..c3c0cfe61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/commands/acpihalt.c: Gettextized. + * grub-core/commands/cacheinfo.c: Likewise. + * grub-core/commands/cmp.c: Likewise. + * grub-core/commands/efi/loadbios.c: Likewise. + * grub-core/commands/gptsync.c: Likewise. + * grub-core/commands/ieee1275/suspend.c: Likewise. + * grub-core/commands/legacycfg.c: Likewise. + * grub-core/commands/memrw.c: Likewise. + * grub-core/commands/minicmd.c: Likewise. + * grub-core/commands/parttool.c: Likewise. + * grub-core/commands/time.c: Likewise. + * grub-core/commands/videoinfo.c: Likewise. + * grub-core/disk/geli.c: Likewise. + * grub-core/disk/i386/pc/biosdisk.c: Likewise. + * grub-core/disk/luks.c: Likewise. + * grub-core/disk/lvm.c: Likewise. + * grub-core/font/font_cmd.c: Likewise. + * grub-core/fs/zfs/zfscrypt.c: Likewise. + * grub-core/fs/zfs/zfsinfo.c: Likewise. + * grub-core/gfxmenu/view.c: Likewise. + * grub-core/kern/emu/hostdisk.c: Likewise. + * grub-core/kern/emu/main.c: Likewise. + * grub-core/kern/emu/misc.c: Likewise. + * grub-core/kern/emu/mm.c: Likewise. + * grub-core/kern/mips/arc/init.c: Likewise. + * grub-core/kern/mips/loongson/init.c: Likewise. + * grub-core/kern/partition.c: Likewise. + * grub-core/lib/i386/halt.c: Likewise. + * grub-core/lib/mips/arc/reboot.c: Likewise. + * grub-core/lib/mips/loongson/reboot.c: Likewise. + * grub-core/loader/i386/pc/chainloader.c: Likewise. + * grub-core/loader/i386/xnu.c: Likewise. + * grub-core/loader/multiboot.c: Likewise. + * grub-core/net/bootp.c: Likewise. + * grub-core/net/net.c: Likewise. + * grub-core/normal/term.c: Likewise. + * grub-core/partmap/bsdlabel.c: Likewise. + * grub-core/parttool/msdospart.c: Likewise. + * grub-core/term/gfxterm.c: Likewise. + * grub-core/term/terminfo.c: Likewise. + * grub-core/video/i386/pc/vbe.c: Likewise. + * util/grub-menulst2cfg.c: Likewise. + * util/grub-mkdevicemap.c: Likewise. + * util/grub-mklayout.c: Likewise. + * util/grub-mkrelpath.c: Likewise. + * util/grub-script-check.c: Likewise. + * util/ieee1275/grub-ofpathname.c: Likewise. + * util/resolve.c: Likewise. + 2011-11-11 Vladimir Serbinenko Support %1$d syntax. diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c index 9a4cda521..177ec15f0 100644 --- a/grub-core/commands/acpihalt.c +++ b/grub-core/commands/acpihalt.c @@ -33,6 +33,7 @@ typedef uint8_t grub_uint8_t; #endif #include +#include #ifndef GRUB_DSDT_TEST #include @@ -327,6 +328,6 @@ grub_acpi_halt (void) grub_millisleep (1500); - grub_printf ("ACPI shutdown failed\n"); + grub_puts_ (N_("ACPI shutdown failed")); } #endif diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c index 771763c9c..92aaa218d 100644 --- a/grub-core/commands/cacheinfo.c +++ b/grub-core/commands/cacheinfo.c @@ -31,14 +31,14 @@ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)), unsigned long hits, misses; grub_disk_cache_get_performance (&hits, &misses); - grub_printf ("Disk cache: hits = %lu, misses = %lu ", hits, misses); + grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses); if (hits + misses) { unsigned long ratio = hits * 10000 / (hits + misses); grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100); } else - grub_printf ("(N/A)\n"); + grub_puts_ (N_("(N/A)")); return 0; } diff --git a/grub-core/commands/cmp.c b/grub-core/commands/cmp.c index 526459311..5d5925dd5 100644 --- a/grub-core/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -42,8 +42,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), if (argc != 2) return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required"); - grub_printf ("Compare file `%s' with `%s':\n", args[0], - args[1]); + grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], + args[1]); file1 = grub_file_open (args[0]); file2 = grub_file_open (args[1]); @@ -51,9 +51,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), goto cleanup; if (grub_file_size (file1) != grub_file_size (file2)) - grub_printf ("Files differ in size: %llu [%s], %llu [%s]\n", - (unsigned long long) grub_file_size (file1), args[0], - (unsigned long long) grub_file_size (file2), args[1]); + grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"), + (unsigned long long) grub_file_size (file1), args[0], + (unsigned long long) grub_file_size (file2), args[1]); else { pos = 0; @@ -78,9 +78,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), { if (buf1[i] != buf2[i]) { - grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n", - (unsigned long long) (i + pos), buf1[i], args[0], - buf2[i], args[1]); + grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"), + (unsigned long long) (i + pos), buf1[i], + args[0], buf2[i], args[1]); goto cleanup; } } @@ -89,7 +89,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), } while (rd2); - grub_printf ("The files are identical.\n"); + /* TRANSLATORS: it's always exactly 2 files. */ + grub_printf_ (N_("The files are identical.\n")); } cleanup: diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c index 138311222..5eb490fd4 100644 --- a/grub-core/commands/efi/loadbios.c +++ b/grub-core/commands/efi/loadbios.c @@ -49,7 +49,7 @@ enable_rom_area (void) rom_ptr = (grub_uint32_t *) VBIOS_ADDR; if (*rom_ptr != BLANK_MEM) { - grub_printf ("ROM image is present.\n"); + grub_puts_ (N_("ROM image is present.")); return 0; } @@ -67,7 +67,7 @@ enable_rom_area (void) *rom_ptr = 0; if (*rom_ptr != 0) { - grub_printf ("Can\'t enable ROM area.\n"); + grub_puts_ (N_("Can\'t enable ROM area.")); return 0; } @@ -209,7 +209,7 @@ GRUB_MOD_INIT(loadbios) 0, N_("Fake BIOS.")); cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios, - "BIOS_DUMP [INT10_DUMP]", + N_("BIOS_DUMP [INT10_DUMP]"), N_("Load BIOS dump.")); } diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c index e92dc20ec..88d4b6296 100644 --- a/grub-core/commands/gptsync.c +++ b/grub-core/commands/gptsync.c @@ -231,7 +231,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } - grub_printf ("New MBR is written to '%s'\n", args[0]); + grub_printf_ (N_("New MBR is written to '%s'\n"), args[0]); return GRUB_ERR_NONE; } diff --git a/grub-core/commands/ieee1275/suspend.c b/grub-core/commands/ieee1275/suspend.c index de068951d..844485077 100644 --- a/grub-core/commands/ieee1275/suspend.c +++ b/grub-core/commands/ieee1275/suspend.c @@ -31,7 +31,7 @@ grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_printf ("Run 'go' to resume GRUB.\n"); + grub_puts_ (N_("Run 'go' to resume GRUB.")); grub_ieee1275_enter (); grub_cls (); return 0; diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 4e87adafc..4de2d84d5 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -723,7 +723,7 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); - grub_printf ("Enter password:"); + grub_puts_ (N_("Enter password: ")); if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) return GRUB_ACCESS_DENIED; diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c index 3b51189d6..5984288ce 100644 --- a/grub-core/commands/memrw.c +++ b/grub-core/commands/memrw.c @@ -31,7 +31,7 @@ static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword; static const struct grub_arg_option options[] = { {0, 'v', 0, N_("Save read value into variable VARNAME."), - "VARNAME", ARG_TYPE_STRING}, + N_("VARNAME"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index b9cbd06c1..1bb0147df 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -145,7 +145,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), { grub_dl_t mod; - grub_printf ("Name\tRef Count\tDependencies\n"); + grub_printf_ (N_("Name\tRef Count\tDependencies\n")); FOR_DL_MODULES (mod) { grub_dl_dep_t dep; diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c index a54286161..ab5ab5ea4 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -37,9 +37,9 @@ static struct grub_parttool *parts = 0; static int curhandle = 0; static grub_dl_t mymod; static char helpmsg[] = - "Perform COMMANDS on partition.\n" - "Use \"parttool PARTITION help\" for the list " - "of available commands."; + N_("Perform COMMANDS on partition.\n" + "Use \"parttool PARTITION help\" for the list " + "of available commands."); int grub_parttool_register(const char *part_name, @@ -128,7 +128,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), break; case GRUB_PARTTOOL_ARG_VAL: - grub_printf ("=VAL"); + grub_xputs (_("=VAL")); spacing -= 4; break; @@ -137,18 +137,18 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), } while (spacing-- > 0) grub_printf (" "); - grub_printf ("%s\n", curarg->desc); + grub_puts_ (curarg->desc); } } if (! found) - grub_printf ("Sorry no parttool is available for %s\n", + grub_printf_ (N_("Sorry no parttool is available for %s\n"), dev->disk->partition->partmap->name); return GRUB_ERR_NONE; } if (argc < 1) { - grub_printf ("%s\n", helpmsg); + grub_puts_ (helpmsg); return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments"); } diff --git a/grub-core/commands/time.c b/grub-core/commands/time.c index 687495964..224f92b3f 100644 --- a/grub-core/commands/time.c +++ b/grub-core/commands/time.c @@ -47,8 +47,8 @@ grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)), (cmd->func) (cmd, argc - 1, &args[1]); end = grub_get_time_ms (); - grub_printf ("Elapsed time: %d.%03d seconds \n", (end - start) / 1000, - (end - start) % 1000); + grub_printf_ (N_("Elapsed time: %d.%03d seconds \n"), (end - start) / 1000, + (end - start) % 1000); return grub_errno; } diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 7ff172fd7..9e12ff55e 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -52,36 +52,36 @@ hook (const struct grub_video_mode_info *info) grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) - grub_printf ("Text-only "); + grub_xputs (_("Text-only ")); /* Show mask and position details for direct color modes. */ if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) - grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", - info->red_mask_size, - info->green_mask_size, - info->blue_mask_size, - info->reserved_mask_size, - info->red_field_pos, - info->green_field_pos, - info->blue_field_pos, - info->reserved_field_pos); + grub_printf_ (N_("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d"), + info->red_mask_size, + info->green_mask_size, + info->blue_mask_size, + info->reserved_mask_size, + info->red_field_pos, + info->green_field_pos, + info->blue_field_pos, + info->reserved_field_pos); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) - grub_printf ("Packed "); + grub_xputs (_("Packed ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) - grub_printf ("YUV "); + grub_xputs (_("YUV ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) - grub_printf ("Planar "); + grub_xputs (_("Planar ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES) - grub_printf ("Hercules "); + grub_xputs (_("Hercules ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA) - grub_printf ("CGA "); + grub_xputs (_("CGA ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4) - grub_printf ("Non-chain 4 "); + grub_xputs (_("Non-chain 4 ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) - grub_printf ("Monochrome "); + grub_xputs (_("Monochrome ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN) - grub_printf ("Unknown "); + grub_xputs (_("Unknown ")); - grub_printf ("\n"); + grub_xputs ("\n"); return 0; } @@ -93,19 +93,19 @@ print_edid (struct grub_video_edid_info *edid_info) if (grub_video_edid_checksum (edid_info)) { - grub_printf (" EDID checksum invalid\n"); + grub_puts_ (N_(" EDID checksum invalid")); grub_errno = GRUB_ERR_NONE; return; } - grub_printf (" EDID version: %u.%u\n", - edid_info->version, edid_info->revision); + grub_printf_ (N_(" EDID version: %u.%u\n"), + edid_info->version, edid_info->revision); if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height) == GRUB_ERR_NONE) - grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height); + grub_printf_ (N_(" Preferred mode: %ux%u\n"), edid_width, edid_height); else { - grub_printf (" No preferred mode available\n"); + grub_printf_ (N_(" No preferred mode available\n")); grub_errno = GRUB_ERR_NONE; } } @@ -147,20 +147,20 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), id = grub_video_get_driver_id (); - grub_printf ("List of supported video modes:\n"); - grub_printf ("Legend: P=Packed pixel, D=Direct color, " - "mask/pos=R/G/B/reserved\n"); + grub_puts_ (N_("List of supported video modes:")); + grub_puts_ (N_("Legend: P=Packed pixel, D=Direct color, " + "mask/pos=R/G/B/reserved")); FOR_VIDEO_ADAPTERS (adapter) { struct grub_video_mode_info info; struct grub_video_edid_info edid_info; - grub_printf ("Adapter '%s':\n", adapter->name); + grub_printf_ (N_("Adapter '%s':\n"), adapter->name); if (!adapter->iterate) { - grub_printf (" No info available\n"); + grub_puts_ (N_(" No info available")); continue; } @@ -178,7 +178,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), { if (adapter->init ()) { - grub_printf (" Failed\n"); + grub_puts_ (N_(" Failed")); grub_errno = GRUB_ERR_NONE; continue; } @@ -215,12 +215,13 @@ static grub_command_t cmd_vbe; GRUB_MOD_INIT(videoinfo) { - cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]", + cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, N_("[WxH[xD]]"), N_("List available video modes. If " "resolution is given show only modes" " matching it.")); #ifdef GRUB_MACHINE_PCBIOS - cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]", + cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, + N_("[WxH[xD]]"), N_("List available video modes. If " "resolution is given show only modes" " matching it.")); diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index ab94b4131..d3137bc16 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -226,7 +226,7 @@ grub_util_get_geli_uuid (const char *dev) uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1); if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0) - grub_util_error ("couldn't read ELI metadata"); + grub_util_error (_("couldn't read ELI metadata")); COMPILE_TIME_ASSERT (sizeof (header) <= 512); header = (void *) &hdr; @@ -235,7 +235,7 @@ grub_util_get_geli_uuid (const char *dev) if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) || grub_le_to_cpu32 (header->version) > 5 || grub_le_to_cpu32 (header->version) < 1) - grub_util_error ("wrong ELI magic or version"); + grub_util_error (_("wrong ELI magic or version")); err = make_uuid ((void *) &hdr, uuid); if (err) @@ -418,15 +418,15 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) keysize = grub_le_to_cpu16 (header.keylen) / 8; grub_memset (zero, 0, sizeof (zero)); - grub_printf ("Attempting to decrypt master key...\n"); + grub_puts_ (N_("Attempting to decrypt master key...")); /* Get the passphrase from the user. */ tmp = NULL; if (source->partition) tmp = grub_partition_get_name (source->partition); - grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name, - source->partition ? "," : "", tmp ? : "", - dev->uuid); + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, + source->partition ? "," : "", tmp ? : "", + dev->uuid); grub_free (tmp); if (!grub_password_get (passphrase, MAX_PASSPHRASE)) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); @@ -513,7 +513,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0) continue; - grub_printf ("Slot %d opened\n", i); + grub_printf_ (N_("Slot %d opened\n"), i); /* Set the master key. */ if (!dev->rekey) diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index e152b9d89..25f683fd1 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -27,6 +27,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -625,7 +626,7 @@ GRUB_MOD_INIT(biosdisk) if (grub_disk_firmware_is_tainted) { - grub_printf ("Firmware is marked as tainted, refusing to initialize.\n"); + grub_puts_ (N_("Firmware is marked as tainted, refusing to initialize.")); return; } grub_disk_firmware_fini = grub_disk_biosdisk_fini; diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 0ec95fccd..a5c0d3418 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -316,7 +316,7 @@ luks_recover_key (grub_disk_t source, if (err) return err; - grub_printf ("Attempting to decrypt master key...\n"); + grub_puts_ (N_("Attempting to decrypt master key...")); keysize = grub_be_to_cpu32 (header.keyBytes); for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) @@ -332,7 +332,7 @@ luks_recover_key (grub_disk_t source, tmp = NULL; if (source->partition) tmp = grub_partition_get_name (source->partition); - grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name, + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, source->partition ? "," : "", tmp ? : "", dev->uuid); grub_free (tmp); @@ -434,7 +434,7 @@ luks_recover_key (grub_disk_t source, continue; } - grub_printf ("Slot %d opened\n", i); + grub_printf_ (N_("Slot %d opened\n"), i); /* Set the master key. */ gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 4020fc427..388c7f173 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include @@ -775,7 +776,7 @@ grub_lvm_memberlist (grub_disk_t disk) for (pv = lv->vg->pvs; pv; pv = pv->next) { if (!pv->disk) - grub_util_error ("Couldn't find PV %s. Check your device.map", + grub_util_error (_("Couldn't find PV %s. Check your device.map"), pv->name); tmp = grub_malloc (sizeof (*tmp)); tmp->disk = pv->disk; diff --git a/grub-core/font/font_cmd.c b/grub-core/font/font_cmd.c index 98f0b88d6..b38eccd6d 100644 --- a/grub-core/font/font_cmd.c +++ b/grub-core/font/font_cmd.c @@ -49,7 +49,7 @@ lsfonts_command (grub_command_t cmd __attribute__ ((unused)), { struct grub_font_node *node; - grub_printf ("Loaded fonts:\n"); + grub_puts_ (N_("Loaded fonts:")); for (node = grub_font_list; node; node = node->next) { grub_font_t font = node->value; diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 619878243..63380f66a 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -421,7 +421,7 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) } else { - grub_printf ("Enter ZFS password: "); + grub_xputs (_("Enter ZFS password: ")); if (!grub_password_get ((char *) buf, 1023)) return grub_errno; real_size = grub_strlen ((char *) buf); @@ -460,8 +460,8 @@ GRUB_MOD_INIT(zfscrypt) grub_zfs_decrypt = grub_zfs_decrypt_real; grub_zfs_load_key = grub_zfs_load_key_real; cmd_key = grub_register_extcmd ("zfskey", grub_cmd_zfs_key, 0, - "zfskey [-h|-p|-r] [FILE]", - "Import ZFS wrapping key stored in FILE.", + N_("[-h|-p|-r] [FILE]"), + N_("Import ZFS wrapping key stored in FILE."), options); } diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index 8c073fab5..94f2a1ac8 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -44,32 +45,32 @@ print_state (char *nvlist, int tab) int isok = 1; print_tabs (tab); - grub_printf ("State: "); + grub_xputs (_("State: ")); if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival)) { - grub_printf ("removed "); + grub_xputs (_("removed ")); isok = 0; } if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival)) { - grub_printf ("faulted "); + grub_xputs (_("faulted ")); isok = 0; } if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival)) { - grub_printf ("offline "); + grub_xputs (_("offline ")); isok = 0; } if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival)) - grub_printf ("degraded "); + grub_xputs (_("degraded ")); if (isok) - grub_printf ("online"); - grub_printf ("\n"); + grub_xputs (_("online")); + grub_xputs ("\n"); return GRUB_ERR_NONE; } @@ -84,7 +85,7 @@ print_vdev_info (char *nvlist, int tab) if (!type) { print_tabs (tab); - grub_printf ("Incorrect VDEV: no type available\n"); + grub_puts_ (N_("Incorrect VDEV: no type available")); return grub_errno; } @@ -95,7 +96,7 @@ print_vdev_info (char *nvlist, int tab) char *devid = 0; print_tabs (tab); - grub_printf ("Leaf VDEV\n"); + grub_puts_ (N_("Leaf VDEV")); print_state (nvlist, tab); @@ -103,23 +104,23 @@ print_vdev_info (char *nvlist, int tab) grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_PHYS_PATH); print_tabs (tab); if (!bootpath) - grub_printf ("Bootpath: unavailable\n"); + grub_puts_ (N_("Bootpath: unavailable\n")); else - grub_printf ("Bootpath: %s\n", bootpath); + grub_printf_ (N_("Bootpath: %s\n"), bootpath); path = grub_zfs_nvlist_lookup_string (nvlist, "path"); print_tabs (tab); if (!path) - grub_printf ("Path: unavailable\n"); + grub_puts_ (N_("Path: unavailable")); else - grub_printf ("Path: %s\n", path); + grub_printf_ (N_("Path: %s\n"), path); devid = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_DEVID); print_tabs (tab); if (!devid) - grub_printf ("Devid: unavailable\n"); + grub_puts_ (N_("Devid: unavailable")); else - grub_printf ("Devid: %s\n", devid); + grub_printf_ (N_("Devid: %s\n"), devid); grub_free (bootpath); grub_free (devid); grub_free (path); @@ -136,10 +137,10 @@ print_vdev_info (char *nvlist, int tab) print_tabs (tab); if (nelm <= 0) { - grub_printf ("Incorrect mirror VDEV\n"); + grub_puts_ (N_("Incorrect mirror VDEV")); return GRUB_ERR_NONE; } - grub_printf ("Mirror VDEV with %d children\n", nelm); + grub_printf_ (N_("Mirror VDEV with %d children\n"), nelm); print_state (nvlist, tab); for (i = 0; i < nelm; i++) { @@ -151,11 +152,11 @@ print_vdev_info (char *nvlist, int tab) print_tabs (tab); if (!child) { - grub_printf ("Mirror VDEV element %d isn't correct\n", i); + grub_printf_ (N_("Mirror VDEV element %d isn't correct\n"), i); continue; } - grub_printf ("Mirror VDEV element %d:\n", i); + grub_printf_ (N_("Mirror VDEV element %d:\n"), i); print_vdev_info (child, tab + 1); grub_free (child); @@ -164,7 +165,7 @@ print_vdev_info (char *nvlist, int tab) } print_tabs (tab); - grub_printf ("Unknown VDEV type: %s\n", type); + grub_printf_ (N_("Unknown VDEV type: %s\n"), type); return GRUB_ERR_NONE; } @@ -221,15 +222,15 @@ get_bootpath (char *nvlist, char **bootpath, char **devid) return GRUB_ERR_NONE; } -static char *poolstates[] = { - [POOL_STATE_ACTIVE] = "active", - [POOL_STATE_EXPORTED] = "exported", - [POOL_STATE_DESTROYED] = "destroyed", - [POOL_STATE_SPARE] = "reserved for hot spare", - [POOL_STATE_L2CACHE] = "level 2 ARC device", - [POOL_STATE_UNINITIALIZED] = "uninitialized", - [POOL_STATE_UNAVAIL] = "unavailable", - [POOL_STATE_POTENTIALLY_ACTIVE] = "potentially active" +static const char *poolstates[] = { + [POOL_STATE_ACTIVE] = N_("Pool state: active"), + [POOL_STATE_EXPORTED] = N_("Pool state: exported"), + [POOL_STATE_DESTROYED] = N_("Pool state: destroyed"), + [POOL_STATE_SPARE] = N_("Pool state: reserved for hot spare"), + [POOL_STATE_L2CACHE] = N_("Pool state: level 2 ARC device"), + [POOL_STATE_UNINITIALIZED] = N_("Pool state: uninitialized"), + [POOL_STATE_UNAVAIL] = N_("Pool state: unavailable"), + [POOL_STATE_POTENTIALLY_ACTIVE] = N_("Pool state: potentially active") }; static grub_err_t @@ -274,30 +275,30 @@ grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc, poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME); if (!poolname) - grub_printf ("Pool name: unavailable\n"); + grub_puts_ (N_("Pool name: unavailable")); else - grub_printf ("Pool name: %s\n", poolname); + grub_printf_ (N_("Pool name: %s\n"), poolname); found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_GUID, &guid); if (!found) - grub_printf ("Pool GUID: unavailable\n"); + grub_puts_ (N_("Pool GUID: unavailable")); else - grub_printf ("Pool GUID: %016llx\n", (long long unsigned) guid); + grub_printf_ (N_("Pool GUID: %016llx\n"), (long long unsigned) guid); found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE, &pool_state); if (!found) - grub_printf ("Unable to retrieve pool state\n"); + grub_puts_ (N_("Unable to retrieve pool state")); else if (pool_state >= ARRAY_SIZE (poolstates)) - grub_printf ("Unrecognized pool state\n"); + grub_puts_ (N_("Unrecognized pool state")); else - grub_printf ("Pool state: %s\n", poolstates[pool_state]); + grub_puts_ (poolstates[pool_state]); nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE); if (!nv) - grub_printf ("No vdev tree available\n"); + grub_puts_ (N_("No vdev tree available")); else print_vdev_info (nv, 1); @@ -395,11 +396,11 @@ static grub_command_t cmd_info, cmd_bootfs; GRUB_MOD_INIT (zfsinfo) { cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo, - "zfsinfo DEVICE", - "Print ZFS info about DEVICE."); + N_("DEVICE"), + N_("Print ZFS info about DEVICE.")); cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs, - "zfs-bootfs FILESYSTEM [VARIABLE]", - "Print ZFS-BOOTFSOBJ or set it to VARIABLE"); + N_("FILESYSTEM [VARIABLE]"), + N_("Print ZFS-BOOTFSOBJ or set it to VARIABLE")); } GRUB_MOD_FINI (zfsinfo) diff --git a/grub-core/gfxmenu/view.c b/grub-core/gfxmenu/view.c index 836a9884d..9023fd3c4 100644 --- a/grub-core/gfxmenu/view.c +++ b/grub-core/gfxmenu/view.c @@ -36,6 +36,7 @@ #include #include #include +#include static void init_terminal (grub_gfxmenu_view_t view); @@ -77,7 +78,7 @@ grub_gfxmenu_view_new (const char *theme_path, view->desktop_image = 0; view->desktop_color = default_bg_color; view->terminal_box = grub_gfxmenu_create_box (0, 0); - view->title_text = grub_strdup ("GRUB Boot Menu"); + view->title_text = grub_strdup (_("GRUB Boot Menu")); view->progress_message_text = 0; view->theme_path = 0; diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 7bfc66fef..f537b2759 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -269,7 +269,7 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) struct stat st; if (fstat (fd, &st) < 0) - grub_util_error ("fstat failed"); + grub_util_error (_("fstat failed")); #if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) \ @@ -324,7 +324,7 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) return minfo.dki_capacity; # else if (nr & ((1 << log_sector_size) - 1)) - grub_util_error ("unaligned device size"); + grub_util_error (_("unaligned device size")); return (nr >> log_sector_size); # endif @@ -373,7 +373,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) size = grub_util_get_disk_size (map[drive].device); if (size % 512) - grub_util_error ("unaligned device size"); + grub_util_error (_("unaligned device size")); disk->total_sectors = size >> 9; @@ -442,13 +442,13 @@ grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **n error = geom_gettree (&mesh); if (error != 0) - grub_util_error ("couldn't open geom"); + grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) if (strcasecmp (class->lg_name, "part") == 0) break; if (!class) - grub_util_error ("couldn't open geom part"); + grub_util_error (_("couldn't open geom part")); LIST_FOREACH (geom, &class->lg_geom, lg_geom) { @@ -1144,18 +1144,18 @@ read_device_map (const char *dev_map) continue; if (*p != '(') - show_error ("No open parenthesis found"); + show_error (_("No open parenthesis found")); p++; /* Find a free slot. */ drive = find_free_slot (); if (drive < 0) - show_error ("Map table size exceeded"); + show_error (_("Map table size exceeded")); e = p; p = strchr (p, ')'); if (! p) - show_error ("No close parenthesis found"); + show_error (_("No close parenthesis found")); map[drive].drive = xmalloc (p - e + sizeof ('\0')); strncpy (map[drive].drive, e, p - e + sizeof ('\0')); @@ -1167,7 +1167,7 @@ read_device_map (const char *dev_map) p++; if (*p == '\0') - show_error ("No filename found"); + show_error (_("No filename found")); /* NUL-terminate the filename. */ e = p; @@ -1196,7 +1196,7 @@ read_device_map (const char *dev_map) { map[drive].device = xmalloc (PATH_MAX); if (! realpath (p, map[drive].device)) - grub_util_error ("cannot get the real path of `%s'", p); + grub_util_error (_("cannot get the real path of `%s'"), p); } else #endif diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 8d15f17c5..725d1ac7f 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -98,10 +98,10 @@ usage (int status) { if (status) fprintf (stderr, - "Try `%s --help' for more information.\n", program_name); + _("Try `%s --help' for more information.\n"), program_name); else printf ( - "Usage: %s [OPTION]...\n" + _("Usage: %s [OPTION]...\n" "\n" "GRUB emulator.\n" "\n" @@ -113,7 +113,7 @@ usage (int status) " -h, --help display this message and exit\n" " -V, --version print version information and exit\n" "\n" - "Report bugs to <%s>.\n", program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); + "Report bugs to <%s>.\n"), program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); return status; } @@ -166,13 +166,13 @@ main (int argc, char *argv[]) if (optind < argc) { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind]); + fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind]); return usage (1); } /* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */ if (hold && verbosity > 0) - printf ("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n", + printf (_("Run \"gdb %s %d\", and set ARGS.HOLD to zero.\n"), program_name, (int) getpid ()); while (hold) { diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 6f5ea9fb9..21f314d55 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -117,7 +117,7 @@ xmalloc (grub_size_t size) p = malloc (size); if (! p) - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); return p; } @@ -127,7 +127,7 @@ xrealloc (void *ptr, grub_size_t size) { ptr = realloc (ptr, size); if (! ptr) - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); return ptr; } @@ -185,7 +185,7 @@ xasprintf (const char *fmt, ...) if (vasprintf (&result, fmt, ap) < 0) { if (errno == ENOMEM) - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); return NULL; } diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c index 6a70efb4c..b58ccc794 100644 --- a/grub-core/kern/emu/mm.c +++ b/grub-core/kern/emu/mm.c @@ -77,7 +77,7 @@ grub_memalign (grub_size_t align, grub_size_t size) #else (void) align; (void) size; - grub_util_error ("grub_memalign is not supported"); + grub_util_error (_("grub_memalign is not supported")); #endif if (!p) diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index ec0fa521a..41545b11f 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -33,6 +33,7 @@ #include #include #include +#include const char *type_names[] = { #ifdef GRUB_CPU_WORDS_BIGENDIAN @@ -178,7 +179,7 @@ grub_halt (void) grub_millisleep (1500); - grub_printf ("Shutdown failed\n"); + grub_puts_ (N_("Shutdown failed")); grub_refresh (); while (1); } @@ -190,7 +191,7 @@ grub_exit (void) grub_millisleep (1500); - grub_printf ("Exit failed\n"); + grub_puts_ (N_("Exit failed")); grub_refresh (); while (1); } diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 6ddf151f2..3b282e1e0 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -31,6 +31,7 @@ #include #include #include +#include extern void grub_video_sm712_init (void); extern void grub_video_sis315pro_init (void); @@ -254,7 +255,7 @@ grub_halt (void) break; } - grub_printf ("Shutdown failed\n"); + grub_puts_ (N_("Shutdown failed")); grub_refresh (); while (1); } diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c index a2f5dd722..cd9e8ae0f 100644 --- a/grub-core/kern/partition.c +++ b/grub-core/kern/partition.c @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include @@ -47,7 +48,7 @@ grub_partition_check_containment (const grub_disk_t disk, grub_dprintf ("partition", "sub-partition %s%d of (%s,%s) ends after parent.\n", part->partmap->name, part->number + 1, disk->name, partname); #ifdef GRUB_UTIL - grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)", + grub_util_warn (_("Discarding improperly nested partition (%s,%s,%s%d)"), disk->name, partname, part->partmap->name, part->number + 1); #endif grub_free (partname); diff --git a/grub-core/lib/i386/halt.c b/grub-core/lib/i386/halt.c index 15c4ba0d6..bd878c9bf 100644 --- a/grub-core/lib/i386/halt.c +++ b/grub-core/lib/i386/halt.c @@ -19,6 +19,7 @@ #include #include #include +#include const char bochs_shutdown[] = "Shutdown"; @@ -52,7 +53,7 @@ grub_halt (void) for (i = 0; i < sizeof (bochs_shutdown) - 1; i++) grub_outb (bochs_shutdown[i], 0x8900); - grub_printf ("GRUB doesn't know how to halt this machine yet!\n"); + grub_puts_ (N_("GRUB doesn't know how to halt this machine yet!")); /* In order to return we'd have to check what the previous status of IF flag was. But user most likely doesn't want to return anyway ... */ diff --git a/grub-core/lib/mips/arc/reboot.c b/grub-core/lib/mips/arc/reboot.c index f0d085765..ecf12a7ed 100644 --- a/grub-core/lib/mips/arc/reboot.c +++ b/grub-core/lib/mips/arc/reboot.c @@ -20,6 +20,7 @@ #include #include #include +#include void grub_reboot (void) @@ -28,7 +29,7 @@ grub_reboot (void) grub_millisleep (1500); - grub_printf ("Reboot failed\n"); + grub_puts_ (N_("Reboot failed")); grub_refresh (); while (1); } diff --git a/grub-core/lib/mips/loongson/reboot.c b/grub-core/lib/mips/loongson/reboot.c index f099ba250..1b510784b 100644 --- a/grub-core/lib/mips/loongson/reboot.c +++ b/grub-core/lib/mips/loongson/reboot.c @@ -24,6 +24,7 @@ #include #include #include +#include void grub_reboot (void) @@ -51,7 +52,7 @@ grub_reboot (void) } grub_millisleep (1500); - grub_printf ("Reboot failed\n"); + grub_puts_ (N_("Reboot failed")); grub_refresh (); while (1); } diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index 8d6ec8f20..42fbdeb32 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -247,7 +247,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(chainloader) { cmd = grub_register_command ("chainloader", grub_cmd_chainloader, - "[--force|--bpb] FILE", + N_("[--force|--bpb] FILE"), N_("Load another boot loader.")); my_mod = mod; } diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index fa7af514b..36893ae62 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -1018,7 +1018,7 @@ grub_xnu_boot (void) { grub_print_error (); grub_errno = GRUB_ERR_NONE; - grub_printf ("Booting in blind mode\n"); + grub_puts_ (N_("Booting in blind mode")); bootparams->lfb_mode = 0; bootparams->lfb_width = 0; diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index d9e74b3c7..2de8e0909 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -182,7 +182,7 @@ grub_multiboot_set_console (int console_type, int accepted_consoles, if (console_required) return grub_error (GRUB_ERR_BAD_OS, "OS requires a console but none is available"); - grub_printf ("WARNING: no console will be available to OS"); + grub_puts_ (N_("WARNING: no console will be available to OS")); accepts_video = 0; accepts_ega_text = 0; return GRUB_ERR_NONE; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 84bdc04d7..ba6a29020 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -520,10 +520,10 @@ void grub_bootp_init (void) { cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, - "[CARD]", + N_("[CARD]"), N_("perform a bootp autoconfiguration")); cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, - "[CARD]", + N_("[CARD]"), N_("perform a bootp autoconfiguration")); cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, N_("VAR INTERFACE NUMBER DESCRIPTION"), diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 0f8a60413..09acea900 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -946,16 +946,16 @@ static grub_command_t cmd_lsaddr; GRUB_MOD_INIT(net) { cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, - "SHORTNAME CARD ADDRESS [HWADDRESS]", + N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), N_("Add a network address.")); cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, - "SHORTNAME", + N_("SHORTNAME"), N_("Delete a network address.")); cmd_addroute = grub_register_command ("net_add_route", grub_cmd_addroute, - "SHORTNAME NET [INTERFACE| gw GATEWAY]", + N_("SHORTNAME NET [INTERFACE| gw GATEWAY]"), N_("Add a network route.")); cmd_delroute = grub_register_command ("net_del_route", grub_cmd_delroute, - "SHORTNAME", + N_("SHORTNAME"), N_("Delete a network route.")); cmd_lsroutes = grub_register_command ("net_ls_routes", grub_cmd_listroutes, "", N_("list network routes")); diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c index a8b9e6683..922f8518f 100644 --- a/grub-core/normal/term.c +++ b/grub-core/normal/term.c @@ -24,6 +24,7 @@ #include #include #include +#include struct term_state { @@ -63,7 +64,9 @@ print_more (void) pos = grub_term_save_pos (); - grub_utf8_to_ucs4_alloc ("--MORE--", &unicode_str, + /* TRANSLATORS: This has to fit on one line. It's ok to include few + words but don't write poems. */ + grub_utf8_to_ucs4_alloc (_("--MORE--"), &unicode_str, &unicode_last_position); if (!unicode_str) diff --git a/grub-core/partmap/bsdlabel.c b/grub-core/partmap/bsdlabel.c index 888100aa2..490fbdd7b 100644 --- a/grub-core/partmap/bsdlabel.c +++ b/grub-core/partmap/bsdlabel.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -105,7 +106,7 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd, /* disk->partition != NULL as 0 < delta */ partname = disk->partition ? grub_partition_get_name (disk->partition) : ""; - grub_util_warn ("Discarding improperly nested partition (%s,%s,%s%d)", + grub_util_warn (_("Discarding improperly nested partition (%s,%s,%s%d)"), disk->name, partname, p.partmap->name, p.number + 1); grub_free (partname); #endif diff --git a/grub-core/parttool/msdospart.c b/grub-core/parttool/msdospart.c index ecaca140a..3377a2ccc 100644 --- a/grub-core/parttool/msdospart.c +++ b/grub-core/parttool/msdospart.c @@ -27,6 +27,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv2+"); @@ -35,7 +36,7 @@ static int type_table_handle = -1; static struct grub_parttool_argdesc grub_pcpart_bootargs[] = { - {"boot", "Make partition active", GRUB_PARTTOOL_ARG_BOOL}, + {"boot", N_("Make partition active"), GRUB_PARTTOOL_ARG_BOOL}, {0, 0, 0} }; @@ -65,12 +66,12 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev, for (i = 0; i < 4; i++) mbr.entries[i].flag = 0x0; mbr.entries[index].flag = 0x80; - grub_printf ("Partition %d is active now. \n", index); + grub_printf_ (N_("Partition %d is active now. \n"), index); } else { mbr.entries[index].flag = 0x0; - grub_printf ("Cleared active flag on %d. \n", index); + grub_printf (N_("Cleared active flag on %d. \n"), index); } /* Write the MBR. */ @@ -83,8 +84,8 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev, static struct grub_parttool_argdesc grub_pcpart_typeargs[] = { - {"type", "Change partition type", GRUB_PARTTOOL_ARG_VAL}, - {"hidden", "Make partition hidden", GRUB_PARTTOOL_ARG_BOOL}, + {"type", N_("Change partition type"), GRUB_PARTTOOL_ARG_VAL}, + {"hidden", N_("Make partition hidden"), GRUB_PARTTOOL_ARG_BOOL}, {0, 0, 0} }; @@ -129,7 +130,7 @@ static grub_err_t grub_pcpart_type (const grub_device_t dev, } mbr.entries[index].type = type; - grub_printf ("Setting partition type to 0x%x\n", type); + grub_printf_ (N_("Setting partition type to 0x%x\n"), type); /* Write the parttable. */ grub_disk_write (dev->disk, part->offset, 0, diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 2f8deac18..a10af5930 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -1111,7 +1111,10 @@ grub_gfxterm_set_repaint_callback (grub_gfxterm_repaint_callback_t func) static const struct grub_arg_option background_image_cmd_options[] = { - {"mode", 'm', 0, "Background image mode.", "stretch|normal", + /* TRANSLATORS: note that GRUB will accept only original keywords stretch + and normal, not the translated ones. So please put both in translation + e.g. stretch=(%STRETCH%)|normal(=%NORMAL). */ + {"mode", 'm', 0, N_("Background image mode."), N_("stretch|normal"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c index 3419a5117..f8b29ec2e 100644 --- a/grub-core/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -606,7 +606,7 @@ print_terminfo (void) }; struct grub_term_output *cur; - grub_printf ("Current terminfo types: \n"); + grub_puts_ (N_("Current terminfo types:")); for (cur = terminfo_outputs; cur; cur = ((struct grub_terminfo_output_state *) cur->data)->next) grub_printf ("%s: %s\t%s\n", cur->name, diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 438ac92b2..92dd7ec07 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -993,15 +994,15 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, static void grub_video_vbe_print_adapter_specific_info (void) { - grub_printf (" VBE info: version: %d.%d OEM software rev: %d.%d\n", - controller_info.version >> 8, - controller_info.version & 0xFF, - controller_info.oem_software_rev >> 8, - controller_info.oem_software_rev & 0xFF); - + grub_printf_ (N_(" VBE info: version: %d.%d OEM software rev: %d.%d\n"), + controller_info.version >> 8, + controller_info.version & 0xFF, + controller_info.oem_software_rev >> 8, + controller_info.oem_software_rev & 0xFF); + /* The total_memory field is in 64 KiB units. */ - grub_printf (" total memory: %d KiB\n", - (controller_info.total_memory << 16) / 1024); + grub_printf_ (N_(" total memory: %d KiB\n"), + (controller_info.total_memory << 16) / 1024); } static struct grub_video_adapter grub_video_vbe_adapter = diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c index 513af47c1..aeabad976 100644 --- a/util/grub-menulst2cfg.c +++ b/util/grub-menulst2cfg.c @@ -24,6 +24,7 @@ #include #include #include +#include int main (int argc, char **argv) @@ -37,7 +38,7 @@ main (int argc, char **argv) if (argc >= 2 && argv[1][0] == '-') { - fprintf (stdout, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]); + fprintf (stdout, _("Usage: %s [INFILE [OUTFILE]]\n"), argv[0]); return 0; } @@ -46,7 +47,7 @@ main (int argc, char **argv) in = fopen (argv[1], "r"); if (!in) { - fprintf (stderr, "Couldn't open %s for reading: %s\n", + fprintf (stderr, _("Couldn't open %s for reading: %s\n"), argv[1], strerror (errno)); return 1; } @@ -61,7 +62,7 @@ main (int argc, char **argv) { if (in != stdin) fclose (in); - fprintf (stderr, "Couldn't open %s for writing: %s\n", + fprintf (stderr, _("Couldn't open %s for writing: %s\n"), argv[2], strerror (errno)); return 1; } diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c index bdecae4a3..bdf8ef1c6 100644 --- a/util/grub-mkdevicemap.c +++ b/util/grub-mkdevicemap.c @@ -62,7 +62,7 @@ make_device_map (const char *device_map, int floppy_disks) fp = fopen (device_map, "w"); if (! fp) - grub_util_error ("cannot open %s", device_map); + grub_util_error (_("cannot open %s"), device_map); grub_util_iterate_devices (process_device, floppy_disks); @@ -86,9 +86,9 @@ usage (int status) { if (status) fprintf (stderr, - "Try `%s --help' for more information.\n", program_name); + _("Try `%s --help' for more information.\n"), program_name); else - printf ("\ + printf (_("\ Usage: %s [OPTION]...\n\ \n\ Generate a device map file automatically.\n\ @@ -101,7 +101,7 @@ Generate a device map file automatically.\n\ -v, --verbose print verbose messages\n\ \n\ Report bugs to <%s>.\n\ -", program_name, +"), program_name, DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); exit (status); diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index 04501cb40..8de07747d 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -260,9 +260,9 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else - printf ("\ + printf (_("\ Usage: %s [OPTIONS]\n\ -i, --input set input filename. Default is STDIN\n\ -o, --output set output filename. Default is STDOUT\n\ @@ -270,7 +270,7 @@ Usage: %s [OPTIONS]\n\ -V, --version print version information and exit.\n\ -v, --verbose print verbose messages.\n\ \n\ -Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); +Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); exit (status); } @@ -300,7 +300,7 @@ lookup (char *code, int shift) if (strcmp (code, console_grub_equivalences_common[i].layout) == 0) return console_grub_equivalences_common[i].grub; - fprintf (stderr, "Unknown key %s\n", code); + fprintf (stderr, _("Unknown key %s\n"), code); return '\0'; } @@ -396,7 +396,7 @@ write_keymaps (FILE *in, FILE *out) if (keycode_usb == 0 || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) { - fprintf (stderr, "Unknown keycode 0x%02x\n", keycode_linux); + fprintf (stderr, _("Unknown keycode 0x%02x\n"), keycode_linux); continue; } if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) @@ -414,7 +414,7 @@ write_keymaps (FILE *in, FILE *out) if (ok == 0) { - fprintf (stderr, "ERROR: no keycodes found. Check output of %s.\n", + fprintf (stderr, _("ERROR: no keycodes found. Check output of %s.\n"), CKBCOMP); exit (1); } @@ -479,7 +479,7 @@ main (int argc, char *argv[]) in = stdin; if (!in) - grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); + grub_util_error (_("Couldn't open input file: %s\n"), strerror (errno)); if (outfile_name) out = fopen (outfile_name, "wb"); @@ -490,7 +490,7 @@ main (int argc, char *argv[]) { if (in != stdin) fclose (in); - grub_util_error ("Couldn't open output file: %s\n", strerror (errno)); + grub_util_error (_("Couldn't open output file: %s\n"), strerror (errno)); } write_keymaps (in, out); diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c index 3fe3fe698..788db38a2 100644 --- a/util/grub-mkrelpath.c +++ b/util/grub-mkrelpath.c @@ -38,9 +38,9 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else - printf ("\ + printf (_("\ Usage: %s [OPTIONS] PATH\n\ \n\ Make a system path relative to its root.\n\ @@ -49,7 +49,7 @@ Options:\n\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ \n\ -Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); +Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); exit (status); } @@ -89,13 +89,13 @@ main (int argc, char *argv[]) if (optind >= argc) { - fprintf (stderr, "No path is specified.\n"); + fprintf (stderr, _("No path is specified.\n")); usage (1); } if (optind + 1 != argc) { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); + fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); usage (1); } diff --git a/util/grub-script-check.c b/util/grub-script-check.c index 2d1b31c9a..25358a553 100644 --- a/util/grub-script-check.c +++ b/util/grub-script-check.c @@ -51,9 +51,9 @@ usage (int status) { if (status) fprintf (stderr, - "Try ``%s --help'' for more information.\n", program_name); + _("Try ``%s --help'' for more information.\n"), program_name); else - printf ("\ + printf (_("\ Usage: %s [PATH]\n\ \n\ Checks GRUB script configuration file for syntax errors.\n\ @@ -63,7 +63,7 @@ Checks GRUB script configuration file for syntax errors.\n\ -v, --verbose print the script as it is being processed\n\ \n\ Report bugs to <%s>.\n\ -", program_name, +"), program_name, PACKAGE_BUGREPORT); exit (status); } @@ -157,7 +157,7 @@ main (int argc, char *argv[]) } else if (optind + 1 != argc) { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); + fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); usage (1); } else @@ -193,7 +193,7 @@ main (int argc, char *argv[]) if (found_input && script == 0) { - fprintf (stderr, "error: line no: %u\n", lineno); + fprintf (stderr, _("error: line no: %u\n"), lineno); return 1; } diff --git a/util/ieee1275/grub-ofpathname.c b/util/ieee1275/grub-ofpathname.c index ee81457b3..03d47bc99 100644 --- a/util/ieee1275/grub-ofpathname.c +++ b/util/ieee1275/grub-ofpathname.c @@ -36,7 +36,7 @@ int main(int argc, char **argv) if (argc != 2 || strcmp (argv[1], "--help") == 0) { - printf("Usage: %s DEVICE\n", program_name); + printf(_("Usage: %s DEVICE\n"), program_name); return 1; } if (strcmp (argv[1], "--version") == 0) diff --git a/util/resolve.c b/util/resolve.c index 63bd7ccb2..3eb8bfb14 100644 --- a/util/resolve.c +++ b/util/resolve.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Module. */ struct mod_list @@ -87,7 +88,7 @@ read_dep_list (FILE *fp) /* Get the target name. */ p = strchr (buf, ':'); if (! p) - grub_util_error ("invalid line format: %s", buf); + grub_util_error (_("invalid line format: %s"), buf); *p++ = '\0'; @@ -240,7 +241,7 @@ grub_util_resolve_dependencies (const char *prefix, path = grub_util_get_path (prefix, dep_list_file); fp = fopen (path, "r"); if (! fp) - grub_util_error ("cannot open %s", path); + grub_util_error (_("cannot open %s"), path); free (path); dep_list = read_dep_list (fp); From 119d11c8857ce2d354fbbada64cc27f783b57ecb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 11 Nov 2011 22:35:09 +0100 Subject: [PATCH 544/673] Replace grub_fatal with normal errors in i386 linux loader. * grub-core/loader/i386/linux.c (find_efi_mmap_size): Return 0 on error. (allocate_pages): Check find_efi_mmap_size return value. (grub_e820_add_region): Return error. (grub_linux_boot): Check mmap return value. --- ChangeLog | 9 +++++++++ grub-core/loader/i386/linux.c | 38 ++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index c3c0cfe61..490bc693b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-11-11 Vladimir Serbinenko + + Replace grub_fatal with normal errors in i386 linux loader. + + * grub-core/loader/i386/linux.c (find_efi_mmap_size): Return 0 on error. + (allocate_pages): Check find_efi_mmap_size return value. + (grub_e820_add_region): Return error. + (grub_linux_boot): Check mmap return value. + 2011-11-11 Vladimir Serbinenko * grub-core/commands/acpihalt.c: Gettextized. diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index a6eb95028..c63c6c3ef 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -130,7 +130,10 @@ find_efi_mmap_size (void) grub_free (mmap); if (ret < 0) - grub_fatal ("cannot get memory map"); + { + grub_error (GRUB_ERR_IO, "cannot get memory map"); + return 0; + } else if (ret > 0) break; @@ -198,6 +201,8 @@ allocate_pages (grub_size_t prot_size) #ifdef GRUB_MACHINE_EFI efi_mmap_size = find_efi_mmap_size (); + if (efi_mmap_size == 0) + return grub_errno; #endif grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n", @@ -291,7 +296,7 @@ allocate_pages (grub_size_t prot_size) return err; } -static void +static grub_err_t grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num, grub_uint64_t start, grub_uint64_t size, grub_uint32_t type) @@ -299,7 +304,10 @@ grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num, int n = *e820_num; if (n >= GRUB_E820_MAX_ENTRY) - grub_fatal ("Too many e820 memory map entries"); + { + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Too many e820 memory map entries"); + } if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) && (e820_map[n - 1].type == type)) @@ -311,6 +319,7 @@ grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num, e820_map[n].type = type; (*e820_num)++; } + return GRUB_ERR_NONE; } static grub_err_t @@ -446,37 +455,38 @@ grub_linux_boot (void) int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type) { + grub_uint32_t e820_type; switch (type) { case GRUB_MEMORY_AVAILABLE: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_RAM); + e820_type = GRUB_E820_RAM; break; case GRUB_MEMORY_ACPI: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_ACPI); + e820_type = GRUB_E820_ACPI; break; case GRUB_MEMORY_NVS: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_NVS); + e820_type = GRUB_E820_NVS; break; case GRUB_MEMORY_BADRAM: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_BADRAM); + e820_type = GRUB_E820_BADRAM; break; default: - grub_e820_add_region (params->e820_map, &e820_num, - addr, size, GRUB_E820_RESERVED); + e820_type = GRUB_E820_RESERVED; } + if (grub_e820_add_region (params->e820_map, &e820_num, + addr, size, e820_type)) + return 1; + return 0; } e820_num = 0; - grub_mmap_iterate (hook); + if (grub_mmap_iterate (hook)) + return grub_errno; params->mmap_size = e820_num; modevar = grub_env_get ("gfxpayload"); From 566f779bd8a7245f5c867ab276d62a0b54d3c222 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 11 Nov 2011 22:58:18 +0100 Subject: [PATCH 545/673] 2011-11-11 Robert Millan * util/getroot.c (grub_util_get_geom_abstraction): Remove __attribute__((unused)) from `os_dev', which *is* being used. --- ChangeLog | 5 +++++ util/getroot.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 490bc693b..6b726987a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-11 Robert Millan + + * util/getroot.c (grub_util_get_geom_abstraction): Remove + __attribute__((unused)) from `os_dev', which *is* being used. + 2011-11-11 Vladimir Serbinenko Replace grub_fatal with normal errors in i386 linux loader. diff --git a/util/getroot.c b/util/getroot.c index 41fbdec10..750773c90 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -826,7 +826,7 @@ grub_util_get_geom_abstraction (const char *dev) #endif int -grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) +grub_util_get_dev_abstraction (const char *os_dev) { #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) /* User explicitly claims that this drive is visible by BIOS. */ From b50787de091db9e94dc48fe68e3d79d5126d065d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 00:26:04 +0100 Subject: [PATCH 546/673] * include/grub/dl.h (GRUB_ARCH_DL_TRAMP_SIZE) [__ia64__]: Add back forgotten define. (GRUB_ARCH_DL_GOT_ALIGN) [__ia64__]: Redefine in terms of GRUB_IA64_DL_GOT_ALIGN. (GRUB_ARCH_DL_TRAMP_ALIGN) [__ia64__]: Redefine in terms of GRUB_IA64_DL_TRAMP_ALIGN. --- ChangeLog | 9 +++++++++ include/grub/dl.h | 5 +++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b726987a..3970ec293 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,15 @@ * util/getroot.c (grub_util_get_geom_abstraction): Remove __attribute__((unused)) from `os_dev', which *is* being used. +2011-11-11 Vladimir Serbinenko + + * include/grub/dl.h (GRUB_ARCH_DL_TRAMP_SIZE) [__ia64__]: Add back + forgotten define. + (GRUB_ARCH_DL_GOT_ALIGN) [__ia64__]: Redefine in terms of + GRUB_IA64_DL_GOT_ALIGN. + (GRUB_ARCH_DL_TRAMP_ALIGN) [__ia64__]: Redefine in terms of + GRUB_IA64_DL_TRAMP_ALIGN. + 2011-11-11 Vladimir Serbinenko Replace grub_fatal with normal errors in i386 linux loader. diff --git a/include/grub/dl.h b/include/grub/dl.h index 886e966cc..d5f009829 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -178,8 +178,9 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got); #if defined (__ia64__) -#define GRUB_ARCH_DL_TRAMP_ALIGN 16 -#define GRUB_ARCH_DL_GOT_ALIGN 16 +#define GRUB_ARCH_DL_TRAMP_ALIGN GRUB_IA64_DL_TRAMP_ALIGN +#define GRUB_ARCH_DL_GOT_ALIGN GRUB_IA64_DL_GOT_ALIGN +#define GRUB_ARCH_DL_TRAMP_SIZE GRUB_IA64_DL_TRAMP_SIZE #define grub_arch_dl_get_tramp_got_size grub_ia64_dl_get_tramp_got_size #else void From 10f0117bf93a31cdf952a6379ab33a03e4920993 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 00:34:14 +0100 Subject: [PATCH 547/673] * grub-core/commands/efi/fixvideo.c: Gettextize. * grub-core/commands/hashsum.c: Likewise. * grub-core/commands/i386/cmostest.c: Likewise. * grub-core/commands/i386/pc/drivemap.c: Likewise. * grub-core/commands/i386/pc/lsapm.c: Likewise. * grub-core/commands/i386/pc/sendkey.c: Likewise. * grub-core/commands/lsmmap.c: Likewise. * grub-core/commands/menuentry.c: Likewise. * grub-core/commands/mips/loongson/lsspd.c: Likewise. * grub-core/commands/setpci.c: Likewise. * grub-core/loader/i386/bsd.c: Likewise. * grub-core/loader/i386/linux.c: Likewise. * util/getroot.c: Likewise. * util/grub-editenv.c: Likewise. * util/grub-fstest.c: Likewise. * util/grub-mkfont.c: Likewise. * util/grub-mkimage.c: Likewise. * util/grub-mkpasswd-pbkdf2.c: Likewise. * util/grub-pe2elf.c: Likewise. * util/grub-probe.c: Likewise. * util/grub-setup.c: Likewise. * util/ieee1275/ofpath.c: Likewise. * util/misc.c: Likewise. * util/raid.c: Likewise. --- ChangeLog | 27 +++++++++++ grub-core/commands/efi/fixvideo.c | 10 ++-- grub-core/commands/hashsum.c | 10 ++-- grub-core/commands/i386/cmostest.c | 9 ++-- grub-core/commands/i386/pc/drivemap.c | 4 +- grub-core/commands/i386/pc/lsapm.c | 32 ++++++------- grub-core/commands/i386/pc/sendkey.c | 39 ++++++++-------- grub-core/commands/lsmmap.c | 22 ++++----- grub-core/commands/menuentry.c | 8 ++-- grub-core/commands/mips/loongson/lsspd.c | 24 +++++----- grub-core/commands/setpci.c | 14 +++--- grub-core/loader/i386/bsd.c | 10 ++-- grub-core/loader/i386/linux.c | 28 ++++++------ util/getroot.c | 58 ++++++++++++------------ util/grub-editenv.c | 28 ++++++------ util/grub-fstest.c | 10 ++-- util/grub-mkfont.c | 57 +++++++++++------------ util/grub-mkimage.c | 22 ++++----- util/grub-mkpasswd-pbkdf2.c | 35 +++++++------- util/grub-pe2elf.c | 2 + util/grub-probe.c | 29 ++++++------ util/grub-setup.c | 29 ++++++------ util/ieee1275/ofpath.c | 20 ++++---- util/misc.c | 22 ++++----- util/raid.c | 13 +++--- 25 files changed, 302 insertions(+), 260 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3970ec293..23679917c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2011-11-11 Vladimir Serbinenko + + * grub-core/commands/efi/fixvideo.c: Gettextize. + * grub-core/commands/hashsum.c: Likewise. + * grub-core/commands/i386/cmostest.c: Likewise. + * grub-core/commands/i386/pc/drivemap.c: Likewise. + * grub-core/commands/i386/pc/lsapm.c: Likewise. + * grub-core/commands/i386/pc/sendkey.c: Likewise. + * grub-core/commands/lsmmap.c: Likewise. + * grub-core/commands/menuentry.c: Likewise. + * grub-core/commands/mips/loongson/lsspd.c: Likewise. + * grub-core/commands/setpci.c: Likewise. + * grub-core/loader/i386/bsd.c: Likewise. + * grub-core/loader/i386/linux.c: Likewise. + * util/getroot.c: Likewise. + * util/grub-editenv.c: Likewise. + * util/grub-fstest.c: Likewise. + * util/grub-mkfont.c: Likewise. + * util/grub-mkimage.c: Likewise. + * util/grub-mkpasswd-pbkdf2.c: Likewise. + * util/grub-pe2elf.c: Likewise. + * util/grub-probe.c: Likewise. + * util/grub-setup.c: Likewise. + * util/ieee1275/ofpath.c: Likewise. + * util/misc.c: Likewise. + * util/raid.c: Likewise. + 2011-11-11 Robert Millan * util/getroot.c (grub_util_get_geom_abstraction): Remove diff --git a/grub-core/commands/efi/fixvideo.c b/grub-core/commands/efi/fixvideo.c index c53e47d8a..a58c27916 100644 --- a/grub-core/commands/efi/fixvideo.c +++ b/grub-core/commands/efi/fixvideo.c @@ -56,24 +56,24 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid) { grub_target_addr_t base; - grub_printf ("Found graphic card: %s\n", p->name); + grub_dprintf ("fixvideo", "Found graphic card: %s\n", p->name); addr += 8 + p->mmio_bar * 4; base = grub_pci_read (addr); if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) || (base & GRUB_PCI_ADDR_MEM_PREFETCH)) - grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar); + grub_dprintf ("fixvideo", "Invalid MMIO bar %d\n", p->mmio_bar); else { base &= GRUB_PCI_ADDR_MEM_MASK; base += p->mmio_reg; if (*((volatile grub_uint32_t *) base) != p->mmio_old) - grub_printf ("Old value don't match\n"); + grub_dprintf ("fixvideo", "Old value doesn't match\n"); else { *((volatile grub_uint32_t *) base) = 0; if (*((volatile grub_uint32_t *) base)) - grub_printf ("Set MMIO fails\n"); + grub_dprintf ("fixvideo", "Setting MMIO fails\n"); } } @@ -82,7 +82,7 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid) p++; } - grub_printf ("Unknown graphic card: %x\n", pciid); + grub_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid); } return 0; diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index 6825d4811..fb737c2f8 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -141,7 +141,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, grub_file_close (file); if (err) { - grub_printf ("%s: READ ERROR\n", p); + grub_printf_ (N_("%s: READ ERROR\n"), p); if (!keep) { grub_file_close (hashlist); @@ -155,7 +155,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, } if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0) { - grub_printf ("%s: HASH MISMATCH\n", p); + grub_printf_ (N_("%s: HASH MISMATCH\n"), p); if (!keep) { grub_file_close (hashlist); @@ -166,7 +166,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, mismatch++; continue; } - grub_printf ("%s: OK\n", p); + grub_printf_ (N_("%s: OK\n"), p); } if (mismatch || unread) return grub_error (GRUB_ERR_TEST_FAILURE, @@ -257,8 +257,8 @@ static grub_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc; GRUB_MOD_INIT(hashsum) { cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0, - "hashsum -h HASH [-c FILE [-p PREFIX]] " - "[FILE1 [FILE2 ...]]", + N_("-h HASH [-c FILE [-p PREFIX]] " + "[FILE1 [FILE2 ...]]"), N_("Compute or check hash checksum."), options); cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0, diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index 6439159bd..6a4290155 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -20,6 +20,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -86,11 +87,11 @@ static grub_command_t cmd, cmd_clean; GRUB_MOD_INIT(cmostest) { cmd = grub_register_command ("cmostest", grub_cmd_cmostest, - "cmostest BYTE:BIT", - "Test bit at BYTE:BIT in CMOS."); + N_("BYTE:BIT"), + N_("Test bit at BYTE:BIT in CMOS.")); cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, - "cmosclean BYTE:BIT", - "Clean bit at BYTE:BIT in CMOS."); + N_("BYTE:BIT"), + N_("Clean bit at BYTE:BIT in CMOS.")); } GRUB_MOD_FINI(cmostest) diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 9a89f968c..4f752bed5 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -178,11 +178,11 @@ list_mappings (void) /* Show: list mappings. */ if (! map_head) { - grub_printf ("No drives have been remapped\n"); + grub_puts_ (N_("No drives have been remapped")); return GRUB_ERR_NONE; } - grub_printf ("OS disk #num ------> GRUB/BIOS device\n"); + grub_puts_ (N_("OS disk #num ------> GRUB/BIOS device")); drivemap_node_t *curnode = map_head; while (curnode) { diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c index 17bcfd6eb..45b43b242 100644 --- a/grub-core/commands/i386/pc/lsapm.c +++ b/grub-core/commands/i386/pc/lsapm.c @@ -74,27 +74,27 @@ grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)), if (!grub_apm_get_info (&info)) return grub_error (GRUB_ERR_IO, "no APM found"); - grub_printf ("Vesion %u.%u\n" - "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n" - "16-bit CS = 0x%x, len = 0x%x\n" - "DS = 0x%x, len = 0x%x\n", - info.version >> 8, info.version & 0xff, - info.cseg, info.cseg_len, info.offset, - info.cseg_16, info.cseg_16_len, - info.dseg, info.dseg_len); + grub_printf_ (N_("Vesion %u.%u\n" + "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n" + "16-bit CS = 0x%x, len = 0x%x\n" + "DS = 0x%x, len = 0x%x\n"), + info.version >> 8, info.version & 0xff, + info.cseg, info.cseg_len, info.offset, + info.cseg_16, info.cseg_16_len, + info.dseg, info.dseg_len); grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED - ? "16-bit protected interface supported\n" - : "16-bit protected interface unsupported\n"); + ? _("16-bit protected interface supported\n") + : _("16-bit protected interface unsupported\n")); grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED - ? "32-bit protected interface supported\n" - : "32-bit protected interface unsupported\n"); + ? _("32-bit protected interface supported\n") + : _("32-bit protected interface unsupported\n")); grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN - ? "CPU Idle slows down processor\n" - : "CPU Idle doesn't slow down processor\n"); + ? _("CPU Idle slows down processor\n") + : _("CPU Idle doesn't slow down processor\n")); grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED - ? "APM disabled\n" : "APM enabled\n"); + ? _("APM disabled\n") : _("APM enabled\n")); grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED - ? "APM disengaged\n" : "APM engaged\n"); + ? _("APM disengaged\n") : _("APM engaged\n")); return GRUB_ERR_NONE; } diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index a55d17bd0..83400c347 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv2+"); @@ -35,23 +36,23 @@ static int keylen = 0; static int noled = 0; static const struct grub_arg_option options[] = { - {"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING}, - {"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING}, - {"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING}, - {"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING}, - {"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING}, - {"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING}, - {"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING}, - {"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING}, - {"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING}, - {"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING}, - {"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING}, - {"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING}, - {"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING}, - {"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING}, - {"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING}, - {"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING}, - {"no-led", 0, 0, "don't update LED state", 0, 0}, + {"num", 'n', 0, N_("set numlock mode"), "[on|off]", ARG_TYPE_STRING}, + {"caps", 'c', 0, N_("set capslock mode"), "[on|off]", ARG_TYPE_STRING}, + {"scroll", 's', 0, N_("set scrolllock mode"), "[on|off]", ARG_TYPE_STRING}, + {"insert", 0, 0, N_("set insert mode"), "[on|off]", ARG_TYPE_STRING}, + {"pause", 0, 0, N_("set pause mode"), "[on|off]", ARG_TYPE_STRING}, + {"left-shift", 0, 0, N_("press left shift"), "[on|off]", ARG_TYPE_STRING}, + {"right-shift", 0, 0, N_("press right shift"), "[on|off]", ARG_TYPE_STRING}, + {"sysrq", 0, 0, N_("press SysRq"), "[on|off]", ARG_TYPE_STRING}, + {"numkey", 0, 0, N_("press NumLock key"), "[on|off]", ARG_TYPE_STRING}, + {"capskey", 0, 0, N_("press CapsLock key"), "[on|off]", ARG_TYPE_STRING}, + {"scrollkey", 0, 0, N_("press ScrollLock key"), "[on|off]", ARG_TYPE_STRING}, + {"insertkey", 0, 0, N_("press Insert key"), "[on|off]", ARG_TYPE_STRING}, + {"left-alt", 0, 0, N_("press left alt"), "[on|off]", ARG_TYPE_STRING}, + {"right-alt", 0, 0, N_("press right alt"), "[on|off]", ARG_TYPE_STRING}, + {"left-ctrl", 0, 0, N_("press left ctrl"), "[on|off]", ARG_TYPE_STRING}, + {"right-ctrl", 0, 0, N_("press right ctrl"), "[on|off]", ARG_TYPE_STRING}, + {"no-led", 0, 0, N_("don't update LED state"), 0, 0}, {0, 0, 0, 0, 0, 0} }; static int simple_flag_offsets[] @@ -369,8 +370,8 @@ static void *preboot_hook; GRUB_MOD_INIT (sendkey) { cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0, - "sendkey [KEYSTROKE1] [KEYSTROKE2] ...", - "Emulate a keystroke", options); + N_("[KEYSTROKE1] [KEYSTROKE2] ..."), + N_("Emulate a keystroke"), options); preboot_hook = grub_loader_register_preboot_hook (grub_sendkey_preboot, diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c index 44598f0df..4815fd174 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -26,13 +26,13 @@ GRUB_MOD_LICENSE ("GPLv3+"); static const char *names[] = { - [GRUB_MEMORY_AVAILABLE] = "available", - [GRUB_MEMORY_RESERVED] = "reserved", - [GRUB_MEMORY_ACPI] = "ACPI reclamaible", - [GRUB_MEMORY_NVS] = "NVS", - [GRUB_MEMORY_BADRAM] = "BadRAM", - [GRUB_MEMORY_CODE] = "firmware code", - [GRUB_MEMORY_HOLE] = "hole" + [GRUB_MEMORY_AVAILABLE] = N_("available"), + [GRUB_MEMORY_RESERVED] = N_("reserved"), + [GRUB_MEMORY_ACPI] = N_("ACPI reclamaible"), + [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage"), + [GRUB_MEMORY_BADRAM] = N_("BadRAM"), + [GRUB_MEMORY_CODE] = N_("firmware code"), + [GRUB_MEMORY_HOLE] = N_("hole") }; static grub_err_t @@ -46,11 +46,11 @@ grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)), grub_memory_type_t type) { if (type < ARRAY_SIZE (names) && names[type]) - grub_printf ("base_addr = 0x%llx, length = 0x%llx, %s\n", - (long long) addr, (long long) size, names[type]); + grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"), + (long long) addr, (long long) size, _(names[type])); else - grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", - (long long) addr, (long long) size, type); + grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"), + (long long) addr, (long long) size, type); return 0; } #ifndef GRUB_MACHINE_EMU diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index 4849f8bb8..f5ec60bff 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -28,13 +28,13 @@ static const struct grub_arg_option options[] = { {"class", 1, GRUB_ARG_OPTION_REPEATABLE, - N_("Menu entry type."), "STRING", ARG_TYPE_STRING}, + N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING}, {"users", 2, 0, - N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING}, + N_("Users allowed to boot this entry."), N_("USERNAME"), ARG_TYPE_STRING}, {"hotkey", 3, 0, - N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING}, + N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING}, {"source", 4, 0, - N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING}, + N_("Menu entry definition as a string."), N_("STRING"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; diff --git a/grub-core/commands/mips/loongson/lsspd.c b/grub-core/commands/mips/loongson/lsspd.c index c1c5e2ef7..76999368f 100644 --- a/grub-core/commands/mips/loongson/lsspd.c +++ b/grub-core/commands/mips/loongson/lsspd.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -38,43 +39,44 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)), if (!grub_cs5536_find (&dev)) { - grub_printf ("No CS5536 found\n"); + grub_puts_ (N_("No CS5536 found")); return GRUB_ERR_NONE; } - grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev), - grub_pci_get_device (dev), grub_pci_get_function (dev)); + grub_printf_ (N_("CS5536 at %d:%d.%d\n"), grub_pci_get_bus (dev), + grub_pci_get_device (dev), grub_pci_get_function (dev)); err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase); if (err) return err; - grub_printf ("SMB base = 0x%x\n", smbbase); + grub_printf_ (N_("SMB base = 0x%x\n"), smbbase); for (i = GRUB_SMB_RAM_START_ADDR; i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++) { struct grub_smbus_spd spd; grub_memset (&spd, 0, sizeof (spd)); - grub_printf ("Device %d\n", i); + grub_printf_ (N_("Device %d\n"), i); err = grub_cs5536_read_spd (smbbase, i, &spd); if (err) { grub_print_error (); continue; } - grub_printf ("Written SPD bytes: %d B.\n", spd.written_size); - grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size); + grub_printf_ (N_("Written SPD bytes: %d B.\n"), spd.written_size); + grub_printf_ (N_("Total flash size: %d B.\n"), + 1 << spd.log_total_flash_size); if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2) { char str[sizeof (spd.ddr2.part_number) + 1]; - grub_printf ("Memory type: DDR2.\n"); + grub_puts_ (N_("Memory type: DDR2.")); grub_memcpy (str, spd.ddr2.part_number, sizeof (spd.ddr2.part_number)); str[sizeof (spd.ddr2.part_number)] = 0; - grub_printf ("Part no: %s.\n", str); + grub_printf_ (N_("Part no: %s.\n"), str); } else - grub_printf ("Memory type: Unknown.\n"); + grub_puts_ (N_("Memory type: Unknown.")); } return GRUB_ERR_NONE; @@ -85,7 +87,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(lsspd) { cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0, - "Print Memory information."); + N_("Print Memory information.")); } GRUB_MOD_FINI(lsspd) diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index 70f5bcdad..81e7f726d 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -66,12 +66,12 @@ static struct pci_register pci_registers[] = static const struct grub_arg_option options[] = { - {0, 'd', 0, "Select device by vendor and device IDs.", - "[vendor]:[device]", ARG_TYPE_STRING}, - {0, 's', 0, "Select device by its position on the bus.", - "[bus]:[slot][.func]", ARG_TYPE_STRING}, - {0, 'v', 0, "Save read value into variable VARNAME.", - "VARNAME", ARG_TYPE_STRING}, + {0, 'd', 0, N_("Select device by vendor and device IDs."), + N_("[vendor]:[device]"), ARG_TYPE_STRING}, + {0, 's', 0, N_("Select device by its position on the bus."), + N_("[bus]:[slot][.func]"), ARG_TYPE_STRING}, + {0, 'v', 0, N_("Save read value into variable VARNAME."), + N_("VARNAME"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -128,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) if (!write_mask) { - grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr, + grub_printf (N_("Register %x of %d:%d.%d is %x\n"), regaddr, grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev), diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index f2d0845f8..6746b3853 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -450,7 +450,8 @@ grub_freebsd_list_modules (void) { struct bsd_tag *tag; - grub_printf (" %-18s %-18s%14s%14s\n", "name", "type", "addr", "size"); + grub_printf (" %-18s %-18s%14s%14s\n", _("name"), _("type"), _("addr"), + _("size")); for (tag = tags; tag; tag = tag->next) { @@ -515,7 +516,8 @@ grub_netbsd_list_modules (void) { struct netbsd_module *mod; - grub_printf (" %-18s%14s%14s%14s\n", "name", "type", "addr", "size"); + grub_printf (" %-18s%14s%14s%14s\n", _("name"), _("type"), _("addr"), + _("size")); for (mod = netbsd_mods; mod; mod = mod->next) grub_printf (" %-18s 0x%08x 0x%08x 0x%08x", mod->mod.name, @@ -1050,7 +1052,7 @@ grub_netbsd_boot (void) if (err) { grub_print_error (); - grub_printf ("Booting however\n"); + grub_puts_ (N_("Booting in blind mode")); grub_errno = GRUB_ERR_NONE; } @@ -2061,7 +2063,7 @@ GRUB_MOD_INIT (bsd) cmd_openbsd_ramdisk = grub_register_command ("kopenbsd_ramdisk", grub_cmd_openbsd_ramdisk, 0, - "Load kOpenBSD ramdisk. "); + N_("Load kOpenBSD ramdisk.")); my_mod = mod; } diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index c63c6c3ef..80ad542e3 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -517,7 +517,7 @@ grub_linux_boot (void) if (err) { grub_print_error (); - grub_printf ("Booting however\n"); + grub_puts_ (N_("Booting in blind mode")); grub_errno = GRUB_ERR_NONE; } @@ -793,7 +793,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), vid_mode = GRUB_LINUX_VID_MODE_EXTENDED; else if (grub_strcmp (val, "ask") == 0) { - grub_printf ("Legacy `ask' parameter no longer supported.\n"); + grub_puts_ (N_("Legacy `ask' parameter no longer supported.")); /* We usually would never do this in a loader, but "vga=ask" means user requested interaction, so it can't hurt to request keyboard input. */ @@ -809,9 +809,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), case 0: case GRUB_LINUX_VID_MODE_NORMAL: grub_env_set ("gfxpayload", "text"); - grub_printf ("%s is deprecated. " - "Use set gfxpayload=text before " - "linux command instead.\n", + grub_printf_ (N_("%s is deprecated. " + "Use set gfxpayload=text before " + "linux command instead.\n"), argv[i]); break; @@ -819,9 +819,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), case GRUB_LINUX_VID_MODE_EXTENDED: /* FIXME: support 80x50 text. */ grub_env_set ("gfxpayload", "text"); - grub_printf ("%s is deprecated. " - "Use set gfxpayload=text before " - "linux command instead.\n", + grub_printf_ (N_("%s is deprecated. " + "Use set gfxpayload=text before " + "linux command instead.\n"), argv[i]); break; default: @@ -830,9 +830,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), vid_mode > GRUB_VESA_MODE_TABLE_END) { grub_env_set ("gfxpayload", "text"); - grub_printf ("%s is deprecated. Mode %d isn't recognized. " - "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] before " - "linux command instead.\n", + grub_printf_ (N_("%s is deprecated. Mode %d isn't recognized. " + "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] " + "before linux command instead.\n"), argv[i], vid_mode); break; } @@ -847,9 +847,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (! buf) goto fail; - grub_printf ("%s is deprecated. " - "Use set gfxpayload=%s before " - "linux command instead.\n", + grub_printf_ (N_("%s is deprecated. " + "Use set gfxpayload=%s before " + "linux command instead.\n"), argv[i], buf); err = grub_env_set ("gfxpayload", buf); grub_free (buf); diff --git a/util/getroot.c b/util/getroot.c index 750773c90..f5d6d3f62 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef HAVE_DEVICE_MAPPER # include @@ -454,7 +455,7 @@ grub_find_device (const char *dir, dev_t dev) continue; if (chdir (saved_cwd) < 0) - grub_util_error ("cannot restore the original directory"); + grub_util_error (_("cannot restore the original directory")); free (saved_cwd); closedir (dp); @@ -463,7 +464,7 @@ grub_find_device (const char *dir, dev_t dev) } if (chdir (saved_cwd) < 0) - grub_util_error ("cannot restore the original directory"); + grub_util_error (_("cannot restore the original directory")); free (saved_cwd); closedir (dp); @@ -581,17 +582,17 @@ grub_guess_root_device (const char *dir) &data, &data_len); if (num_ints < 1) - grub_util_error ("Storage info for `%s' does not include type", dir); + grub_util_error (_("Storage info for `%s' does not include type"), dir); if (ints[0] != STORAGE_DEVICE) - grub_util_error ("Filesystem of `%s' is not stored on local disk", dir); + grub_util_error (_("Filesystem of `%s' is not stored on local disk"), dir); if (num_ints < 5) - grub_util_error ("Storage info for `%s' does not include name", dir); + grub_util_error (_("Storage info for `%s' does not include name"), dir); name_len = ints[4]; if (name_len < data_len) - grub_util_error ("Bogus name length for storage info for `%s'", dir); + grub_util_error (_("Bogus name length for storage info for `%s'"), dir); if (data[name_len - 1] != '\0') - grub_util_error ("Storage name for `%s' not NUL-terminated", dir); + grub_util_error (_("Storage name for `%s' not NUL-terminated"), dir); os_dev = xmalloc (strlen ("/dev/") + data_len); memcpy (os_dev, "/dev/", strlen ("/dev/")); @@ -653,7 +654,7 @@ grub_guess_root_device (const char *dir) } if (stat (dir, &st) < 0) - grub_util_error ("cannot stat `%s'", dir); + grub_util_error (_("cannot stat `%s'"), dir); dev = st.st_dev; @@ -692,7 +693,7 @@ grub_util_open_dm (const char *os_dev, struct dm_tree **tree, *tree = dm_tree_create (); if (! *tree) { - grub_printf ("Failed to create tree\n"); + grub_puts_ (N_("Failed to create tree")); grub_dprintf ("hostdisk", "dm_tree_create failed\n"); return 0; } @@ -808,7 +809,7 @@ grub_util_get_geom_abstraction (const char *dev) error = geom_gettree (&mesh); if (error != 0) - grub_util_error ("couldn't open geom"); + grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) { @@ -874,13 +875,14 @@ get_mdadm_uuid (const char *os_dev) if (pipe (mdadm_pipe) < 0) { - grub_util_warn ("Unable to create pipe for mdadm: %s", strerror (errno)); + grub_util_warn (_("Unable to create pipe for mdadm: %s"), + strerror (errno)); return NULL; } mdadm_pid = fork (); if (mdadm_pid < 0) - grub_util_warn ("Unable to fork mdadm: %s", strerror (errno)); + grub_util_warn (_("Unable to fork mdadm: %s"), strerror (errno)); else if (mdadm_pid == 0) { /* Child. */ @@ -911,7 +913,7 @@ get_mdadm_uuid (const char *os_dev) mdadm = fdopen (mdadm_pipe[0], "r"); if (! mdadm) { - grub_util_warn ("Unable to open stream from mdadm: %s", + grub_util_warn (_("Unable to open stream from mdadm: %s"), strerror (errno)); goto out; } @@ -971,7 +973,7 @@ grub_util_pull_device (const char *os_dev) error = geom_gettree (&mesh); if (error != 0) - grub_util_error ("couldn't open geom"); + grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) { @@ -989,7 +991,7 @@ grub_util_pull_device (const char *os_dev) LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer) break; if (!consumer) - grub_util_error ("couldn't find geli consumer"); + grub_util_error (_("couldn't find geli consumer")); fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name); grub_util_info ("consumer %s", consumer->lg_provider->lg_name); lastsubdev = consumer->lg_provider->lg_name; @@ -1009,7 +1011,7 @@ grub_util_pull_device (const char *os_dev) grub_err_t err; err = grub_cryptodisk_cheat_mount (grdev, os_dev); if (err) - grub_util_error ("Can't mount crypto: %s", grub_errmsg); + grub_util_error (_("Can't mount crypto: %s"), _(grub_errmsg)); } grub_free (grdev); @@ -1053,7 +1055,7 @@ grub_util_pull_device (const char *os_dev) grub_err_t err; err = grub_cryptodisk_cheat_mount (grdev, os_dev); if (err) - grub_util_error ("Can't mount crypto: %s", grub_errmsg); + grub_util_error (_("Can't mount crypto: %s"), _(grub_errmsg)); } grub_free (grdev); } @@ -1141,7 +1143,7 @@ grub_util_get_grub_dev (const char *os_dev) error = geom_gettree (&mesh); if (error != 0) - grub_util_error ("couldn't open geom"); + grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) { @@ -1159,11 +1161,11 @@ grub_util_get_grub_dev (const char *os_dev) LIST_FOREACH (consumer, &geom->lg_consumer, lg_consumer) break; if (!consumer) - grub_util_error ("couldn't find geli consumer"); + grub_util_error (_("couldn't find geli consumer")); fname = xasprintf ("/dev/%s", consumer->lg_provider->lg_name); uuid = grub_util_get_geli_uuid (fname); if (!uuid) - grub_util_error ("couldn't retrieve geli UUID"); + grub_util_error (_("couldn't retrieve geli UUID")); grub_dev = xasprintf ("cryptouuid/%s", uuid); free (fname); free (uuid); @@ -1248,7 +1250,7 @@ grub_util_get_grub_dev (const char *os_dev) free (p); } else - grub_util_error ("unknown kind of RAID device `%s'", os_dev); + grub_util_error (_("unknown kind of RAID device `%s'"), os_dev); { char *mdadm_name = get_mdadm_uuid (os_dev); @@ -1290,7 +1292,7 @@ grub_util_check_block_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error ("cannot stat `%s'", blk_dev); + grub_util_error (_("cannot stat `%s'"), blk_dev); if (S_ISBLK (st.st_mode)) return (blk_dev); @@ -1304,7 +1306,7 @@ grub_util_check_char_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error ("cannot stat `%s'", blk_dev); + grub_util_error (_("cannot stat `%s'"), blk_dev); if (S_ISCHR (st.st_mode)) return (blk_dev); @@ -1320,7 +1322,7 @@ get_win32_path (const char *path) { char winpath[PATH_MAX]; if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, path, winpath, sizeof(winpath))) - grub_util_error ("cygwin_conv_path() failed"); + grub_util_error (_("cygwin_conv_path() failed")); int len = strlen (winpath); int offs = (len > 2 && winpath[1] == ':' ? 2 : 0); @@ -1438,7 +1440,7 @@ grub_make_system_path_relative_to_its_root (const char *path) /* canonicalize. */ p = canonicalize_file_name (path); if (p == NULL) - grub_util_error ("failed to get canonical path of %s", path); + grub_util_error (_("failed to get canonical path of %s"), path); #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */ @@ -1453,7 +1455,7 @@ grub_make_system_path_relative_to_its_root (const char *path) free (p); if (stat (buf, &st) < 0) - grub_util_error ("cannot stat %s: %s", buf, strerror (errno)); + grub_util_error (_("cannot stat %s: %s"), buf, strerror (errno)); buf2 = xstrdup (buf); num = st.st_dev; @@ -1465,14 +1467,14 @@ grub_make_system_path_relative_to_its_root (const char *path) p = strrchr (buf, '/'); if (p == NULL) /* This should never happen. */ - grub_util_error ("FIXME: no / in buf. (make_system_path_relative_to_its_root)"); + grub_util_error (_("FIXME: no / in buf. (make_system_path_relative_to_its_root)")); if (p != buf) *p = 0; else *++p = 0; if (stat (buf, &st) < 0) - grub_util_error ("cannot stat %s: %s", buf, strerror (errno)); + grub_util_error (_("cannot stat %s: %s"), buf, strerror (errno)); /* buf is another filesystem; we found it. */ if (st.st_dev != num) diff --git a/util/grub-editenv.c b/util/grub-editenv.c index 519945411..2bff80612 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -115,26 +115,26 @@ create_envblk_file (const char *name) buf = malloc (DEFAULT_ENVBLK_SIZE); if (! buf) - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); namenew = xasprintf ("%s.new", name); fp = fopen (namenew, "wb"); if (! fp) - grub_util_error ("cannot open the file %s", namenew); + grub_util_error (_("cannot open the file %s"), namenew); memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); if (fwrite (buf, 1, DEFAULT_ENVBLK_SIZE, fp) != DEFAULT_ENVBLK_SIZE) - grub_util_error ("cannot write to the file %s", namenew); + grub_util_error (_("cannot write to the file %s"), namenew); fsync (fileno (fp)); free (buf); fclose (fp); if (rename (namenew, name) < 0) - grub_util_error ("cannot rename the file %s to %s", namenew, name); + grub_util_error (_("cannot rename the file %s to %s"), namenew, name); free (namenew); } @@ -153,29 +153,29 @@ open_envblk_file (const char *name) create_envblk_file (name); fp = fopen (name, "rb"); if (! fp) - grub_util_error ("cannot open the file %s", name); + grub_util_error (_("cannot open the file %s"), name); } if (fseek (fp, 0, SEEK_END) < 0) - grub_util_error ("cannot seek the file %s", name); + grub_util_error (_("cannot seek the file %s"), name); size = (size_t) ftell (fp); if (fseek (fp, 0, SEEK_SET) < 0) - grub_util_error ("cannot seek the file %s", name); + grub_util_error (_("cannot seek the file %s"), name); buf = malloc (size); if (! buf) - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); if (fread (buf, 1, size, fp) != size) - grub_util_error ("cannot read the file %s", name); + grub_util_error (_("cannot read the file %s"), name); fclose (fp); envblk = grub_envblk_open (buf, size); if (! envblk) - grub_util_error ("invalid environment block"); + grub_util_error (_("invalid environment block")); return envblk; } @@ -204,11 +204,11 @@ write_envblk (const char *name, grub_envblk_t envblk) fp = fopen (name, "wb"); if (! fp) - grub_util_error ("cannot open the file %s", name); + grub_util_error (_("cannot open the file %s"), name); if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp) != grub_envblk_size (envblk)) - grub_util_error ("cannot write to the file %s", name); + grub_util_error (_("cannot write to the file %s"), name); fsync (fileno (fp)); fclose (fp); @@ -226,12 +226,12 @@ set_variables (const char *name, int argc, char *argv[]) p = strchr (argv[0], '='); if (! p) - grub_util_error ("invalid parameter %s", argv[0]); + grub_util_error (_("invalid parameter %s"), argv[0]); *(p++) = 0; if (! grub_envblk_set (envblk, argv[0], p)) - grub_util_error ("environment block too small"); + grub_util_error (_("environment block too small")); argc--; argv++; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 47b536771..c9f24ff08 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -395,11 +395,11 @@ fstest (int n, char **args) if (!fs) grub_util_error (grub_errmsg); if (!fs->uuid) - grub_util_error ("couldn't retrieve UUID"); + grub_util_error (_("couldn't retrieve UUID")); if (fs->uuid (dev, &uuid)) grub_util_error (grub_errmsg); if (!uuid) - grub_util_error ("couldn't retrieve UUID"); + grub_util_error (_("couldn't retrieve UUID")); argv[1] = uuid; execute_command ("xnu_uuid", 2, argv); grub_free (uuid); @@ -470,7 +470,7 @@ argp_parser (int key, char *arg, struct argp_state *state) if (strcmp (arg, "prompt") == 0) { char buf[1024]; - grub_printf ("Enter ZFS password: "); + grub_puts_ (N_("Enter ZFS password: ")); if (grub_password_get (buf, 1023)) { grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1); @@ -484,13 +484,13 @@ argp_parser (int key, char *arg, struct argp_state *state) f = fopen (arg, "rb"); if (!f) { - printf ("Error loading file %s: %s\n", arg, strerror (errno)); + printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); return 0; } real_size = fread (buf, 1, 1024, f); if (real_size < 0) { - printf ("Error loading file %s: %s\n", arg, strerror (errno)); + printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); fclose (f); return 0; } diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index 3108d4694..1fad15660 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -121,9 +121,10 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_name); else - printf ("\ + printf (_("\ Usage: %s [OPTIONS] FONT_FILES\n\ \nOptions:\n\ -o, --output=FILE_NAME set output file name\n\ @@ -143,7 +144,7 @@ Usage: %s [OPTIONS] FONT_FILES\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ \n\ -Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); +Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); exit (status); } @@ -188,12 +189,12 @@ add_glyph (struct grub_font_info *font_info, FT_UInt glyph_idx, FT_Face face, err = FT_Load_Glyph (face, glyph_idx, flag); if (err) { - printf ("Freetype Error %d loading glyph 0x%x for U+0x%x%s", + printf (_("Freetype Error %d loading glyph 0x%x for U+0x%x%s"), err, glyph_idx, char_code & GRUB_FONT_CODE_CHAR_MASK, char_code & GRUB_FONT_CODE_RIGHT_JOINED - ? ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (medial)": - " (leftmost)") - : ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? " (rightmost)": + ? ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? _(" (medial)"): + _(" (leftmost)")) + : ((char_code & GRUB_FONT_CODE_LEFT_JOINED) ? _(" (rightmost)"): "")); if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) @@ -519,7 +520,7 @@ process_cursive (struct gsub_feature *feature, if (substtype == GSUB_SUBSTITUTION_DELTA) add_subst (glyph, glyph + grub_be_to_cpu16 (sub->delta), target); else if (i >= grub_be_to_cpu16 (sub->count)) - printf ("Out of range substitution (%d, %d)\n", i, + printf (_("Out of range substitution (%d, %d)\n"), i, grub_be_to_cpu16 (sub->count)); else add_subst (glyph, grub_be_to_cpu16 (sub->repl[i++]), target); @@ -531,7 +532,7 @@ process_cursive (struct gsub_feature *feature, struct gsub_lookup *lookup; if (lookup_index >= grub_be_to_cpu16 (lookups->count)) { - printf ("Out of range lookup: %d\n", lookup_index); + printf (_("Out of range lookup: %d\n"), lookup_index); continue; } lookup = (struct gsub_lookup *) @@ -539,13 +540,13 @@ process_cursive (struct gsub_feature *feature, + grub_be_to_cpu16 (lookups->offsets[lookup_index])); if (grub_be_to_cpu16 (lookup->type) != GSUB_SINGLE_SUBSTITUTION) { - printf ("Unsupported substitution type: %d\n", + printf (_("Unsupported substitution type: %d\n"), grub_be_to_cpu16 (lookup->type)); continue; } if (grub_be_to_cpu16 (lookup->flag) & ~GSUB_RTL_CHAR) { - printf ("Unsupported substitution flag: 0x%x\n", + printf (_("Unsupported substitution flag: 0x%x\n"), grub_be_to_cpu16 (lookup->flag)); } switch (feattag) @@ -575,7 +576,7 @@ process_cursive (struct gsub_feature *feature, if (substtype != GSUB_SUBSTITUTION_MAP && substtype != GSUB_SUBSTITUTION_DELTA) { - printf ("Unsupported substitution specification: %d\n", + printf (_("Unsupported substitution specification: %d\n"), substtype); continue; } @@ -601,7 +602,7 @@ process_cursive (struct gsub_feature *feature, subst (m); } else - printf ("Unsupported coverage specification: %d\n", covertype); + printf (_("Unsupported coverage specification: %d\n"), covertype); } } } @@ -640,7 +641,7 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut) grub_uint32_t feattag = grub_be_to_cpu32 (features->features[i].feature_tag); if (feature->params) - printf ("WARNING: unsupported feature parameters: %x\n", + printf (_("WARNING: unsupported feature parameters: %x\n"), grub_be_to_cpu16 (feature->params)); switch (feattag) { @@ -670,7 +671,7 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut) for (j = 0; j < 4; j++) if (!grub_isgraph (str[j])) str[j] = '?'; - printf ("Unknown gsub feature 0x%x (%s)\n", feattag, str); + printf (_("Unknown gsub feature 0x%x (%s)\n"), feattag, str); } } } @@ -739,8 +740,8 @@ print_glyphs (struct grub_font_info *font_info) int x, y, xmax, xmin, ymax, ymin; grub_uint8_t *bitmap, mask; - printf ("\nGlyph #%d, U+%04x\n", num, glyph->char_code); - printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n", + printf (_("\nGlyph #%d, U+%04x\n"), num, glyph->char_code); + printf (_("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n"), glyph->width, glyph->height, glyph->x_ofs, glyph->y_ofs, glyph->device_width); @@ -807,7 +808,7 @@ write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error ("Can\'t write to file %s.", output_file); + grub_util_error (_("Can\'t write to file %s."), output_file); int correct_size; for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs; @@ -843,7 +844,7 @@ write_font_width_spec (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error ("Can\'t write to file %s.", output_file); + grub_util_error (_("Can\'t write to file %s."), output_file); for (glyph = font_info->glyphs_sorted; glyph < font_info->glyphs_sorted + font_info->num_glyphs; glyph++) @@ -866,7 +867,7 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error ("can\'t write to file %s.", output_file); + grub_util_error (_("Can\'t write to file %s."), output_file); offset = 0; @@ -1063,7 +1064,7 @@ main (int argc, char *argv[]) a = strtoul (p, &p, 0); if (*p != '-') - grub_util_error ("invalid font range"); + grub_util_error (_("invalid font range")); b = strtoul (p + 1, &p, 0); if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0) font_info.ranges = xrealloc (font_info.ranges, @@ -1078,7 +1079,7 @@ main (int argc, char *argv[]) if (*p) { if (*p != ',') - grub_util_error ("invalid font range"); + grub_util_error (_("invalid font range")); else p++; } @@ -1124,7 +1125,7 @@ main (int argc, char *argv[]) if (file_format == ASCII_BITMAPS && font_info.num_range > 0) { - grub_util_error ("Option --ascii-bitmaps doesn't accept ranges (use ASCII)."); + grub_util_error (_("Option --ascii-bitmaps doesn't accept ranges (use ASCII).")); return 1; } @@ -1140,10 +1141,10 @@ main (int argc, char *argv[]) } if (! output_file) - grub_util_error ("no output file is specified"); + grub_util_error (_("no output file is specified")); if (FT_Init_FreeType (&ft_lib)) - grub_util_error ("FT_Init_FreeType fails"); + grub_util_error (_("FT_Init_FreeType fails")); for (; optind < argc; optind++) { @@ -1154,8 +1155,8 @@ main (int argc, char *argv[]) err = FT_New_Face (ft_lib, argv[optind], font_index, &ft_face); if (err) { - grub_printf ("can't open file %s, index %d: error %d", argv[optind], - font_index, err); + grub_printf (_("can't open file %s, index %d: error %d"), + argv[optind], font_index, err); if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) printf (": %s\n", ft_errmsgs[err]); else @@ -1181,7 +1182,7 @@ main (int argc, char *argv[]) font_info.size = size; if (FT_Set_Pixel_Sizes (ft_face, size, size)) - grub_util_error ("can't set %dx%d font size", size, size); + grub_util_error (_("can't set %dx%d font size"), size, size); add_font (&font_info, ft_face, file_format != PF2); FT_Done_Face (ft_face); } diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index fb1c5babe..9369fba3d 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -703,7 +703,7 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img, if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS && (comp != COMPRESSION_NONE)) - grub_util_error ("unknown compression %d\n", comp); + grub_util_error (_("unknown compression %d\n"), comp); *core_img = xmalloc (kernel_size); memcpy (*core_img, kernel_img, kernel_size); @@ -945,7 +945,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], name = "none_decompress.img"; break; default: - grub_util_error ("unknown compression %d\n", comp); + grub_util_error (_("unknown compression %d\n"), comp); } decompress_path = grub_util_get_path (dir, name); @@ -1301,7 +1301,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], boot_path = grub_util_get_path (dir, "diskboot.img"); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("diskboot.img is not one sector size"); + grub_util_error (_("diskboot.img is not one sector size")); boot_img = grub_util_read_image (boot_path); @@ -1366,11 +1366,11 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], GRUB_MD_SHA512->final (context); if (grub_memcmp (GRUB_MD_SHA512->read (context), fwstart_good_hash, GRUB_MD_SHA512->mdlen) != 0) - grub_util_warn ("fwstart.img doesn't match the known good version. " - "Proceed at your own risk"); + grub_util_warn (_("fwstart.img doesn't match the known good version. " + "proceed at your own risk")); if (core_size + boot_size > 512 * 1024) - grub_util_error ("firmware image is too big"); + grub_util_error (_("firmware image is too big")); rom_size = 512 * 1024; rom_img = xmalloc (rom_size); @@ -1394,7 +1394,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], size_t rom_size; if (core_size > 512 * 1024) - grub_util_error ("firmware image is too big"); + grub_util_error (_("firmware image is too big")); rom_size = 512 * 1024; rom_img = xmalloc (rom_size); @@ -1762,7 +1762,7 @@ main (int argc, char *argv[]) image_target = &image_targets[i]; if (!image_target) { - printf ("unknown target format %s\n", optarg); + printf (_("unknown target format %s\n"), optarg); usage (1); } break; @@ -1803,14 +1803,14 @@ main (int argc, char *argv[]) #ifdef HAVE_LIBLZMA comp = COMPRESSION_XZ; #else - grub_util_error ("grub-mkimage is compiled without XZ support", + grub_util_error (_("grub-mkimage is compiled without XZ support"), optarg); #endif } else if (grub_strcmp (optarg, "none") == 0) comp = COMPRESSION_NONE; else - grub_util_error ("Unknown compression format %s", optarg); + grub_util_error (_("Unknown compression format %s"), optarg); break; case 'h': @@ -1840,7 +1840,7 @@ main (int argc, char *argv[]) if (!image_target) { - printf ("Target format not specified (use the -O option).\n"); + printf (_("Target format not specified (use the -O option).\n")); usage (1); } diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index f75f27611..9c676a100 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -46,16 +46,17 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), + program_name); else - printf ("\ + printf (_("\ Usage: %s [OPTIONS]\n\ \nOptions:\n\ -c number, --iteration-count=number Number of PBKDF2 iterations\n\ -l number, --buflen=number Length of generated hash\n\ -s number, --salt=number Length of salt\n\ \n\ -Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); +Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); exit (status); } @@ -135,12 +136,12 @@ main (int argc, char *argv[]) bufhex = malloc (buflen * 2 + 1); if (!bufhex) - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); buf = malloc (buflen); if (!buf) { free (bufhex); - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); } salt = malloc (saltlen); @@ -148,7 +149,7 @@ main (int argc, char *argv[]) { free (bufhex); free (buf); - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); } salthex = malloc (saltlen * 2 + 1); if (!salthex) @@ -156,26 +157,26 @@ main (int argc, char *argv[]) free (salt); free (bufhex); free (buf); - grub_util_error ("out of memory"); + grub_util_error (_("out of memory")); } - printf ("Enter password: "); + printf ("%s", _("Enter password: ")); if (!grub_password_get (pass1, GRUB_AUTH_MAX_PASSLEN)) { free (buf); free (bufhex); free (salthex); free (salt); - grub_util_error ("failure to read password"); + grub_util_error (_("failure to read password")); } - printf ("\nReenter password: "); + printf ("\n%s", _("Reenter password: ")); if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN)) { free (buf); free (bufhex); free (salthex); free (salt); - grub_util_error ("failure to read password"); + grub_util_error (_("failure to read password")); } if (strcmp (pass1, pass2) != 0) @@ -186,12 +187,12 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error ("passwords don't match"); + grub_util_error (_("passwords don't match")); } memset (pass2, 0, sizeof (pass2)); #if ! defined (__linux__) && ! defined (__FreeBSD__) - printf ("WARNING: your random generator isn't known to be secure\n"); + printf ("%s", _("WARNING: your random generator isn't known to be secure\n")); #endif { @@ -206,7 +207,7 @@ main (int argc, char *argv[]) free (salthex); free (salt); fclose (f); - grub_util_error ("couldn't retrieve random data for salt"); + grub_util_error (_("couldn't retrieve random data for salt")); } rd = fread (salt, 1, saltlen, f); if (rd != saltlen) @@ -217,7 +218,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error ("couldn't retrieve random data for salt"); + grub_util_error (_("couldn't retrieve random data for salt")); } fclose (f); } @@ -238,13 +239,13 @@ main (int argc, char *argv[]) memset (salthex, 0, 2 * saltlen); free (salt); free (salthex); - grub_util_error ("cryptographic error number %d", gcry_err); + grub_util_error (_("cryptographic error number %d"), gcry_err); } hexify (bufhex, buf, buflen); hexify (salthex, salt, saltlen); - printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", + printf (_("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n"), count, salthex, bufhex); memset (buf, 0, buflen); memset (bufhex, 0, 2 * buflen); diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c index 4b93faa05..51d41c9f0 100644 --- a/util/grub-pe2elf.c +++ b/util/grub-pe2elf.c @@ -31,6 +31,8 @@ #include "progname.h" +/* Please don't internationalise this file. It's pointless. */ + static struct option options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, diff --git a/util/grub-probe.c b/util/grub-probe.c index 54b9d03c6..795a9344e 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -173,10 +173,10 @@ probe (const char *path, char *device_name) { #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__sun__) if (! grub_util_check_char_device (device_name)) - grub_util_error ("%s is not a character device", device_name); + grub_util_error (_("%s is not a character device"), device_name); #else if (! grub_util_check_block_device (device_name)) - grub_util_error ("%s is not a block device", device_name); + grub_util_error (_("%s is not a block device"), device_name); #endif } else @@ -186,7 +186,7 @@ probe (const char *path, char *device_name) } if (! device_name) - grub_util_error ("cannot find a device for %s (is /dev mounted?)", path); + grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path); if (print == PRINT_DEVICE) { @@ -196,7 +196,8 @@ probe (const char *path, char *device_name) drive_name = grub_util_get_grub_dev (device_name); if (! drive_name) - grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name); + grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), + device_name); if (print == PRINT_DRIVE) { @@ -207,7 +208,7 @@ probe (const char *path, char *device_name) grub_util_info ("opening %s", drive_name); dev = grub_device_open (drive_name); if (! dev) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); if (print == PRINT_ABSTRACTION) { @@ -233,7 +234,7 @@ probe (const char *path, char *device_name) fs = grub_fs_probe (dev); if (! fs) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); if (print == PRINT_FS) { @@ -243,7 +244,7 @@ probe (const char *path, char *device_name) { char *uuid; if (! fs->uuid) - grub_util_error ("%s does not support UUIDs", fs->name); + grub_util_error (_("%s does not support UUIDs"), fs->name); if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) grub_util_error ("%s", grub_errmsg); @@ -254,10 +255,10 @@ probe (const char *path, char *device_name) { char *label; if (! fs->label) - grub_util_error ("%s does not support labels", fs->name); + grub_util_error (_("%s does not support labels"), fs->name); if (fs->label (dev, &label) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); printf ("%s\n", label); } @@ -287,9 +288,9 @@ usage (int status) { if (status) fprintf (stderr, - "Try `%s --help' for more information.\n", program_name); + _("Try `%s --help' for more information.\n"), program_name); else - printf ("\ + printf (_("\ Usage: %s [OPTION]... [PATH|DEVICE]\n\ \n\ Probe device information for a given path (or device, if the -d option is given).\n\ @@ -303,7 +304,7 @@ Probe device information for a given path (or device, if the -d option is given) -v, --verbose print verbose messages\n\ \n\ Report bugs to <%s>.\n\ -", program_name, +"), program_name, DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); exit (status); @@ -385,13 +386,13 @@ main (int argc, char *argv[]) /* Obtain ARGUMENT. */ if (optind >= argc) { - fprintf (stderr, "No path or device is specified.\n"); + fprintf (stderr, _("No path or device is specified.\n")); usage (1); } if (optind + 1 != argc) { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); + fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); usage (1); } diff --git a/util/grub-setup.c b/util/grub-setup.c index d3f6fe8b8..f185ed747 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -125,8 +125,8 @@ write_rootdev (char *core_img, grub_device_t root_dev, if (root_dev->disk->partition->parent) { if (root_dev->disk->partition->parent->parent) - grub_util_error ("Installing on doubly nested partitions is " - "not supported"); + grub_util_error (_("Installing on doubly nested partitions " + "is not supported")); dos_part = root_dev->disk->partition->parent->number; bsd_part = root_dev->disk->partition->number; } @@ -283,22 +283,22 @@ setup (const char *dir, grub_util_info ("Opening root"); root_dev = grub_device_open (root); if (! root_dev) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); grub_util_info ("Opening dest"); dest_dev = grub_device_open (dest); if (! dest_dev) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); grub_util_info ("setting the root device to `%s'", root); if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); #ifdef GRUB_MACHINE_PCBIOS /* Read the original sector from the disk. */ tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); #endif #ifdef GRUB_MACHINE_PCBIOS @@ -421,14 +421,14 @@ setup (const char *dir, if (dest_partmap && !dest_partmap->embed) { - grub_util_warn ("Partition style '%s' doesn't support embeding", + grub_util_warn (_("Partition style '%s' doesn't support embeding"), dest_partmap->name); goto unable_to_embed; } if (fs && !fs->embed) { - grub_util_warn ("File system '%s' doesn't support embeding", + grub_util_warn (_("File system '%s' doesn't support embeding"), fs->name); goto unable_to_embed; } @@ -443,13 +443,13 @@ setup (const char *dir, if (!err && nsec < core_sectors) { err = grub_error (GRUB_ERR_OUT_OF_RANGE, - "Your embedding area is unusually small. " - "core.img won't fit in it."); + N_("Your embedding area is unusually small. " + "core.img won't fit in it.")); } if (err) { - grub_util_warn ("%s", grub_errmsg); + grub_util_warn ("%s", _(grub_errmsg)); grub_errno = GRUB_ERR_NONE; goto unable_to_embed; } @@ -466,7 +466,7 @@ setup (const char *dir, block--; if ((char *) block <= core_img) - grub_util_error ("No terminator in the core image"); + grub_util_error (_("No terminator in the core image")); } save_first_sector (sectors[0] + grub_partition_get_start (container), @@ -626,7 +626,7 @@ unable_to_embed: grub_file_filter_disable_compression (); file = grub_file_open (core_path_dev); if (! file) - grub_util_error ("%s", grub_errmsg); + grub_util_error ("%s", _(grub_errmsg)); file->read_hook = save_first_sector; if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) @@ -687,8 +687,7 @@ unable_to_embed: /* Write the boot image onto the disk. */ if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", grub_errmsg); - + grub_util_error ("%s", _(grub_errmsg)); grub_util_biosdisk_flush (root_dev->disk); grub_util_biosdisk_flush (dest_dev->disk); diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c index f72bea8a5..20a571191 100644 --- a/util/ieee1275/ofpath.c +++ b/util/ieee1275/ofpath.c @@ -23,6 +23,7 @@ #include #include #include +#include #endif #include @@ -53,6 +54,7 @@ grub_util_error (const char *fmt, ...) exit (1); } +#define _(x) x #endif static void @@ -106,7 +108,7 @@ find_obppath(char *of_path, const char *sysfs_path_orig) { kill_trailing_dir(sysfs_path); if (!strcmp(sysfs_path, "/sys")) - grub_util_error("'obppath' not found in parent dirs of %s", + grub_util_error(_("'obppath' not found in parent dirs of %s"), sysfs_path_orig); continue; } @@ -131,12 +133,12 @@ block_device_get_sysfs_path_and_link(const char *devicenode, snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode); if (!realpath (sysfs_path, rpath)) - grub_util_error ("cannot get the real path of `%s'", sysfs_path); + grub_util_error (_("cannot get the real path of `%s'"), sysfs_path); strcat(rpath, "/device"); if (!realpath (rpath, sysfs_path)) - grub_util_error ("cannot get the real path of `%s'", rpath); + grub_util_error (_("cannot get the real path of `%s'"), rpath); free (rpath); } @@ -247,12 +249,12 @@ vendor_is_ATA(const char *path) snprintf(buf, PATH_MAX, "%s/vendor", path); fd = open(buf, O_RDONLY); if (fd < 0) - grub_util_error ("cannot open 'vendor' node of `%s'", path); + grub_util_error (_("cannot open 'vendor' node of `%s'"), path); memset(buf, 0, PATH_MAX); err = read(fd, buf, PATH_MAX); if (err < 0) - grub_util_error ("cannot read 'vendor' node of `%s'", path); + grub_util_error (_("cannot read 'vendor' node of `%s'"), path); close(fd); @@ -288,7 +290,7 @@ check_sas (char *sysfs_path, int *tgt) fd = open(path, O_RDONLY); if (fd < 0) - grub_util_error("cannot open SAS PHY ID `%s'\n", path); + grub_util_error(_("cannot open SAS PHY ID `%s'\n"), path); memset (phy, 0, sizeof (phy)); read (fd, phy, sizeof (phy)); @@ -376,7 +378,7 @@ grub_util_devname_to_ofpath (const char *devname) name_buf = xmalloc (PATH_MAX); name_buf = realpath (devname, name_buf); if (! name_buf) - grub_util_error ("cannot get the real path of `%s'", devname); + grub_util_error (_("cannot get the real path of `%s'"), devname); device = get_basename (name_buf); devnode = strip_trailing_digits (name_buf); @@ -398,7 +400,7 @@ grub_util_devname_to_ofpath (const char *devname) New models have no floppy at all. */ strcpy (ofpath, "floppy"); else - grub_util_error ("unknown device type %s\n", device); + grub_util_error (_("unknown device type %s\n"), device); free (devnode); free (devicenode); @@ -414,7 +416,7 @@ int main(int argc, char **argv) if (argc != 2) { - printf("Usage: grub-ofpathname DEVICE\n"); + printf(_("Usage: %s DEVICE\n"), argv[0]); return 1; } diff --git a/util/misc.c b/util/misc.c index 72bedde0c..6ebaf30bc 100644 --- a/util/misc.c +++ b/util/misc.c @@ -89,10 +89,10 @@ grub_util_get_fp_size (FILE *fp) struct stat st; if (fflush (fp) == EOF) - grub_util_error ("fflush failed"); + grub_util_error (_("fflush failed")); if (fstat (fileno (fp), &st) == -1) - grub_util_error ("fstat failed"); + grub_util_error (_("fstat failed")); return st.st_size; } @@ -105,7 +105,7 @@ grub_util_get_image_size (const char *path) grub_util_info ("getting the size of %s", path); if (stat (path, &st) == -1) - grub_util_error ("cannot stat %s", path); + grub_util_error (_("cannot stat %s"), path); return st.st_size; } @@ -114,10 +114,10 @@ void grub_util_read_at (void *img, size_t size, off_t offset, FILE *fp) { if (fseeko (fp, offset, SEEK_SET) == -1) - grub_util_error ("seek failed"); + grub_util_error (_("seek failed")); if (fread (img, 1, size, fp) != size) - grub_util_error ("read failed"); + grub_util_error (_("read failed")); } char * @@ -134,7 +134,7 @@ grub_util_read_image (const char *path) fp = fopen (path, "rb"); if (! fp) - grub_util_error ("cannot open %s", path); + grub_util_error (_("cannot open %s"), path); grub_util_read_at (img, size, 0, fp); @@ -155,10 +155,10 @@ grub_util_load_image (const char *path, char *buf) fp = fopen (path, "rb"); if (! fp) - grub_util_error ("cannot open %s", path); + grub_util_error (_("cannot open %s"), path); if (fread (buf, 1, size, fp) != size) - grub_util_error ("cannot read %s", path); + grub_util_error (_("cannot read %s"), path); fclose (fp); } @@ -168,9 +168,9 @@ grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out) { grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset); if (fseeko (out, offset, SEEK_SET) == -1) - grub_util_error ("seek failed"); + grub_util_error (_("seek failed")); if (fwrite (img, 1, size, out) != size) - grub_util_error ("write failed"); + grub_util_error (_("write failed")); } void @@ -178,7 +178,7 @@ grub_util_write_image (const char *img, size_t size, FILE *out) { grub_util_info ("writing 0x%x bytes", size); if (fwrite (img, 1, size, out) != size) - grub_util_error ("write failed"); + grub_util_error (_("write failed")); } char * diff --git a/util/raid.c b/util/raid.c index 1e312491b..8de5fbac0 100644 --- a/util/raid.c +++ b/util/raid.c @@ -33,6 +33,7 @@ #include #include #include +#include char ** grub_util_raid_getmembers (const char *name, int bootable) @@ -46,26 +47,26 @@ grub_util_raid_getmembers (const char *name, int bootable) fd = open (name, O_RDONLY); if (fd == -1) - grub_util_error ("can't open %s: %s", name, strerror (errno)); + grub_util_error (_("can't open %s: %s"), name, strerror (errno)); ret = ioctl (fd, RAID_VERSION, &version); if (ret != 0) - grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno)); + grub_util_error (_("ioctl RAID_VERSION error: %s"), strerror (errno)); if ((version.major != 0 || version.minor != 90) && (version.major != 1 || version.minor != 0) && (version.major != 1 || version.minor != 1) && (version.major != 1 || version.minor != 2)) - grub_util_error ("unsupported RAID version: %d.%d", + grub_util_error (_("unsupported RAID version: %d.%d"), version.major, version.minor); if (bootable && (version.major != 0 || version.minor != 90)) - grub_util_error ("unsupported RAID version: %d.%d", + grub_util_error (_("unsupported RAID version: %d.%d"), version.major, version.minor); ret = ioctl (fd, GET_ARRAY_INFO, &info); if (ret != 0) - grub_util_error ("ioctl GET_ARRAY_INFO error: %s", strerror (errno)); + grub_util_error (_("ioctl GET_ARRAY_INFO error: %s"), strerror (errno)); devicelist = xmalloc ((info.nr_disks + 1) * sizeof (char *)); @@ -74,7 +75,7 @@ grub_util_raid_getmembers (const char *name, int bootable) disk.number = i; ret = ioctl (fd, GET_DISK_INFO, &disk); if (ret != 0) - grub_util_error ("ioctl GET_DISK_INFO error: %s", strerror (errno)); + grub_util_error (_("ioctl GET_DISK_INFO error: %s"), strerror (errno)); if (disk.state & (1 << MD_DISK_ACTIVE)) { From f1f233ba430c27cbc6a327751bd3da53798cdf2f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 00:56:20 +0100 Subject: [PATCH 548/673] Add crypto support to grub-mount --- Makefile.util.def | 1 + util/grub-mount.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/Makefile.util.def b/Makefile.util.def index 567747fc7..5f655b73d 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -246,6 +246,7 @@ program = { common = grub-core/disk/host.c; ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; ldadd = libgrubkern.a; ldadd = grub-core/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse'; diff --git a/util/grub-mount.c b/util/grub-mount.c index 434772eec..7c75acd15 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,7 @@ static char *debug_str = NULL; static char **fuse_args = NULL; static int fuse_argc = 0; static int num_disks = 0; +static int mount_crypt = 0; static grub_err_t execute_command (char *name, int n, char **args) @@ -333,6 +335,13 @@ fuse_init (void) grub_free (host_file); } + if (mount_crypt) + { + char *argv[2] = { "-a", NULL}; + if (execute_command ("cryptomount", 1, argv)) + grub_util_error (_("cryptomount command fails: %s"), grub_errmsg); + } + grub_lvm_fini (); grub_mdraid09_fini (); grub_mdraid1x_fini (); @@ -378,6 +387,8 @@ fuse_init (void) static struct argp_option options[] = { {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, + {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, + {"zfs-key", 'K', N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2}, {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, {0, 0, 0, 0, 0, 0} }; @@ -401,6 +412,42 @@ argp_parser (int key, char *arg, struct argp_state *state) root = arg; return 0; + case 'K': + if (strcmp (arg, "prompt") == 0) + { + char buf[1024]; + grub_printf ("Enter ZFS password: "); + if (grub_password_get (buf, 1023)) + { + grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1); + } + } + else + { + FILE *f; + ssize_t real_size; + grub_uint8_t buf[1024]; + f = fopen (arg, "rb"); + if (!f) + { + printf ("Error loading file %s: %s\n", arg, strerror (errno)); + return 0; + } + real_size = fread (buf, 1, 1024, f); + if (real_size < 0) + { + printf ("Error loading file %s: %s\n", arg, strerror (errno)); + fclose (f); + return 0; + } + grub_zfs_add_key (buf, real_size, 0); + } + return 0; + + case 'C': + mount_crypt = 1; + return 0; + case 'd': debug_str = arg; return 0; From d8e62bbeb95c357ac597db5ce28df20f7a9d9823 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 01:19:06 +0100 Subject: [PATCH 549/673] gettextize --- util/grub-mount.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index 7c75acd15..f084fbf98 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -416,7 +416,7 @@ argp_parser (int key, char *arg, struct argp_state *state) if (strcmp (arg, "prompt") == 0) { char buf[1024]; - grub_printf ("Enter ZFS password: "); + grub_printf ("%s", _("Enter ZFS password: ")); if (grub_password_get (buf, 1023)) { grub_zfs_add_key ((grub_uint8_t *) buf, grub_strlen (buf), 1); @@ -430,13 +430,13 @@ argp_parser (int key, char *arg, struct argp_state *state) f = fopen (arg, "rb"); if (!f) { - printf ("Error loading file %s: %s\n", arg, strerror (errno)); + printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); return 0; } real_size = fread (buf, 1, 1024, f); if (real_size < 0) { - printf ("Error loading file %s: %s\n", arg, strerror (errno)); + printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); fclose (f); return 0; } @@ -507,7 +507,7 @@ main (int argc, char *argv[]) argp_parse (&argp, argc, argv, 0, 0, 0); if (num_disks < 2) - grub_util_error ("need an image and mountpoint"); + grub_util_error (_("need an image and mountpoint")); fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0])); fuse_args[fuse_argc] = images[num_disks - 1]; fuse_argc++; From ae60d685fad88cb461b6479ee28115c1d5251293 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 01:20:23 +0100 Subject: [PATCH 550/673] fill attr on readdir --- util/grub-mount.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/util/grub-mount.c b/util/grub-mount.c index f084fbf98..a4be21738 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -281,7 +281,26 @@ fuse_readdir (const char *path, void *buf, const struct grub_dirhook_info *info); int call_fill (const char *filename, const struct grub_dirhook_info *info) { - fill (buf, filename, NULL, 0); + struct stat st; + grub_memset (&st, 0, sizeof (st)); + st.st_mode = info->dir ? (0555 | S_IFDIR) : (0444 | S_IFREG); + if (!info->dir) + { + grub_file_t file; + char *tmp; + tmp = xasprintf ("%s/%s", path, filename); + file = grub_file_open (tmp); + free (tmp); + if (! file) + return translate_error (); + st.st_size = file->size; + grub_file_close (file); + } + st.st_blksize = 512; + st.st_blocks = (st.st_size + 511) >> 9; + st.st_atime = st.st_mtime = st.st_ctime + = info->mtimeset ? info->mtime : 0; + fill (buf, filename, &st, 0); return 0; } From 2b23074a0c082219fe4490fa05b13a481b34b41e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 16:29:04 +0100 Subject: [PATCH 551/673] Move assembly code to C by using intwrap. It increases core size by 88 bytes but improves compatibility and maintainability. * grub-core/kern/i386/pc/startup.S (grub_console_putchar): Moved to ... * grub-core/term/i386/pc/console.c (grub_console_putchar_real): ... here. Translated to C. * grub-core/kern/i386/pc/startup.S (grub_console_getkey): Moved to ... * grub-core/term/i386/pc/console.c (grub_console_getkey): ... here. Translated to C. * grub-core/kern/i386/pc/startup.S (grub_console_getxy): Moved to ... * grub-core/term/i386/pc/console.c (grub_console_getxy): ... here. Translated to C. * grub-core/kern/i386/pc/startup.S (grub_console_gotoxy): Moved to ... * grub-core/term/i386/pc/console.c (grub_console_gotoxy): ... here. Translated to C. * grub-core/kern/i386/pc/startup.S (grub_console_cls): Moved to ... * grub-core/term/i386/pc/console.c (grub_console_cls): ... here. Translated to C. * grub-core/kern/i386/pc/startup.S (grub_console_setcursor): Moved to .. * grub-core/term/i386/pc/console.c (grub_console_setcursor): ... here. Translated to C. * grub-core/kern/i386/pc/startup.S (grub_get_rtc): Moved to .. * grub-core/kern/i386/pc/init.c (grub_get_rtc): ... here. Translated to C. * grub-core/term/i386/pc/console.c (int10_9): New function. (grub_console_putchar): Likewise. * include/grub/i386/pc/console.h: Removed the not anymore shared functions. --- ChangeLog | 31 +++ grub-core/kern/i386/pc/init.c | 16 ++ grub-core/kern/i386/pc/startup.S | 365 ------------------------------- grub-core/term/i386/pc/console.c | 219 +++++++++++++++++++ include/grub/i386/pc/console.h | 10 - 5 files changed, 266 insertions(+), 375 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7743aa2d4..3d8bd25e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2011-11-12 Vladimir Serbinenko + + Move assembly code to C by using intwrap. It increases core size + by 88 bytes but improves compatibility and maintainability. + + * grub-core/kern/i386/pc/startup.S (grub_console_putchar): Moved to ... + * grub-core/term/i386/pc/console.c (grub_console_putchar_real): + ... here. Translated to C. + * grub-core/kern/i386/pc/startup.S (grub_console_getkey): Moved to ... + * grub-core/term/i386/pc/console.c (grub_console_getkey): + ... here. Translated to C. + * grub-core/kern/i386/pc/startup.S (grub_console_getxy): Moved to ... + * grub-core/term/i386/pc/console.c (grub_console_getxy): + ... here. Translated to C. + * grub-core/kern/i386/pc/startup.S (grub_console_gotoxy): Moved to ... + * grub-core/term/i386/pc/console.c (grub_console_gotoxy): + ... here. Translated to C. + * grub-core/kern/i386/pc/startup.S (grub_console_cls): Moved to ... + * grub-core/term/i386/pc/console.c (grub_console_cls): + ... here. Translated to C. + * grub-core/kern/i386/pc/startup.S (grub_console_setcursor): Moved to .. + * grub-core/term/i386/pc/console.c (grub_console_setcursor): + ... here. Translated to C. + * grub-core/kern/i386/pc/startup.S (grub_get_rtc): Moved to .. + * grub-core/kern/i386/pc/init.c (grub_get_rtc): ... here. + Translated to C. + * grub-core/term/i386/pc/console.c (int10_9): New function. + (grub_console_putchar): Likewise. + * include/grub/i386/pc/console.h: Removed the not anymore shared + functions. + 2011-11-12 Vladimir Serbinenko Move grub_chainloader_real_boot out of the kernel. diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index be26fdea1..6fbfab3b8 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -47,6 +47,22 @@ static int num_regions; void (*grub_pc_net_config) (char **device, char **path); +/* + * return the real time in ticks, of which there are about + * 18-20 per second + */ +grub_uint32_t +grub_get_rtc (void) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x1a, ®s); + + return (regs.ecx << 16) | (regs.edx & 0xffff); +} + void grub_machine_get_bootlocation (char **device, char **path) { diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index df8992278..94d4f02ee 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -464,371 +464,6 @@ FUNCTION(grub_exit) ljmp $0xf000, $0xfff0 .code32 -/* - * void grub_console_putchar (int c) - * - * Put the character C on the console. Because GRUB wants to write a - * character with an attribute, this implementation is a bit tricky. - * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh - * (TELETYPE OUTPUT). Otherwise, save the original position, put a space, - * save the current position, restore the original position, write the - * character and the attribute, and restore the current position. - * - * The reason why this is so complicated is that there is no easy way to - * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't - * support setting a background attribute. - */ -FUNCTION(grub_console_putchar) - /* Retrieve the base character. */ - movl 0(%edx), %edx - pusha - movb EXT_C(grub_console_cur_color), %bl - - call prot_to_real - .code16 - movb %dl, %al - xorb %bh, %bh - - /* use teletype output if control character */ - cmpb $0x7, %al - je 1f - cmpb $0x8, %al - je 1f - cmpb $0xa, %al - je 1f - cmpb $0xd, %al - je 1f - - /* save the character and the attribute on the stack */ - pushw %ax - pushw %bx - - /* get the current position */ - movb $0x3, %ah - int $0x10 - - /* check the column with the width */ - cmpb $79, %dl - jl 2f - - /* print CR and LF, if next write will exceed the width */ - movw $0x0e0d, %ax - int $0x10 - movb $0x0a, %al - int $0x10 - - /* get the current position */ - movb $0x3, %ah - int $0x10 - -2: - /* restore the character and the attribute */ - popw %bx - popw %ax - - /* write the character with the attribute */ - movb $0x9, %ah - movw $1, %cx - int $0x10 - - /* move the cursor forward */ - incb %dl - movb $0x2, %ah - int $0x10 - - jmp 3f - -1: movw $1, %bx - movb $0xe, %ah - int $0x10 - -3: DATA32 call real_to_prot - .code32 - - popa - ret - - -LOCAL(bypass_table): - .word 0x011b, 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r' - .word 0x1c00 | '\n' -LOCAL(bypass_table_end): - -/* - * int grub_console_getkey (void) - * if there is a character pending, return it; otherwise return -1 - * BIOS call "INT 16H Function 01H" to check whether a character is pending - * Call with %ah = 0x1 - * Return: - * If key waiting to be input: - * %ah = keyboard scan code - * %al = ASCII character - * Zero flag = clear - * else - * Zero flag = set - * BIOS call "INT 16H Function 00H" to read character from keyboard - * Call with %ah = 0x0 - * Return: %ah = keyboard scan code - * %al = ASCII character - */ - -FUNCTION(grub_console_getkey) - pushl %ebp - pushl %edi - - call prot_to_real - .code16 - - /* - * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would - * cause the machine to hang at the second keystroke. However, we can - * work around this problem by ensuring the presence of keystroke with - * INT 16/AH = 1 before calling INT 16/AH = 0. - */ - - movb $1, %ah - int $0x16 - jz notpending - - movb $0, %ah - int $0x16 - - xorl %edx, %edx - movw %ax, %dx /* real_to_prot uses %eax */ - - DATA32 call real_to_prot - .code32 - - movl $0xff, %eax - testl %eax, %edx - jz 1f - - andl %edx, %eax - cmpl $0x20, %eax - jae 2f - movl %edx, %eax - leal LOCAL(bypass_table), %edi - movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) >> 1), %ecx - repne scasw - jz 3f - - andl $0xff, %eax - addl $(('a' - 1) | GRUB_TERM_CTRL), %eax - jmp 2f -3: - andl $0xff, %eax - jmp 2f - -1: movl %edx, %eax - shrl $8, %eax - orl $GRUB_TERM_EXTENDED, %eax -2: - popl %edi - popl %ebp - ret - -notpending: - .code16 - DATA32 call real_to_prot - .code32 -#if GRUB_TERM_NO_KEY != 0 -#error Fix this asm code -#endif - jmp 2b - - -/* - * grub_uint16_t grub_console_getxy (void) - * BIOS call "INT 10H Function 03h" to get cursor position - * Call with %ah = 0x03 - * %bh = page - * Returns %ch = starting scan line - * %cl = ending scan line - * %dh = row (0 is top) - * %dl = column (0 is left) - */ - - -FUNCTION(grub_console_getxy) - pushl %ebp - pushl %ebx /* save EBX */ - - call prot_to_real - .code16 - - xorb %bh, %bh /* set page to 0 */ - movb $0x3, %ah - int $0x10 /* get cursor position */ - - DATA32 call real_to_prot - .code32 - - movb %dl, %ah - movb %dh, %al - - popl %ebx - popl %ebp - ret - - -/* - * void grub_console_gotoxy(grub_uint8_t x, grub_uint8_t y) - * BIOS call "INT 10H Function 02h" to set cursor position - * Call with %ah = 0x02 - * %bh = page - * %dh = row (0 is top) - * %dl = column (0 is left) - */ - - -FUNCTION(grub_console_gotoxy) - pushl %ebp - pushl %ebx /* save EBX */ - - movb %cl, %dh /* %dh = y */ - /* %dl = x */ - - call prot_to_real - .code16 - - xorb %bh, %bh /* set page to 0 */ - movb $0x2, %ah - int $0x10 /* set cursor position */ - - DATA32 call real_to_prot - .code32 - - popl %ebx - popl %ebp - ret - - -/* - * void grub_console_cls (void) - * BIOS call "INT 10H Function 09h" to write character and attribute - * Call with %ah = 0x09 - * %al = (character) - * %bh = (page number) - * %bl = (attribute) - * %cx = (number of times) - */ - -FUNCTION(grub_console_cls) - pushl %ebp - pushl %ebx /* save EBX */ - - call prot_to_real - .code16 - - /* move the cursor to the beginning */ - movb $0x02, %ah - xorb %bh, %bh - xorw %dx, %dx - int $0x10 - - /* write spaces to the entire screen */ - movw $0x0920, %ax - movw $0x07, %bx - movw $(80 * 25), %cx - int $0x10 - - /* move back the cursor */ - movb $0x02, %ah - int $0x10 - - DATA32 call real_to_prot - .code32 - - popl %ebx - popl %ebp - ret - - -/* - * void grub_console_setcursor (int on) - * BIOS call "INT 10H Function 01h" to set cursor type - * Call with %ah = 0x01 - * %ch = cursor starting scanline - * %cl = cursor ending scanline - */ - -console_cursor_state: - .byte 1 -console_cursor_shape: - .word 0 - -FUNCTION(grub_console_setcursor) - pushl %ebp - pushl %ebx - - /* push ON */ - pushl %edx - - /* check if the standard cursor shape has already been saved */ - movw console_cursor_shape, %ax - testw %ax, %ax - jne 1f - - call prot_to_real - .code16 - - movb $0x03, %ah - xorb %bh, %bh - int $0x10 - - DATA32 call real_to_prot - .code32 - - cmp %cl, %ch - jb 3f - movw $0x0d0e, %cx -3: - movw %cx, console_cursor_shape -1: - /* set %cx to the designated cursor shape */ - movw $0x2000, %cx - popl %eax - testl %eax, %eax - jz 2f - movw console_cursor_shape, %cx -2: - call prot_to_real - .code16 - - movb $0x1, %ah - int $0x10 - - DATA32 call real_to_prot - .code32 - - popl %ebx - popl %ebp - ret - -/* - * grub_get_rtc() - * return the real time in ticks, of which there are about - * 18-20 per second - */ -FUNCTION(grub_get_rtc) - pushl %ebp - - call prot_to_real /* enter real mode */ - .code16 - - /* %ax is already zero */ - int $0x1a - - DATA32 call real_to_prot - .code32 - - movl %ecx, %eax - shll $16, %eax - movw %dx, %ax - - popl %ebp - ret - /* * int grub_pxe_call (int func, void* data, grub_uint32_t pxe_rm_entry); */ diff --git a/grub-core/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c index 0efeafe4e..7cf5ffc5f 100644 --- a/grub-core/term/i386/pc/console.c +++ b/grub-core/term/i386/pc/console.c @@ -20,6 +20,225 @@ #include #include #include +#include + +static void +int10_9 (grub_uint8_t ch, grub_uint16_t n) +{ + struct grub_bios_int_registers regs; + + regs.eax = ch | 0x0900; + regs.ebx = grub_console_cur_color & 0xff; + regs.ecx = n; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); +} + +/* + * BIOS call "INT 10H Function 03h" to get cursor position + * Call with %ah = 0x03 + * %bh = page + * Returns %ch = starting scan line + * %cl = ending scan line + * %dh = row (0 is top) + * %dl = column (0 is left) + */ + + +static grub_uint16_t +grub_console_getxy (struct grub_term_output *term __attribute__ ((unused))) +{ + struct grub_bios_int_registers regs; + + regs.eax = 0x0300; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + + return ((regs.edx & 0xff) << 8) | ((regs.edx & 0xff00) >> 8); +} + +/* + * BIOS call "INT 10H Function 02h" to set cursor position + * Call with %ah = 0x02 + * %bh = page + * %dh = row (0 is top) + * %dl = column (0 is left) + */ +static void +grub_console_gotoxy (struct grub_term_output *term __attribute__ ((unused)), + grub_uint8_t x, grub_uint8_t y) +{ + struct grub_bios_int_registers regs; + + /* set page to 0 */ + regs.ebx = 0; + regs.eax = 0x0200; + regs.edx = (y << 8) | x; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); +} + +/* + * + * Put the character C on the console. Because GRUB wants to write a + * character with an attribute, this implementation is a bit tricky. + * If C is a control character (CR, LF, BEL, BS), use INT 10, AH = 0Eh + * (TELETYPE OUTPUT). Otherwise, save the original position, put a space, + * save the current position, restore the original position, write the + * character and the attribute, and restore the current position. + * + * The reason why this is so complicated is that there is no easy way to + * get the height of the screen, and the TELETYPE OUTPUT BIOS call doesn't + * support setting a background attribute. + */ +static void +grub_console_putchar_real (grub_uint8_t c) +{ + struct grub_bios_int_registers regs; + grub_uint16_t pos; + + if (c == 7 || c == 8 || c == 0xa || c == 0xd) + { + regs.eax = c | 0x0e00; + regs.ebx = 0x0001; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + return; + } + + /* get the current position */ + pos = grub_console_getxy (NULL); + + /* check the column with the width */ + if ((pos & 0xff00) >= (79 << 8)) + { + grub_console_putchar_real (0x0d); + grub_console_putchar_real (0x0a); + /* get the current position */ + pos = grub_console_getxy (NULL); + } + + /* write the character with the attribute */ + int10_9 (c, 1); + + grub_console_gotoxy (NULL, ((pos & 0xff00) >> 8) + 1, (pos & 0xff)); +} + +static void +grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)), + const struct grub_unicode_glyph *c) +{ + grub_console_putchar_real (c->base); +} + +/* + * BIOS call "INT 10H Function 09h" to write character and attribute + * Call with %ah = 0x09 + * %al = (character) + * %bh = (page number) + * %bl = (attribute) + * %cx = (number of times) + */ +static void +grub_console_cls (struct grub_term_output *term) +{ + /* move the cursor to the beginning */ + grub_console_gotoxy (term, 0, 0); + + /* write spaces to the entire screen */ + int10_9 (' ', 80 * 25); + + /* move back the cursor */ + grub_console_gotoxy (term, 0, 0); +} + +/* + * void grub_console_setcursor (int on) + * BIOS call "INT 10H Function 01h" to set cursor type + * Call with %ah = 0x01 + * %ch = cursor starting scanline + * %cl = cursor ending scanline + */ +static void +grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)), + int on) +{ + static grub_uint16_t console_cursor_shape = 0; + struct grub_bios_int_registers regs; + + /* check if the standard cursor shape has already been saved */ + if (!console_cursor_shape) + { + regs.eax = 0x0300; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); + console_cursor_shape = regs.ecx; + if ((console_cursor_shape >> 8) >= (console_cursor_shape & 0xff)) + console_cursor_shape = 0x0d0e; + } + /* set %cx to the designated cursor shape */ + regs.ecx = on ? console_cursor_shape : 0x2000; + regs.eax = 0x0100; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x10, ®s); +} + +/* + * if there is a character pending, return it; otherwise return -1 + * BIOS call "INT 16H Function 01H" to check whether a character is pending + * Call with %ah = 0x1 + * Return: + * If key waiting to be input: + * %ah = keyboard scan code + * %al = ASCII character + * Zero flag = clear + * else + * Zero flag = set + * BIOS call "INT 16H Function 00H" to read character from keyboard + * Call with %ah = 0x0 + * Return: %ah = keyboard scan code + * %al = ASCII character + */ + +static int +grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) +{ + const grub_uint16_t bypass_table[] = { + 0x0100 | '\e', 0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r', 0x1c00 | '\n' + }; + struct grub_bios_int_registers regs; + unsigned i; + + /* + * Due to a bug in apple's bootcamp implementation, INT 16/AH = 0 would + * cause the machine to hang at the second keystroke. However, we can + * work around this problem by ensuring the presence of keystroke with + * INT 16/AH = 1 before calling INT 16/AH = 0. + */ + + regs.eax = 0x0100; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x16, ®s); + if (regs.flags & GRUB_CPU_INT_FLAGS_ZERO) + return GRUB_TERM_NO_KEY; + + regs.eax = 0x0000; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x16, ®s); + if (!(regs.eax & 0xff)) + return ((regs.eax >> 8) & 0xff) | GRUB_TERM_EXTENDED; + + if ((regs.eax & 0xff) >= ' ') + return regs.eax & 0xff; + + for (i = 0; i < ARRAY_SIZE (bypass_table); i++) + if (bypass_table[i] == (regs.eax & 0xffff)) + return regs.eax & 0xff; + + return (regs.eax & 0xff) + (('a' - 1) | GRUB_TERM_CTRL); +} static const struct grub_machine_bios_data_area *bios_data_area = (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h index 1631a40ad..f752b9a25 100644 --- a/include/grub/i386/pc/console.h +++ b/include/grub/i386/pc/console.h @@ -26,16 +26,6 @@ #include #include -/* These are global to share code between C and asm. */ -int grub_console_getkey (struct grub_term_input *term); -grub_uint16_t grub_console_getxy (struct grub_term_output *term); -void grub_console_gotoxy (struct grub_term_output *term, - grub_uint8_t x, grub_uint8_t y); -void grub_console_cls (struct grub_term_output *term); -void grub_console_setcursor (struct grub_term_output *term, int on); -void grub_console_putchar (struct grub_term_output *term, - const struct grub_unicode_glyph *c); - /* Initialize the console system. */ void grub_console_init (void); From e9d3421c050df3f3b77b5f9bceb758d663fb229d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 19:18:42 +0100 Subject: [PATCH 552/673] * configure.ac: Add -fno-asynchronous-unwind-tables. --- ChangeLog | 4 ++++ configure.ac | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3d8bd25e7..409a41ca5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-12 Vladimir Serbinenko + + * configure.ac: Add -fno-asynchronous-unwind-tables. + 2011-11-12 Vladimir Serbinenko Move assembly code to C by using intwrap. It increases core size diff --git a/configure.ac b/configure.ac index 3d6cc9a9e..7699e8330 100644 --- a/configure.ac +++ b/configure.ac @@ -413,6 +413,23 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" fi +# By default, GCC 4.6 generates .eh_frame sections containing unwind +# information in some cases where it previously did not. GRUB doesn't need +# these and they just use up vital space. Restore the old compiler +# behaviour. +AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [ + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_asynchronous_unwind_tables=yes], + [grub_cv_cc_fno_asynchronous_unwind_tables=no]) + CFLAGS="$SAVE_CFLAGS" +]) + +if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables" +fi + grub_apple_target_cc if test x$grub_cv_apple_target_cc = xyes ; then TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1" From 60240b8bc1a501951944c9e07d094c9e5e5e7084 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 19:53:25 +0100 Subject: [PATCH 553/673] Use decompressors framework on i386-pc. It increases core size by 46 bytes but improves compatibility and maintainability. * grub-core/Makefile.core.def (lzma_decompress): New image. (kernel): Add i386_pc_ldflags. * grub-core/kern/i386/pc/startup.S: Move intial part to .. * grub-core/boot/i386/pc/startup_raw.S: ... here. Pass pointers to real_to_prot, prot_to_real and device info. * include/grub/offsets.h: Renamed decompressor offsets. * util/grub-mkimage.c (grub_compression_t): New cmpression lzma. (image_target_desc): Remove raw_size and rename decompressor fields. (compress_kernel): Handle lzma. (generate_image): Handle decompressors on i386-pc. --- ChangeLog | 16 + grub-core/Makefile.core.def | 11 +- grub-core/boot/i386/pc/lnxboot.S | 8 +- .../{kern => boot}/i386/pc/lzma_decode.S | 0 grub-core/boot/i386/pc/startup_raw.S | 369 +++++++++++++++++ grub-core/boot/mips/startup_raw.S | 6 +- grub-core/kern/i386/int.S | 4 +- grub-core/kern/i386/pc/init.c | 3 +- grub-core/kern/i386/pc/startup.S | 392 ++---------------- grub-core/kern/i386/realmode.S | 27 ++ include/grub/offsets.h | 16 +- util/grub-mkimage.c | 235 ++++++----- 12 files changed, 601 insertions(+), 486 deletions(-) rename grub-core/{kern => boot}/i386/pc/lzma_decode.S (100%) create mode 100644 grub-core/boot/i386/pc/startup_raw.S diff --git a/ChangeLog b/ChangeLog index 409a41ca5..eeb9bda57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2011-11-12 Vladimir Serbinenko + + Use decompressors framework on i386-pc. It increases core size + by 46 bytes but improves compatibility and maintainability. + + * grub-core/Makefile.core.def (lzma_decompress): New image. + (kernel): Add i386_pc_ldflags. + * grub-core/kern/i386/pc/startup.S: Move intial part to .. + * grub-core/boot/i386/pc/startup_raw.S: ... here. Pass pointers + to real_to_prot, prot_to_real and device info. + * include/grub/offsets.h: Renamed decompressor offsets. + * util/grub-mkimage.c (grub_compression_t): New cmpression lzma. + (image_target_desc): Remove raw_size and rename decompressor fields. + (compress_kernel): Handle lzma. + (generate_image): Handle decompressors on i386-pc. + 2011-11-12 Vladimir Serbinenko * configure.ac: Add -fno-asynchronous-unwind-tables. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 9590188fb..18264f98f 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -34,7 +34,7 @@ kernel = { ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; - i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; @@ -356,6 +356,15 @@ image = { enable = mips; }; +image = { + name = lzma_decompress; + i386_pc = boot/i386/pc/startup_raw.S; + + objcopyflags = '-O binary'; + ldflags = '-Wl,-Ttext,0x8200'; + enable = i386_pc; +}; + image = { name = fwstart; mips_loongson = boot/mips/loongson/fwstart.S; diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index bb43ed73c..e5227d174 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -199,12 +199,8 @@ real_code_2: 1: - movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx -#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200 - addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx -#else - addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx -#endif + movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx + addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx 2: call LOCAL(move_memory) diff --git a/grub-core/kern/i386/pc/lzma_decode.S b/grub-core/boot/i386/pc/lzma_decode.S similarity index 100% rename from grub-core/kern/i386/pc/lzma_decode.S rename to grub-core/boot/i386/pc/lzma_decode.S diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S new file mode 100644 index 000000000..4820e3442 --- /dev/null +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -0,0 +1,369 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 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 . + */ + +#include +#include +#include +#include +#include +#include + +#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) + + .file "startup_raw.S" + + .text + + /* Tell GAS to generate 16-bit instructions so that this code works + in real mode. */ + .code16 + + .globl start, _start +start: +_start: +LOCAL (base): + /* + * Guarantee that "main" is loaded at 0x0:0x8200. + */ +#ifdef __APPLE__ + ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000) +#else + ljmp $0, $ABS(LOCAL (codestart)) +#endif + + /* + * This is a special data area. + */ + + . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE +LOCAL(compressed_size): + .long 0 + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE +LOCAL(uncompressed_size): + .long 0 + + . = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART +LOCAL(dos_part): + .long 0xFFFFFFFF + . = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART +LOCAL(bsd_part): + .long 0xFFFFFFFF + + . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY +reed_solomon_redundancy: + .long 0 + +/* + * This is the area for all of the special variables. + */ + +LOCAL(boot_drive): + .byte 0 + +/* the real mode code continues... */ +LOCAL (codestart): + cli /* we're not safe here! */ + + /* set up %ds, %ss, and %es */ + xorw %ax, %ax + movw %ax, %ds + movw %ax, %ss + movw %ax, %es + + /* set up the real mode/BIOS stack */ + movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp + movl %ebp, %esp + + sti /* we're safe again */ + + /* save the boot drive */ + ADDR32 movb %dl, LOCAL(boot_drive) + + /* reset disk system (%ah = 0) */ + int $0x13 + + /* transition to protected mode */ + DATA32 call real_to_prot + + /* The ".code32" directive takes GAS out of 16-bit mode. */ + .code32 + + incl %eax + call grub_gate_a20 + + movl LOCAL(compressed_size), %edx + addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx + movl reed_solomon_redundancy, %ecx + leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax + call EXT_C (grub_reed_solomon_recover) + jmp post_reed_solomon + +#include + + .text + + . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART +/* + * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). + * This uses the a.out kludge to load raw binary to the area starting at 1MB, + * and relocates itself after loaded. + */ + .p2align 2 /* force 4-byte alignment */ +multiboot_header: + /* magic */ + .long 0x1BADB002 + /* flags */ + .long (1 << 16) + /* checksum */ + .long -0x1BADB002 - (1 << 16) + /* header addr */ + .long multiboot_header - _start + 0x100000 + 0x200 + /* load addr */ + .long 0x100000 + /* load end addr */ + .long 0 + /* bss end addr */ + .long 0 + /* entry addr */ + .long multiboot_entry - _start + 0x100000 + 0x200 + +multiboot_entry: + .code32 + /* obtain the boot device */ + movl 12(%ebx), %edx + + movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp + movl %ebp, %esp + + /* relocate the code */ + movl $(LOCAL(decompressor_end) + 0x200), %ecx + addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx + movl $0x100000, %esi + movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi + cld + rep + movsb + /* jump to the real address */ + movl $multiboot_trampoline, %eax + jmp *%eax + +multiboot_trampoline: + /* fill the boot information */ + movl %edx, %eax + shrl $8, %eax + xorl %ebx, %ebx + cmpb $0xFF, %ah + je 1f + movb %ah, %bl + movl %ebx, LOCAL(dos_part) +1: + cmpb $0xFF, %al + je 2f + movb %al, %bl + movl %ebx, LOCAL(bsd_part) +2: + shrl $24, %edx + movb %dl, LOCAL(boot_drive) + movb $0xFF, %dh + movl $GRUB_MEMORY_MACHINE_PROT_STACK, %esp + /* enter the usual booting */ + call prot_to_real + .code16 + jmp LOCAL (codestart) + + .code32 + +post_reed_solomon: + +#ifdef ENABLE_LZMA + movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi + movl $LOCAL(decompressor_end), %esi + pushl %edi + movl LOCAL (uncompressed_size), %ecx + leal (%edi, %ecx), %ebx + call _LzmaDecodeA + /* _LzmaDecodeA clears DF, so no need to run cld */ + popl %esi +#endif + + movb LOCAL(boot_drive), %dl + movl LOCAL(dos_part), %eax + movl LOCAL(bsd_part), %ebx + movl $prot_to_real, %edi + movl $real_to_prot, %ecx + jmp *%esi + +#include "../../../kern/i386/realmode.S" + +/* + * grub_gate_a20(int on) + * + * Gate address-line 20 for high memory. + * + * This routine is probably overconservative in what it does, but so what? + * + * It also eats any keystrokes in the keyboard buffer. :-( + */ + +grub_gate_a20: + movl %eax, %edx + +gate_a20_test_current_state: + /* first of all, test if already in a good state */ + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_bios + ret + +gate_a20_try_bios: + /* second, try a BIOS call */ + pushl %ebp + call prot_to_real + + .code16 + movw $0x2400, %ax + testb %dl, %dl + jz 1f + incw %ax +1: int $0x15 + + DATA32 call real_to_prot + .code32 + + popl %ebp + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_system_control_port_a + ret + +gate_a20_try_system_control_port_a: + /* + * In macbook, the keyboard test would hang the machine, so we move + * this forward. + */ + /* fourth, try the system control port A */ + inb $0x92 + andb $(~0x03), %al + testb %dl, %dl + jz 6f + orb $0x02, %al +6: outb $0x92 + + /* When turning off Gate A20, do not check the state strictly, + because a failure is not fatal usually, and Gate A20 is always + on some modern machines. */ + testb %dl, %dl + jz 7f + call gate_a20_check_state + cmpb %al, %dl + jnz gate_a20_try_keyboard_controller +7: ret + +gate_a20_flush_keyboard_buffer: + inb $0x64 + andb $0x02, %al + jnz gate_a20_flush_keyboard_buffer +2: + inb $0x64 + andb $0x01, %al + jz 3f + inb $0x60 + jmp 2b +3: + ret + +gate_a20_try_keyboard_controller: + /* third, try the keyboard controller */ + call gate_a20_flush_keyboard_buffer + + movb $0xd1, %al + outb $0x64 +4: + inb $0x64 + andb $0x02, %al + jnz 4b + + movb $0xdd, %al + testb %dl, %dl + jz 5f + orb $0x02, %al +5: outb $0x60 + call gate_a20_flush_keyboard_buffer + + /* output a dummy command (USB keyboard hack) */ + movb $0xff, %al + outb $0x64 + call gate_a20_flush_keyboard_buffer + + call gate_a20_check_state + cmpb %al, %dl + /* everything failed, so restart from the beginning */ + jnz gate_a20_try_bios + ret + +gate_a20_check_state: + /* iterate the checking for a while */ + movl $100, %ecx +1: + call 3f + cmpb %al, %dl + jz 2f + loop 1b +2: + ret +3: + pushl %ebx + pushl %ecx + xorl %eax, %eax + /* compare the byte at 0x8000 with that at 0x108000 */ + movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx + pushl %ebx + /* save the original byte in CL */ + movb (%ebx), %cl + /* store the value at 0x108000 in AL */ + addl $0x100000, %ebx + movb (%ebx), %al + /* try to set one less value at 0x8000 */ + popl %ebx + movb %al, %ch + decb %ch + movb %ch, (%ebx) + /* serialize */ + outb %al, $0x80 + outb %al, $0x80 + /* obtain the value at 0x108000 in CH */ + pushl %ebx + addl $0x100000, %ebx + movb (%ebx), %ch + /* this result is 1 if A20 is on or 0 if it is off */ + subb %ch, %al + xorb $1, %al + /* restore the original */ + popl %ebx + movb %cl, (%ebx) + popl %ecx + popl %ebx + ret + +#ifdef ENABLE_LZMA +#include "lzma_decode.S" +#endif + + .p2align 2 + +LOCAL(decompressor_end): diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index aefd387b6..e76926677 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -38,13 +38,13 @@ start: bal codestart nop base: - . = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE compressed_size: .long 0 - . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE uncompressed_size: .long 0 - . = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR + . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR uncompressed_addr: .long 0 codestart: diff --git a/grub-core/kern/i386/int.S b/grub-core/kern/i386/int.S index 58ccfdaab..7a2b7808a 100644 --- a/grub-core/kern/i386/int.S +++ b/grub-core/kern/i386/int.S @@ -47,7 +47,7 @@ FUNCTION(grub_bios_interrupt) movl 24(%edx), %esi movl 28(%edx), %edx - call prot_to_real + PROT_TO_REAL .code16 pushf cli @@ -98,7 +98,7 @@ intno: movw %ax, LOCAL(bios_register_es) popf - DATA32 call real_to_prot + REAL_TO_PROT .code32 popl %eax diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 6fbfab3b8..da7230c33 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -156,8 +156,7 @@ grub_machine_init (void) int grub_lower_mem; #endif - grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR - + ((_edata - _start) - GRUB_KERNEL_MACHINE_RAW_SIZE); + grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start); /* Initialize the console as early as possible. */ grub_console_init (); diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 94d4f02ee..058f9efa7 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 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 @@ -43,203 +43,30 @@ #include #include -#include -#include -#include -#include -#include -#include #include -#include - -#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200) .file "startup.S" .text - /* Tell GAS to generate 16-bit instructions so that this code works - in real mode. */ - .code16 - .globl start, _start start: _start: -LOCAL (base): - /* - * Guarantee that "main" is loaded at 0x0:0x8200. - */ -#ifdef __APPLE__ - ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000) -#else - ljmp $0, $ABS(LOCAL (codestart)) -#endif - - /* - * This is a special data area. - */ - - . = _start + GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE -VARIABLE(grub_total_module_size) - .long 0 - . = _start + GRUB_KERNEL_I386_PC_COMPRESSED_SIZE -VARIABLE(grub_compressed_size) - .long 0 - . = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART -VARIABLE(grub_install_dos_part) - .long 0xFFFFFFFF - . = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART -VARIABLE(grub_install_bsd_part) - .long 0xFFFFFFFF - . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY -reed_solomon_redundancy: - .long 0 - -#ifdef APPLE_CC -bss_start: - .long 0 -bss_end: - .long 0 -#endif -/* - * This is the area for all of the special variables. - */ - -VARIABLE(grub_boot_drive) - .byte 0 - -/* the real mode code continues... */ -LOCAL (codestart): - cli /* we're not safe here! */ - - /* set up %ds, %ss, and %es */ - xorw %ax, %ax - movw %ax, %ds - movw %ax, %ss - movw %ax, %es - - /* set up the real mode/BIOS stack */ - movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp - movl %ebp, %esp - - sti /* we're safe again */ - - /* save the boot drive */ - ADDR32 movb %dl, EXT_C(grub_boot_drive) - - /* reset disk system (%ah = 0) */ - int $0x13 - - /* transition to protected mode */ - DATA32 call real_to_prot - - /* The ".code32" directive takes GAS out of 16-bit mode. */ .code32 - incl %eax - call grub_gate_a20 - - movl EXT_C(grub_compressed_size), %edx - addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx - movl reed_solomon_redundancy, %ecx - leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax - call EXT_C (grub_reed_solomon_recover) - jmp post_reed_solomon - -#include - - .text - - . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART -/* - * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). - * This uses the a.out kludge to load raw binary to the area starting at 1MB, - * and relocates itself after loaded. - */ - .p2align 2 /* force 4-byte alignment */ -multiboot_header: - /* magic */ - .long 0x1BADB002 - /* flags */ - .long (1 << 16) - /* checksum */ - .long -0x1BADB002 - (1 << 16) - /* header addr */ - .long multiboot_header - _start + 0x100000 + 0x200 - /* load addr */ - .long 0x100000 - /* load end addr */ - .long 0 - /* bss end addr */ - .long 0 - /* entry addr */ - .long multiboot_entry - _start + 0x100000 + 0x200 - -multiboot_entry: - .code32 - /* obtain the boot device */ - movl 12(%ebx), %edx - - movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp - movl %ebp, %esp - - /* relocate the code */ - movl $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx - addl EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx - movl $0x100000, %esi - movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi - cld - rep - movsb - /* jump to the real address */ - movl $multiboot_trampoline, %eax - jmp *%eax - -multiboot_trampoline: - /* fill the boot information */ - movl %edx, %eax - shrl $8, %eax - xorl %ebx, %ebx - cmpb $0xFF, %ah - je 1f - movb %ah, %bl - movl %ebx, EXT_C(grub_install_dos_part) -1: - cmpb $0xFF, %al - je 2f - movb %al, %bl - movl %ebx, EXT_C(grub_install_bsd_part) -2: - shrl $24, %edx - movb $0xFF, %dh - /* enter the usual booting */ - call prot_to_real - jmp LOCAL (codestart) - -post_reed_solomon: - -#ifdef ENABLE_LZMA - movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi - movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi - pushl %edi - pushl %esi - movl $(BSS_START_SYMBOL - _start), %ecx - addl EXT_C(grub_total_module_size), %ecx - subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx - pushl %ecx - leal (%edi, %ecx), %ebx - call _LzmaDecodeA - /* _LzmaDecodeA clears DF, so no need to run cld */ - popl %ecx - popl %edi - popl %esi -#endif + movl %ecx, (LOCAL(real_to_prot_addr) - _start) (%esi) + movl %edi, (LOCAL(prot_to_real_addr) - _start) (%esi) /* copy back the decompressed part (except the modules) */ - subl EXT_C(grub_total_module_size), %ecx + movl $(_edata - _start), %ecx + movl $(_start), %edi rep movsb + movl $LOCAL (cont), %esi + jmp *%esi +LOCAL(cont): + #if 0 /* copy modules before cleaning out the bss */ movl EXT_C(grub_total_module_size), %ecx @@ -255,24 +82,14 @@ post_reed_solomon: movsb #endif -#ifdef APPLE_CC - /* clean out the bss */ - bss_start_abs = ABS (bss_start) - bss_end_abs = ABS (bss_end) + movl %eax, %esi - movl bss_start_abs, %edi - - /* compute the bss length */ - movl bss_end_abs, %ecx - subl %edi, %ecx -#else /* clean out the bss */ movl $BSS_START_SYMBOL, %edi /* compute the bss length */ movl $END_SYMBOL, %ecx subl %edi, %ecx -#endif /* clean out */ xorl %eax, %eax @@ -280,172 +97,29 @@ post_reed_solomon: rep stosb + movl %esi, EXT_C(grub_install_dos_part) + movb %dl, EXT_C(grub_boot_drive) + movl %ebx, EXT_C(grub_install_bsd_part) + /* * Call the start of main body of C code. */ call EXT_C(grub_main) -#include "../realmode.S" +LOCAL(real_to_prot_addr): + .long 0 +LOCAL(prot_to_real_addr): + .long 0 -/* - * grub_gate_a20(int on) - * - * Gate address-line 20 for high memory. - * - * This routine is probably overconservative in what it does, but so what? - * - * It also eats any keystrokes in the keyboard buffer. :-( - */ + .macro PROT_TO_REAL + movl LOCAL(prot_to_real_addr), %eax + call *%eax + .endm -grub_gate_a20: - movl %eax, %edx - -gate_a20_test_current_state: - /* first of all, test if already in a good state */ - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_bios - ret - -gate_a20_try_bios: - /* second, try a BIOS call */ - pushl %ebp - call prot_to_real - - .code16 - movw $0x2400, %ax - testb %dl, %dl - jz 1f - incw %ax -1: int $0x15 - - DATA32 call real_to_prot - .code32 - - popl %ebp - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_system_control_port_a - ret - -gate_a20_try_system_control_port_a: - /* - * In macbook, the keyboard test would hang the machine, so we move - * this forward. - */ - /* fourth, try the system control port A */ - inb $0x92 - andb $(~0x03), %al - testb %dl, %dl - jz 6f - orb $0x02, %al -6: outb $0x92 - - /* When turning off Gate A20, do not check the state strictly, - because a failure is not fatal usually, and Gate A20 is always - on some modern machines. */ - testb %dl, %dl - jz 7f - call gate_a20_check_state - cmpb %al, %dl - jnz gate_a20_try_keyboard_controller -7: ret - -gate_a20_flush_keyboard_buffer: - inb $0x64 - andb $0x02, %al - jnz gate_a20_flush_keyboard_buffer -2: - inb $0x64 - andb $0x01, %al - jz 3f - inb $0x60 - jmp 2b -3: - ret - -gate_a20_try_keyboard_controller: - /* third, try the keyboard controller */ - call gate_a20_flush_keyboard_buffer - - movb $0xd1, %al - outb $0x64 -4: - inb $0x64 - andb $0x02, %al - jnz 4b - - movb $0xdd, %al - testb %dl, %dl - jz 5f - orb $0x02, %al -5: outb $0x60 - call gate_a20_flush_keyboard_buffer - - /* output a dummy command (USB keyboard hack) */ - movb $0xff, %al - outb $0x64 - call gate_a20_flush_keyboard_buffer - - call gate_a20_check_state - cmpb %al, %dl - /* everything failed, so restart from the beginning */ - jnz gate_a20_try_bios - ret - -gate_a20_check_state: - /* iterate the checking for a while */ - movl $100, %ecx -1: - call 3f - cmpb %al, %dl - jz 2f - loop 1b -2: - ret -3: - pushl %ebx - pushl %ecx - xorl %eax, %eax - /* compare the byte at 0x8000 with that at 0x108000 */ - movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx - pushl %ebx - /* save the original byte in CL */ - movb (%ebx), %cl - /* store the value at 0x108000 in AL */ - addl $0x100000, %ebx - movb (%ebx), %al - /* try to set one less value at 0x8000 */ - popl %ebx - movb %al, %ch - decb %ch - movb %ch, (%ebx) - /* serialize */ - outb %al, $0x80 - outb %al, $0x80 - /* obtain the value at 0x108000 in CH */ - pushl %ebx - addl $0x100000, %ebx - movb (%ebx), %ch - /* this result is 1 if A20 is on or 0 if it is off */ - subb %ch, %al - xorb $1, %al - /* restore the original */ - popl %ebx - movb %cl, (%ebx) - popl %ecx - popl %ebx - ret - -#ifdef ENABLE_LZMA -#include "lzma_decode.S" -#endif - -/* - * The code beyond this point is compressed. Assert that the uncompressed - * code fits GRUB_KERNEL_MACHINE_RAW_SIZE. - */ - . = _start + GRUB_KERNEL_MACHINE_RAW_SIZE + .macro REAL_TO_PROT + movl LOCAL(real_to_prot_addr), %eax + DATA32 call *%ax + .endm /* * grub_exit() @@ -453,7 +127,7 @@ gate_a20_check_state: * Exit the system. */ FUNCTION(grub_exit) - call prot_to_real + PROT_TO_REAL .code16 /* Tell the BIOS a boot failure. If this does not work, reboot. */ int $0x18 @@ -482,7 +156,7 @@ FUNCTION(grub_pxe_call) shll $16, %edx addl %eax, %edx - call prot_to_real + PROT_TO_REAL .code16 pushl %ebx @@ -494,7 +168,7 @@ FUNCTION(grub_pxe_call) addw $10, %sp movw %ax, %cx - DATA32 call real_to_prot + REAL_TO_PROT .code32 movzwl %cx, %eax @@ -506,3 +180,11 @@ FUNCTION(grub_pxe_call) ret #include "../int.S" + + .bss +VARIABLE(grub_boot_drive) + .byte 0 +VARIABLE(grub_install_dos_part) + .long 0xFFFFFFFF +VARIABLE(grub_install_bsd_part) + .long 0xFFFFFFFF diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S index 3e8a13892..2e16847c8 100644 --- a/grub-core/kern/i386/realmode.S +++ b/grub-core/kern/i386/realmode.S @@ -51,6 +51,14 @@ protstack: .long GRUB_MEMORY_MACHINE_PROT_STACK + .macro PROT_TO_REAL + call prot_to_real + .endm + + .macro REAL_TO_PROT + DATA32 call real_to_prot + .endm + /* * This is the Global Descriptor Table * @@ -162,6 +170,25 @@ protcseg: /* return on the old (or initialized) stack! */ ret +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 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 . + */ + +#include prot_to_real: /* just in case, set GDT */ diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 92354f700..e3b9a377c 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -19,11 +19,11 @@ #ifndef OFFSETS_HEADER #define OFFSETS_HEADER 1 -/* The offset of GRUB_TOTAL_MODULE_SIZE. */ -#define GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE 0x8 +/* The offset of GRUB_COMPRESSED_SIZE. */ +#define GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE 0x08 /* The offset of GRUB_COMPRESSED_SIZE. */ -#define GRUB_KERNEL_I386_PC_COMPRESSED_SIZE 0x0c +#define GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE 0x0c /* The offset of GRUB_INSTALL_DOS_PART. */ #define GRUB_KERNEL_I386_PC_INSTALL_DOS_PART 0x10 @@ -34,15 +34,12 @@ /* Offset of reed_solomon_redundancy. */ #define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x18 -/* The size of the first region which won't be compressed. */ -#define GRUB_KERNEL_I386_PC_RAW_SIZE 0xc70 - #define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x6e0 /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 -#define GRUB_KERNEL_I386_PC_LINK_ADDR 0x8200 +#define GRUB_KERNEL_I386_PC_LINK_ADDR 0x9000 /* The upper memory area (starting at 640 kiB). */ #define GRUB_MEMORY_I386_PC_UPPER 0xa0000 @@ -62,7 +59,6 @@ #define GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE 12 #define GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS 0x4400 -#define GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE 0 #define GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR 0x4400 #define GRUB_KERNEL_POWERPC_IEEE1275_LINK_ALIGN 4 @@ -133,10 +129,12 @@ #define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG) #define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER) -#define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _RAW_SIZE) #define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_BSD_PART) #define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_DOS_PART) #define GRUB_MACHINE_LINK_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _LINK_ADDR) + +#define GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _COMPRESSED_SIZE) +#define GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _UNCOMPRESSED_SIZE) #endif #ifndef ASM_FILE diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 9369fba3d..9da72f6c9 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -54,7 +54,7 @@ #define TARGET_NO_FIELD 0xffffffff typedef enum { - COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ + COMPRESSION_AUTO, COMPRESSION_NONE, COMPRESSION_XZ, COMPRESSION_LZMA } grub_compression_t; struct image_target_desc @@ -73,13 +73,13 @@ struct image_target_desc enum { PLATFORM_FLAGS_NONE = 0, - PLATFORM_FLAGS_LZMA = 1, PLATFORM_FLAGS_DECOMPRESSORS = 2, PLATFORM_FLAGS_MODULES_BEFORE_KERNEL = 4, } flags; - unsigned raw_size; unsigned total_module_size; - unsigned compressed_size; + unsigned decompressor_compressed_size; + unsigned decompressor_uncompressed_size; + unsigned decompressor_uncompressed_addr; unsigned link_align; grub_uint16_t elf_target; unsigned section_align; @@ -107,9 +107,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -127,9 +128,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_COREBOOT, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -146,10 +148,11 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_I386_PC, - .flags = PLATFORM_FLAGS_LZMA, - .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, - .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .total_module_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART, @@ -162,10 +165,11 @@ struct image_target_desc image_targets[] = .voidp_sizeof = 4, .bigendian = 0, .id = IMAGE_I386_PC_PXE, - .flags = PLATFORM_FLAGS_LZMA, - .raw_size = GRUB_KERNEL_I386_PC_RAW_SIZE, - .total_module_size = GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE, - .compressed_size = GRUB_KERNEL_I386_PC_COMPRESSED_SIZE, + .flags = PLATFORM_FLAGS_DECOMPRESSORS, + .total_module_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_I386_PC_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART, @@ -179,9 +183,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = ALIGN_UP (GRUB_PE32_MSDOS_STUB_SIZE + GRUB_PE32_SIGNATURE_SIZE @@ -201,9 +206,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_I386_IEEE1275, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -221,9 +227,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_QEMU, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -237,9 +244,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = EFI64_HEADER_SIZE, .install_dos_part = TARGET_NO_FIELD, @@ -254,9 +262,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_YEELOONG_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -273,9 +282,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_FULOONG2F_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -294,9 +304,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -313,9 +324,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_PPC, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -333,9 +345,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_SPARC64_RAW, .flags = PLATFORM_FLAGS_NONE, - .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -349,9 +362,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_SPARC64_AOUT, .flags = PLATFORM_FLAGS_NONE, - .raw_size = GRUB_KERNEL_SPARC64_IEEE1275_RAW_SIZE, .total_module_size = GRUB_KERNEL_SPARC64_IEEE1275_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -365,9 +379,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_EFI, .flags = PLATFORM_FLAGS_NONE, - .raw_size = 0, .total_module_size = TARGET_NO_FIELD, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_size = TARGET_NO_FIELD, + .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = EFI64_HEADER_SIZE, .install_dos_part = TARGET_NO_FIELD, @@ -383,9 +398,10 @@ struct image_target_desc image_targets[] = .id = IMAGE_MIPS_ARC, .flags = (PLATFORM_FLAGS_DECOMPRESSORS | PLATFORM_FLAGS_MODULES_BEFORE_KERNEL), - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -402,9 +418,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -421,9 +438,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -440,9 +458,10 @@ struct image_target_desc image_targets[] = .bigendian = 0, .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -459,9 +478,10 @@ struct image_target_desc image_targets[] = .bigendian = 1, .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, - .raw_size = 0, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .compressed_size = TARGET_NO_FIELD, + .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .install_dos_part = TARGET_NO_FIELD, @@ -593,7 +613,7 @@ static ISzAlloc g_Alloc = { SzAlloc, SzFree }; static void compress_kernel_lzma (char *kernel_img, size_t kernel_size, - char **core_img, size_t *core_size, size_t raw_size) + char **core_img, size_t *core_size) { CLzmaEncProps props; unsigned char out_props[5]; @@ -606,27 +626,21 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size, props.pb = 2; props.numThreads = 1; - if (kernel_size < raw_size) - grub_util_error (_("the core image is too small")); - *core_img = xmalloc (kernel_size); - memcpy (*core_img, kernel_img, raw_size); - *core_size = kernel_size - raw_size; - if (LzmaEncode ((unsigned char *) *core_img + raw_size, core_size, - (unsigned char *) kernel_img + raw_size, - kernel_size - raw_size, + *core_size = kernel_size; + if (LzmaEncode ((unsigned char *) *core_img, core_size, + (unsigned char *) kernel_img, + kernel_size, &props, out_props, &out_props_size, 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK) grub_util_error (_("cannot compress the kernel image")); - - *core_size += raw_size; } #ifdef HAVE_LIBLZMA static void compress_kernel_xz (char *kernel_img, size_t kernel_size, - char **core_img, size_t *core_size, size_t raw_size) + char **core_img, size_t *core_size) { lzma_stream strm = LZMA_STREAM_INIT; lzma_ret xzret; @@ -647,20 +661,16 @@ compress_kernel_xz (char *kernel_img, size_t kernel_size, { .id = LZMA_VLI_UNKNOWN, .options = NULL} }; - if (kernel_size < raw_size) - grub_util_error (_("the core image is too small")); - xzret = lzma_stream_encoder (&strm, fltrs, LZMA_CHECK_NONE); if (xzret != LZMA_OK) grub_util_error (_("cannot compress the kernel image")); *core_img = xmalloc (kernel_size); - memcpy (*core_img, kernel_img, raw_size); - *core_size = kernel_size - raw_size; - strm.next_in = (unsigned char *) kernel_img + raw_size; - strm.avail_in = kernel_size - raw_size; - strm.next_out = (unsigned char *) *core_img + raw_size; + *core_size = kernel_size; + strm.next_in = (unsigned char *) kernel_img; + strm.avail_in = kernel_size; + strm.next_out = (unsigned char *) *core_img; strm.avail_out = *core_size; while (1) @@ -674,8 +684,6 @@ compress_kernel_xz (char *kernel_img, size_t kernel_size, } *core_size -= strm.avail_out; - - *core_size += raw_size; } #endif @@ -684,19 +692,20 @@ compress_kernel (struct image_target_desc *image_target, char *kernel_img, size_t kernel_size, char **core_img, size_t *core_size, grub_compression_t comp) { - if (image_target->flags & PLATFORM_FLAGS_LZMA) - { - compress_kernel_lzma (kernel_img, kernel_size, core_img, - core_size, image_target->raw_size); - return; - } + if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS + && (comp == COMPRESSION_LZMA)) + { + compress_kernel_lzma (kernel_img, kernel_size, core_img, + core_size); + return; + } #ifdef HAVE_LIBLZMA if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS && (comp == COMPRESSION_XZ)) { compress_kernel_xz (kernel_img, kernel_size, core_img, - core_size, image_target->raw_size); + core_size); return; } #endif @@ -747,6 +756,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if (comp == COMPRESSION_AUTO) comp = image_target->default_compression; + if (image_target->id == IMAGE_I386_PC + || image_target->id == IMAGE_I386_PC_PXE) + comp = COMPRESSION_LZMA; + path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); kernel_path = grub_util_get_path (dir, "kernel.img"); @@ -903,31 +916,12 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], &core_img, &core_size, comp); free (kernel_img); - if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) - kernel_img = core_img + total_module_size; - else - kernel_img = core_img; - grub_util_info ("the core size is 0x%x", core_size); if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) && image_target->total_module_size != TARGET_NO_FIELD) - *((grub_uint32_t *) (kernel_img + image_target->total_module_size)) + *((grub_uint32_t *) (core_img + image_target->total_module_size)) = grub_host_to_target32 (total_module_size); - if (image_target->compressed_size != TARGET_NO_FIELD) - *((grub_uint32_t *) (kernel_img + image_target->compressed_size)) - = grub_host_to_target32 (core_size - image_target->raw_size); - - /* If we included a drive in our prefix, let GRUB know it doesn't have to - prepend the drive told by BIOS. */ - if (image_target->install_dos_part != TARGET_NO_FIELD - && image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(') - { - *((grub_int32_t *) (kernel_img + image_target->install_dos_part)) - = grub_host_to_target32 (-2); - *((grub_int32_t *) (kernel_img + image_target->install_bsd_part)) - = grub_host_to_target32 (-2); - } if (image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) { @@ -941,6 +935,9 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], case COMPRESSION_XZ: name = "xz_decompress.img"; break; + case COMPRESSION_LZMA: + name = "lzma_decompress.img"; + break; case COMPRESSION_NONE: name = "none_decompress.img"; break; @@ -952,19 +949,30 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], decompress_size = grub_util_get_image_size (decompress_path); decompress_img = grub_util_read_image (decompress_path); - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE)) - = grub_host_to_target32 (core_size); + if ((image_target->id == IMAGE_I386_PC + || image_target->id == IMAGE_I386_PC_PXE) + && decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200) + grub_util_error (_("Decompressor is too big")); - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE)) - = grub_host_to_target32 (kernel_size + total_module_size); + if (image_target->decompressor_compressed_size != TARGET_NO_FIELD) + *((grub_uint32_t *) (decompress_img + + image_target->decompressor_compressed_size)) + = grub_host_to_target32 (core_size); - if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR)) - = grub_host_to_target_addr (image_target->link_addr - total_module_size); - else - *((grub_uint32_t *) (decompress_img + GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR)) - = grub_host_to_target_addr (image_target->link_addr); + if (image_target->decompressor_uncompressed_size != TARGET_NO_FIELD) + *((grub_uint32_t *) (decompress_img + + image_target->decompressor_uncompressed_size)) + = grub_host_to_target32 (kernel_size + total_module_size); + if (image_target->decompressor_uncompressed_addr != TARGET_NO_FIELD) + { + if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL) + *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr)) + = grub_host_to_target_addr (image_target->link_addr - total_module_size); + else + *((grub_uint32_t *) (decompress_img + image_target->decompressor_uncompressed_addr)) + = grub_host_to_target_addr (image_target->link_addr); + } full_size = core_size + decompress_size; full_img = xmalloc (full_size); @@ -982,6 +990,17 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], core_size = full_size; } + /* If we included a drive in our prefix, let GRUB know it doesn't have to + prepend the drive told by BIOS. */ + if (image_target->install_dos_part != TARGET_NO_FIELD + && image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(') + { + *((grub_int32_t *) (core_img + image_target->install_dos_part)) + = grub_host_to_target32 (-2); + *((grub_int32_t *) (core_img + image_target->install_bsd_part)) + = grub_host_to_target32 (-2); + } + switch (image_target->id) { case IMAGE_I386_PC: @@ -1249,7 +1268,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], rom_img = xmalloc (rom_size); memset (rom_img, 0, rom_size); - *((grub_int32_t *) (kernel_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR)) + *((grub_int32_t *) (core_img + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR)) = grub_host_to_target32 ((grub_uint32_t) -rom_size); memcpy (rom_img, core_img, core_size); From 691cbb58163628d7244b66997e713f443b8af8e3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 20:53:46 +0100 Subject: [PATCH 554/673] Fix bug introduced by previous commit. * grub-core/boot/i386/pc/startup_raw.S: Compute RS start correctly. --- ChangeLog | 6 ++++++ grub-core/boot/i386/pc/startup_raw.S | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index eeb9bda57..70db75379 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-11-12 Vladimir Serbinenko + + Fix bug introduced by previous commit. + + * grub-core/boot/i386/pc/startup_raw.S: Compute RS start correctly. + 2011-11-12 Vladimir Serbinenko Use decompressors framework on i386-pc. It increases core size diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 4820e3442..09b6fed76 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -107,7 +107,7 @@ LOCAL (codestart): call grub_gate_a20 movl LOCAL(compressed_size), %edx - addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx + addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - _start), %edx movl reed_solomon_redundancy, %ecx leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax call EXT_C (grub_reed_solomon_recover) From 5fbdac149b05ce50a3de0dfb6ef6d37e29bc8575 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 21:12:52 +0100 Subject: [PATCH 555/673] Defer multiboot device parsing until we're in compressed part. * grub-core/boot/i386/pc/lnxboot.S: Remove setting dos_part and bsd_part. setdevice has fallen into disuse. * grub-core/boot/i386/pc/startup_raw.S (dos_part): Removed. (bsd_part): Likewise. (boot_dev): New variable. (multiboot_trampoline): Don't parse multiboot device. Pass multiboot device in %edx. * grub-core/disk/i386/pc/biosdisk.c (GRUB_MOD_INIT): Parse grub_boot_device. * grub-core/kern/i386/pc/init.c (grub_machine_get_bootlocation): Likewise. * grub-core/kern/i386/pc/startup.S: Save edx. (grub_boot_drive): Removed. (grub_install_dos_part): Likewise. (grub_install_bsd_part): Likewise. (grub_boot_device): New variable. * include/grub/i386/pc/kernel.h (grub_install_dos_part): Removed. (grub_install_bsd_part): Likewise. (grub_boot_drive): Likewise. (grub_boot_device): New variable. * include/grub/offsets.h (GRUB_KERNEL_I386_PC_INSTALL_DOS_PART): Removed. (GRUB_KERNEL_I386_PC_INSTALL_BSD_PART): Likewise. (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): Moved lower. (GRUB_KERNEL_MACHINE_INSTALL_BSD_PART): Removed. (GRUB_KERNEL_MACHINE_INSTALL_DOS_PART): Likewise. * util/grub-install.in: Remove redundant condition. --- ChangeLog | 32 +++++++++++++++++ grub-core/boot/i386/pc/lnxboot.S | 5 --- grub-core/boot/i386/pc/startup_raw.S | 33 +++--------------- grub-core/disk/i386/pc/biosdisk.c | 14 ++++---- grub-core/kern/i386/pc/init.c | 19 ++++++---- grub-core/kern/i386/pc/startup.S | 14 ++------ include/grub/i386/pc/kernel.h | 9 +---- include/grub/offsets.h | 10 +----- util/grub-install.in | 2 +- util/grub-mkimage.c | 52 ---------------------------- util/grub-setup.c | 44 ----------------------- 11 files changed, 63 insertions(+), 171 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70db75379..b5124c18a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2011-11-12 Vladimir Serbinenko + + Defer multiboot device parsing until we're in compressed part. + + * grub-core/boot/i386/pc/lnxboot.S: Remove setting dos_part and + bsd_part. setdevice has fallen into disuse. + * grub-core/boot/i386/pc/startup_raw.S (dos_part): Removed. + (bsd_part): Likewise. + (boot_dev): New variable. + (multiboot_trampoline): Don't parse multiboot device. + Pass multiboot device in %edx. + * grub-core/disk/i386/pc/biosdisk.c (GRUB_MOD_INIT): Parse + grub_boot_device. + * grub-core/kern/i386/pc/init.c (grub_machine_get_bootlocation): + Likewise. + * grub-core/kern/i386/pc/startup.S: Save edx. + (grub_boot_drive): Removed. + (grub_install_dos_part): Likewise. + (grub_install_bsd_part): Likewise. + (grub_boot_device): New variable. + * include/grub/i386/pc/kernel.h (grub_install_dos_part): Removed. + (grub_install_bsd_part): Likewise. + (grub_boot_drive): Likewise. + (grub_boot_device): New variable. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_INSTALL_DOS_PART): + Removed. + (GRUB_KERNEL_I386_PC_INSTALL_BSD_PART): Likewise. + (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): Moved lower. + (GRUB_KERNEL_MACHINE_INSTALL_BSD_PART): Removed. + (GRUB_KERNEL_MACHINE_INSTALL_DOS_PART): Likewise. + * util/grub-install.in: Remove redundant condition. + 2011-11-12 Vladimir Serbinenko Fix bug introduced by previous commit. diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index e5227d174..4fe0df139 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -205,11 +205,6 @@ real_code_2: 2: call LOCAL(move_memory) - movsbl %dh, %eax - movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART) - movsbl (reg_edx + 2 - start), %eax - movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART) - movb $0xFF, %dh ljmp $(DATA_ADDR >> 4), $0 diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 09b6fed76..9e0f23d71 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -57,13 +57,6 @@ LOCAL(compressed_size): LOCAL(uncompressed_size): .long 0 - . = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART -LOCAL(dos_part): - .long 0xFFFFFFFF - . = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART -LOCAL(bsd_part): - .long 0xFFFFFFFF - . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY reed_solomon_redundancy: .long 0 @@ -72,8 +65,10 @@ reed_solomon_redundancy: * This is the area for all of the special variables. */ +LOCAL(boot_dev): + .byte 0xFF, 0xFF, 0xFF LOCAL(boot_drive): - .byte 0 + .byte 0x00 /* the real mode code continues... */ LOCAL (codestart): @@ -164,28 +159,12 @@ multiboot_entry: multiboot_trampoline: /* fill the boot information */ - movl %edx, %eax - shrl $8, %eax - xorl %ebx, %ebx - cmpb $0xFF, %ah - je 1f - movb %ah, %bl - movl %ebx, LOCAL(dos_part) -1: - cmpb $0xFF, %al - je 2f - movb %al, %bl - movl %ebx, LOCAL(bsd_part) -2: + movl %edx, LOCAL(boot_dev) shrl $24, %edx - movb %dl, LOCAL(boot_drive) - movb $0xFF, %dh - movl $GRUB_MEMORY_MACHINE_PROT_STACK, %esp /* enter the usual booting */ call prot_to_real .code16 jmp LOCAL (codestart) - .code32 post_reed_solomon: @@ -201,9 +180,7 @@ post_reed_solomon: popl %esi #endif - movb LOCAL(boot_drive), %dl - movl LOCAL(dos_part), %eax - movl LOCAL(bsd_part), %ebx + movl LOCAL(boot_dev), %edx movl $prot_to_real, %edi movl $real_to_prot, %ecx jmp *%esi diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 25f683fd1..173e734d8 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -622,7 +622,8 @@ grub_disk_biosdisk_fini (void) GRUB_MOD_INIT(biosdisk) { struct grub_biosdisk_cdrp *cdrp - = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_uint8_t boot_drive; if (grub_disk_firmware_is_tainted) { @@ -634,15 +635,16 @@ GRUB_MOD_INIT(biosdisk) grub_memset (cdrp, 0, sizeof (*cdrp)); cdrp->size = sizeof (*cdrp); cdrp->media_type = 0xFF; - if ((! grub_biosdisk_get_cdinfo_int13_extensions (grub_boot_drive, cdrp)) && - ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK) - == GRUB_BIOSDISK_CDTYPE_NO_EMUL)) + boot_drive = (grub_boot_device >> 24); + if ((! grub_biosdisk_get_cdinfo_int13_extensions (boot_drive, cdrp)) + && ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK) + == GRUB_BIOSDISK_CDTYPE_NO_EMUL)) cd_drive = cdrp->drive_no; /* Since diskboot.S rejects devices over 0x90 it must be a CD booted with cdboot.S */ - if (grub_boot_drive >= 0x90) - cd_drive = grub_boot_drive; + if (boot_drive >= 0x90) + cd_drive = boot_drive; grub_disk_dev_register (&grub_biosdisk_dev); } diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index da7230c33..c6492619f 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -67,10 +67,15 @@ void grub_machine_get_bootlocation (char **device, char **path) { char *ptr; + grub_uint8_t boot_drive, dos_part, bsd_part; + + boot_drive = (grub_boot_device >> 24); + dos_part = (grub_boot_device >> 16); + bsd_part = (grub_boot_device >> 8); /* No hardcoded root partition - make it from the boot drive and the partition number encoded at the install time. */ - if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) + if (boot_drive == GRUB_BOOT_MACHINE_PXE_DL) { if (grub_pc_net_config) grub_pc_net_config (device, path); @@ -82,18 +87,18 @@ grub_machine_get_bootlocation (char **device, char **path) *device = grub_malloc (DEV_SIZE); ptr = *device; grub_snprintf (*device, DEV_SIZE, - "%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', - grub_boot_drive & 0x7f); + "%cd%u", (boot_drive & 0x80) ? 'h' : 'f', + boot_drive & 0x7f); ptr += grub_strlen (ptr); - if (grub_install_dos_part >= 0) + if (dos_part != 0xff) grub_snprintf (ptr, DEV_SIZE - (ptr - *device), - ",%u", grub_install_dos_part + 1); + ",%u", dos_part + 1); ptr += grub_strlen (ptr); - if (grub_install_bsd_part >= 0) + if (bsd_part != 0xff) grub_snprintf (ptr, DEV_SIZE - (ptr - *device), ",%u", - grub_install_bsd_part + 1); + bsd_part + 1); ptr += grub_strlen (ptr); *ptr = 0; } diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 058f9efa7..51e19b7f0 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -82,8 +82,6 @@ LOCAL(cont): movsb #endif - movl %eax, %esi - /* clean out the bss */ movl $BSS_START_SYMBOL, %edi @@ -97,9 +95,7 @@ LOCAL(cont): rep stosb - movl %esi, EXT_C(grub_install_dos_part) - movb %dl, EXT_C(grub_boot_drive) - movl %ebx, EXT_C(grub_install_bsd_part) + movl %edx, EXT_C(grub_boot_device) /* * Call the start of main body of C code. @@ -182,9 +178,5 @@ FUNCTION(grub_pxe_call) #include "../int.S" .bss -VARIABLE(grub_boot_drive) - .byte 0 -VARIABLE(grub_install_dos_part) - .long 0xFFFFFFFF -VARIABLE(grub_install_bsd_part) - .long 0xFFFFFFFF +VARIABLE(grub_boot_device) + .long 0 diff --git a/include/grub/i386/pc/kernel.h b/include/grub/i386/pc/kernel.h index 2dcdbb7a6..4f05b74e3 100644 --- a/include/grub/i386/pc/kernel.h +++ b/include/grub/i386/pc/kernel.h @@ -32,14 +32,7 @@ /* The total size of module images following the kernel. */ extern grub_int32_t grub_total_module_size; -/* The DOS partition number of the installed partition. */ -extern grub_int32_t grub_install_dos_part; - -/* The BSD partition number of the installed partition. */ -extern grub_int32_t grub_install_bsd_part; - -/* The boot BIOS drive number. */ -extern grub_uint8_t EXPORT_VAR(grub_boot_drive); +extern grub_uint32_t EXPORT_VAR(grub_boot_device); extern void (*EXPORT_VAR(grub_pc_net_config)) (char **device, char **path); diff --git a/include/grub/offsets.h b/include/grub/offsets.h index e3b9a377c..1269c865d 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -25,14 +25,8 @@ /* The offset of GRUB_COMPRESSED_SIZE. */ #define GRUB_DECOMPRESSOR_I386_PC_UNCOMPRESSED_SIZE 0x0c -/* The offset of GRUB_INSTALL_DOS_PART. */ -#define GRUB_KERNEL_I386_PC_INSTALL_DOS_PART 0x10 - -/* The offset of GRUB_INSTALL_BSD_PART. */ -#define GRUB_KERNEL_I386_PC_INSTALL_BSD_PART 0x14 - /* Offset of reed_solomon_redundancy. */ -#define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x18 +#define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x10 #define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x6e0 @@ -129,8 +123,6 @@ #define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG) #define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER) -#define GRUB_KERNEL_MACHINE_INSTALL_BSD_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_BSD_PART) -#define GRUB_KERNEL_MACHINE_INSTALL_DOS_PART GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _INSTALL_DOS_PART) #define GRUB_MACHINE_LINK_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _LINK_ADDR) #define GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _COMPRESSED_SIZE) diff --git a/util/grub-install.in b/util/grub-install.in index 26a2523f8..ea8699a44 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -564,7 +564,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg" config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" - elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ] || [ "x$platform" = xieee1275 ]; then + else # we need to hardcode the partition number in the core image's prefix. if [ x"$grub_partition" = x ]; then prefix_drive="()" diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 9da72f6c9..3912ad7b2 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -84,7 +84,6 @@ struct image_target_desc grub_uint16_t elf_target; unsigned section_align; signed vaddr_offset; - unsigned install_dos_part, install_bsd_part; grub_uint64_t link_addr; unsigned mod_gap, mod_align; grub_compression_t default_compression; @@ -113,8 +112,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR, .elf_target = EM_386, .link_align = 4, @@ -134,8 +131,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_I386_COREBOOT_LINK_ADDR, .elf_target = EM_386, .link_align = 4, @@ -155,8 +150,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART, - .install_bsd_part = GRUB_KERNEL_I386_PC_INSTALL_BSD_PART, .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR }, { @@ -172,8 +165,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = GRUB_KERNEL_I386_PC_INSTALL_DOS_PART, - .install_bsd_part = GRUB_KERNEL_I386_PC_INSTALL_BSD_PART, .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR }, { @@ -194,8 +185,6 @@ struct image_target_desc image_targets[] = + sizeof (struct grub_pe32_optional_header) + 4 * sizeof (struct grub_pe32_section_table), GRUB_PE32_SECTION_ALIGNMENT), - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .pe_target = GRUB_PE32_MACHINE_I386, .elf_target = EM_386, }, @@ -212,8 +201,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_I386_IEEE1275_LINK_ADDR, .elf_target = EM_386, .mod_gap = GRUB_KERNEL_I386_IEEE1275_MOD_GAP, @@ -233,8 +220,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_I386_QEMU_LINK_ADDR }, { @@ -250,8 +235,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = EFI64_HEADER_SIZE, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .pe_target = GRUB_PE32_MACHINE_X86_64, .elf_target = EM_X86_64, }, @@ -268,8 +251,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN, @@ -288,8 +269,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN, @@ -310,8 +289,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN, @@ -330,8 +307,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_POWERPC_IEEE1275_LINK_ADDR, .elf_target = EM_PPC, .mod_gap = GRUB_KERNEL_POWERPC_IEEE1275_MOD_GAP, @@ -351,8 +326,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR }, { @@ -368,8 +341,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_SPARC64_IEEE1275_LINK_ADDR }, { @@ -385,8 +356,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = GRUB_PE32_SECTION_ALIGNMENT, .vaddr_offset = EFI64_HEADER_SIZE, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .pe_target = GRUB_PE32_MACHINE_IA64, .elf_target = EM_IA_64, }, @@ -404,8 +373,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_ARC_LINK_ALIGN, @@ -424,8 +391,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, @@ -444,8 +409,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, @@ -464,8 +427,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, @@ -484,8 +445,6 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, - .install_dos_part = TARGET_NO_FIELD, - .install_bsd_part = TARGET_NO_FIELD, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, .elf_target = EM_MIPS, .link_align = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN, @@ -990,17 +949,6 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], core_size = full_size; } - /* If we included a drive in our prefix, let GRUB know it doesn't have to - prepend the drive told by BIOS. */ - if (image_target->install_dos_part != TARGET_NO_FIELD - && image_target->install_bsd_part != TARGET_NO_FIELD && prefix[0] == '(') - { - *((grub_int32_t *) (core_img + image_target->install_dos_part)) - = grub_host_to_target32 (-2); - *((grub_int32_t *) (core_img + image_target->install_bsd_part)) - = grub_host_to_target32 (-2); - } - switch (image_target->id) { case IMAGE_I386_PC: diff --git a/util/grub-setup.c b/util/grub-setup.c index f185ed747..055543f2d 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -101,56 +101,12 @@ write_rootdev (char *core_img, grub_device_t root_dev, { #ifdef GRUB_MACHINE_PCBIOS { - grub_int32_t *install_dos_part, *install_bsd_part; - grub_int32_t dos_part, bsd_part; grub_uint8_t *boot_drive; grub_disk_addr_t *kernel_sector; boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); kernel_sector = (grub_disk_addr_t *) (boot_img + GRUB_BOOT_MACHINE_KERNEL_SECTOR); - - install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); - install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); - - /* If we hardcoded drive as part of prefix, we don't want to - override the current setting. */ - if (*install_dos_part != -2) - { - /* Embed information about the installed location. */ - if (root_dev->disk->partition) - { - if (root_dev->disk->partition->parent) - { - if (root_dev->disk->partition->parent->parent) - grub_util_error (_("Installing on doubly nested partitions " - "is not supported")); - dos_part = root_dev->disk->partition->parent->number; - bsd_part = root_dev->disk->partition->number; - } - else - { - dos_part = root_dev->disk->partition->number; - bsd_part = -1; - } - } - else - dos_part = bsd_part = -1; - } - else - { - dos_part = grub_le_to_cpu32 (*install_dos_part); - bsd_part = grub_le_to_cpu32 (*install_bsd_part); - } - - grub_util_info ("dos partition is %d, bsd partition is %d", - dos_part, bsd_part); - - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); - /* FIXME: can this be skipped? */ *boot_drive = 0xFF; From aa94b87027857472aba93d6c7e39abaa10103d96 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 21:38:04 +0100 Subject: [PATCH 556/673] Fix MIPS compilation. * grub-core/boot/mips/startup_raw.S: Use GRUB_DECOMPRESSOR_* * include/grub/offsets.h: Rename decompressor fields from GRUB_KERNEL_* to GRUB_DECOMPRESSOR_*. * util/grub-mkimage.c (image_targets): Use new names. --- ChangeLog | 9 ++++++ grub-core/boot/mips/startup_raw.S | 6 ++-- include/grub/offsets.h | 23 +++++++-------- util/grub-mkimage.c | 48 +++++++++++++++---------------- 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index b5124c18a..15389a335 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-11-12 Vladimir Serbinenko + + Fix MIPS compilation. + + * grub-core/boot/mips/startup_raw.S: Use GRUB_DECOMPRESSOR_* + * include/grub/offsets.h: Rename decompressor fields from + GRUB_KERNEL_* to GRUB_DECOMPRESSOR_*. + * util/grub-mkimage.c (image_targets): Use new names. + 2011-11-12 Vladimir Serbinenko Defer multiboot device parsing until we're in compressed part. diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index e76926677..bbbc1dbec 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -240,9 +240,9 @@ cmdlinedone: subu $a0, $a0, $t0 addu $a0, $a0, $s0 - lw $a1, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0) - lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0) - lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0) + lw $a1, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0) + lw $a2, (GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0) + lw $a3, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0) move $s1, $a1 /* $a0 contains source compressed address, $a1 is destination, diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 1269c865d..68ed084cb 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -62,26 +62,26 @@ #define GRUB_KERNEL_MIPS_LOONGSON_LINK_ALIGN 32 -#define GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE 0x8 -#define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE 0xc -#define GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR 0x10 +#define GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE 0x8 +#define GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE 0xc +#define GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE 0x08 #define GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR 0x80200000 #define GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN 32 -#define GRUB_KERNEL_MIPS_QEMU_MIPS_COMPRESSED_SIZE 0x8 -#define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE 0xc -#define GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR 0x10 +#define GRUB_DECOMPRESSOR_MIPS_QEMU_MIPS_COMPRESSED_SIZE 0x8 +#define GRUB_DECOMPRESSOR_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE 0xc +#define GRUB_DECOMPRESSOR_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE 0x08 #define GRUB_KERNEL_MIPS_ARC_LINK_ADDR 0x8bd00000 #define GRUB_KERNEL_MIPS_ARC_LINK_ALIGN 32 -#define GRUB_KERNEL_MIPS_ARC_COMPRESSED_SIZE 0x8 -#define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_SIZE 0xc -#define GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR 0x10 +#define GRUB_DECOMPRESSOR_MIPS_ARC_COMPRESSED_SIZE 0x8 +#define GRUB_DECOMPRESSOR_MIPS_ARC_UNCOMPRESSED_SIZE 0xc +#define GRUB_DECOMPRESSOR_MIPS_ARC_UNCOMPRESSED_ADDR 0x10 #define GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE 0x08 @@ -116,10 +116,6 @@ #define GRUB_KERNEL_MACHINE_MOD_ALIGN GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _MOD_ALIGN) #define GRUB_KERNEL_MACHINE_MOD_GAP GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _MOD_GAP) #define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _TOTAL_MODULE_SIZE) -#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _KERNEL_IMAGE_SIZE) -#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _COMPRESSED_SIZE) -#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_SIZE) -#define GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR GRUB_OFFSETS_CONCAT (GRUB_KERNEL_, GRUB_MACHINE, _UNCOMPRESSED_ADDR) #define GRUB_BOOT_MACHINE_KERNEL_SEG GRUB_OFFSETS_CONCAT (GRUB_BOOT_, GRUB_MACHINE, _KERNEL_SEG) #define GRUB_MEMORY_MACHINE_UPPER GRUB_OFFSETS_CONCAT (GRUB_MEMORY_, GRUB_MACHINE, _UPPER) @@ -127,6 +123,7 @@ #define GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _COMPRESSED_SIZE) #define GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _UNCOMPRESSED_SIZE) +#define GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR GRUB_OFFSETS_CONCAT (GRUB_DECOMPRESSOR_, GRUB_MACHINE, _UNCOMPRESSED_ADDR) #endif #ifndef ASM_FILE diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 3912ad7b2..0ffeb909e 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -246,9 +246,9 @@ struct image_target_desc image_targets[] = .id = IMAGE_YEELOONG_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, @@ -264,9 +264,9 @@ struct image_target_desc image_targets[] = .id = IMAGE_FULOONG2F_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, @@ -284,9 +284,9 @@ struct image_target_desc image_targets[] = .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .total_module_size = GRUB_KERNEL_MIPS_LOONGSON_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_LOONGSON_LINK_ADDR, @@ -368,9 +368,9 @@ struct image_target_desc image_targets[] = .flags = (PLATFORM_FLAGS_DECOMPRESSORS | PLATFORM_FLAGS_MODULES_BEFORE_KERNEL), .total_module_size = GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_ARC_LINK_ADDR, @@ -386,9 +386,9 @@ struct image_target_desc image_targets[] = .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, @@ -404,9 +404,9 @@ struct image_target_desc image_targets[] = .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, @@ -422,9 +422,9 @@ struct image_target_desc image_targets[] = .id = IMAGE_QEMU_MIPS_FLASH, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, @@ -440,9 +440,9 @@ struct image_target_desc image_targets[] = .id = IMAGE_LOONGSON_ELF, .flags = PLATFORM_FLAGS_DECOMPRESSORS, .total_module_size = GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE, - .decompressor_compressed_size = GRUB_KERNEL_MIPS_LOONGSON_COMPRESSED_SIZE, - .decompressor_uncompressed_size = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_SIZE, - .decompressor_uncompressed_addr = GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR, + .decompressor_compressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_COMPRESSED_SIZE, + .decompressor_uncompressed_size = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_SIZE, + .decompressor_uncompressed_addr = GRUB_DECOMPRESSOR_MIPS_LOONGSON_UNCOMPRESSED_ADDR, .section_align = 1, .vaddr_offset = 0, .link_addr = GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR, From ba102053ce9943a7cf77e9d85f95d5f4bfa8ae1c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 21:46:52 +0100 Subject: [PATCH 557/673] Support ZFS embedding. * grub-core/fs/zfs/zfs.c (grub_zfs_embed): New function. (grub_zfs_fs): Register grub_zfs_embed. --- ChangeLog | 7 +++++++ grub-core/fs/zfs/zfs.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/ChangeLog b/ChangeLog index 15389a335..c12f19951 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-11-12 Vladimir Serbinenko + + Support ZFS embedding. + + * grub-core/fs/zfs/zfs.c (grub_zfs_embed): New function. + (grub_zfs_fs): Register grub_zfs_embed. + 2011-11-12 Vladimir Serbinenko Fix MIPS compilation. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 20cba3509..83a067237 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -3806,6 +3806,35 @@ grub_zfs_dir (grub_device_t device, const char *path, return grub_errno; } +#ifdef GRUB_UTIL +static grub_err_t +grub_zfs_embed (grub_device_t device __attribute__ ((unused)), + unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) +{ + unsigned i; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "ZFS currently supports only PC-BIOS embedding"); + + if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your core.img is unusually large. " + "It won't fit in the embedding area."); + + *nsectors = (VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS); + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) + (*sectors)[i] = i + (VDEV_BOOT_OFFSET >> GRUB_DISK_SECTOR_BITS); + + return GRUB_ERR_NONE; +} +#endif + static struct grub_fs grub_zfs_fs = { .name = "zfs", .dir = grub_zfs_dir, @@ -3815,6 +3844,10 @@ static struct grub_fs grub_zfs_fs = { .label = zfs_label, .uuid = zfs_uuid, .mtime = zfs_mtime, +#ifdef GRUB_UTIL + .embed = grub_zfs_embed, + .reserved_first_sector = 1, +#endif .next = 0 }; From 9edd7be26aef4fe4293835bb9dce3f49e7aff007 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 23:14:51 +0100 Subject: [PATCH 558/673] Fix spaces handling in proc/self/mountinfo. * util/getroot.c (unescape): New function. (grub_find_root_device_from_mountinfo): Use unescape. --- ChangeLog | 7 +++++++ util/getroot.c | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/ChangeLog b/ChangeLog index c12f19951..ab253ddfd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-11-12 Vladimir Serbinenko + + Fix spaces handling in proc/self/mountinfo. + + * util/getroot.c (unescape): New function. + (grub_find_root_device_from_mountinfo): Use unescape. + 2011-11-12 Vladimir Serbinenko Support ZFS embedding. diff --git a/util/getroot.c b/util/getroot.c index f5d6d3f62..96879f545 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -129,6 +129,27 @@ struct mountinfo_entry can't deal with the multiple-device case yet, but in the meantime, we can at least cope with the single-device case by scanning /proc/self/mountinfo. */ +static void +unescape (char *str) +{ + char *optr; + const char *iptr; + for (iptr = optr = str; *iptr; optr++) + { + if (iptr[0] == '\\' && iptr[1] >= '0' && iptr[1] < '8' + && iptr[2] >= '0' && iptr[2] < '8' + && iptr[3] >= '0' && iptr[3] < '8') + { + *optr = (((iptr[1] - '0') << 6) | ((iptr[2] - '0') << 3) + | (iptr[3] - '0')); + iptr += 4; + } + else + *optr = *iptr++; + } + *optr = 0; +} + char * grub_find_root_device_from_mountinfo (const char *dir, char **relroot) { @@ -165,6 +186,9 @@ grub_find_root_device_from_mountinfo (const char *dir, char **relroot) entry.enc_root, entry.enc_path, &count) < 6) continue; + unescape (entry.enc_root); + unescape (entry.enc_path); + enc_path_len = strlen (entry.enc_path); /* Check that enc_path is a prefix of dir. The prefix must either be the entire string, or end with a slash, or be immediately followed From 0cddeb0360d60b518b721996d0dd5d0e5eff476a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 23:16:48 +0100 Subject: [PATCH 559/673] Add copyright year. --- grub-core/disk/lvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 388c7f173..2fd736439 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -1,7 +1,7 @@ /* lvm.c - module to read Logical Volumes. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008,2009,2011 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 From 91e5a33da510d7e48e35c76f54f8ff3b53c19c0e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 23:35:20 +0100 Subject: [PATCH 560/673] * include/grub/lvm.h (grub_lvm_pv): Correct start type. --- ChangeLog | 4 ++++ include/grub/lvm.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ab253ddfd..9f5b71fe4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-12 Vladimir Serbinenko + + * include/grub/lvm.h (grub_lvm_pv): Correct start type. + 2011-11-12 Vladimir Serbinenko Fix spaces handling in proc/self/mountinfo. diff --git a/include/grub/lvm.h b/include/grub/lvm.h index b5352c75c..d77b88ff5 100644 --- a/include/grub/lvm.h +++ b/include/grub/lvm.h @@ -38,7 +38,7 @@ struct grub_lvm_pv { char id[GRUB_LVM_ID_STRLEN+1]; char *name; grub_disk_t disk; - int start; /* Sector number where the data area starts. */ + grub_disk_addr_t start; /* Sector number where the data area starts. */ struct grub_lvm_pv *next; }; From 91ee7b6d737fdba31e052fbe44349d94895df99f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 23:42:49 +0100 Subject: [PATCH 561/673] * grub-core/kern/emu/hostdisk.c (find_system_device): Fix a memory leak. --- ChangeLog | 4 ++++ grub-core/kern/emu/hostdisk.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9f5b71fe4..1ce25663d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-12 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (find_system_device): Fix a memory leak. + 2011-11-12 Vladimir Serbinenko * include/grub/lvm.h (grub_lvm_pv): Correct start type. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index f537b2759..ede765d83 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1751,7 +1751,10 @@ find_system_device (const char *os_dev, struct stat *st, int convert, int add) } if (!add) - return -1; + { + free (os_disk); + return -1; + } if (i == ARRAY_SIZE (map)) grub_util_error (_("device count exceeds limit")); From d89ee4141a1bc3ad1dd5bdacedbd2a2b2409f09b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 12 Nov 2011 23:46:47 +0100 Subject: [PATCH 562/673] * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): Fix a memory leak. (grub_util_biosdisk_get_grub_dev): Add a useful debug info. --- ChangeLog | 6 ++++++ grub-core/kern/emu/hostdisk.c | 12 +++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1ce25663d..230eb0cec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-11-12 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): + Fix a memory leak. + (grub_util_biosdisk_get_grub_dev): Add a useful debug info. + 2011-11-12 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (find_system_device): Fix a memory leak. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index ede765d83..da2cc6aa2 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1781,6 +1781,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) { struct stat st; int drive; + char *sys_disk; grub_util_info ("Looking for %s", os_dev); @@ -1800,9 +1801,13 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return 0; } - if (grub_strcmp (os_dev, - convert_system_partition_to_system_disk (os_dev, &st)) == 0) - return make_device_name (drive, -1, -1); + sys_disk = convert_system_partition_to_system_disk (os_dev, &st); + if (grub_strcmp (os_dev, sys_disk) == 0) + { + free (sys_disk); + return make_device_name (drive, -1, -1); + } + free (sys_disk); #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__) if (! S_ISCHR (st.st_mode)) @@ -1914,6 +1919,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) if (partname == NULL) { grub_disk_close (disk); + grub_util_info ("cannot find the partition of `%s'", os_dev); grub_error (GRUB_ERR_BAD_DEVICE, "cannot find the partition of `%s'", os_dev); return 0; From a346b81c7d9e3c0ebca495f6b4f0bc49baa72712 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 13 Nov 2011 00:01:06 +0100 Subject: [PATCH 563/673] * grub-core/partmap/gpt.c (gpt_partition_map_embed): Restore disk->partiton for safety. --- ChangeLog | 5 +++++ grub-core/partmap/gpt.c | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 230eb0cec..95aed126c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-12 Vladimir Serbinenko + + * grub-core/partmap/gpt.c (gpt_partition_map_embed): Restore + disk->partiton for safety. + 2011-11-12 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index 73a1c3b19..c8bc52609 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -140,11 +140,17 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, const grub_partition_t p) { struct grub_gpt_partentry gptdata; + grub_partition_t p2; + p2 = disk->partition; disk->partition = p->parent; if (grub_disk_read (disk, p->offset, p->index, sizeof (gptdata), &gptdata)) - return 0; + { + disk->partition = p2; + return 0; + } + disk->partition = p2; /* If there's an embed region, it is in a dedicated partition. */ if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) From fa5aeffcc279dc7ac6a6c75c7151651c87d02322 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 13 Nov 2011 00:07:08 +0100 Subject: [PATCH 564/673] * grub-core/partmap/gpt.c (gpt_partition_map_embed): Fix spelling. --- ChangeLog | 4 ++++ grub-core/partmap/gpt.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 95aed126c..623313b3c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-12 Vladimir Serbinenko + + * grub-core/partmap/gpt.c (gpt_partition_map_embed): Fix spelling. + 2011-11-12 Vladimir Serbinenko * grub-core/partmap/gpt.c (gpt_partition_map_embed): Restore diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index c8bc52609..049fda850 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -165,7 +165,7 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, if (embed_type != GRUB_EMBED_PCBIOS) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "GPT curently supports only PC-BIOS embedding"); + "GPT currently supports only PC-BIOS embedding"); err = gpt_partition_map_iterate (disk, find_usable_region); if (err) From 383ceaf0609040610c7ebc8279d958971ca96084 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 13 Nov 2011 12:52:21 +0100 Subject: [PATCH 565/673] Fix a mismerge --- grub-core/loader/i386/pc/plan9.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 73d4eed38..6e49a34b6 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -78,8 +78,7 @@ grub_plan9_boot (void) .edi = 0, .esp = 0, .ebp = 0, - .esi = 0, - .a20 = 1 + .esi = 0 }; grub_video_set_mode ("text", 0, 0); From c30be3b694dbc95c38df9212d1f01b68c8ecdd26 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 13 Nov 2011 14:48:19 +0100 Subject: [PATCH 566/673] Make Reed-Solomon faster by using power of generator representation of GF(256)*. * grub-core/lib/reed_solomon.c (grub_uint16_t) [TEST]: Removed. (gf_double_t): Likewise. (gf_invert): Removed. (gf_powx): New array. (gf_powx_inv): Likewise. (scratch): Move higher. (gf_reduce): Removed. (gf_mul): Use powx. (gf_invert): Likewise. (init_inverts): Replaced with ... (init_powx): ...this. All users updated. (pol_evaluate): Replace multiplications with additions. (rs_encode): Likewise. (gauss_eliminate): Call gf_invert. (grub_reed_solomon_add_redundancy): Call init_powx. (grub_reed_solomon_recover): Call init_powx unconditionally. --- ChangeLog | 22 ++++++++ grub-core/lib/reed_solomon.c | 105 +++++++++++++++++++---------------- 2 files changed, 78 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 623313b3c..229567014 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2011-11-13 Vladimir Serbinenko + + Make Reed-Solomon faster by using power of generator representation of + GF(256)*. + + * grub-core/lib/reed_solomon.c (grub_uint16_t) [TEST]: Removed. + (gf_double_t): Likewise. + (gf_invert): Removed. + (gf_powx): New array. + (gf_powx_inv): Likewise. + (scratch): Move higher. + (gf_reduce): Removed. + (gf_mul): Use powx. + (gf_invert): Likewise. + (init_inverts): Replaced with ... + (init_powx): ...this. All users updated. + (pol_evaluate): Replace multiplications with additions. + (rs_encode): Likewise. + (gauss_eliminate): Call gf_invert. + (grub_reed_solomon_add_redundancy): Call init_powx. + (grub_reed_solomon_recover): Call init_powx unconditionally. + 2011-11-12 Vladimir Serbinenko * grub-core/partmap/gpt.c (gpt_partition_map_embed): Fix spelling. diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 78d249c2f..7da5f204c 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -29,7 +29,6 @@ #ifdef TEST typedef unsigned int grub_size_t; typedef unsigned char grub_uint8_t; -typedef unsigned short grub_uint16_t; #else #include #include @@ -42,7 +41,6 @@ typedef unsigned short grub_uint16_t; #ifdef TEST typedef unsigned int grub_size_t; typedef unsigned char grub_uint8_t; -typedef unsigned short grub_uint16_t; #else #include #include @@ -53,65 +51,72 @@ grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs); #define GF_SIZE 8 typedef grub_uint8_t gf_single_t; -typedef grub_uint16_t gf_double_t; #define GF_POLYNOMIAL 0x1d #define GF_INVERT2 0x8e #if defined (STANDALONE) && !defined (TEST) -static gf_single_t * const gf_invert __attribute__ ((section(".text"))) = (void *) 0x100000; -static char *scratch __attribute__ ((section(".text"))) = (void *) 0x100100; +static gf_single_t * const gf_powx __attribute__ ((section(".text"))) = (void *) 0x100000; +static gf_single_t * const gf_powx_inv __attribute__ ((section(".text"))) = (void *) 0x100200; + +static char *scratch __attribute__ ((section(".text"))) = (void *) 0x100300; #else #if defined (STANDALONE) static char *scratch; #endif -static gf_single_t gf_invert[256]; +static gf_single_t gf_powx[255 * 2]; +static gf_single_t gf_powx_inv[256]; #endif #define SECTOR_SIZE 512 #define MAX_BLOCK_SIZE (200 * SECTOR_SIZE) -static gf_single_t -gf_reduce (gf_double_t a) -{ - int i; - for (i = GF_SIZE - 1; i >= 0; i--) - if (a & (1ULL << (i + GF_SIZE))) - a ^= (((gf_double_t) GF_POLYNOMIAL) << i); - return a & ((1ULL << GF_SIZE) - 1); -} - static gf_single_t gf_mul (gf_single_t a, gf_single_t b) { - gf_double_t res = 0; - int i; - for (i = 0; i < GF_SIZE; i++) - if (b & (1 << i)) - res ^= ((gf_double_t) a) << i; - return gf_reduce (res); + if (a == 0 || b == 0) + return 0; + return gf_powx[(int) gf_powx_inv[a] + (int) gf_powx_inv[b]]; +} + +static inline gf_single_t +gf_invert (gf_single_t a) +{ + return gf_powx[255 - (int) gf_powx_inv[a]]; } static void -init_inverts (void) +init_powx (void) { - gf_single_t a = 1, ai = 1; - do + int i; + grub_uint8_t cur = 1; + + for (i = 0; i < 255; i++) { - a = gf_mul (a, 2); - ai = gf_mul (ai, GF_INVERT2); - gf_invert[a] = ai; + gf_powx[i] = cur; + gf_powx[i + 255] = cur; + gf_powx_inv[cur] = i; + if (cur & (1ULL << (GF_SIZE - 1))) + cur = (cur << 1) ^ GF_POLYNOMIAL; + else + cur <<= 1; } - while (a != 1); } static gf_single_t pol_evaluate (gf_single_t *pol, grub_size_t degree, gf_single_t x) { int i; - gf_single_t xn = 1, s = 0; + gf_single_t s = 0; + int log_xn = 0, log_x; + if (x == 0) + return pol[0]; + log_x = gf_powx_inv[x]; for (i = degree; i >= 0; i--) { - s ^= gf_mul (pol[i], xn); - xn = gf_mul (x, xn); + if (pol[i]) + s ^= gf_powx[(int) gf_powx_inv[pol[i]] + log_xn]; + log_xn += log_x; + if (log_xn >= ((1 << GF_SIZE) - 1)) + log_xn -= ((1 << GF_SIZE) - 1); } return s; } @@ -120,7 +125,7 @@ pol_evaluate (gf_single_t *pol, grub_size_t degree, gf_single_t x) static void rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) { - gf_single_t *rs_polynomial, a = 1; + gf_single_t *rs_polynomial; int i, j; gf_single_t *m; m = xmalloc ((s + rs) * sizeof (gf_single_t)); @@ -132,16 +137,14 @@ rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) /* Multiply with X - a^r */ for (j = 0; j < rs; j++) { - if (a & (1 << (GF_SIZE - 1))) - { - a <<= 1; - a ^= GF_POLYNOMIAL; - } - else - a <<= 1; for (i = 0; i < rs; i++) - rs_polynomial[i] = rs_polynomial[i + 1] ^ gf_mul (a, rs_polynomial[i]); - rs_polynomial[rs] = gf_mul (a, rs_polynomial[rs]); + if (rs_polynomial[i]) + rs_polynomial[i] = (rs_polynomial[i + 1] + ^ gf_powx[j + (int) gf_powx_inv[rs_polynomial[i]]]); + else + rs_polynomial[i] = rs_polynomial[i + 1]; + if (rs_polynomial[rs]) + rs_polynomial[rs] = gf_powx[j + (int) gf_powx_inv[rs_polynomial[rs]]]; } for (j = 0; j < s; j++) if (m[j]) @@ -190,7 +193,7 @@ gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen) if (nzidx == m) continue; chosen[i] = nzidx; - r = gf_invert [eq[i * (m + 1) + nzidx]]; + r = gf_invert (eq[i * (m + 1) + nzidx]); for (j = 0; j < m + 1; j++) eq[i * (m + 1) + j] = gf_mul (eq[i * (m + 1) + j], r); for (j = i + 1; j < n; j++) @@ -437,6 +440,8 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, if (!rs) return; + init_powx (); + while (s > 0) { grub_size_t tt; @@ -468,9 +473,7 @@ grub_reed_solomon_recover (void *ptr_, grub_size_t s, grub_size_t rs) if (!rs) return; -#if defined (STANDALONE) - init_inverts (); -#endif + init_powx (); while (s > 0) { @@ -500,12 +503,15 @@ main (int argc, char **argv) grub_size_t s, rs; char *buf; + grub_memset (gf_powx, 0xee, sizeof (gf_powx)); + grub_memset (gf_powx_inv, 0xdd, sizeof (gf_powx_inv)); + #ifdef STANDALONE scratch = xmalloc (1048576); #endif #ifndef STANDALONE - init_inverts (); + init_powx (); #endif in = fopen ("tst.bin", "rb"); @@ -514,7 +520,7 @@ main (int argc, char **argv) fseek (in, 0, SEEK_END); s = ftell (in); fseek (in, 0, SEEK_SET); - rs = s / 3; + rs = 0x7007; buf = xmalloc (s + rs + SECTOR_SIZE); fread (buf, 1, s, in); fclose (in); @@ -524,8 +530,9 @@ main (int argc, char **argv) out = fopen ("tst_rs.bin", "wb"); fwrite (buf, 1, s + rs, out); fclose (out); - +#if 0 grub_memset (buf + 512 * 15, 0, 512); +#endif out = fopen ("tst_dam.bin", "wb"); fwrite (buf, 1, s + rs, out); From bc108a4a8a4d20dd122cee786befc99bcbe48735 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 13 Nov 2011 19:53:12 +0100 Subject: [PATCH 567/673] * util/grub-mount.c (argp_parser): Accept relative pathes. * util/grub-fstest.c (argp_parser): Likewise. --- ChangeLog | 5 +++++ util/grub-fstest.c | 7 +------ util/grub-mount.c | 7 +------ 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8c3ccb631..d3c48339e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-13 Vladimir Serbinenko + + * util/grub-mount.c (argp_parser): Accept relative pathes. + * util/grub-fstest.c (argp_parser): Likewise. + 2011-11-13 Vladimir Serbinenko Plan9 support. diff --git a/util/grub-fstest.c b/util/grub-fstest.c index c9f24ff08..886155fe2 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -562,14 +562,9 @@ argp_parser (int key, char *arg, struct argp_state *state) if (args_count < num_disks) { - if (arg[0] != '/') - { - fprintf (stderr, "%s", _("Must use absolute path.\n")); - argp_usage (state); - } if (args_count == 0) images = xmalloc (num_disks * sizeof (images[0])); - images[args_count] = xstrdup (arg); + images[args_count] = canonicalize_file_name (arg); args_count++; return 0; } diff --git a/util/grub-mount.c b/util/grub-mount.c index a4be21738..da7d604a2 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -489,13 +489,8 @@ argp_parser (int key, char *arg, struct argp_state *state) return 0; } - if (arg[0] != '/') - { - fprintf (stderr, "%s", _("Must use absolute path.\n")); - argp_usage (state); - } images = xrealloc (images, (num_disks + 1) * sizeof (images[0])); - images[num_disks] = xstrdup (arg); + images[num_disks] = canonicalize_file_name (arg); num_disks++; return 0; From 2536cf64633e7334d1c04bc865907feee5128fdb Mon Sep 17 00:00:00 2001 From: Lubomir Kundrak Date: Sun, 13 Nov 2011 22:59:46 +0100 Subject: [PATCH 568/673] Add facility to debug GRUB with gdb under qemu. * grub-core/gdb_grub.in: New file. * grub-core/gmodule.pl.in: Likewise. * grub-core/Makefile.core.def (gmodule.pl): New script. (gdb_grub): Likewise. --- ChangeLog | 9 ++++ grub-core/Makefile.core.def | 12 ++++++ grub-core/gdb_grub.in | 82 +++++++++++++++++++++++++++++++++++++ grub-core/gmodule.pl.in | 30 ++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 grub-core/gdb_grub.in create mode 100644 grub-core/gmodule.pl.in diff --git a/ChangeLog b/ChangeLog index d3c48339e..22421a715 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-11-13 Lubomir Kundrak + + Add facility to debug GRUB with gdb under qemu. + + * grub-core/gdb_grub.in: New file. + * grub-core/gmodule.pl.in: Likewise. + * grub-core/Makefile.core.def (gmodule.pl): New script. + (gdb_grub): Likewise. + 2011-11-13 Vladimir Serbinenko * util/grub-mount.c (argp_parser): Accept relative pathes. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index fc0472d32..cae79b381 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -18,6 +18,18 @@ script = { common = modinfo.sh.in; }; +script = { + installdir = noinst; + name = gmodule.pl; + common = gmodule.pl.in; +}; + +script = { + installdir = noinst; + name = gdb_grub; + common = gdb_grub.in; +}; + kernel = { name = kernel; diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in new file mode 100644 index 000000000..4a55233da --- /dev/null +++ b/grub-core/gdb_grub.in @@ -0,0 +1,82 @@ +### +### Load debuging information about GNU GRUB 2 modules into GDB +### automatically. Needs readelf, Perl and gmodule.pl script +### +### $Id: .gdbinit,v 1.1 2006/05/14 11:38:08 lkundrak Exp $ +### Lubomir Kundrak +### + +# Add section numbers and addresses to .segments.tmp +define dump_module_sections + set $mod = $arg0 + + # FIXME: save logging status + set logging file .segments.tmp + set logging redirect on + set logging overwrite off + set logging on + + printf "%s", $mod->name + set $segment = $mod->segment + while ($segment) + printf " %i 0x%x", $segment->section, $segment->addr + set $segment = $segment->next + end + printf "\n" + + set logging off + # FIXME: restore logging status +end +document dump_module_sections + Gather information about module whose mod structure was + given for use with match_and_load_symbols +end + +# Generate and execute GDB commands and delete temporary files +# afterwards +define match_and_load_symbols + shell perl gmodule.pl <.segments.tmp >.loadsym.gdb + source .loadsym.gdb + shell rm -f .segments.tmp .loadsym.gdb +end +document match_and_load_symbols + Launch script, that matches section names with information + generated by dump_module_sections and load debugging info + apropriately +end + +### + +define load_module + dump_module_sections $arg0 + match_and_load_symbols +end +document load_module + Load debugging information for module given as argument. +end + +define load_all_modules + set $this = grub_dl_head + while ($this != 0) + dump_module_sections $this->mod + set $this = $this->next + end + match_and_load_symbols +end +document load_all_modules + Load debugging information for all loaded modules. +end + +### + +set confirm off +file kernel.exec +target remote :1234 + +# inform when module is loaded +break grub_dl_add +commands + silent + load_module mod + cont +end diff --git a/grub-core/gmodule.pl.in b/grub-core/gmodule.pl.in new file mode 100644 index 000000000..6739a6f1c --- /dev/null +++ b/grub-core/gmodule.pl.in @@ -0,0 +1,30 @@ +### +### Generate GDB commands, that load symbols for specified module, +### with proper section relocations. See .gdbinit +### +### $Id: gmodule.pl,v 1.2 2006/05/14 11:38:42 lkundrak Exp lkundrak $ +### Lubomir Kundrak +### + +use strict; + +while (<>) { + my ($name, %sections) = split; + + print "add-symbol-file $name.module"; + + open (READELF, "readelf -S $name.mod |") or die; + while () { + /\[\s*(\d+)\]\s+(\.\S+)/ or next; + + if ($2 eq '.text') { + print " $sections{$1}"; + next; + } + + print " -s $2 $sections{$1}" + if ($sections{$1} ne '0x0'); + }; + close (READELF); + print "\n"; +} From 581ffa8a24d8c7db638ee2e0e812f5c30155c7ec Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 14 Nov 2011 14:25:09 +0100 Subject: [PATCH 569/673] * grub-core/lib/adler32.c: Add missing license specification. * grub-core/lib/crc64.c: Likewise. * grub-core/loader/i386/pc/plan9.c: Likewise. * grub-core/partmap/plan.c: Likewise. --- ChangeLog | 7 +++++++ grub-core/lib/adler32.c | 2 ++ grub-core/lib/crc64.c | 2 ++ grub-core/loader/i386/pc/plan9.c | 2 ++ grub-core/partmap/plan.c | 2 ++ 5 files changed, 15 insertions(+) diff --git a/ChangeLog b/ChangeLog index 22421a715..143a189c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-11-14 Vladimir Serbinenko + + * grub-core/lib/adler32.c: Add missing license specification. + * grub-core/lib/crc64.c: Likewise. + * grub-core/loader/i386/pc/plan9.c: Likewise. + * grub-core/partmap/plan.c: Likewise. + 2011-11-13 Lubomir Kundrak Add facility to debug GRUB with gdb under qemu. diff --git a/grub-core/lib/adler32.c b/grub-core/lib/adler32.c index 6fb0b00f8..2a2464db3 100644 --- a/grub-core/lib/adler32.c +++ b/grub-core/lib/adler32.c @@ -21,6 +21,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + /* Based on adler32() from adler32.c of zlib-1.2.5 library. */ #define BASE 65521UL diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c index 92c398d1e..4b1c92cf0 100644 --- a/grub-core/lib/crc64.c +++ b/grub-core/lib/crc64.c @@ -21,6 +21,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_uint64_t crc64_table [256]; static void diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 7bcd4ff3a..5528b2c9f 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -34,6 +34,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_dl_t my_mod; static struct grub_relocator *rel; static grub_uint32_t eip = 0xffffffff; diff --git a/grub-core/partmap/plan.c b/grub-core/partmap/plan.c index c62d04b73..e6e311319 100644 --- a/grub-core/partmap/plan.c +++ b/grub-core/partmap/plan.c @@ -25,6 +25,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static struct grub_partition_map grub_plan_partition_map; static grub_err_t From bdfe9eeb2c0b28eabea0e4b583f26399cceacf33 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 16 Nov 2011 21:35:40 +0100 Subject: [PATCH 570/673] * grub-core/kern/x86_64/efi/callwrap.S: Fix the comment. --- ChangeLog | 4 ++++ grub-core/kern/x86_64/efi/callwrap.S | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 143a189c4..b3fd9bf78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-16 Vladimir Serbinenko + + * grub-core/kern/x86_64/efi/callwrap.S: Fix the comment. + 2011-11-14 Vladimir Serbinenko * grub-core/lib/adler32.c: Add missing license specification. diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S index dced859ac..2df95dda1 100644 --- a/grub-core/kern/x86_64/efi/callwrap.S +++ b/grub-core/kern/x86_64/efi/callwrap.S @@ -25,7 +25,7 @@ * different call conversion, so we need to do some conversion. * * gcc: - * %rdi, %esi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ... + * %rdi, %rsi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ... * * efi: * %rcx, %rdx, %r8, %r9, 32(%rsp), 40(%rsp), 48(%rsp), ... From bb41695449030bee6b5679096ebe3d8f7ddd9a68 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 16 Nov 2011 21:38:00 +0100 Subject: [PATCH 571/673] * grub-core/kern/dl.c (grub_dl_unload): Fix freeing segments. --- ChangeLog | 4 ++++ grub-core/kern/dl.c | 9 +-------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3fd9bf78..1c000592f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-16 Vladimir Serbinenko + + * grub-core/kern/dl.c (grub_dl_unload): Fix freeing segments. + 2011-11-16 Vladimir Serbinenko * grub-core/kern/x86_64/efi/callwrap.S: Fix the comment. diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 26cf0d21d..345e80b90 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -729,7 +729,6 @@ int grub_dl_unload (grub_dl_t mod) { grub_dl_dep_t dep, depn; - grub_dl_segment_t seg, segn; if (mod->ref_count > 0) return 0; @@ -749,13 +748,7 @@ grub_dl_unload (grub_dl_t mod) grub_free (dep); } - for (seg = mod->segment; seg; seg = segn) - { - segn = seg->next; - grub_free (seg->addr); - grub_free (seg); - } - + grub_free (mod->base); grub_free (mod->name); #ifdef GRUB_MODULES_MACHINE_READONLY grub_free (mod->symtab); From 10b64f1cf410f5019c105d80913053d13973b9ed Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 16 Nov 2011 21:40:50 +0100 Subject: [PATCH 572/673] * grub-core/kern/dl.c (grub_dl_load_segments): Fix alignment handling. --- ChangeLog | 4 ++++ grub-core/kern/dl.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1c000592f..50d552fcf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-16 Vladimir Serbinenko + + * grub-core/kern/dl.c (grub_dl_load_segments): Fix alignment handling. + 2011-11-16 Vladimir Serbinenko * grub-core/kern/dl.c (grub_dl_unload): Fix freeing segments. diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 345e80b90..aaeb01f00 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -243,7 +243,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) i < e->e_shnum; i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) { - tsize += ALIGN_UP (s->sh_size, s->sh_addralign); + tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; if (talign < s->sh_addralign) talign = s->sh_addralign; } From adac52113dd713a01655ad95ff3924ce3cb31810 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 25 Nov 2011 14:12:05 +0100 Subject: [PATCH 573/673] * grub-core/fs/cpio.c (grub_cpio_dir): Handle subdirs correctly. --- ChangeLog | 4 ++++ grub-core/fs/cpio.c | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 50d552fcf..d75957f57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-25 Vladimir Serbinenko + + * grub-core/fs/cpio.c (grub_cpio_dir): Handle subdirs correctly. + 2011-11-16 Vladimir Serbinenko * grub-core/kern/dl.c (grub_dl_load_segments): Fix alignment handling. diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 39b35b335..63a1d1f43 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -404,13 +404,15 @@ grub_cpio_dir (grub_device_t device, const char *path_in, { struct grub_cpio_data *data; grub_disk_addr_t ofs; - char *prev, *name, *path; + char *prev, *name, *path, *ptr; grub_size_t len; int symlinknest = 0; path = grub_strdup (path_in + 1); if (!path) return grub_errno; + for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--) + *ptr = 0; grub_dl_ref (my_mod); @@ -443,14 +445,14 @@ grub_cpio_dir (grub_device_t device, const char *path_in, char *p, *n; n = name + len; - if (*n == '/') + while (*n == '/') n++; - p = grub_strchr (name + len, '/'); + p = grub_strchr (n, '/'); if (p) *p = 0; - if (((!prev) || (grub_strcmp (prev, name) != 0)) && name[len] != 0) + if (((!prev) || (grub_strcmp (prev, n) != 0)) && *n != 0) { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); @@ -458,7 +460,7 @@ grub_cpio_dir (grub_device_t device, const char *path_in, info.mtime = mtime; info.mtimeset = 1; - hook (name + len, &info); + hook (n, &info); grub_free (prev); prev = name; } From 78845dc270e72f6f6b542568372b023b4b81b6e2 Mon Sep 17 00:00:00 2001 From: Seth Goldberg Date: Fri, 25 Nov 2011 14:16:44 +0100 Subject: [PATCH 574/673] * po/Makefile.in.in: Add missing escape-continuation. --- ChangeLog | 4 ++++ po/Makefile.in.in | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d75957f57..1b336c942 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-25 Seth Goldberg + + * po/Makefile.in.in: Add missing escape-continuation. + 2011-11-25 Vladimir Serbinenko * grub-core/fs/cpio.c (grub_cpio_dir): Handle subdirs correctly. diff --git a/po/Makefile.in.in b/po/Makefile.in.in index b0e7b8fa2..5a7c07c5b 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -165,7 +165,7 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell --package-version='@VERSION@' \ --msgid-bugs-address="$$msgid_bugs_address" \ ;; \ - esac + esac; \ case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ @@ -187,7 +187,7 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell --join-existing --language=Shell \ --keyword=gettext_quoted --keyword=gettext_printf \ ;; \ - esac + esac ; \ test ! -f $(DOMAIN).po || { \ sed -f grub.d.sed < $(DOMAIN).po > $(DOMAIN).1po && \ mv $(DOMAIN).1po $(DOMAIN).po; \ From fd258e5cce01dcb354b4a01578577542a4ee108f Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 25 Nov 2011 23:07:33 +0100 Subject: [PATCH 575/673] 2011-11-25 Robert Millan * util/getroot.c [HAVE_LIMITS_H]: Include `'. (find_root_device_from_libzfs): Add zpool output parser to be used as fallback when libzfs isn't available. --- ChangeLog | 6 ++++ util/getroot.c | 74 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b336c942..cb98ebf0a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-11-25 Robert Millan + + * util/getroot.c [HAVE_LIMITS_H]: Include `'. + (find_root_device_from_libzfs): Add zpool output parser to be used + as fallback when libzfs isn't available. + 2011-11-25 Seth Goldberg * po/Makefile.in.in: Add missing escape-continuation. diff --git a/util/getroot.c b/util/getroot.c index 96879f545..cc3fdf77d 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -32,6 +32,9 @@ #include #include #include +#ifdef HAVE_LIMITS_H +#include +#endif #include #include #include @@ -273,7 +276,6 @@ grub_find_root_device_from_mountinfo (const char *dir, char **relroot) #endif /* __linux__ */ -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) static char * find_root_device_from_libzfs (const char *dir) { @@ -285,6 +287,7 @@ find_root_device_from_libzfs (const char *dir) if (! poolname) return NULL; +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) { zpool_handle_t *zpool; libzfs_handle_t *libzfs; @@ -340,6 +343,61 @@ find_root_device_from_libzfs (const char *dir) zpool_close (zpool); } +#else + { + char *cmd; + FILE *fp; + int ret; + char *line; + size_t len; + int st; + + char name[PATH_MAX], state[256], readlen[256], writelen[256], cksum[256], notes[256]; + unsigned int dummy; + + asprintf (&cmd, "zpool status %s", poolname); + fp = popen (cmd, "r"); + free (cmd); + + st = 0; + while (st < 3) + { + line = NULL; + ret = getline (&line, &len, fp); + if (ret == -1) + goto fail; + + if (sscanf (line, " %s %256s %256s %256s %256s %256s", name, state, readlen, writelen, cksum, notes) >= 5) + switch (st) + { + case 0: + if (!strcmp (name, "NAME") + && !strcmp (state, "STATE") + && !strcmp (readlen, "READ") + && !strcmp (writelen, "WRITE") + && !strcmp (cksum, "CKSUM")) + st++; + break; + case 1: + if (!strcmp (name, poolname)) + st++; + break; + case 2: + if (strcmp (name, "mirror") && !sscanf (name, "mirror-%u", &dummy) + && !sscanf (name, "raidz%u", &dummy) + && !strcmp (state, "ONLINE")) + st++; + break; + } + + free (line); + } + asprintf (&device, "/dev/%s", name); + + fail: + pclose (fp); + } +#endif free (poolname); if (poolfs) @@ -347,7 +405,6 @@ find_root_device_from_libzfs (const char *dir) return device; } -#endif #ifdef __MINGW32__ @@ -650,10 +707,8 @@ grub_guess_root_device (const char *dir) os_dev = grub_find_root_device_from_mountinfo (dir, NULL); #endif /* __linux__ */ -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (!os_dev) os_dev = find_root_device_from_libzfs (dir); -#endif if (os_dev) { @@ -1383,7 +1438,6 @@ grub_get_libzfs_handle (void) } #endif /* HAVE_LIBZFS */ -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) /* ZFS has similar problems to those of btrfs (see above). */ void grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) @@ -1444,7 +1498,6 @@ grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) else *poolfs = xstrdup (""); } -#endif /* This function never prints trailing slashes (so that its output can be appended a slash unconditionally). */ @@ -1456,23 +1509,18 @@ grub_make_system_path_relative_to_its_root (const char *path) uintptr_t offset = 0; dev_t num; size_t len; - -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) char *poolfs = NULL; -#endif /* canonicalize. */ p = canonicalize_file_name (path); if (p == NULL) grub_util_error (_("failed to get canonical path of %s"), path); -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */ { char *dummy; grub_find_zpool_from_dir (p, &dummy, &poolfs); } -#endif len = strlen (p) + 1; buf = xstrdup (p); @@ -1524,10 +1572,8 @@ grub_make_system_path_relative_to_its_root (const char *path) } #endif free (buf2); -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (poolfs) return xasprintf ("/%s/@", poolfs); -#endif return xstrdup (""); } else @@ -1584,14 +1630,12 @@ grub_make_system_path_relative_to_its_root (const char *path) len--; } -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (poolfs) { ret = xasprintf ("/%s/@%s", poolfs, buf3); free (buf3); } else -#endif ret = buf3; return ret; From 49e891ac9ca701513172cf2fec5b9c5c73e89c4f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 27 Nov 2011 02:34:22 +0100 Subject: [PATCH 576/673] * grub-core/fs/zfs/zfs.c (recovery): Fix spelling. (read_device): Fix size calculation. --- ChangeLog | 5 +++++ grub-core/fs/zfs/zfs.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index cb98ebf0a..52da3c3a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-11-27 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (recovery): Fix spelling. + (read_device): Fix size calculation. + 2011-11-25 Robert Millan * util/getroot.c [HAVE_LIMITS_H]: Include `'. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 83a067237..be659f52c 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -1001,7 +1001,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, const unsigned *powers, const int *idx) { - grub_dprintf ("zfs", "recovering %u bufers\n", nbufs); + grub_dprintf ("zfs", "recovering %u buffers\n", nbufs); /* Now we have */ /* b_i = sum (r_j* (x ** (powers[i] * idx[j])))*/ /* Let's invert the matrix in question. */ @@ -1338,8 +1338,8 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, { grub_uint8_t *tmp_recovery_buf[4]; for (j = 0; j < i; j++) - tmp_recovery_buf[j] = recovery_buf[j] + recovery_len[j] - 1; - err = recovery (tmp_recovery_buf, 1, i, redundancy_pow, + tmp_recovery_buf[j] = recovery_buf[j] + recovery_len[failed_devices - 1]; + err = recovery (tmp_recovery_buf, recovery_len[0] - recovery_len[failed_devices - 1], i, redundancy_pow, recovery_idx); if (err) return err; From 112b483765b3e301396bb807b547ee1e1fb2392b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 28 Nov 2011 01:10:00 +0000 Subject: [PATCH 577/673] * util/getroot.c (find_root_device_from_libzfs): Use xasprintf. --- ChangeLog | 4 ++++ util/getroot.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 52da3c3a6..07f3fb62c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-11-28 Colin Watson + + * util/getroot.c (find_root_device_from_libzfs): Use xasprintf. + 2011-11-27 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (recovery): Fix spelling. diff --git a/util/getroot.c b/util/getroot.c index cc3fdf77d..05bee4964 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -355,7 +355,7 @@ find_root_device_from_libzfs (const char *dir) char name[PATH_MAX], state[256], readlen[256], writelen[256], cksum[256], notes[256]; unsigned int dummy; - asprintf (&cmd, "zpool status %s", poolname); + cmd = xasprintf ("zpool status %s", poolname); fp = popen (cmd, "r"); free (cmd); @@ -392,7 +392,7 @@ find_root_device_from_libzfs (const char *dir) free (line); } - asprintf (&device, "/dev/%s", name); + device = xasprintf ("/dev/%s", name); fail: pclose (fp); From bf3a3857928e4647a85386f8975dae7a44bf4f4e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 30 Nov 2011 16:20:13 +0100 Subject: [PATCH 578/673] Add missing const qualifiers. * grub-core/commands/i386/pc/sendkey.c (keysym): Add missing const. * grub-core/commands/lspci.c (grub_pci_classname): Likewise. * grub-core/commands/menuentry.c (hotkey_aliases): Likewise. * grub-core/disk/lvm.c (grub_lvm_getvalue): Likewise. (grub_lvm_check_flag): Likewise. * grub-core/efiemu/i386/coredetect.c (grub_efiemu_get_default_core_name): Likewise * grub-core/efiemu/main.c (grub_efiemu_autocore): Likewise. * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Likewise. * grub-core/fs/ntfs.c (fixup): Likewise. * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Likewise. * grub-core/fs/zfs/zfs.c (decomp_entry): Likewise. (fzap_lookup): Likewise. (zap_lookup): Likewise. * grub-core/gnulib/regcomp.c (init_dfa): Likewise. * grub-core/lib/legacy_parse.c (check_option): Likewise. * grub-core/lib/posix_wrap/langinfo.h (nl_langinfo): Likewise. * grub-core/loader/i386/bsd.c (grub_bsd_add_meta): Likewise. (grub_freebsd_add_meta_module): Likewise. (grub_cmd_freebsd_module): Likewise. * grub-core/loader/i386/xnu.c (tbl_alias): Likewise. * grub-core/loader/xnu.c (grub_xnu_register_memory): Likewise. (grub_xnu_writetree_get_size): Likewise. (grub_xnu_writetree_toheap_real): Likewise. (grub_xnu_find_key): Likewise. (grub_xnu_create_key): Likewise. (grub_xnu_create_value): Likewise. (grub_xnu_register_memory): Likewise. (grub_xnu_check_os_bundle_required): Likewise. (grub_xnu_scan_dir_for_kexts): Likewise. (grub_xnu_load_kext_from_dir): Likewise. * grub-core/normal/color.c (color_list): Likewise. * grub-core/normal/completion.c (current_word): Likewise. * grub-core/normal/menu_entry.c (insert_string): Likewise. * grub-core/term/serial.c (grub_serial_find): Likewise. * grub-core/term/tparm.c (grub_terminfo_tparm): Likewise. * include/grub/efiemu/efiemu.h (grub_efiemu_get_default_core_name): Likewise. * include/grub/i386/bsd.h (grub_bsd_add_meta): Likewise. (grub_freebsd_add_meta_module): Likewise. * include/grub/lib/arg.h (grub_arg_option): Likewise. * include/grub/net.h (grub_net_card_driver): Likewise. (grub_net_card): Likewise. (grub_net_app_protocol): Likewise. * include/grub/parttool.h (grub_parttool_argdesc): Likewise. * include/grub/serial.h (grub_serial_find): Likewise. * include/grub/tparm.h (grub_terminfo_tparm): Likewise. * include/grub/xnu.h (grub_xnu_create_key): Likewise. (grub_xnu_create_value): Likewise. (grub_xnu_find_key): Likewise. (grub_xnu_scan_dir_for_kexts): Likewise. (grub_xnu_load_kext_from_dir): Likewise. * include/grub/zfs/zio_checksum.h (zio_checksum_t): Moved from here ... * grub-core/fs/zfs/zfs.c (zio_checksum_t): ...here. * include/grub/zfs/zio_checksum.h (zio_checksum_info): Moved from here ... * grub-core/fs/zfs/zfs.c (zio_checksum_info): ... here. Added missing const. --- ChangeLog | 63 ++++++++++++++++++++++++++++ grub-core/commands/i386/pc/sendkey.c | 4 +- grub-core/commands/lspci.c | 2 +- grub-core/commands/menuentry.c | 2 +- grub-core/disk/lvm.c | 4 +- grub-core/efiemu/i386/coredetect.c | 2 +- grub-core/efiemu/main.c | 2 +- grub-core/fs/hfsplus.c | 2 +- grub-core/fs/ntfs.c | 2 +- grub-core/fs/xfs.c | 4 +- grub-core/fs/zfs/zfs.c | 24 +++++++++-- grub-core/gnulib/regcomp.c | 2 +- grub-core/lib/legacy_parse.c | 2 +- grub-core/lib/posix_wrap/langinfo.h | 2 +- grub-core/loader/i386/bsd.c | 9 ++-- grub-core/loader/i386/xnu.c | 2 +- grub-core/loader/xnu.c | 23 +++++----- grub-core/normal/color.c | 2 +- grub-core/normal/completion.c | 2 +- grub-core/normal/menu_entry.c | 4 +- grub-core/term/serial.c | 4 +- grub-core/term/tparm.c | 2 +- include/grub/efiemu/efiemu.h | 2 +- include/grub/i386/bsd.h | 4 +- include/grub/lib/arg.h | 4 +- include/grub/net.h | 6 +-- include/grub/parttool.h | 4 +- include/grub/serial.h | 2 +- include/grub/tparm.h | 2 +- include/grub/xnu.h | 12 +++--- include/grub/zfs/zio_checksum.h | 16 ------- 31 files changed, 143 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index 07f3fb62c..0d0219d9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,66 @@ +2011-11-30 Vladimir Serbinenko + + Add missing const qualifiers. + + * grub-core/commands/i386/pc/sendkey.c (keysym): Add missing const. + * grub-core/commands/lspci.c (grub_pci_classname): Likewise. + * grub-core/commands/menuentry.c (hotkey_aliases): Likewise. + * grub-core/disk/lvm.c (grub_lvm_getvalue): Likewise. + (grub_lvm_check_flag): Likewise. + * grub-core/efiemu/i386/coredetect.c + (grub_efiemu_get_default_core_name): Likewise + * grub-core/efiemu/main.c (grub_efiemu_autocore): Likewise. + * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Likewise. + * grub-core/fs/ntfs.c (fixup): Likewise. + * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Likewise. + * grub-core/fs/zfs/zfs.c (decomp_entry): Likewise. + (fzap_lookup): Likewise. + (zap_lookup): Likewise. + * grub-core/gnulib/regcomp.c (init_dfa): Likewise. + * grub-core/lib/legacy_parse.c (check_option): Likewise. + * grub-core/lib/posix_wrap/langinfo.h (nl_langinfo): Likewise. + * grub-core/loader/i386/bsd.c (grub_bsd_add_meta): Likewise. + (grub_freebsd_add_meta_module): Likewise. + (grub_cmd_freebsd_module): Likewise. + * grub-core/loader/i386/xnu.c (tbl_alias): Likewise. + * grub-core/loader/xnu.c (grub_xnu_register_memory): Likewise. + (grub_xnu_writetree_get_size): Likewise. + (grub_xnu_writetree_toheap_real): Likewise. + (grub_xnu_find_key): Likewise. + (grub_xnu_create_key): Likewise. + (grub_xnu_create_value): Likewise. + (grub_xnu_register_memory): Likewise. + (grub_xnu_check_os_bundle_required): Likewise. + (grub_xnu_scan_dir_for_kexts): Likewise. + (grub_xnu_load_kext_from_dir): Likewise. + * grub-core/normal/color.c (color_list): Likewise. + * grub-core/normal/completion.c (current_word): Likewise. + * grub-core/normal/menu_entry.c (insert_string): Likewise. + * grub-core/term/serial.c (grub_serial_find): Likewise. + * grub-core/term/tparm.c (grub_terminfo_tparm): Likewise. + * include/grub/efiemu/efiemu.h (grub_efiemu_get_default_core_name): + Likewise. + * include/grub/i386/bsd.h (grub_bsd_add_meta): Likewise. + (grub_freebsd_add_meta_module): Likewise. + * include/grub/lib/arg.h (grub_arg_option): Likewise. + * include/grub/net.h (grub_net_card_driver): Likewise. + (grub_net_card): Likewise. + (grub_net_app_protocol): Likewise. + * include/grub/parttool.h (grub_parttool_argdesc): Likewise. + * include/grub/serial.h (grub_serial_find): Likewise. + * include/grub/tparm.h (grub_terminfo_tparm): Likewise. + * include/grub/xnu.h (grub_xnu_create_key): Likewise. + (grub_xnu_create_value): Likewise. + (grub_xnu_find_key): Likewise. + (grub_xnu_scan_dir_for_kexts): Likewise. + (grub_xnu_load_kext_from_dir): Likewise. + + * include/grub/zfs/zio_checksum.h (zio_checksum_t): Moved from here ... + * grub-core/fs/zfs/zfs.c (zio_checksum_t): ...here. + * include/grub/zfs/zio_checksum.h (zio_checksum_info): + Moved from here ... + * grub-core/fs/zfs/zfs.c (zio_checksum_info): ... here. Added missing const. + 2011-11-28 Colin Watson * util/getroot.c (find_root_device_from_libzfs): Use xasprintf. diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 83400c347..80094c795 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -63,8 +63,8 @@ static grub_uint32_t andmask = 0xffffffff, ormask = 0; struct keysym { - char *unshifted_name; /* the name in unshifted state */ - char *shifted_name; /* the name in shifted state */ + const char *unshifted_name; /* the name in unshifted state */ + const char *shifted_name; /* the name in shifted state */ unsigned char unshifted_ascii; /* the ascii code in unshifted state */ unsigned char shifted_ascii; /* the ascii code in shifted state */ unsigned char keycode; /* keyboard scancode */ diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index 03541df6c..9f836298f 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -29,7 +29,7 @@ struct grub_pci_classname { int class; int subclass; - char *desc; + const char *desc; }; static const struct grub_pci_classname grub_pci_classes[] = diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index f5ec60bff..57e4baa61 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -40,7 +40,7 @@ static const struct grub_arg_option options[] = static struct { - char *name; + const char *name; int key; } hotkey_aliases[] = { diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 2fd736439..f3a99c66e 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -44,7 +44,7 @@ static int is_lv_readable (struct grub_lvm_lv *lv); at the number. In case STR is not found, *P will be NULL and the return value will be 0. */ static int -grub_lvm_getvalue (char **p, char *str) +grub_lvm_getvalue (char **p, const char *str) { *p = grub_strstr (*p, str); if (! *p) @@ -69,7 +69,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl) #endif static int -grub_lvm_check_flag (char *p, char *str, char *flag) +grub_lvm_check_flag (char *p, const char *str, const char *flag) { int len_str = grub_strlen (str), len_flag = grub_strlen (flag); while (1) diff --git a/grub-core/efiemu/i386/coredetect.c b/grub-core/efiemu/i386/coredetect.c index 975c4aa5d..c3782fda9 100644 --- a/grub-core/efiemu/i386/coredetect.c +++ b/grub-core/efiemu/i386/coredetect.c @@ -26,7 +26,7 @@ #define bit_LM (1 << 29) -char * +const char * grub_efiemu_get_default_core_name (void) { diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c index 126ecf9e7..f2c038110 100644 --- a/grub-core/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -227,7 +227,7 @@ grub_efiemu_autocore (void) { const char *prefix; char *filename; - char *suffix; + const char *suffix; grub_err_t err; if (grub_efiemu_sizeof_uintn_t () != 0) diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 3d9bc42fa..00b2366bf 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -181,7 +181,7 @@ enum grub_hfsplus_filetype struct grub_hfsplus_catkey_internal { grub_uint32_t parent; - char *name; + const char *name; }; /* Internal representation of an extent overflow key. */ diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index ac695a29f..a432adce3 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -47,7 +47,7 @@ static grub_dl_t my_mod; grub_ntfscomp_func_t grub_ntfscomp_func; static grub_err_t -fixup (struct grub_ntfs_data *data, char *buf, int len, char *magic) +fixup (struct grub_ntfs_data *data, char *buf, int len, const char *magic) { int ss; char *pu; diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index c4d47a099..c7ce3aac9 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -451,9 +451,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_node_t node)) { struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; - auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename); + auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename); - int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename) + int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename) { struct grub_fshelp_node *fdiro; diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index be659f52c..9de2ab586 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -131,10 +131,26 @@ typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len); typedef struct decomp_entry { - char *name; + const char *name; zfs_decomp_func_t *decomp_func; } decomp_entry_t; +/* + * Signature for checksum functions. + */ +typedef void zio_checksum_t(const void *data, grub_uint64_t size, + grub_zfs_endian_t endian, zio_cksum_t *zcp); + +/* + * Information about each checksum function. + */ +typedef struct zio_checksum_info { + zio_checksum_t *ci_func; /* checksum function for each byteorder */ + int ci_correctable; /* number of correctable bits */ + int ci_eck; /* uses zio embedded checksum? */ + const char *ci_name; /* descriptive name */ +} zio_checksum_info_t; + typedef struct dnode_end { dnode_phys_t dn; @@ -1933,8 +1949,8 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) /* XXX */ static grub_err_t fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, - char *name, grub_uint64_t * value, struct grub_zfs_data *data, - int case_insensitive) + const char *name, grub_uint64_t * value, + struct grub_zfs_data *data, int case_insensitive) { void *l; grub_uint64_t hash, idx, blkid; @@ -2096,7 +2112,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, * */ static grub_err_t -zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val, +zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, struct grub_zfs_data *data, int case_insensitive) { grub_uint64_t block_type; diff --git a/grub-core/gnulib/regcomp.c b/grub-core/gnulib/regcomp.c index 86ca02b0c..23f3afa01 100644 --- a/grub-core/gnulib/regcomp.c +++ b/grub-core/gnulib/regcomp.c @@ -851,7 +851,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) { __re_size_t table_size; #ifndef _LIBC - char *codeset_name; + const char *codeset_name; #endif #ifdef RE_ENABLE_I18N size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 43fca51dc..e429f2f1b 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -402,7 +402,7 @@ adjust_file (const char *in, grub_size_t len) } static int -check_option (const char *a, char *b, grub_size_t len) +check_option (const char *a, const char *b, grub_size_t len) { if (grub_strlen (b) != len) return 0; diff --git a/grub-core/lib/posix_wrap/langinfo.h b/grub-core/lib/posix_wrap/langinfo.h index 72b5b9612..ab75af15d 100644 --- a/grub-core/lib/posix_wrap/langinfo.h +++ b/grub-core/lib/posix_wrap/langinfo.h @@ -23,7 +23,7 @@ typedef enum { CODESET } nl_item; -static inline char * +static inline const char * nl_langinfo (nl_item item) { switch (item) diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 6746b3853..f9bab21e6 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -206,7 +206,7 @@ grub_bsd_get_device (grub_uint32_t * biosdev, } grub_err_t -grub_bsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len) +grub_bsd_add_meta (grub_uint32_t type, const void *data, grub_uint32_t len) { struct bsd_tag *newtag; @@ -383,10 +383,11 @@ grub_bsd_add_mmap (void) } grub_err_t -grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv, +grub_freebsd_add_meta_module (const char *filename, const char *type, + int argc, char **argv, grub_addr_t addr, grub_uint32_t size) { - char *name; + const char *name; name = grub_strrchr (filename, '/'); if (name) name++; @@ -1806,7 +1807,7 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)), grub_file_t file = 0; int modargc; char **modargv; - char *type; + const char *type; grub_err_t err; void *src; diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index 36893ae62..1df8dc4c0 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -46,7 +46,7 @@ grub_uint32_t grub_xnu_entry_point, grub_xnu_arg1, grub_xnu_stack; struct tbl_alias { grub_efi_guid_t guid; - char *name; + const char *name; }; static struct tbl_alias table_aliases[] = diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c index a98d60c20..f96bc2b75 100644 --- a/grub-core/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -50,7 +50,7 @@ grub_size_t grub_xnu_heap_size = 0; struct grub_relocator *grub_xnu_relocator; static grub_err_t -grub_xnu_register_memory (char *prefix, int *suffix, +grub_xnu_register_memory (const char *prefix, int *suffix, grub_addr_t addr, grub_size_t size); grub_err_t grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target) @@ -103,7 +103,8 @@ grub_xnu_free_devtree (struct grub_xnu_devtree_key *cur) /* Compute the size of device tree in xnu format. */ static grub_size_t -grub_xnu_writetree_get_size (struct grub_xnu_devtree_key *start, char *name) +grub_xnu_writetree_get_size (struct grub_xnu_devtree_key *start, + const char *name) { grub_size_t ret; struct grub_xnu_devtree_key *cur; @@ -134,7 +135,8 @@ grub_xnu_writetree_get_size (struct grub_xnu_devtree_key *start, char *name) /* Write devtree in XNU format at curptr assuming the head is named NAME.*/ static void * grub_xnu_writetree_toheap_real (void *curptr, - struct grub_xnu_devtree_key *start, char *name) + struct grub_xnu_devtree_key *start, + const char *name) { struct grub_xnu_devtree_key *cur; int nkeys = 0, nvals = 0; @@ -249,7 +251,7 @@ grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size) /* Find a key or value in parent key. */ struct grub_xnu_devtree_key * -grub_xnu_find_key (struct grub_xnu_devtree_key *parent, char *name) +grub_xnu_find_key (struct grub_xnu_devtree_key *parent, const char *name) { struct grub_xnu_devtree_key *cur; for (cur = parent; cur; cur = cur->next) @@ -259,7 +261,7 @@ grub_xnu_find_key (struct grub_xnu_devtree_key *parent, char *name) } struct grub_xnu_devtree_key * -grub_xnu_create_key (struct grub_xnu_devtree_key **parent, char *name) +grub_xnu_create_key (struct grub_xnu_devtree_key **parent, const char *name) { struct grub_xnu_devtree_key *ret; ret = grub_xnu_find_key (*parent, name); @@ -285,7 +287,7 @@ grub_xnu_create_key (struct grub_xnu_devtree_key **parent, char *name) } struct grub_xnu_devtree_key * -grub_xnu_create_value (struct grub_xnu_devtree_key **parent, char *name) +grub_xnu_create_value (struct grub_xnu_devtree_key **parent, const char *name) { struct grub_xnu_devtree_key *ret; ret = grub_xnu_find_key (*parent, name); @@ -562,7 +564,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), /* Register a memory in a memory map under name PREFIXSUFFIX and increment SUFFIX. */ static grub_err_t -grub_xnu_register_memory (char *prefix, int *suffix, +grub_xnu_register_memory (const char *prefix, int *suffix, grub_addr_t addr, grub_size_t size) { struct grub_xnu_devtree_key *chosen; @@ -918,7 +920,8 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), /* Returns true if the kext should be loaded according to plist and osbundlereq. Also fill BINNAME. */ static int -grub_xnu_check_os_bundle_required (char *plistname, char *osbundlereq, +grub_xnu_check_os_bundle_required (char *plistname, + const char *osbundlereq, char **binname) { grub_file_t file; @@ -1033,7 +1036,7 @@ grub_xnu_check_os_bundle_required (char *plistname, char *osbundlereq, /* Load all loadable kexts placed under DIRNAME and matching OSBUNDLEREQUIRED */ grub_err_t -grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, +grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired, int maxrecursion) { grub_device_t dev; @@ -1099,7 +1102,7 @@ grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, /* Load extension DIRNAME. (extensions are directories in xnu) */ grub_err_t -grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, +grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired, int maxrecursion) { grub_device_t dev; diff --git a/grub-core/normal/color.c b/grub-core/normal/color.c index 2e6c80b94..06f1a877c 100644 --- a/grub-core/normal/color.c +++ b/grub-core/normal/color.c @@ -23,7 +23,7 @@ #include /* Borrowed from GRUB Legacy */ -static char *color_list[16] = +static const char *color_list[16] = { "black", "blue", diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c index 67676dfe4..8568cd892 100644 --- a/grub-core/normal/completion.c +++ b/grub-core/normal/completion.c @@ -28,7 +28,7 @@ #include /* The current word. */ -static char *current_word; +static const char *current_word; /* The matched string. */ static char *match; diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c index dc5ab528f..7af093fd8 100644 --- a/grub-core/normal/menu_entry.c +++ b/grub-core/normal/menu_entry.c @@ -317,7 +317,7 @@ update_screen_all (struct screen *screen, } static int -insert_string (struct screen *screen, char *s, int update) +insert_string (struct screen *screen, const char *s, int update) { int region_start = screen->num_lines; int region_column = 0; @@ -397,7 +397,7 @@ insert_string (struct screen *screen, char *s, int update) else { /* All but LF. */ - char *p; + const char *p; struct line *current_linep; int size; int orig_num[screen->nterms], new_num[screen->nterms]; diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index 86935626c..7b970587f 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -126,7 +126,7 @@ static struct grub_term_output grub_serial_term_output = struct grub_serial_port * -grub_serial_find (char *name) +grub_serial_find (const char *name) { struct grub_serial_port *port; @@ -157,7 +157,7 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; char pname[40]; - char *name = NULL; + const char *name = NULL; struct grub_serial_port *port; struct grub_serial_config config; grub_err_t err; diff --git a/grub-core/term/tparm.c b/grub-core/term/tparm.c index 076a192a5..8c1c288a0 100644 --- a/grub-core/term/tparm.c +++ b/grub-core/term/tparm.c @@ -745,7 +745,7 @@ tparam_internal(const char *string, va_list ap) return (out_buff); } -char * +const char * grub_terminfo_tparm (const char *string, ...) { va_list ap; diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 9cedc3226..7b9551627 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -272,7 +272,7 @@ grub_err_t grub_efiemu_write_value (void * addr, grub_uint32_t value, grub_err_t grub_efiemu_write_sym_markers (void); grub_err_t grub_efiemu_pnvram (void); grub_err_t grub_efiemu_prepare (void); -char *grub_efiemu_get_default_core_name (void); +const char *grub_efiemu_get_default_core_name (void); void grub_efiemu_pnvram_cmd_unregister (void); grub_err_t grub_efiemu_autocore (void); grub_err_t grub_efiemu_crc32 (void); diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h index 53008cdaf..c9e8b7dd2 100644 --- a/include/grub/i386/bsd.h +++ b/include/grub/i386/bsd.h @@ -94,8 +94,8 @@ grub_err_t grub_netbsd_load_elf_meta64 (struct grub_relocator *relocator, grub_addr_t *kern_end); grub_err_t grub_bsd_add_meta (grub_uint32_t type, - void *data, grub_uint32_t len); -grub_err_t grub_freebsd_add_meta_module (char *filename, char *type, + const void *data, grub_uint32_t len); +grub_err_t grub_freebsd_add_meta_module (const char *filename, const char *type, int argc, char **argv, grub_addr_t addr, grub_uint32_t size); diff --git a/include/grub/lib/arg.h b/include/grub/lib/arg.h index b61f6f30e..f81af85ee 100644 --- a/include/grub/lib/arg.h +++ b/include/grub/lib/arg.h @@ -53,8 +53,8 @@ struct grub_arg_option const char *longarg; int shortarg; int flags; - char *doc; - char *arg; + const char *doc; + const char *arg; grub_arg_type_t type; }; diff --git a/include/grub/net.h b/include/grub/net.h index 45d08f3f5..03af637b5 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -59,7 +59,7 @@ struct grub_net_card; struct grub_net_card_driver { struct grub_net_card_driver *next; - char *name; + const char *name; grub_err_t (*open) (const struct grub_net_card *dev); void (*close) (const struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, @@ -89,7 +89,7 @@ typedef struct grub_net_packets struct grub_net_card { struct grub_net_card *next; - char *name; + const char *name; struct grub_net_card_driver *driver; grub_net_link_level_address_t default_address; grub_net_card_flags_t flags; @@ -188,7 +188,7 @@ typedef struct grub_net_socket *grub_net_socket_t; struct grub_net_app_protocol { struct grub_net_app_protocol *next; - char *name; + const char *name; grub_err_t (*dir) (grub_device_t device, const char *path, int (*hook) (const char *filename, const struct grub_dirhook_info *info)); diff --git a/include/grub/parttool.h b/include/grub/parttool.h index 8291e1161..4e8f8d5e5 100644 --- a/include/grub/parttool.h +++ b/include/grub/parttool.h @@ -21,8 +21,8 @@ struct grub_parttool_argdesc { - char *name; - char *desc; + const char *name; + const char *desc; enum {GRUB_PARTTOOL_ARG_END, GRUB_PARTTOOL_ARG_BOOL, GRUB_PARTTOOL_ARG_VAL} type; }; diff --git a/include/grub/serial.h b/include/grub/serial.h index 49ac0623a..feaa5b1a7 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -143,7 +143,7 @@ grub_serial_config_defaults (struct grub_serial_port *port) void grub_ns8250_init (void); char *grub_serial_ns8250_add_port (grub_port_t port); -struct grub_serial_port *grub_serial_find (char *name); +struct grub_serial_port *grub_serial_find (const char *name); extern struct grub_serial_driver grub_ns8250_driver; void EXPORT_FUNC(grub_serial_unregister_driver) (struct grub_serial_driver *driver); diff --git a/include/grub/tparm.h b/include/grub/tparm.h index 642a22f90..0c6f9e0f0 100644 --- a/include/grub/tparm.h +++ b/include/grub/tparm.h @@ -21,6 +21,6 @@ #define GRUB_TPARM_HEADER 1 /* Function prototypes. */ -char *grub_terminfo_tparm (const char *string, ...); +const char *grub_terminfo_tparm (const char *string, ...); #endif /* ! GRUB_TPARM_HEADER */ diff --git a/include/grub/xnu.h b/include/grub/xnu.h index 076aeb5ed..2a096d803 100644 --- a/include/grub/xnu.h +++ b/include/grub/xnu.h @@ -81,7 +81,7 @@ struct grub_xnu_extheader } __attribute__ ((packed)); struct grub_xnu_devtree_key *grub_xnu_create_key (struct grub_xnu_devtree_key **parent, - char *name); + const char *name); extern struct grub_xnu_devtree_key *grub_xnu_devtree_root; @@ -89,18 +89,20 @@ void grub_xnu_free_devtree (struct grub_xnu_devtree_key *cur); grub_err_t grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size); struct grub_xnu_devtree_key *grub_xnu_create_value (struct grub_xnu_devtree_key **parent, - char *name); + const char *name); void grub_xnu_lock (void); void grub_xnu_unlock (void); grub_err_t grub_xnu_resume (char *imagename); grub_err_t grub_xnu_boot_resume (void); struct grub_xnu_devtree_key *grub_xnu_find_key (struct grub_xnu_devtree_key *parent, - char *name); + const char *name); grub_err_t grub_xnu_align_heap (int align); -grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, +grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, + const char *osbundlerequired, int maxrecursion); -grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, +grub_err_t grub_xnu_load_kext_from_dir (char *dirname, + const char *osbundlerequired, int maxrecursion); grub_err_t grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target); grub_err_t grub_xnu_fill_devicetree (void); diff --git a/include/grub/zfs/zio_checksum.h b/include/grub/zfs/zio_checksum.h index 0ef5a3ec7..e03c85a83 100644 --- a/include/grub/zfs/zio_checksum.h +++ b/include/grub/zfs/zio_checksum.h @@ -23,22 +23,6 @@ #ifndef _SYS_ZIO_CHECKSUM_H #define _SYS_ZIO_CHECKSUM_H -/* - * Signature for checksum functions. - */ -typedef void zio_checksum_t(const void *data, grub_uint64_t size, - grub_zfs_endian_t endian, zio_cksum_t *zcp); - -/* - * Information about each checksum function. - */ -typedef struct zio_checksum_info { - zio_checksum_t *ci_func; /* checksum function for each byteorder */ - int ci_correctable; /* number of correctable bits */ - int ci_eck; /* uses zio embedded checksum? */ - char *ci_name; /* descriptive name */ -} zio_checksum_info_t; - extern void zio_checksum_SHA256 (const void *, grub_uint64_t, grub_zfs_endian_t endian, zio_cksum_t *); extern void fletcher_2 (const void *, grub_uint64_t, grub_zfs_endian_t endian, From 48d6e4565339147c635a4ab47e76a82fb2f40283 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 12 Dec 2011 22:20:14 +0100 Subject: [PATCH 579/673] * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix compat condition. --- ChangeLog | 4 ++++ grub-core/disk/ahci.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0d0219d9e..492c45b72 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-12 Vladimir Serbinenko + + * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix compat condition. + 2011-11-30 Vladimir Serbinenko Add missing const qualifiers. diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 38c4d5e2d..00fc889a7 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -305,7 +305,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); - if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) + if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); else grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); From 1bc8f60db7e7da5ea77d4bf21b82a3731a5c462f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 12 Dec 2011 22:40:43 +0100 Subject: [PATCH 580/673] * include/grub/charset.h (GRUB_MAX_UTF8_PER_UTF16): New const. * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Change to UTF-16-BE. All users updated. (grub_hfsplus_cmp_catkey): Fix unicode handling. (grub_hfsplus_iterate_dir): Likewise. (grub_hfsplus_label): Likewise. --- ChangeLog | 9 ++++ grub-core/fs/hfsplus.c | 93 +++++++++++++++--------------------------- include/grub/charset.h | 2 + 3 files changed, 43 insertions(+), 61 deletions(-) diff --git a/ChangeLog b/ChangeLog index 492c45b72..485d37f30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-12-12 Vladimir Serbinenko + + * include/grub/charset.h (GRUB_MAX_UTF8_PER_UTF16): New const. + * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Change to + UTF-16-BE. All users updated. + (grub_hfsplus_cmp_catkey): Fix unicode handling. + (grub_hfsplus_iterate_dir): Likewise. + (grub_hfsplus_label): Likewise. + 2011-12-12 Vladimir Serbinenko * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix compat condition. diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 00b2366bf..9d5f20181 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -181,7 +181,8 @@ enum grub_hfsplus_filetype struct grub_hfsplus_catkey_internal { grub_uint32_t parent; - const char *name; + const grub_uint16_t *name; + grub_size_t namelen; }; /* Internal representation of an extent overflow key. */ @@ -519,8 +520,6 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya, { struct grub_hfsplus_catkey *catkey_a = &keya->catkey; struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey; - char *filename; - int i; int diff; /* Safe unsigned comparison */ @@ -530,26 +529,13 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya, if (aparent < catkey_b->parent) return -1; - /* Change the filename in keya so the endianness is correct. */ - for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++) - catkey_a->name[i] = grub_be_to_cpu16 (catkey_a->name[i]); + diff = grub_memcmp (catkey_a->name, catkey_b->name, + grub_min (grub_be_to_cpu16 (catkey_a->namelen), + catkey_b->namelen) + * sizeof (catkey_a->name[0])); + if (diff == 0) + diff = grub_be_to_cpu16 (catkey_a->namelen) - catkey_b->namelen; - filename = grub_malloc (grub_be_to_cpu16 (catkey_a->namelen) + 1); - - if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey_a->name, - grub_be_to_cpu16 (catkey_a->namelen))) - return -1; /* XXX: This error never occurs, but in case it happens - just skip this entry. */ - - diff = grub_strncmp (filename, catkey_b->name, - grub_be_to_cpu16 (catkey_a->namelen)); - - grub_free (filename); - - /* The endianness was changed to host format, change it back to - whatever it was. */ - for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++) - catkey_a->name[i] = grub_cpu_to_be16 (catkey_a->name[i]); return diff; } @@ -792,6 +778,11 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, if (type == GRUB_FSHELP_UNKNOWN) return 0; + filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + * GRUB_MAX_UTF8_PER_UTF16 + 1); + if (! filename) + return 0; + /* Make sure the byte order of the UTF16 string is correct. */ for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) { @@ -802,18 +793,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, return 0; } - filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + 1); - if (! filename) - return 0; - - if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name, - grub_be_to_cpu16 (catkey->namelen))) - { - grub_free (filename); - return 0; - } - - filename[grub_be_to_cpu16 (catkey->namelen)] = '\0'; + *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name, + grub_be_to_cpu16 (catkey->namelen)) = '\0'; /* Restore the byte order to what it was previously. */ for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) @@ -823,22 +804,18 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, if (! dir->data->case_sensitive) type |= GRUB_FSHELP_CASE_INSENSITIVE; - /* Only accept valid nodes. */ - if (grub_strlen (filename) == grub_be_to_cpu16 (catkey->namelen)) - { - /* A valid node is found; setup the node and call the - callback function. */ - node = grub_malloc (sizeof (*node)); - node->data = dir->data; + /* A valid node is found; setup the node and call the + callback function. */ + node = grub_malloc (sizeof (*node)); + node->data = dir->data; - grub_memcpy (node->extents, fileinfo->data.extents, - sizeof (node->extents)); - node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; - node->size = grub_be_to_cpu64 (fileinfo->data.size); - node->fileid = grub_be_to_cpu32 (fileinfo->fileid); + grub_memcpy (node->extents, fileinfo->data.extents, + sizeof (node->extents)); + node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; + node->size = grub_be_to_cpu64 (fileinfo->data.size); + node->fileid = grub_be_to_cpu32 (fileinfo->fileid); - ret = hook (filename, type, node); - } + ret = hook (filename, type, node); grub_free (filename); @@ -851,7 +828,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, /* Create a key that points to the first entry in the directory. */ intern.catkey.parent = dir->fileid; - intern.catkey.name = ""; + intern.catkey.name = 0; + intern.catkey.namelen = 0; /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern, @@ -999,7 +977,8 @@ grub_hfsplus_label (grub_device_t device, char **label) /* Create a key that points to the label. */ intern.catkey.parent = 1; - intern.catkey.name = ""; + intern.catkey.name = 0; + intern.catkey.namelen = 0; /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&data->catalog_tree, &intern, @@ -1022,20 +1001,12 @@ grub_hfsplus_label (grub_device_t device, char **label) return 0; } - *label = grub_malloc (label_len + 1); + *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! *label) return grub_errno; - if (! grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, - label_len)) - { - grub_free (node); - grub_free (*label); - grub_free (data); - *label = 0; - return grub_errno; - } - (*label)[label_len] = '\0'; + *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, + label_len) = '\0'; grub_free (node); grub_free (data); diff --git a/include/grub/charset.h b/include/grub/charset.h index c8247f78a..13443dad2 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -36,6 +36,8 @@ #define GRUB_UINT8_5_TRAILINGBITS 0x1f #define GRUB_UINT8_6_TRAILINGBITS 0x3f +#define GRUB_MAX_UTF8_PER_UTF16 4 + #define GRUB_UCS2_LIMIT 0x10000 #define GRUB_UTF16_UPPER_SURROGATE(code) \ (0xD800 + ((((code) - GRUB_UCS2_LIMIT) >> 12) & 0xfff)) From 74dbd24466ce74d6925a804d9a2c77227583ba7a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 00:28:14 +0100 Subject: [PATCH 581/673] * include/grub/loader.h (grub_loader_register_preboot_hook): Use struct preboot * and not void * for handle. All users updated. (grub_loader_unregister_preboot_hook): Likewise. --- ChangeLog | 6 ++++++ grub-core/bus/usb/ohci.c | 2 +- grub-core/commands/boot.c | 22 +++++++++++----------- grub-core/commands/i386/pc/sendkey.c | 2 +- grub-core/disk/ahci.c | 2 +- grub-core/mmap/i386/pc/mmap.c | 2 +- grub-core/net/net.c | 2 +- include/grub/loader.h | 10 ++++++---- 8 files changed, 28 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 485d37f30..ec65fb11e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/loader.h (grub_loader_register_preboot_hook): + Use struct preboot * and not void * for handle. All users updated. + (grub_loader_unregister_preboot_hook): Likewise. + 2011-12-12 Vladimir Serbinenko * include/grub/charset.h (GRUB_MAX_UTF8_PER_UTF16): New const. diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index b659c3f62..2291619cb 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -1426,7 +1426,7 @@ static struct grub_usb_controller_dev usb_controller = .detect_dev = grub_ohci_detect_dev }; -static void *fini_hnd; +static struct grub_preboot *fini_hnd; GRUB_MOD_INIT(ohci) { diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c index 7714011bf..5149074c7 100644 --- a/grub-core/commands/boot.c +++ b/grub-core/commands/boot.c @@ -31,17 +31,17 @@ static grub_err_t (*grub_loader_boot_func) (void); static grub_err_t (*grub_loader_unload_func) (void); static int grub_loader_noreturn; -struct grub_preboot_t +struct grub_preboot { grub_err_t (*preboot_func) (int); grub_err_t (*preboot_rest_func) (void); grub_loader_preboot_hook_prio_t prio; - struct grub_preboot_t *next; - struct grub_preboot_t *prev; + struct grub_preboot *next; + struct grub_preboot *prev; }; static int grub_loader_loaded; -static struct grub_preboot_t *preboots_head = 0, +static struct grub_preboot *preboots_head = 0, *preboots_tail = 0; int @@ -51,18 +51,18 @@ grub_loader_is_loaded (void) } /* Register a preboot hook. */ -void * +struct grub_preboot * grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn), grub_err_t (*preboot_rest_func) (void), grub_loader_preboot_hook_prio_t prio) { - struct grub_preboot_t *cur, *new_preboot; + struct grub_preboot *cur, *new_preboot; if (! preboot_func && ! preboot_rest_func) return 0; - new_preboot = (struct grub_preboot_t *) - grub_malloc (sizeof (struct grub_preboot_t)); + new_preboot = (struct grub_preboot *) + grub_malloc (sizeof (struct grub_preboot)); if (! new_preboot) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added"); @@ -96,9 +96,9 @@ grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn), } void -grub_loader_unregister_preboot_hook (void *hnd) +grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) { - struct grub_preboot_t *preb = hnd; + struct grub_preboot *preb = hnd; if (preb->next) preb->next->prev = preb->prev; @@ -143,7 +143,7 @@ grub_err_t grub_loader_boot (void) { grub_err_t err = GRUB_ERR_NONE; - struct grub_preboot_t *cur; + struct grub_preboot *cur; if (! grub_loader_loaded) return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel"); diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 80094c795..ab1090672 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -365,7 +365,7 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args) } static grub_extcmd_t cmd; -static void *preboot_hook; +static struct grub_preboot *preboot_hook; GRUB_MOD_INIT (sendkey) { diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 00fc889a7..10b7be687 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -706,7 +706,7 @@ static struct grub_ata_dev grub_ahci_dev = -static void *fini_hnd; +static struct grub_preboot *fini_hnd; GRUB_MOD_INIT(ahci) { diff --git a/grub-core/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c index 8dec083f8..baa41aa2d 100644 --- a/grub-core/mmap/i386/pc/mmap.c +++ b/grub-core/mmap/i386/pc/mmap.c @@ -191,7 +191,7 @@ grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), int handle __attribute__ ((unused))) { grub_err_t err; - static void *preb_handle = 0; + static struct grub_preboot *preb_handle = 0; err = malloc_hook (); if (err) diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 09acea900..d4e445e71 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -937,7 +937,7 @@ grub_net_restore_hw (void) return GRUB_ERR_NONE; } -static void *fini_hnd; +static struct grub_preboot *fini_hnd; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards; diff --git a/include/grub/loader.h b/include/grub/loader.h index f38deb96a..1d70ef049 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -56,11 +56,13 @@ typedef enum { } grub_loader_preboot_hook_prio_t; /* Register a preboot hook. */ -void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret), - grub_err_t (*preboot_rest_func) (void), - grub_loader_preboot_hook_prio_t prio); +struct grub_preboot; + +struct grub_preboot *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret), + grub_err_t (*preboot_rest_func) (void), + grub_loader_preboot_hook_prio_t prio); /* Unregister given preboot hook. */ -void EXPORT_FUNC (grub_loader_unregister_preboot_hook) (void *hnd); +void EXPORT_FUNC (grub_loader_unregister_preboot_hook) (struct grub_preboot *hnd); #endif /* ! GRUB_LOADER_HEADER */ From 0af2346fdb41b8663ccdfa887e1c699209ca792d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 00:29:42 +0100 Subject: [PATCH 582/673] * grub-core/bus/usb/ohci.c (grub_ohci_check_transfer): Add an unsigned specification. --- ChangeLog | 5 +++++ grub-core/bus/usb/ohci.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index ec65fb11e..43b5d59d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/bus/usb/ohci.c (grub_ohci_check_transfer): Add an unsigned + specification. + 2011-12-13 Vladimir Serbinenko * include/grub/loader.h (grub_loader_register_preboot_hook): diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 2291619cb..3f5ca7b03 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -1152,8 +1152,8 @@ grub_ohci_check_transfer (grub_usb_controller_t dev, return parse_halt (dev, transfer, actual); /* Finished ED detection */ - if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) == - (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */ + if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) == + (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */ { /* Check the HALT bit */ /* It looks like nonsense - it was tested previously... From c5fc563aff65bd7c9211841cbe5cd23b70084a6a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 00:50:49 +0100 Subject: [PATCH 583/673] Enable UTF8 in gnulib regexp. * config.h.in (RE_ENABLE_I18N) [!GRUB_UTIL]: New define. * grub-core/lib/posix_wrap/ctype.h (islower): Use grub_islower. (isupper): Use grub_isupper. (isascii): New inline function. * grub-core/lib/posix_wrap/wchar.h: Replace dummy with real contents. * grub-core/lib/posix_wrap/wctype.h: Likewise. * grub-core/normal/charset.c (grub_utf8_process): New function. (grub_utf8_to_utf16): Use grub_utf8_process. (grub_encode_utf8_character): New function. (grub_ucs4_to_utf8): Use grub_encode_utf8_character. * include/grub/charset.h (grub_utf8_process): New declaration. (grub_encode_utf8_character): Likewise. * include/grub/misc.h (grub_islower): New inline function. (grub_isupper): Likewise. (grub_strchrsub): Moved down to fix the definitions. --- ChangeLog | 20 +++ config.h.in | 2 + grub-core/lib/posix_wrap/ctype.h | 10 +- grub-core/lib/posix_wrap/wchar.h | 87 ++++++++++++- grub-core/lib/posix_wrap/wctype.h | 106 ++++++++++++++++ grub-core/normal/charset.c | 197 +++++++++++++++++------------- include/grub/charset.h | 11 ++ include/grub/misc.h | 53 ++++---- 8 files changed, 380 insertions(+), 106 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43b5d59d3..91eca49ae 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2011-12-13 Vladimir Serbinenko + + Enable UTF8 in gnulib regexp. + + * config.h.in (RE_ENABLE_I18N) [!GRUB_UTIL]: New define. + * grub-core/lib/posix_wrap/ctype.h (islower): Use grub_islower. + (isupper): Use grub_isupper. + (isascii): New inline function. + * grub-core/lib/posix_wrap/wchar.h: Replace dummy with real contents. + * grub-core/lib/posix_wrap/wctype.h: Likewise. + * grub-core/normal/charset.c (grub_utf8_process): New function. + (grub_utf8_to_utf16): Use grub_utf8_process. + (grub_encode_utf8_character): New function. + (grub_ucs4_to_utf8): Use grub_encode_utf8_character. + * include/grub/charset.h (grub_utf8_process): New declaration. + (grub_encode_utf8_character): Likewise. + * include/grub/misc.h (grub_islower): New inline function. + (grub_isupper): Likewise. + (grub_strchrsub): Moved down to fix the definitions. + 2011-12-13 Vladimir Serbinenko * grub-core/bus/usb/ohci.c (grub_ohci_check_transfer): Add an unsigned diff --git a/config.h.in b/config.h.in index 92d7a07f2..39b8fbafd 100644 --- a/config.h.in +++ b/config.h.in @@ -39,6 +39,8 @@ /* Define to 1 to enable disk cache statistics. */ #define DISK_CACHE_STATS @DISK_CACHE_STATS@ +#define RE_ENABLE_I18N 1 + #if defined(__i386__) #define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) #else diff --git a/grub-core/lib/posix_wrap/ctype.h b/grub-core/lib/posix_wrap/ctype.h index 9589778b6..38b572703 100644 --- a/grub-core/lib/posix_wrap/ctype.h +++ b/grub-core/lib/posix_wrap/ctype.h @@ -42,13 +42,19 @@ isdigit (int c) static inline int islower (int c) { - return (c >= 'a' && c <= 'z'); + return grub_islower (c); +} + +static inline int +isascii (int c) +{ + return !(c & ~0x7f); } static inline int isupper (int c) { - return (c >= 'A' && c <= 'Z'); + return grub_isupper (c); } static inline int diff --git a/grub-core/lib/posix_wrap/wchar.h b/grub-core/lib/posix_wrap/wchar.h index fd56fd332..a696643de 100644 --- a/grub-core/lib/posix_wrap/wchar.h +++ b/grub-core/lib/posix_wrap/wchar.h @@ -19,7 +19,92 @@ #ifndef GRUB_POSIX_WCHAR_H #define GRUB_POSIX_WCHAR_H 1 +#include + /* UCS-4. */ -typedef grub_uint32_t wchar_t; +typedef grub_int32_t wint_t; +enum + { + WEOF = -1 + }; + +#define MB_LEN_MAX 4 + +/* UCS-4. */ +typedef grub_int32_t wchar_t; + +typedef struct mbstate { + grub_uint32_t code; + int count; +} mbstate_t; + +static inline size_t +mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ + const char *ptr; + if (!s) + { + pwc = 0; + s = ""; + n = 1; + } + + for (ptr = s; ptr < s + n; ptr++) + { + if (!grub_utf8_process (*ptr, &ps->code, &ps->count)) + return -1; + if (ps->count) + continue; + if (pwc) + *pwc = ps->code; + if (ps->code == 0) + return 0; + return ptr - s + 1; + } + return -2; +} + +static inline int +mbsinit(const mbstate_t *ps) +{ + return ps->count == 0; +} + +static inline size_t +wcrtomb (char *s, wchar_t wc, mbstate_t *ps __attribute__ ((unused))) +{ + if (s == 0) + return 1; + return grub_encode_utf8_character ((grub_uint8_t *) s, + (grub_uint8_t *) s + MB_LEN_MAX, + wc); +} + +static inline wint_t btowc (int c) +{ + if (c & ~0x7f) + return WEOF; + return c; +} + + +static inline int +wcscoll (const wchar_t *s1, const wchar_t *s2) +{ + while (*s1 && *s2) + { + if (*s1 != *s2) + break; + + s1++; + s2++; + } + + if (*s1 < *s2) + return -1; + if (*s1 > *s2) + return +1; + return 0; +} #endif diff --git a/grub-core/lib/posix_wrap/wctype.h b/grub-core/lib/posix_wrap/wctype.h index e69de29bb..b2b33ab08 100644 --- a/grub-core/lib/posix_wrap/wctype.h +++ b/grub-core/lib/posix_wrap/wctype.h @@ -0,0 +1,106 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010, 2011 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 . + */ + +#ifndef GRUB_POSIX_WCTYPE_H +#define GRUB_POSIX_WCTYPE_H 1 + +#include +#include + +typedef enum { GRUB_CTYPE_INVALID, + GRUB_CTYPE_ALNUM, GRUB_CTYPE_CNTRL, GRUB_CTYPE_LOWER, + GRUB_CTYPE_SPACE, GRUB_CTYPE_ALPHA, GRUB_CTYPE_DIGIT, + GRUB_CTYPE_PRINT, GRUB_CTYPE_UPPER, GRUB_CTYPE_BLANK, + GRUB_CTYPE_GRAPH, GRUB_CTYPE_PUNCT, GRUB_CTYPE_XDIGIT, + GRUB_CTYPE_MAX} wctype_t; + +static inline wctype_t +wctype (const char *name) +{ + wctype_t i; + static const char names[][10] = { "", + "alnum", "cntrl", "lower", + "space", "alpha", "digit", + "print", "upper", "blank", + "graph", "punct", "xdigit" }; + for (i = GRUB_CTYPE_INVALID; i < GRUB_CTYPE_MAX; i++) + if (grub_strcmp (names[i], name) == 0) + return i; + return GRUB_CTYPE_INVALID; +} + +/* FIXME: take into account international lowercase characters. */ +static inline int +iswlower (wint_t wc) +{ + return grub_islower (wc); +} + +static inline wint_t +towlower (wint_t c) +{ + return grub_tolower (c); +} + +static inline wint_t +towupper (wint_t c) +{ + return grub_toupper (c); +} + +static inline int +iswalnum (wint_t c) +{ + return grub_isalpha (c) || grub_isdigit (c); +} + +static inline int +iswctype (wint_t wc, wctype_t desc) +{ + switch (desc) + { + case GRUB_CTYPE_ALNUM: + return iswalnum (wc); + case GRUB_CTYPE_CNTRL: + return grub_iscntrl (wc); + case GRUB_CTYPE_LOWER: + return iswlower (wc); + case GRUB_CTYPE_SPACE: + return grub_isspace (wc); + case GRUB_CTYPE_ALPHA: + return grub_isalpha (wc); + case GRUB_CTYPE_DIGIT: + return grub_isdigit (wc); + case GRUB_CTYPE_PRINT: + return grub_isprint (wc); + case GRUB_CTYPE_UPPER: + return grub_isupper (wc); + case GRUB_CTYPE_BLANK: + return wc == ' ' || wc == '\t'; + case GRUB_CTYPE_GRAPH: + return grub_isgraph (wc); + case GRUB_CTYPE_PUNCT: + return grub_isprint (wc) && !grub_isspace (wc) && !iswalnum (wc); + case GRUB_CTYPE_XDIGIT: + return grub_isxdigit (wc); + default: + return 0; + } +} + +#endif diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c index 85ead53c4..d089843cc 100644 --- a/grub-core/normal/charset.c +++ b/grub-core/normal/charset.c @@ -60,6 +60,51 @@ #include "widthspec.h" #endif +int +grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count) +{ + if (*count) + { + if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT) + { + /* invalid */ + return 0; + } + else + { + *code <<= 6; + *code |= (c & GRUB_UINT8_6_TRAILINGBITS); + (*count)--; + return 1; + } + } + + if ((c & GRUB_UINT8_1_LEADINGBIT) == 0) + { + *code = c; + return 1; + } + if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS) + { + *count = 1; + *code = c & GRUB_UINT8_5_TRAILINGBITS; + return 1; + } + if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS) + { + *count = 2; + *code = c & GRUB_UINT8_4_TRAILINGBITS; + return 1; + } + if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS) + { + *count = 3; + *code = c & GRUB_UINT8_3_TRAILINGBITS; + return 1; + } + return 0; +} + grub_ssize_t grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, @@ -74,64 +119,27 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, while (srcsize && destsize) { - grub_uint32_t c = *src++; + grub_uint8_t c = *src++; if (srcsize != (grub_size_t)-1) srcsize--; - if (count) + if (!grub_utf8_process (c, &code, &count)) + return -1; + if (count != 0) + continue; + if (code == 0) + break; + if (destsize < 2 && code >= GRUB_UCS2_LIMIT) + break; + if (code >= GRUB_UCS2_LIMIT) { - if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT) - { - /* invalid */ - return -1; - } - else - { - code <<= 6; - code |= (c & GRUB_UINT8_6_TRAILINGBITS); - count--; - } + *p++ = GRUB_UTF16_UPPER_SURROGATE (code); + *p++ = GRUB_UTF16_LOWER_SURROGATE (code); + destsize -= 2; } else { - if (c == 0) - break; - - if ((c & GRUB_UINT8_1_LEADINGBIT) == 0) - code = c; - else if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS) - { - count = 1; - code = c & GRUB_UINT8_5_TRAILINGBITS; - } - else if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS) - { - count = 2; - code = c & GRUB_UINT8_4_TRAILINGBITS; - } - else if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS) - { - count = 3; - code = c & GRUB_UINT8_3_TRAILINGBITS; - } - else - return -1; - } - - if (count == 0) - { - if (destsize < 2 && code >= GRUB_UCS2_LIMIT) - break; - if (code >= GRUB_UCS2_LIMIT) - { - *p++ = GRUB_UTF16_UPPER_SURROGATE (code); - *p++ = GRUB_UTF16_LOWER_SURROGATE (code); - destsize -= 2; - } - else - { - *p++ = code; - destsize--; - } + *p++ = code; + destsize--; } } @@ -140,6 +148,53 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, return p - dest; } +/* Returns -2 if not enough space, -1 on invalid character. */ +grub_ssize_t +grub_encode_utf8_character (grub_uint8_t *dest, grub_uint8_t *destend, + grub_uint32_t code) +{ + if (dest >= destend) + return -2; + if (code <= 0x007F) + { + *dest++ = code; + return 1; + } + if (code <= 0x07FF) + { + if (dest + 1 >= destend) + return -2; + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + return 2; + } + if ((code >= 0xDC00 && code <= 0xDFFF) + || (code >= 0xD800 && code <= 0xDBFF)) + { + /* No surrogates in UCS-4... */ + return -1; + } + if (code < 0x10000) + { + if (dest + 2 >= destend) + return -2; + *dest++ = (code >> 12) | 0xE0; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + return 3; + } + { + if (dest + 3 >= destend) + return -2; + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + return 4; + } + +} + /* Convert UCS-4 to UTF-8. */ void grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, @@ -151,39 +206,17 @@ grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, while (size-- && dest < destend) { grub_uint32_t code = *src++; - - if (code <= 0x007F) - *dest++ = code; - else if (code <= 0x07FF) + grub_ssize_t s; + s = grub_encode_utf8_character (dest, destend, + code); + if (s == -2) + break; + if (s == -1) { - if (dest + 1 >= destend) - break; - *dest++ = (code >> 6) | 0xC0; - *dest++ = (code & 0x3F) | 0x80; - } - else if ((code >= 0xDC00 && code <= 0xDFFF) - || (code >= 0xD800 && code <= 0xDBFF)) - { - /* No surrogates in UCS-4... */ *dest++ = '?'; + continue; } - else if (code < 0x10000) - { - if (dest + 2 >= destend) - break; - *dest++ = (code >> 12) | 0xE0; - *dest++ = ((code >> 6) & 0x3F) | 0x80; - *dest++ = (code & 0x3F) | 0x80; - } - else - { - if (dest + 3 >= destend) - break; - *dest++ = (code >> 18) | 0xF0; - *dest++ = ((code >> 12) & 0x3F) | 0x80; - *dest++ = ((code >> 6) & 0x3F) | 0x80; - *dest++ = (code & 0x3F) | 0x80; - } + dest += s; } *dest = 0; } diff --git a/include/grub/charset.h b/include/grub/charset.h index 13443dad2..c7f86a1ef 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -126,11 +126,22 @@ grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize); int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, grub_uint32_t **last_position); + +/* Process one character from UTF8 sequence. + At beginning set *code = 0, *count = 0. Returns 0 on failure and + 1 on success. *count holds the number of trailing bytes. */ +int +grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count); + void grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, grub_uint8_t *dest, grub_size_t destsize); grub_size_t grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t **srcend); +/* Returns -2 if not enough space, -1 on invalid character. */ +grub_ssize_t +grub_encode_utf8_character (grub_uint8_t *dest, grub_uint8_t *destend, + grub_uint32_t code); #endif diff --git a/include/grub/misc.h b/include/grub/misc.h index 358f73258..0344d528b 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -175,6 +175,18 @@ grub_isalpha (int c) return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +static inline int +grub_islower (int c) +{ + return (c >= 'a' && c <= 'z'); +} + +static inline int +grub_isupper (int c) +{ + return (c >= 'A' && c <= 'Z'); +} + static inline int grub_isgraph (int c) { @@ -250,27 +262,6 @@ grub_strncasecmp (const char *s1, const char *s2, grub_size_t n) return (int) grub_tolower (*s1) - (int) grub_tolower (*s2); } -/* Replace all `ch' characters of `input' with `with' and copy the - result into `output'; return EOS address of `output'. */ -static inline char * -grub_strchrsub (char *output, const char *input, char ch, const char *with) -{ - grub_size_t grub_strlen (const char *s); - while (*input) - { - if (*input == ch) - { - grub_strcpy (output, with); - output += grub_strlen (with); - input++; - continue; - } - *output++ = *input++; - } - *output = '\0'; - return output; -} - unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base); unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base); @@ -317,6 +308,26 @@ grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) __attribute__ ((warn_unused int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +/* Replace all `ch' characters of `input' with `with' and copy the + result into `output'; return EOS address of `output'. */ +static inline char * +grub_strchrsub (char *output, const char *input, char ch, const char *with) +{ + while (*input) + { + if (*input == ch) + { + grub_strcpy (output, with); + output += grub_strlen (with); + input++; + continue; + } + *output++ = *input++; + } + *output = '\0'; + return output; +} + extern void (*EXPORT_VAR (grub_xputs)) (const char *str); static inline int From cc8f366887c838bce6c74aee45914623076cca4a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 00:55:00 +0100 Subject: [PATCH 584/673] * grub-core/commands/acpi.c (grub_acpi_create_ebda) [!x86]: Disable. (grub_cmd_acpi) [!x86]: Disable EBDA. --- ChangeLog | 5 +++++ grub-core/commands/acpi.c | 20 ++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91eca49ae..e6a2125dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/commands/acpi.c (grub_acpi_create_ebda) [!x86]: Disable. + (grub_cmd_acpi) [!x86]: Disable EBDA. + 2011-12-13 Vladimir Serbinenko Enable UTF8 in gnulib regexp. diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 8f4429627..f394e3233 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -138,6 +138,7 @@ iszero (grub_uint8_t *reg, int size) return 1; } +#if defined (__i386__) || defined (__x86_64__) grub_err_t grub_acpi_create_ebda (void) { @@ -297,6 +298,7 @@ grub_acpi_create_ebda (void) return GRUB_ERR_NONE; } +#endif /* Create tables common to ACPIv1 and ACPIv2+ */ static void @@ -463,7 +465,6 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) struct grub_arg_list *state = ctxt->state; struct grub_acpi_rsdp_v10 *rsdp; struct efiemu_acpi_table *cur, *t; - grub_err_t err; int i, mmapregion; int numoftables; @@ -732,13 +733,20 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) } acpi_tables = 0; - if (! state[9].set && (err = grub_acpi_create_ebda ())) +#if defined (__i386__) || defined (__x86_64__) + if (! state[9].set) { - rsdpv1_new = 0; - rsdpv2_new = 0; - grub_mmap_free_and_unregister (mmapregion); - return err; + grub_err_t err; + err = grub_acpi_create_ebda (); + if (err) + { + rsdpv1_new = 0; + rsdpv2_new = 0; + grub_mmap_free_and_unregister (mmapregion); + return err; + } } +#endif #ifdef GRUB_MACHINE_EFI { From ee533335f54c938184b782a52ca8a29209491772 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:00:34 +0100 Subject: [PATCH 585/673] * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_finddevice): Make first argument a const pointer. * grub-core/kern/ieee1275/openfw.c (grub_children_iterate): Likewise. * include/grub/ieee1275/ieee1275.h (grub_ieee1275_finddevice): Update proto. (grub_children_iterate): Likewise. (grub_machine_mmap_iterate): Remove redundant declaration. --- ChangeLog | 10 ++++++++++ grub-core/kern/ieee1275/ieee1275.c | 2 +- grub-core/kern/ieee1275/openfw.c | 2 +- include/grub/ieee1275/ieee1275.h | 6 ++---- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e6a2125dd..0d92fb424 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_finddevice): Make + first argument a const pointer. + * grub-core/kern/ieee1275/openfw.c (grub_children_iterate): Likewise. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_finddevice): Update + proto. + (grub_children_iterate): Likewise. + (grub_machine_mmap_iterate): Remove redundant declaration. + 2011-12-13 Vladimir Serbinenko * grub-core/commands/acpi.c (grub_acpi_create_ebda) [!x86]: Disable. diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c index b32fd2d8b..b20f64d68 100644 --- a/grub-core/kern/ieee1275/ieee1275.c +++ b/grub-core/kern/ieee1275/ieee1275.c @@ -27,7 +27,7 @@ int -grub_ieee1275_finddevice (char *name, grub_ieee1275_phandle_t *phandlep) +grub_ieee1275_finddevice (const char *name, grub_ieee1275_phandle_t *phandlep) { struct find_device_args { diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 3568ffe64..ee81b4ef9 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -34,7 +34,7 @@ enum grub_ieee1275_parse_type /* Walk children of 'devpath', calling hook for each. */ int -grub_children_iterate (char *devpath, +grub_children_iterate (const char *devpath, int (*hook) (struct grub_ieee1275_devalias *alias)) { grub_ieee1275_phandle_t dev; diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index be3835a42..b84d75697 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -125,7 +125,7 @@ extern void EXPORT_FUNC(grub_ieee1275_set_flag) (enum grub_ieee1275_flag flag); void EXPORT_FUNC(grub_ieee1275_init) (void); -int EXPORT_FUNC(grub_ieee1275_finddevice) (char *name, +int EXPORT_FUNC(grub_ieee1275_finddevice) (const char *name, grub_ieee1275_phandle_t *phandlep); int EXPORT_FUNC(grub_ieee1275_get_property) (grub_ieee1275_phandle_t phandle, const char *property, void *buf, @@ -184,10 +184,8 @@ int EXPORT_FUNC(grub_ieee1275_milliseconds) (grub_uint32_t *msecs); int EXPORT_FUNC(grub_devalias_iterate) (int (*hook) (struct grub_ieee1275_devalias *alias)); -int EXPORT_FUNC(grub_children_iterate) (char *devpath, +int EXPORT_FUNC(grub_children_iterate) (const char *devpath, int (*hook) (struct grub_ieee1275_devalias *alias)); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size); int From 5d048bf210da3c5bc4666f90341461e4703f7dcb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:07:06 +0100 Subject: [PATCH 586/673] * grub-core/net/drivers/ieee1275/ofnet.c (bootp_response_properties): Make name a const ptr. --- ChangeLog | 5 +++++ grub-core/net/drivers/ieee1275/ofnet.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0d92fb424..7198d951f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/net/drivers/ieee1275/ofnet.c (bootp_response_properties): + Make name a const ptr. + 2011-12-13 Vladimir Serbinenko * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_finddevice): Make diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 20d45ee3d..7a1edcc1b 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -106,7 +106,7 @@ static struct grub_net_card_driver ofdriver = static const struct { - char *name; + const char *name; int offset; } From ef6e433586fca0d21ffaa776f84cfd5b463f630e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:19:47 +0100 Subject: [PATCH 587/673] * grub-core/disk/raid.c (scan_devices): Fix condition. --- ChangeLog | 4 ++++ grub-core/disk/raid.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7198d951f..b157a8e40 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/disk/raid.c (scan_devices): Fix condition. + 2011-12-13 Vladimir Serbinenko * grub-core/net/drivers/ieee1275/ofnet.c (bootp_response_properties): diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index e4c53e73b..aeba2a22f 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -120,7 +120,7 @@ scan_devices (const char *arname) struct grub_raid_member *m; for (m = arr->members; m < arr->members + arr->nr_devs; m++) if (m->device && m->device->id == disk->id - && m->device->dev->id == m->device->dev->id + && m->device->dev->id == disk->dev->id && grub_partition_get_start (m->device->partition) == grub_partition_get_start (disk->partition) && grub_disk_get_size (m->device) From 496bd07446c4e8a09146004a16971ad37fc973c1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:26:53 +0100 Subject: [PATCH 588/673] Unify and improve RAID and crypto xor. * grub-core/disk/raid.c (grub_raid_block_xor): Removed. All users changed to grub_crypto_xor * grub-core/lib/crypto.c (grub_crypto_xor): Moved from here ... * include/grub/crypto.h (grub_crypto_xor): ... here. Inlined. Use bigger types when possible. --- ChangeLog | 10 ++++++++++ grub-core/disk/raid.c | 17 ---------------- grub-core/disk/raid5_recover.c | 3 ++- grub-core/disk/raid6_recover.c | 15 +++++++------- grub-core/lib/crypto.c | 14 ------------- include/grub/crypto.h | 36 ++++++++++++++++++++++++++++++++-- 6 files changed, 54 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index b157a8e40..801681ef5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-12-13 Vladimir Serbinenko + + Unify and improve RAID and crypto xor. + + * grub-core/disk/raid.c (grub_raid_block_xor): Removed. All users + changed to grub_crypto_xor + * grub-core/lib/crypto.c (grub_crypto_xor): Moved from here ... + * include/grub/crypto.h (grub_crypto_xor): ... here. Inlined. + Use bigger types when possible. + 2011-12-13 Vladimir Serbinenko * grub-core/disk/raid.c (scan_devices): Fix condition. diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index aeba2a22f..db1e969b3 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -332,23 +332,6 @@ grub_raid_close (grub_disk_t disk __attribute ((unused))) return; } -void -grub_raid_block_xor (char *buf1, const char *buf2, int size) -{ - grub_size_t *p1; - const grub_size_t *p2; - - p1 = (grub_size_t *) buf1; - p2 = (const grub_size_t *) buf2; - size /= GRUB_CPU_SIZEOF_VOID_P; - - while (size) - { - *(p1++) ^= *(p2++); - size--; - } -} - static grub_err_t grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) diff --git a/grub-core/disk/raid5_recover.c b/grub-core/disk/raid5_recover.c index c26d05e94..dfc89a71d 100644 --- a/grub-core/disk/raid5_recover.c +++ b/grub-core/disk/raid5_recover.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -57,7 +58,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr, return err; } - grub_raid_block_xor (buf, buf2, size); + grub_crypto_xor (buf, buf2, buf2, size); } grub_free (buf2); diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index e91992547..05d8511c5 100644 --- a/grub-core/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -98,9 +99,9 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, array->members[pos].start_sector + sector, 0, size, buf))) { - grub_raid_block_xor (pbuf, buf, size); + grub_crypto_xor (pbuf, pbuf, buf, size); grub_raid_block_mulx (i, buf, size); - grub_raid_block_xor (qbuf, buf, size); + grub_crypto_xor (qbuf, qbuf, buf, size); } else { @@ -130,7 +131,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, array->members[p].start_sector + sector, 0, size, buf))) { - grub_raid_block_xor (buf, pbuf, size); + grub_crypto_xor (buf, buf, pbuf, size); goto quit; } @@ -145,7 +146,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, array->members[q].start_sector + sector, 0, size, buf)) goto quit; - grub_raid_block_xor (buf, qbuf, size); + grub_crypto_xor (buf, buf, qbuf, size); grub_raid_block_mulx (255 - bad1, buf, size); } @@ -165,14 +166,14 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, 0, size, buf)) goto quit; - grub_raid_block_xor (pbuf, buf, size); + grub_crypto_xor (pbuf, pbuf, buf, size); if (grub_disk_read (array->members[q].device, array->members[q].start_sector + sector, 0, size, buf)) goto quit; - grub_raid_block_xor (qbuf, buf, size); + grub_crypto_xor (qbuf, qbuf, buf, size); c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255; grub_raid_block_mulx (c, qbuf, size); @@ -180,7 +181,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, c = (bad2 + c) % 255; grub_raid_block_mulx (c, pbuf, size); - grub_raid_block_xor (pbuf, qbuf, size); + grub_crypto_xor (pbuf, pbuf, qbuf, size); grub_memcpy (buf, pbuf, size); } diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index 4dec5c694..48d860335 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -169,20 +169,6 @@ grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher, return cipher->cipher->setkey (cipher->ctx, key, keylen); } -void -grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size) -{ - const grub_uint8_t *in1ptr = in1, *in2ptr = in2; - grub_uint8_t *outptr = out; - while (size--) - { - *outptr = *in1ptr ^ *in2ptr; - in1ptr++; - in2ptr++; - outptr++; - } -} - gcry_err_code_t grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, void *out, const void *in, grub_size_t size) diff --git a/include/grub/crypto.h b/include/grub/crypto.h index b8a5b3a22..9a67c5e11 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -198,8 +198,40 @@ grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher) grub_free (cipher); } -void -grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size); +static inline void +grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size) +{ + const grub_uint8_t *in1ptr = in1, *in2ptr = in2; + grub_uint8_t *outptr = out; + while (size && (((grub_addr_t) in1ptr & (sizeof (grub_uint64_t) - 1)) + || ((grub_addr_t) in2ptr & (sizeof (grub_uint64_t) - 1)) + || ((grub_addr_t) outptr & (sizeof (grub_uint64_t) - 1)))) + { + *outptr = *in1ptr ^ *in2ptr; + in1ptr++; + in2ptr++; + outptr++; + size--; + } + while (size >= sizeof (grub_uint64_t)) + { + *(grub_uint64_t *) (void *) outptr + = (*(grub_uint64_t *) (void *) in1ptr + ^ *(grub_uint64_t *) (void *) in2ptr); + in1ptr += sizeof (grub_uint64_t); + in2ptr += sizeof (grub_uint64_t); + outptr += sizeof (grub_uint64_t); + size -= sizeof (grub_uint64_t); + } + while (size) + { + *outptr = *in1ptr ^ *in2ptr; + in1ptr++; + in2ptr++; + outptr++; + size--; + } +} gcry_err_code_t grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, From 055dc23978de3a439d6f3481a547d27b31e4b790 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:32:41 +0100 Subject: [PATCH 589/673] * grub-core/kern/emu/main.c (main): Add missing const qualifier. * grub-core/loader/efi/appleloader.c (devdata): Likewise. --- ChangeLog | 5 +++++ grub-core/kern/emu/main.c | 2 +- grub-core/loader/efi/appleloader.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 801681ef5..f14ce3de2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/emu/main.c (main): Add missing const qualifier. + * grub-core/loader/efi/appleloader.c (devdata): Likewise. + 2011-12-13 Vladimir Serbinenko Unify and improve RAID and crypto xor. diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 725d1ac7f..64e72dff6 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -127,7 +127,7 @@ void grub_emu_init (void); int main (int argc, char *argv[]) { - char *dev_map = DEFAULT_DEVICE_MAP; + const char *dev_map = DEFAULT_DEVICE_MAP; volatile int hold = 0; int opt; diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c index db57a573c..d0211a80f 100644 --- a/grub-core/loader/efi/appleloader.c +++ b/grub-core/loader/efi/appleloader.c @@ -126,7 +126,7 @@ static struct piwg_full_device_path devpath_6 = MAKE_PIWG_PATH (0xffcc4000, struct devdata { - char *model; + const char *model; grub_efi_device_path_t *devpath; }; From 53072f9b96ae2333382f64df95198d7bb1e5227d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:36:09 +0100 Subject: [PATCH 590/673] * grub-core/term/at_keyboard.c (set_scancodes): Fix preprocessor conditionals. --- ChangeLog | 5 +++++ grub-core/term/at_keyboard.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f14ce3de2..088f6f848 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c (set_scancodes): Fix preprocessor + conditionals. + 2011-12-13 Vladimir Serbinenko * grub-core/kern/emu/main.c (main): Add missing const qualifier. diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index b81e76230..bcd20d3ff 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -332,10 +332,10 @@ set_scancodes (void) return; } -#if !(defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU)) +#if !(defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)) current_set = 1; return; -#endif +#else grub_keyboard_controller_write (grub_keyboard_controller_orig & ~KEYBOARD_AT_TRANSLATE); @@ -352,6 +352,7 @@ set_scancodes (void) if (current_set == 1) return; grub_printf ("No supported scancode set found\n"); +#endif } static void From 78c2cd1c627e58ac102dc03dbf811f03c8d1c9d0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:41:16 +0100 Subject: [PATCH 591/673] * grub-core/fs/udf.c (read_string): Macroify GRUB_MAX_UTF8_PER_UTF16. * grub-core/fs/jfs.c (grub_jfs_diropen): Likewise. * grub-core/fs/fat.c (grub_fat_iterate_dir): Likewise. --- ChangeLog | 6 ++++++ grub-core/fs/fat.c | 4 ++-- grub-core/fs/jfs.c | 2 +- grub-core/fs/udf.c | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 088f6f848..0780a3691 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/udf.c (read_string): Macroify GRUB_MAX_UTF8_PER_UTF16. + * grub-core/fs/jfs.c (grub_jfs_diropen): Likewise. + * grub-core/fs/fat.c (grub_fat_iterate_dir): Likewise. + 2011-12-13 Vladimir Serbinenko * grub-core/term/at_keyboard.c (set_scancodes): Fix preprocessor diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 0d32e229d..0569120fb 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -589,7 +589,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, char *filename; unibuf = grub_malloc (15 * 256 * 2); - filename = grub_malloc (15 * 256 * 4 + 1); + filename = grub_malloc (15 * 256 * GRUB_MAX_UTF8_PER_UTF16 + 1); while (1) { @@ -696,7 +696,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); /* Allocate space enough to hold a long name. */ - filename = grub_malloc (0x40 * 13 * 4 + 1); + filename = grub_malloc (0x40 * 13 * GRUB_MAX_UTF8_PER_UTF16 + 1); unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2); if (! filename || ! unibuf) { diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 91497f143..3554803cb 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -241,7 +241,7 @@ struct grub_jfs_diropen /* On-disk name is at most 255 UTF-16 codepoints. Every UTF-16 codepoint is at most 4 UTF-8 bytes. */ - char name[256 * 4 + 1]; + char name[256 * GRUB_MAX_UTF8_PER_UTF16 + 1]; grub_uint32_t ino; } __attribute__ ((packed)); diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index e1f115015..4097fd2e6 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -820,7 +820,7 @@ read_string (grub_uint8_t *raw, grub_size_t sz) for (i = 0; i < utf16len; i++) utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; } - ret = grub_malloc (utf16len * 3 + 1); + ret = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (ret) *grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0'; grub_free (utf16); From 47ae27ec75ff54acd8a04cdda20069092e9e0f74 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:45:38 +0100 Subject: [PATCH 592/673] * grub-core/normal/datetime.c (grub_weekday_names): Make const. --- ChangeLog | 4 ++++ grub-core/normal/datetime.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0780a3691..fd7add031 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/normal/datetime.c (grub_weekday_names): Make const. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/udf.c (read_string): Macroify GRUB_MAX_UTF8_PER_UTF16. diff --git a/grub-core/normal/datetime.c b/grub-core/normal/datetime.c index 8183601ba..bbc2cdea9 100644 --- a/grub-core/normal/datetime.c +++ b/grub-core/normal/datetime.c @@ -20,7 +20,7 @@ #include #include -static const char *grub_weekday_names[] = +static const char *const grub_weekday_names[] = { N_("Sunday"), N_("Monday"), From 1f313b942bb509d4a17a2f78b6d077ccbe7eb93f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:54:59 +0100 Subject: [PATCH 593/673] * include/grub/types.h (grub_properly_aligned_t): New type. (GRUB_PROPERLY_ALIGNED_ARRAY): New macro. (grub_get_unaligned16): Add explicit casts. (grub_get_unaligned32): Likewise. (grub_get_unaligned64): Likewise. (grub_set_unaligned16): New function. (grub_set_unaligned32): Likewise. --- ChangeLog | 10 +++++++ include/grub/types.h | 66 ++++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index fd7add031..c64fe07b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/types.h (grub_properly_aligned_t): New type. + (GRUB_PROPERLY_ALIGNED_ARRAY): New macro. + (grub_get_unaligned16): Add explicit casts. + (grub_get_unaligned32): Likewise. + (grub_get_unaligned64): Likewise. + (grub_set_unaligned16): New function. + (grub_set_unaligned32): Likewise. + 2011-12-13 Vladimir Serbinenko * grub-core/normal/datetime.c (grub_weekday_names): Make const. diff --git a/include/grub/types.h b/include/grub/types.h index f057dd3d3..e61a9a5c6 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -140,6 +140,10 @@ typedef grub_int32_t grub_ssize_t; #define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x)) #endif +typedef grub_uint64_t grub_properly_aligned_t; + +#define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[(size + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] + /* The type for representing a file offset. */ typedef grub_uint64_t grub_off_t; @@ -222,31 +226,57 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x)) #endif /* ! WORDS_BIGENDIAN */ -static inline grub_uint16_t grub_get_unaligned16(void *ptr) +static inline grub_uint16_t grub_get_unaligned16 (const void *ptr) { - struct - { - grub_uint16_t d; - } __attribute__((packed)) *dd = ptr; - return dd->d; + struct grub_unaligned_uint16_t + { + grub_uint16_t d; + } __attribute__ ((packed)); + const struct grub_unaligned_uint16_t *dd + = (const struct grub_unaligned_uint16_t *) ptr; + return dd->d; } -static inline grub_uint32_t grub_get_unaligned32(void *ptr) +static inline void grub_set_unaligned16 (void *ptr, grub_uint16_t val) { - struct - { - grub_uint32_t d; - } __attribute__((packed)) *dd = ptr; - return dd->d; + struct grub_unaligned_uint16_t + { + grub_uint16_t d; + } __attribute__ ((packed)); + struct grub_unaligned_uint16_t *dd = (struct grub_unaligned_uint16_t *) ptr; + dd->d = val; } -static inline grub_uint64_t grub_get_unaligned64(void *ptr) +static inline grub_uint32_t grub_get_unaligned32 (const void *ptr) { - struct - { - grub_uint64_t d; - } __attribute__((packed)) *dd = ptr; - return dd->d; + struct grub_unaligned_uint32_t + { + grub_uint32_t d; + } __attribute__ ((packed)); + const struct grub_unaligned_uint32_t *dd + = (const struct grub_unaligned_uint32_t *) ptr; + return dd->d; +} + +static inline void grub_set_unaligned32 (void *ptr, grub_uint32_t val) +{ + struct grub_unaligned_uint32_t + { + grub_uint32_t d; + } __attribute__ ((packed)); + struct grub_unaligned_uint32_t *dd = (struct grub_unaligned_uint32_t *) ptr; + dd->d = val; +} + +static inline grub_uint64_t grub_get_unaligned64 (const void *ptr) +{ + struct grub_unaligned_uint64_t + { + grub_uint64_t d; + } __attribute__ ((packed)); + const struct grub_unaligned_uint64_t *dd + = (const struct grub_unaligned_uint64_t *)ptr; + return dd->d; } #endif /* ! GRUB_TYPES_HEADER */ From 20993fbb9f820ecd0d9245c64574b5333d330779 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:57:07 +0100 Subject: [PATCH 594/673] * grub-core/fs/romfs.c (grub_romfs_iterate_dir): Properly align name for checksum and fix allocation algorithm. --- ChangeLog | 5 +++++ grub-core/fs/romfs.c | 18 ++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index c64fe07b7..086b61ff9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/romfs.c (grub_romfs_iterate_dir): Properly align + name for checksum and fix allocation algorithm. + 2011-12-13 Vladimir Serbinenko * include/grub/types.h (grub_properly_aligned_t): New type. diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 202ca102e..76e13727d 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -166,17 +166,18 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, { grub_disk_addr_t caddr; struct grub_romfs_file_header hdr; - grub_size_t a = 0; - char *name = NULL; unsigned nptr; unsigned i, j; + grub_size_t a = 0; + grub_properly_aligned_t *name = NULL; + for (caddr = dir->data_addr; caddr; caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1)) { grub_disk_addr_t naddr = caddr + sizeof (hdr); grub_uint32_t csum = 0; enum grub_fshelp_filetype filetype = GRUB_FSHELP_UNKNOWN; - struct grub_fshelp_node *node; + struct grub_fshelp_node *node = NULL; grub_err_t err; err = grub_disk_read (dir->data->disk, caddr >> GRUB_DISK_SECTOR_BITS, @@ -189,9 +190,9 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, } for (nptr = 0; ; nptr++, naddr += 16) { - if (a >= nptr) + if (a <= nptr) { - char *on; + grub_properly_aligned_t *on; a = 2 * (nptr + 1); on = name; name = grub_realloc (name, a * 16); @@ -201,13 +202,14 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, return 1; } } + COMPILE_TIME_ASSERT (16 % sizeof (name[0]) == 0); err = grub_disk_read (dir->data->disk, naddr >> GRUB_DISK_SECTOR_BITS, naddr & (GRUB_DISK_SECTOR_SIZE - 1), - 16, name + 16 * nptr); + 16, name + (16 / sizeof (name[0])) * nptr); if (err) return 1; for (j = 0; j < 16; j++) - if (!name[16 * nptr + j]) + if (!((char *) name)[16 * nptr + j]) break; if (j != 16) break; @@ -292,7 +294,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, } } - if (hook (name, filetype, node)) + if (hook ((char *) name, filetype, node)) { grub_free (name); return 1; From 812e249302778f6b0709f33578be111e219c6263 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 01:58:35 +0100 Subject: [PATCH 595/673] * grub-core/fs/ext2.c (grub_ext4_find_leaf): MAke buf as pointer to properly aligned memory. (grub_ext2_read_block): Ensure buffer alignment. --- ChangeLog | 6 ++++++ grub-core/fs/ext2.c | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 086b61ff9..99fcb1f95 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/ext2.c (grub_ext4_find_leaf): MAke buf as pointer to + properly aligned memory. + (grub_ext2_read_block): Ensure buffer alignment. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/romfs.c (grub_romfs_iterate_dir): Properly align diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index 0fdf151a2..6eb53d3f8 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -337,7 +337,7 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group, } static struct grub_ext4_extent_header * -grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf, +grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, struct grub_ext4_extent_header *ext_block, grub_uint32_t fileblock) { @@ -387,7 +387,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG) { - char buf[EXT2_BLOCK_SIZE(data)]; + GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data)); struct grub_ext4_extent_header *leaf; struct grub_ext4_extent *ext; int i; From eb561f31234767d9a0f247350bbdb25eb45489fc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 02:00:44 +0100 Subject: [PATCH 596/673] * grub-core/fs/nilfs2.c (grub_nilfs2_btree_node): Add zero-size keys array. (grub_nilfs2_btree_node_dkeys): Ensure return pointer alignment. (grub_nilfs2_btree_lookup): Ensure buffer alignment. --- ChangeLog | 7 +++++++ grub-core/fs/nilfs2.c | 9 +++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99fcb1f95..1fe654de5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (grub_nilfs2_btree_node): Add zero-size keys + array. + (grub_nilfs2_btree_node_dkeys): Ensure return pointer alignment. + (grub_nilfs2_btree_lookup): Ensure buffer alignment. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/ext2.c (grub_ext4_find_leaf): MAke buf as pointer to diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 35a040b97..0b001eb0e 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -208,6 +208,7 @@ struct grub_nilfs2_btree_node grub_uint8_t bn_level; grub_uint16_t bn_nchildren; grub_uint32_t bn_pad; + grub_uint64_t keys[0]; }; struct grub_nilfs2_palloc_group_desc @@ -399,9 +400,9 @@ grub_nilfs2_btree_get_level (struct grub_nilfs2_btree_node *node) static inline grub_uint64_t * grub_nilfs2_btree_node_dkeys (struct grub_nilfs2_btree_node *node) { - return (grub_uint64_t *) ((char *) (node + 1) + - ((node->bn_flags & NILFS_BTREE_NODE_ROOT) ? - 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); + return (node->keys + + ((node->bn_flags & NILFS_BTREE_NODE_ROOT) ? + 0 : (NILFS_BTREE_NODE_EXTRA_PAD_SIZE / sizeof (grub_uint64_t)))); } static inline grub_uint64_t @@ -502,7 +503,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_uint64_t key, int need_translate) { struct grub_nilfs2_btree_node *node; - unsigned char block[NILFS2_BLOCK_SIZE (data)]; + GRUB_PROPERLY_ALIGNED_ARRAY (block, NILFS2_BLOCK_SIZE (data)); grub_uint64_t ptr; int level, found, index; From 728cba91d205037ae906daa922573034fe89b5ee Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 02:02:38 +0100 Subject: [PATCH 597/673] * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Use grub_get_unaligned16 to get freetag and skip. --- ChangeLog | 5 +++++ grub-core/fs/xfs.c | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1fe654de5..f83c57348 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Use grub_get_unaligned16 + to get freetag and skip. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/nilfs2.c (grub_nilfs2_btree_node): Add zero-size keys diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index c7ce3aac9..fbadc8fa5 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -589,18 +589,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, - (int) sizeof (struct grub_xfs_dir2_entry))) { struct grub_xfs_dir2_entry *direntry; - grub_uint16_t *freetag; + grub_uint8_t *freetag; char *filename; direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos]; - freetag = (grub_uint16_t *) direntry; + freetag = (grub_uint8_t *) direntry; - if (*freetag == 0XFFFF) + if (grub_get_unaligned16 (freetag) == 0XFFFF) { - grub_uint16_t *skip = (grub_uint16_t *) (freetag + 1); + grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t)); /* This entry is not used, go to the next one. */ - pos += grub_be_to_cpu16 (*skip); + pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip)); continue; } From 4c5f3056c23933963e3bb052d20508511627a3c0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 02:05:58 +0100 Subject: [PATCH 598/673] * grub-core/fs/hfsplus.c (grub_hfsplus_btree_recoffset): Handle the case of aunaligned recptr. (grub_hfsplus_read_block): Declare extoverflow as key to ensure alignment. (grub_hfsplus_btree_search): Handle unaligned index. --- ChangeLog | 8 ++++++++ grub-core/fs/hfsplus.c | 25 ++++++++++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index f83c57348..cbe2c13f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/hfsplus.c (grub_hfsplus_btree_recoffset): Handle the + case of aunaligned recptr. + (grub_hfsplus_read_block): Declare extoverflow as key to ensure + alignment. + (grub_hfsplus_btree_search): Handle unaligned index. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Use grub_get_unaligned16 diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 9d5f20181..7e859be41 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -251,10 +251,9 @@ grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *node, int index) { char *cnode = (char *) node; - grub_uint16_t *recptr; - recptr = (grub_uint16_t *) (&cnode[btree->nodesize - - index * sizeof (grub_uint16_t) - 2]); - return grub_be_to_cpu16 (*recptr); + void *recptr; + recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]); + return grub_be_to_cpu16 (grub_get_unaligned16 (recptr)); } /* Return a pointer to the record with the index INDEX, in the node @@ -315,7 +314,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) while (1) { struct grub_hfsplus_extkey *key; - struct grub_hfsplus_extkey_internal extoverflow; + struct grub_hfsplus_key_internal extoverflow; grub_disk_addr_t blk; grub_off_t ptr; @@ -343,11 +342,11 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } /* Set up the key to look for in the extent overflow file. */ - extoverflow.fileid = node->fileid; - extoverflow.start = fileblock - blksleft; + extoverflow.extkey.fileid = node->fileid; + extoverflow.extkey.start = fileblock - blksleft; if (grub_hfsplus_btree_search (&node->data->extoverflow_tree, - (struct grub_hfsplus_key_internal *) &extoverflow, + &extoverflow, grub_hfsplus_cmp_extkey, &nnode, &ptr)) { grub_error (GRUB_ERR_READ_ERROR, @@ -697,7 +696,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, } else if (nodedesc->type == GRUB_HFSPLUS_BTNODE_TYPE_INDEX) { - grub_uint32_t *pointer; + void *pointer; /* The place where the key could have been found didn't contain the key. This means that the previous match @@ -709,10 +708,10 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, that we are looking for. The last match that is found will be used to locate the child which can contain the record. */ - pointer = (grub_uint32_t *) ((char *) currkey - + grub_be_to_cpu16 (currkey->keylen) - + 2); - currnode = grub_be_to_cpu32 (*pointer); + pointer = ((char *) currkey + + grub_be_to_cpu16 (currkey->keylen) + + 2); + currnode = grub_be_to_cpu32 (grub_get_unaligned32 (pointer)); match = 1; } } From d1c930f99be8b836eea675232dc5628f7e9d8a46 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 02:08:14 +0100 Subject: [PATCH 599/673] * include/grub/list.h: Explicitly cast return of grub_bad_type_cast to match types. --- ChangeLog | 5 +++++ include/grub/list.h | 16 +++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index cbe2c13f5..672bb9dd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/list.h: Explicitly cast return of grub_bad_type_cast + to match types. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/hfsplus.c (grub_hfsplus_btree_recoffset): Handle the diff --git a/include/grub/list.h b/include/grub/list.h index 75353010c..3dfb97ac6 100644 --- a/include/grub/list.h +++ b/include/grub/list.h @@ -54,11 +54,11 @@ grub_bad_type_cast_real (int line, const char *file) #define GRUB_AS_LIST(ptr) \ (GRUB_FIELD_MATCH (ptr, grub_list_t, next) ? \ - (grub_list_t) ptr : grub_bad_type_cast ()) + (grub_list_t) ptr : (grub_list_t) grub_bad_type_cast ()) #define GRUB_AS_LIST_P(pptr) \ (GRUB_FIELD_MATCH (*pptr, grub_list_t, next) ? \ - (grub_list_t *) (void *) pptr : grub_bad_type_cast ()) + (grub_list_t *) (void *) pptr : (grub_list_t *) grub_bad_type_cast ()) struct grub_named_list { @@ -73,12 +73,12 @@ void * EXPORT_FUNC(grub_named_list_find) (grub_named_list_t head, #define GRUB_AS_NAMED_LIST(ptr) \ ((GRUB_FIELD_MATCH (ptr, grub_named_list_t, next) && \ GRUB_FIELD_MATCH (ptr, grub_named_list_t, name))? \ - (grub_named_list_t) ptr : grub_bad_type_cast ()) + (grub_named_list_t) ptr : (grub_named_list_t) grub_bad_type_cast ()) #define GRUB_AS_NAMED_LIST_P(pptr) \ ((GRUB_FIELD_MATCH (*pptr, grub_named_list_t, next) && \ GRUB_FIELD_MATCH (*pptr, grub_named_list_t, name))? \ - (grub_named_list_t *) (void *) pptr : grub_bad_type_cast ()) + (grub_named_list_t *) (void *) pptr : (grub_named_list_t *) grub_bad_type_cast ()) #define GRUB_PRIO_LIST_PRIO_MASK 0xff #define GRUB_PRIO_LIST_FLAG_ACTIVE 0x100 @@ -106,12 +106,14 @@ grub_prio_list_remove (grub_prio_list_t *head, grub_prio_list_t item) ((GRUB_FIELD_MATCH (ptr, grub_prio_list_t, next) && \ GRUB_FIELD_MATCH (ptr, grub_prio_list_t, name) && \ GRUB_FIELD_MATCH (ptr, grub_prio_list_t, prio))? \ - (grub_prio_list_t) ptr : grub_bad_type_cast ()) + (grub_prio_list_t) ptr \ + : (grub_prio_list_t) grub_bad_type_cast ()) #define GRUB_AS_PRIO_LIST_P(pptr) \ ((GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, next) && \ GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, name) && \ - GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, prio))? \ - (grub_prio_list_t *) (void *) pptr : grub_bad_type_cast ()) + GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, prio)) ? \ + (grub_prio_list_t *) (void *) pptr \ + : (grub_prio_list_t *) grub_bad_type_cast ()) #endif /* ! GRUB_LIST_HEADER */ From 9b40df20c4995d81c030eff116661156dd382dfe Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 02:12:23 +0100 Subject: [PATCH 600/673] * include/grub/efiemu/efiemu.h (grub_efiemu_get_memory_map): Remove redundant declaration. (grub_efiemu_mm_obtain_request): Likewise. (grub_efiemu_prepare): Likewise. --- ChangeLog | 7 +++++++ include/grub/efiemu/efiemu.h | 7 ------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 672bb9dd2..99f8a7bbe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/efiemu/efiemu.h (grub_efiemu_get_memory_map): Remove + redundant declaration. + (grub_efiemu_mm_obtain_request): Likewise. + (grub_efiemu_prepare): Likewise. + 2011-12-13 Vladimir Serbinenko * include/grub/list.h: Explicitly cast return of grub_bad_type_cast diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 7b9551627..ec35dac5a 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -200,15 +200,9 @@ grub_efiemu_register_configuration_table (grub_efi_guid_t guid, int grub_efiemu_request_memalign (grub_size_t align, grub_size_t size, grub_efi_memory_type_t type); void *grub_efiemu_mm_obtain_request (int handle); -int grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size, - grub_efi_memory_descriptor_t *memory_map, - grub_efi_uintn_t *map_key, - grub_efi_uintn_t *descriptor_size, - grub_efi_uint32_t *descriptor_version); grub_err_t grub_efiemu_mm_unload (void); grub_err_t grub_efiemu_mm_do_alloc (void); grub_err_t grub_efiemu_mm_init (void); -void *grub_efiemu_mm_obtain_request (int handle); void grub_efiemu_mm_return_request (int handle); grub_efi_memory_type_t grub_efiemu_mm_get_type (int handle); @@ -271,7 +265,6 @@ grub_err_t grub_efiemu_write_value (void * addr, grub_uint32_t value, int minus_handle, int ptv_needed, int size); grub_err_t grub_efiemu_write_sym_markers (void); grub_err_t grub_efiemu_pnvram (void); -grub_err_t grub_efiemu_prepare (void); const char *grub_efiemu_get_default_core_name (void); void grub_efiemu_pnvram_cmd_unregister (void); grub_err_t grub_efiemu_autocore (void); From 564840dc3d7a3588d2b5f695eb8bc7c0f718748f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 02:13:44 +0100 Subject: [PATCH 601/673] * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Change pointer arithmetic to conserve alignment invariants. --- ChangeLog | 5 +++++ grub-core/disk/mdraid_linux.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 99f8a7bbe..b7a5b02f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Change pointer + arithmetic to conserve alignment invariants. + 2011-12-13 Vladimir Serbinenko * include/grub/efiemu/efiemu.h (grub_efiemu_get_memory_map): Remove diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c index 0e2d85009..7ee513d26 100644 --- a/grub-core/disk/mdraid_linux.c +++ b/grub-core/disk/mdraid_linux.c @@ -216,11 +216,11 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, array->chunk_size = grub_le_to_cpu32 (sb.chunk_size) >> 9; array->index = grub_le_to_cpu32 (sb.this_disk.number); array->uuid_len = 16; - array->uuid = grub_malloc (16); + uuid = grub_malloc (16); + array->uuid = (char *) uuid; if (!array->uuid) return grub_errno; - uuid = (grub_uint32_t *) array->uuid; uuid[0] = grub_swap_bytes32 (sb.set_uuid0); uuid[1] = grub_swap_bytes32 (sb.set_uuid1); uuid[2] = grub_swap_bytes32 (sb.set_uuid2); From f138623a601f3fffd09e8a2c21cff36566948319 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 02:15:09 +0100 Subject: [PATCH 602/673] * grub-core/net/netbuff.c (grub_netbuff_alloc): Ensure proper alignment. --- ChangeLog | 4 ++++ grub-core/net/netbuff.c | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b7a5b02f3..be4b26ba2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/net/netbuff.c (grub_netbuff_alloc): Ensure proper alignment. + 2011-12-13 Vladimir Serbinenko * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Change pointer diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index d20104ab0..bee207f90 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -78,6 +78,8 @@ grub_netbuff_alloc (grub_size_t len) struct grub_net_buff *nb; void *data; + COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0); + if (len < NETBUFFMINLEN) len = NETBUFFMINLEN; @@ -85,7 +87,8 @@ grub_netbuff_alloc (grub_size_t len) data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); if (!data) return NULL; - nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); + nb = (struct grub_net_buff *) ((grub_properly_aligned_t *) data + + len / sizeof (grub_properly_aligned_t)); nb->head = nb->data = nb->tail = data; nb->end = (char *) nb; return nb; From fcd232b74e605e59ab77a120a26276f5988d2eaf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 11:33:02 +0100 Subject: [PATCH 603/673] * grub-core/fs/zfs/zfs.c (DVA_OFFSET_TO_PHYS_SECTOR): Make into inline function. (ZAP_HASH_IDX): Likewise. (ZAP_LEAF_HASH_SHIFT): Likewise. (ZAP_LEAF_HASH_NUMENTRIES): Likewise. (LEAF_HASH): Likewise. (ZAP_LEAF_NUMCHUNKS): Likewise. (ZAP_LEAF_CHUNK): Likewise. Changed pointer arithmetic to preserve alignment invariants. Return pointer. All users updated. (ZAP_LEAF_ENTRY): Make into inline function. (NBBY): Removed. (xor): LIkewise. (xor_out): Use grub_crypto_xor. (dnode_get_path): Use grub_get_unaligned. (nvlist_find_value): Likewise. (grub_zfs_nvlist_lookup_uint64): Likewise. (grub_zfs_nvlist_lookup_string): Likewise. (get_nvlist_size): Likewise. (grub_zfs_open): Likewise. (fill_fs_info): Likewise. (grub_zfs_dir): Likewise. * include/grub/zfs/zap_leaf.h (zap_leaf_phys): Adapt to preserve alignment invariants. * include/grub/zfs/zio.h (zio_eck_t): Mark as packed as it's not necessarily aligned. --- ChangeLog | 28 +++++++++ grub-core/fs/zfs/zfs.c | 118 ++++++++++++++++++++++-------------- include/grub/zfs/zap_leaf.h | 3 +- include/grub/zfs/zio.h | 2 +- 4 files changed, 104 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index be4b26ba2..fa3c04c63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (DVA_OFFSET_TO_PHYS_SECTOR): Make into inline + function. + (ZAP_HASH_IDX): Likewise. + (ZAP_LEAF_HASH_SHIFT): Likewise. + (ZAP_LEAF_HASH_NUMENTRIES): Likewise. + (LEAF_HASH): Likewise. + (ZAP_LEAF_NUMCHUNKS): Likewise. + (ZAP_LEAF_CHUNK): Likewise. Changed pointer arithmetic to preserve + alignment invariants. Return pointer. All users updated. + (ZAP_LEAF_ENTRY): Make into inline function. + (NBBY): Removed. + (xor): LIkewise. + (xor_out): Use grub_crypto_xor. + (dnode_get_path): Use grub_get_unaligned. + (nvlist_find_value): Likewise. + (grub_zfs_nvlist_lookup_uint64): Likewise. + (grub_zfs_nvlist_lookup_string): Likewise. + (get_nvlist_size): Likewise. + (grub_zfs_open): Likewise. + (fill_fs_info): Likewise. + (grub_zfs_dir): Likewise. + * include/grub/zfs/zap_leaf.h (zap_leaf_phys): Adapt to preserve + alignment invariants. + * include/grub/zfs/zio.h (zio_eck_t): Mark as packed as it's not + necessarily aligned. + 2011-12-13 Vladimir Serbinenko * grub-core/net/netbuff.c (grub_netbuff_alloc): Ensure proper alignment. diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 9de2ab586..534b7d224 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -77,14 +77,23 @@ static grub_dl_t my_mod; #endif #define P2PHASE(x, align) ((x) & ((align) - 1)) -#define DVA_OFFSET_TO_PHYS_SECTOR(offset) \ - ((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT) + +static inline grub_disk_addr_t +DVA_OFFSET_TO_PHYS_SECTOR (grub_disk_addr_t offset) +{ + return ((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT); +} /* * FAT ZAP data structures */ #define ZFS_CRC64_POLY 0xC96C5795D7870F42ULL /* ECMA-182, reflected form */ -#define ZAP_HASH_IDX(hash, n) (((n) == 0) ? 0 : ((hash) >> (64 - (n)))) +static inline grub_uint64_t +ZAP_HASH_IDX (grub_uint64_t hash, grub_uint64_t n) +{ + return (((n) == 0) ? 0 : ((hash) >> (64 - (n)))); +} + #define CHAIN_END 0xffff /* end of the chunk chain */ /* @@ -93,37 +102,60 @@ static grub_dl_t my_mod; */ #define ZAP_LEAF_ARRAY_BYTES (ZAP_LEAF_CHUNKSIZE - 3) -#define ZAP_LEAF_HASH_SHIFT(bs) (bs - 5) -#define ZAP_LEAF_HASH_NUMENTRIES(bs) (1 << ZAP_LEAF_HASH_SHIFT(bs)) -#define LEAF_HASH(bs, h) \ - ((ZAP_LEAF_HASH_NUMENTRIES(bs)-1) & \ - ((h) >> (64 - ZAP_LEAF_HASH_SHIFT(bs)-l->l_hdr.lh_prefix_len))) +static inline int +ZAP_LEAF_HASH_SHIFT (int bs) +{ + return bs - 5; +} + +static inline int +ZAP_LEAF_HASH_NUMENTRIES (int bs) +{ + return 1 << ZAP_LEAF_HASH_SHIFT(bs); +} + +static inline grub_size_t +LEAF_HASH (int bs, grub_uint64_t h, zap_leaf_phys_t *l) +{ + return ((ZAP_LEAF_HASH_NUMENTRIES (bs)-1) + & ((h) >> (64 - ZAP_LEAF_HASH_SHIFT (bs) - l->l_hdr.lh_prefix_len))); +} /* * The amount of space available for chunks is: * block size shift - hash entry size (2) * number of hash * entries - header space (2*chunksize) */ -#define ZAP_LEAF_NUMCHUNKS(bs) \ - (((1<l_hash + ZAP_LEAF_HASH_NUMENTRIES(bs)))[idx] -#define ZAP_LEAF_ENTRY(l, bs, idx) (&ZAP_LEAF_CHUNK(l, bs, idx).l_entry) +static inline zap_leaf_chunk_t * +ZAP_LEAF_CHUNK (zap_leaf_phys_t *l, int bs, int idx) +{ + return &((zap_leaf_chunk_t *) (l->l_entries + + (ZAP_LEAF_HASH_NUMENTRIES(bs) * 2) + / sizeof (grub_properly_aligned_t)))[idx]; +} + +static inline struct zap_leaf_entry * +ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx) +{ + return &ZAP_LEAF_CHUNK(l, bs, idx)->l_entry; +} /* * Decompression Entry - lzjb */ -#ifndef NBBY -#define NBBY 8 -#endif extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); @@ -969,14 +1001,6 @@ scan_devices (struct grub_zfs_data *data) return GRUB_ERR_NONE; } -static inline void -xor (grub_uint64_t *a, const grub_uint64_t *b, grub_size_t s) -{ - s /= sizeof (grub_uint64_t); - while (s--) - *a++ ^= *b++; -} - /* x**y. */ static grub_uint8_t powx[255 * 2]; /* Such an s that x**s = y */ @@ -985,17 +1009,15 @@ static const grub_uint8_t poly = 0x1d; /* perform the operation a ^= b * (x ** (known_idx * recovery_pow) ) */ static inline void -xor_out (void *a_in, const void *b_in, grub_size_t s, +xor_out (grub_uint8_t *a, const grub_uint8_t *b, grub_size_t s, int known_idx, int recovery_pow) { int add; - grub_uint8_t *a = a_in; - const grub_uint8_t *b = b_in; /* Simple xor. */ if (known_idx == 0 || recovery_pow == 0) { - xor (a_in, b_in, s); + grub_crypto_xor (a, a, b, s); return; } add = (known_idx * recovery_pow) % 255; @@ -1827,7 +1849,7 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, while (bseen < array_len) { - struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array; + struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk)->l_array; int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES); if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) @@ -1851,7 +1873,7 @@ zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, while (bseen < array_len) { - struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array; + struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk)->l_array; int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES); if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) @@ -1887,7 +1909,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != ZAP_LEAF_MAGIC) return grub_error (GRUB_ERR_BAD_FS, "invalid leaf magic"); - for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h)], endian); + for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h, l)], endian); chunk != CHAIN_END; chunk = grub_zfs_to_cpu16 (le->le_next, endian)) { @@ -1917,7 +1939,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, return grub_error (GRUB_ERR_BAD_FS, "invalid leaf chunk entry"); /* get the uint64_t property value */ - la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk).l_array; + la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk)->l_array; *value = grub_be_to_cpu64 (la->la_array64); @@ -2552,11 +2574,17 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - if (((grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_TYPE_OFFSET), dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + if (((grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + + hdrsize + + SA_TYPE_OFFSET), + dnode_path->dn.endian) >> 12) & 0xf) == 0xa) { char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET; grub_size_t sym_sz = - grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dnode_path->dn.endian); + grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + + hdrsize + + SA_SIZE_OFFSET), + dnode_path->dn.endian); char *oldpath = path, *oldpathbuf = path_buf; path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); if (!path_buf) @@ -3009,22 +3037,22 @@ nvlist_find_value (const char *nvlist, const char *name, * Loop thru the nvpair list * The XDR representation of an integer is in big-endian byte order. */ - while ((encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) nvlist))) + while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist)))) { int nelm; nvpair = nvlist + 4 * 2; /* skip the encode/decode size */ - name_len = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair); + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); nvpair += 4; nvp_name = nvpair; nvpair = nvpair + ((name_len + 3) & ~3); /* align */ - type = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair); + type = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); nvpair += 4; - nelm = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair); + nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); if (nelm < 1) return grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); @@ -3061,7 +3089,7 @@ grub_zfs_nvlist_lookup_uint64 (const char *nvlist, const char *name, return 0; } - *out = grub_be_to_cpu64 (*(grub_uint64_t *) nvpair); + *out = grub_be_to_cpu64 (grub_get_unaligned64 (nvpair)); return 1; } @@ -3082,7 +3110,7 @@ grub_zfs_nvlist_lookup_string (const char *nvlist, const char *name) grub_error (GRUB_ERR_BAD_FS, "invalid string"); return 0; } - slen = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair); + slen = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); if (slen > size - 4) slen = size - 4; ret = grub_malloc (slen + 1); @@ -3138,7 +3166,7 @@ get_nvlist_size (const char *beg, const char *limit) ptr = beg + 8; while (ptr < limit - && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) ptr))) + && (encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (ptr)))) ptr += encode_size; /* goto the next nvpair */ ptr += 8; return (ptr > limit) ? -1 : (ptr - beg); @@ -3453,7 +3481,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) } hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - file->size = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian); + file->size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian); } else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE) { @@ -3645,7 +3673,7 @@ fill_fs_info (struct grub_dirhook_info *info, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); info->mtimeset = 1; - info->mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info->mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); } if (dn.dn.dn_bonustype == DMU_OT_ZNODE) @@ -3706,7 +3734,7 @@ grub_zfs_dir (grub_device_t device, const char *path, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); info.case_insensitive = data->subvol.case_insensitive; } diff --git a/include/grub/zfs/zap_leaf.h b/include/grub/zfs/zap_leaf.h index 5adfdc290..f2b7cb1da 100644 --- a/include/grub/zfs/zap_leaf.h +++ b/include/grub/zfs/zap_leaf.h @@ -69,7 +69,8 @@ typedef struct zap_leaf_phys { * with the ZAP_LEAF_CHUNK() macro. */ - grub_uint16_t l_hash[1]; + grub_uint16_t l_hash[0]; + grub_properly_aligned_t l_entries[0]; } zap_leaf_phys_t; typedef union zap_leaf_chunk { diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h index 8b645c063..b1c46da3a 100644 --- a/include/grub/zfs/zio.h +++ b/include/grub/zfs/zio.h @@ -30,7 +30,7 @@ typedef struct zio_eck { grub_uint64_t zec_magic; /* for validation, endianness */ zio_cksum_t zec_cksum; /* 256-bit checksum */ -} zio_eck_t; +} __attribute__ ((packed)) zio_eck_t; /* * Gang block headers are self-checksumming and contain an array From b3950b849fc109954f8bd3671e41118f7ebd6ba2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 11:46:29 +0100 Subject: [PATCH 604/673] * grub-core/kern/mips/qemu_mips/init.c (grub_at_keyboard_init): Remove redundant declaration. (grub_serial_init): Likewise. (grub_terminfo_init): Likewise. --- ChangeLog | 7 +++++++ grub-core/kern/mips/qemu_mips/init.c | 3 --- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index fa3c04c63..13b49c0b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/mips/qemu_mips/init.c (grub_at_keyboard_init): Remove + redundant declaration. + (grub_serial_init): Likewise. + (grub_terminfo_init): Likewise. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/zfs/zfs.c (DVA_OFFSET_TO_PHYS_SECTOR): Make into inline diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index d331e1b24..120b450f5 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -18,9 +18,6 @@ extern void grub_video_init (void); extern void grub_bitmap_init (void); extern void grub_font_init (void); extern void grub_gfxterm_init (void); -extern void grub_at_keyboard_init (void); -extern void grub_serial_init (void); -extern void grub_terminfo_init (void); extern void grub_keylayouts_init (void); extern void grub_boot_init (void); extern void grub_vga_text_init (void); From 9b05cad7686b9b490f7063640aec1eae120736c0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 13:58:33 +0100 Subject: [PATCH 605/673] * grub-core/fs/udf.c (grub_udf_partmap): Add packed attribute as it's not necessarily aligned. --- ChangeLog | 5 +++++ grub-core/fs/udf.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 13b49c0b3..159c14964 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/udf.c (grub_udf_partmap): Add packed attribute + as it's not necessarily aligned. + 2011-12-13 Vladimir Serbinenko * grub-core/kern/mips/qemu_mips/init.c (grub_at_keyboard_init): Remove diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 4097fd2e6..537bb37f0 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -317,7 +317,7 @@ struct grub_udf_partmap grub_uint8_t ident[62]; } type2; }; -}; +} __attribute__ ((packed)); struct grub_udf_lvd { From 58acccd6457dfc71931cc3bd56bdf9d9f9703d0c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 14:17:24 +0100 Subject: [PATCH 606/673] * grub-core/fs/ntfs.c (u16at): Make into inline function. Handle unaligned pointers. (u32at): Likewise. (u64at): Likewise. (fixup): Use byte access instead of v16at. (find_attr): Fix imporper usage of v32at. (read_data): Likewise. (list_file): Handle byte-swapping and unaligned strings. (grub_ntfs_label): Likewise. --- ChangeLog | 12 +++++++++ grub-core/fs/ntfs.c | 62 +++++++++++++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 159c14964..f974c76bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (u16at): Make into inline function. + Handle unaligned pointers. + (u32at): Likewise. + (u64at): Likewise. + (fixup): Use byte access instead of v16at. + (find_attr): Fix imporper usage of v32at. + (read_data): Likewise. + (list_file): Handle byte-swapping and unaligned strings. + (grub_ntfs_label): Likewise. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/udf.c (grub_udf_partmap): Add packed attribute diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index a432adce3..7dbe0e5e5 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -34,15 +34,23 @@ static grub_dl_t my_mod; #define grub_fshelp_node grub_ntfs_file -#define valueat(buf,ofs,type) *((type*)(((char*)buf)+ofs)) +static inline grub_uint16_t +u16at (void *ptr, grub_size_t ofs) +{ + return grub_le_to_cpu16 (grub_get_unaligned16 ((char *) ptr + ofs)); +} -#define u16at(buf,ofs) grub_le_to_cpu16(valueat(buf,ofs,grub_uint16_t)) -#define u32at(buf,ofs) grub_le_to_cpu32(valueat(buf,ofs,grub_uint32_t)) -#define u64at(buf,ofs) grub_le_to_cpu64(valueat(buf,ofs,grub_uint64_t)) +static inline grub_uint32_t +u32at (void *ptr, grub_size_t ofs) +{ + return grub_le_to_cpu32 (grub_get_unaligned32 ((char *) ptr + ofs)); +} -#define v16at(buf,ofs) valueat(buf,ofs,grub_uint16_t) -#define v32at(buf,ofs) valueat(buf,ofs,grub_uint32_t) -#define v64at(buf,ofs) valueat(buf,ofs,grub_uint64_t) +static inline grub_uint64_t +u64at (void *ptr, grub_size_t ofs) +{ + return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs)); +} grub_ntfscomp_func_t grub_ntfscomp_func; @@ -70,7 +78,8 @@ fixup (struct grub_ntfs_data *data, char *buf, int len, const char *magic) pu += 2; if (u16at (buf, 0) != us) return grub_error (GRUB_ERR_BAD_FS, "fixup signature not match"); - v16at (buf, 0) = v16at (pu, 0); + buf[0] = pu[0]; + buf[1] = pu[1]; ss--; } @@ -131,11 +140,11 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) if (at->flags & GRUB_NTFS_AF_MMFT) { if ((grub_disk_read - (at->mft->data->disk, v32at (at->attr_cur, 0x10), 0, + (at->mft->data->disk, u32at (at->attr_cur, 0x10), 0, 512, at->emft_buf)) || (grub_disk_read - (at->mft->data->disk, v32at (at->attr_cur, 0x14), 0, + (at->mft->data->disk, u32at (at->attr_cur, 0x14), 0, 512, at->emft_buf + 512))) return NULL; @@ -228,8 +237,11 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) at->flags |= GRUB_NTFS_AF_GPOS; at->attr_cur = at->attr_nxt; pa = at->attr_cur; - v32at (pa, 0x10) = at->mft->data->mft_start; - v32at (pa, 0x14) = at->mft->data->mft_start + 1; + grub_set_unaligned32 ((char *) pa + 0x10, + grub_cpu_to_le32 (at->mft->data->mft_start)); + grub_set_unaligned32 ((char *) pa + 0x14, + grub_cpu_to_le32 (at->mft->data->mft_start + + 1)); pa = at->attr_nxt + u16at (pa, 4); while (pa < at->attr_end) { @@ -459,8 +471,8 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, return grub_errno; st1 = ctx->curr_lcn * ctx->comp.spc; } - v32at (dest, 0) = st0; - v32at (dest, 4) = st1; + grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0)); + grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1)); return 0; } @@ -636,12 +648,18 @@ list_file (struct grub_ntfs_file *diro, char *pos, else fdiro->mtime = u64at (pos, 0x28); - ustr = grub_malloc (ns * 4 + 1); + ustr = grub_malloc (ns * GRUB_MAX_UTF8_PER_UTF16 + 1); if (ustr == NULL) return 0; - *grub_utf16_to_utf8 ((grub_uint8_t *) ustr, (grub_uint16_t *) np, - ns) = '\0'; + { + grub_uint16_t tmp[ns]; + int i; + for (i = 0; i < ns; i++) + tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 ((char *) np + + 2 * i)); + *grub_utf16_to_utf8 ((grub_uint8_t *) ustr, tmp, ns) = '\0'; + } if (namespace) type |= GRUB_FSHELP_CASE_INSENSITIVE; @@ -1163,8 +1181,14 @@ grub_ntfs_label (grub_device_t device, char **label) len = u32at (pa, 0x10) / 2; buf = grub_malloc (len * 4 + 1); pa += u16at (pa, 0x14); - *grub_utf16_to_utf8 ((grub_uint8_t *) buf, (grub_uint16_t *) pa, len) = - '\0'; + { + grub_uint16_t tmp[len]; + int i; + for (i = 0; i < len; i++) + tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (pa + 2 * i)); + *grub_utf16_to_utf8 ((grub_uint8_t *) buf, tmp, len) = + '\0'; + } *label = buf; } From a23f2cc4d6838c64e54b6c5ea69c9da7731fcbe9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 14:40:41 +0100 Subject: [PATCH 607/673] * grub-core/partmap/sun.c (grub_sun_is_valid): make argument uint16_t * to ensure alignment. (sun_partition_map_iterate): Make `block' a union to ensure alignment. --- ChangeLog | 6 ++++++ grub-core/partmap/sun.c | 26 +++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index f974c76bc..d5d98c193 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/partmap/sun.c (grub_sun_is_valid): make argument uint16_t * + to ensure alignment. + (sun_partition_map_iterate): Make `block' a union to ensure alignment. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/ntfs.c (u16at): Make into inline function. diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c index c7ef681c4..dfe51f35d 100644 --- a/grub-core/partmap/sun.c +++ b/grub-core/partmap/sun.c @@ -71,13 +71,13 @@ static struct grub_partition_map grub_sun_partition_map; /* Verify checksum (true=ok). */ static int -grub_sun_is_valid (struct grub_sun_block *label) +grub_sun_is_valid (grub_uint16_t *label) { grub_uint16_t *pos; grub_uint16_t sum = 0; - for (pos = (grub_uint16_t *) label; - pos < (grub_uint16_t *) (label + 1); + for (pos = label; + pos < (label + sizeof (struct grub_sun_block) / 2); pos++) sum ^= *pos; @@ -90,7 +90,11 @@ sun_partition_map_iterate (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition p; - struct grub_sun_block block; + union + { + struct grub_sun_block sun; + grub_uint16_t raw[0]; + } block; int partnum; grub_err_t err; @@ -100,10 +104,10 @@ sun_partition_map_iterate (grub_disk_t disk, if (err) return err; - if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) + if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.sun.magic)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); - if (! grub_sun_is_valid (&block)) + if (! grub_sun_is_valid (block.raw)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); /* Maybe another error value would be better, because partition @@ -112,14 +116,14 @@ sun_partition_map_iterate (grub_disk_t disk, { struct grub_sun_partition_descriptor *desc; - if (block.infos[partnum].id == 0 - || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) + if (block.sun.infos[partnum].id == 0 + || block.sun.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) continue; - desc = &block.partitions[partnum]; + desc = &block.sun.partitions[partnum]; p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) - * grub_be_to_cpu16 (block.ntrks) - * grub_be_to_cpu16 (block.nsect)); + * grub_be_to_cpu16 (block.sun.ntrks) + * grub_be_to_cpu16 (block.sun.nsect)); p.len = grub_be_to_cpu32 (desc->num_sectors); p.number = p.index = partnum; if (p.len) From 93018f6400a1dd97ae93bc7bfb50c5c844322929 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 14:42:41 +0100 Subject: [PATCH 608/673] * grub-core/partmap/sunpc.c (grub_sun_is_valid): Make argument uint16_t * to ensure alignment. (sun_pc_partition_map_iterate): Make `block' a union to ensure alignment. --- ChangeLog | 9 ++++++++- grub-core/partmap/sunpc.c | 23 ++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5d98c193..c1ac0c00a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,13 @@ 2011-12-13 Vladimir Serbinenko - * grub-core/partmap/sun.c (grub_sun_is_valid): make argument uint16_t * + * grub-core/partmap/sunpc.c (grub_sun_is_valid): Make argument + uint16_t * to ensure alignment. + (sun_pc_partition_map_iterate): Make `block' a union to ensure + alignment. + +2011-12-13 Vladimir Serbinenko + + * grub-core/partmap/sun.c (grub_sun_is_valid): Make argument uint16_t * to ensure alignment. (sun_partition_map_iterate): Make `block' a union to ensure alignment. diff --git a/grub-core/partmap/sunpc.c b/grub-core/partmap/sunpc.c index 28dc4f5be..1c1fdced0 100644 --- a/grub-core/partmap/sunpc.c +++ b/grub-core/partmap/sunpc.c @@ -53,13 +53,13 @@ static struct grub_partition_map grub_sun_pc_partition_map; /* Verify checksum (true=ok). */ static int -grub_sun_is_valid (struct grub_sun_pc_block *label) +grub_sun_is_valid (grub_uint16_t *label) { grub_uint16_t *pos; grub_uint16_t sum = 0; - for (pos = (grub_uint16_t *) label; - pos < (grub_uint16_t *) (label + 1); + for (pos = label; + pos < (label + sizeof (struct grub_sun_pc_block) / 2); pos++) sum ^= *pos; @@ -72,7 +72,11 @@ sun_pc_partition_map_iterate (grub_disk_t disk, const grub_partition_t partition)) { grub_partition_t p; - struct grub_sun_pc_block block; + union + { + struct grub_sun_pc_block sun; + grub_uint16_t raw[0]; + } block; int partnum; grub_err_t err; @@ -88,14 +92,14 @@ sun_pc_partition_map_iterate (grub_disk_t disk, return err; } - if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.magic)) + if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.sun.magic)) { grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun_pc partition table"); } - if (! grub_sun_is_valid (&block)) + if (! grub_sun_is_valid (block.raw)) { grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); @@ -107,11 +111,12 @@ sun_pc_partition_map_iterate (grub_disk_t disk, { struct grub_sun_pc_partition_descriptor *desc; - if (block.partitions[partnum].id == 0 - || block.partitions[partnum].id == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID) + if (block.sun.partitions[partnum].id == 0 + || block.sun.partitions[partnum].id + == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID) continue; - desc = &block.partitions[partnum]; + desc = &block.sun.partitions[partnum]; p->start = grub_le_to_cpu32 (desc->start_sector); p->len = grub_le_to_cpu32 (desc->num_sectors); p->number = partnum; From 85c85365bbc3d6178c20c1fdd4bfe832b883ab7d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 14:44:38 +0100 Subject: [PATCH 609/673] * grub-core/partmap/dvh.c (grub_dvh_is_valid): Make argument uint32_t * to ensure alignment. (dvh_partition_map_iterate): Make `block' a union to ensure alignment. --- ChangeLog | 6 ++++++ grub-core/partmap/dvh.c | 24 ++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index c1ac0c00a..5d4a34fe8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/partmap/dvh.c (grub_dvh_is_valid): Make argument + uint32_t * to ensure alignment. + (dvh_partition_map_iterate): Make `block' a union to ensure alignment. + 2011-12-13 Vladimir Serbinenko * grub-core/partmap/sunpc.c (grub_sun_is_valid): Make argument diff --git a/grub-core/partmap/dvh.c b/grub-core/partmap/dvh.c index 118401612..c8f467eb5 100644 --- a/grub-core/partmap/dvh.c +++ b/grub-core/partmap/dvh.c @@ -49,13 +49,13 @@ static struct grub_partition_map grub_dvh_partition_map; /* Verify checksum (true=ok). */ static int -grub_dvh_is_valid (struct grub_dvh_block *label) +grub_dvh_is_valid (grub_uint32_t *label) { grub_uint32_t *pos; grub_uint32_t sum = 0; - for (pos = (grub_uint32_t *) label; - pos < (grub_uint32_t *) (label + 1); + for (pos = label; + pos < (label + sizeof (struct grub_dvh_block) / 4); pos++) sum += *pos; @@ -68,7 +68,11 @@ dvh_partition_map_iterate (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition p; - struct grub_dvh_block block; + union + { + struct grub_dvh_block dvh; + grub_uint32_t raw[0]; + } block; unsigned partnum; grub_err_t err; @@ -78,24 +82,24 @@ dvh_partition_map_iterate (grub_disk_t disk, if (err) return err; - if (DVH_MAGIC != grub_be_to_cpu32 (block.magic)) + if (DVH_MAGIC != grub_be_to_cpu32 (block.dvh.magic)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a dvh partition table"); - if (! grub_dvh_is_valid (&block)) + if (! grub_dvh_is_valid (block.raw)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); /* Maybe another error value would be better, because partition table _is_ recognized but invalid. */ - for (partnum = 0; partnum < ARRAY_SIZE (block.parts); partnum++) + for (partnum = 0; partnum < ARRAY_SIZE (block.dvh.parts); partnum++) { - if (block.parts[partnum].length == 0) + if (block.dvh.parts[partnum].length == 0) continue; if (partnum == 10) continue; - p.start = grub_be_to_cpu32 (block.parts[partnum].start); - p.len = grub_be_to_cpu32 (block.parts[partnum].length); + p.start = grub_be_to_cpu32 (block.dvh.parts[partnum].start); + p.len = grub_be_to_cpu32 (block.dvh.parts[partnum].length); p.number = p.index = partnum; if (hook (disk, &p)) break; From 753ef8c113267b08ffaf568ac70016c82f35ce96 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 14:47:00 +0100 Subject: [PATCH 610/673] * include/grub/efi/memory.h (grub_machine_mmap_iterate): Remove redundant declaration. (grub_mmap_get_post64): Likewise. (grub_mmap_get_upper): Likewise. (grub_mmap_get_lower): Likewise. --- ChangeLog | 8 ++++++++ include/grub/efi/memory.h | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5d4a34fe8..f6b3d5ef0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/efi/memory.h (grub_machine_mmap_iterate): + Remove redundant declaration. + (grub_mmap_get_post64): Likewise. + (grub_mmap_get_upper): Likewise. + (grub_mmap_get_lower): Likewise. + 2011-12-13 Vladimir Serbinenko * grub-core/partmap/dvh.c (grub_dvh_is_valid): Make argument diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h index 133f9504c..20526b146 100644 --- a/include/grub/efi/memory.h +++ b/include/grub/efi/memory.h @@ -24,15 +24,8 @@ #define GRUB_MMAP_REGISTER_BY_FIRMWARE 1 -grub_err_t grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)); grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size, int type, int handle); grub_err_t grub_machine_mmap_unregister (int handle); -grub_uint64_t grub_mmap_get_post64 (void); -grub_uint64_t grub_mmap_get_upper (void); -grub_uint64_t grub_mmap_get_lower (void); - #endif /* ! GRUB_MEMORY_MACHINE_HEADER */ From 0d51ee20eee82711c859175d7b459cd4b46f6082 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 14:51:41 +0100 Subject: [PATCH 611/673] * include/grub/emu/misc.h (xasprintf): Add missing format attribute. * include/grub/mips/kernel.h (grub_halt): Remove redundant declaration. * include/grub/mips/qemu_mips/kernel.h (grub_halt): Likewise. * include/grub/misc.h (grub_reboot) [GRUB_MACHINE_EMU || GRUB_MACHINE_QEMU_MIPS]: Export. (grub_halt) [__mips__]: Likewise. --- ChangeLog | 9 +++++++++ include/grub/emu/misc.h | 5 +---- include/grub/mips/kernel.h | 6 ------ include/grub/mips/qemu_mips/kernel.h | 1 - include/grub/misc.h | 6 ++++++ 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index f6b3d5ef0..293b11150 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/emu/misc.h (xasprintf): Add missing format attribute. + * include/grub/mips/kernel.h (grub_halt): Remove redundant declaration. + * include/grub/mips/qemu_mips/kernel.h (grub_halt): Likewise. + * include/grub/misc.h (grub_reboot) + [GRUB_MACHINE_EMU || GRUB_MACHINE_QEMU_MIPS]: Export. + (grub_halt) [__mips__]: Likewise. + 2011-12-13 Vladimir Serbinenko * include/grub/efi/memory.h (grub_machine_mmap_iterate): diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index b4b8f7d28..a9365f6a1 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -60,7 +60,7 @@ grub_util_device_is_mapped (const char *dev); void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result)); void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result)); char * EXPORT_FUNC(xstrdup) (const char *str) __attribute__ ((warn_unused_result)); -char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((warn_unused_result)); +char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((warn_unused_result)); void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...); void EXPORT_FUNC(grub_util_info) (const char *fmt, ...); @@ -82,7 +82,4 @@ int grub_device_mapper_supported (void); char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot); -void EXPORT_FUNC(grub_reboot) (void); - - #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h index d351f17cb..07b08848d 100644 --- a/include/grub/mips/kernel.h +++ b/include/grub/mips/kernel.h @@ -21,10 +21,4 @@ #include -#ifndef ASM_FILE - -void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); - -#endif - #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/mips/qemu_mips/kernel.h b/include/grub/mips/qemu_mips/kernel.h index 1e7e32401..8b8b0149e 100644 --- a/include/grub/mips/qemu_mips/kernel.h +++ b/include/grub/mips/qemu_mips/kernel.h @@ -23,7 +23,6 @@ #ifndef ASM_FILE -void EXPORT_FUNC (grub_halt) (void); void grub_qemu_init_cirrus (void); #endif diff --git a/include/grub/misc.h b/include/grub/misc.h index 0344d528b..46715f77c 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -405,12 +405,18 @@ grub_div_roundup (unsigned int x, unsigned int y) } /* Reboot the machine. */ +#if defined (GRUB_MACHINE_EMU) || defined (GRUB_MACHINE_QEMU_MIPS) +void EXPORT_FUNC(grub_reboot) (void) __attribute__ ((noreturn)); +#else void grub_reboot (void) __attribute__ ((noreturn)); +#endif #ifdef GRUB_MACHINE_PCBIOS /* Halt the system, using APM if possible. If NO_APM is true, don't * use APM even if it is available. */ void grub_halt (int no_apm) __attribute__ ((noreturn)); +#elif defined (__mips__) +void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); #else void grub_halt (void) __attribute__ ((noreturn)); #endif From 6166442083b9d7febca0e03300481f528fe79d51 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 14:57:46 +0100 Subject: [PATCH 612/673] * grub-core/commands/hdparm.c (le16_to_char): Make src and dest uint16 * to ensure alignment. (grub_hdparm_print_identify): Make argument uint16 * to ensure alignment. Ensure tmp alignment. (grub_cmd_hdparm): Ensure buf alignment. * grub-core/disk/ata.c (grub_ata_strncpy): Make src and dest uint16 * to ensure alignment. (grub_ata_dumpinfo): Ensure text alignment. (grub_atapi_identify): Preserve alignment invariant. (grub_ata_identify): Likewise. Use grub_get_unaligned32 when necessary. --- ChangeLog | 13 ++++++++++ grub-core/commands/hdparm.c | 18 +++++++------- grub-core/disk/ata.c | 48 ++++++++++++++++++------------------- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 293b11150..55230a081 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/commands/hdparm.c (le16_to_char): Make src and dest uint16 * + to ensure alignment. + (grub_hdparm_print_identify): Make argument uint16 * to ensure + alignment. Ensure tmp alignment. + (grub_cmd_hdparm): Ensure buf alignment. + * grub-core/disk/ata.c (grub_ata_strncpy): Make src and dest uint16 * + to ensure alignment. + (grub_ata_dumpinfo): Ensure text alignment. + (grub_atapi_identify): Preserve alignment invariant. + (grub_ata_identify): Likewise. Use grub_get_unaligned32 when necessary. + 2011-12-13 Vladimir Serbinenko * include/grub/emu/misc.h (xasprintf): Add missing format attribute. diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index 240170734..85189e8bc 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -165,22 +165,20 @@ grub_hdparm_set_val_cmd (const char * msg, int val, } static const char * -le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes) +le16_to_char (grub_uint16_t *dest, const grub_uint16_t * src16, unsigned bytes) { - grub_uint16_t * dest16 = (grub_uint16_t *) dest; unsigned i; for (i = 0; i < bytes / 2; i++) - dest16[i] = grub_be_to_cpu16 (src16[i]); - return dest; + dest[i] = grub_be_to_cpu16 (src16[i]); + dest[i] = 0; + return (char *) dest; } static void -grub_hdparm_print_identify (const char * idbuf) +grub_hdparm_print_identify (const grub_uint16_t * idw) { - const grub_uint16_t * idw = (const grub_uint16_t *) idbuf; - /* Print identity strings. */ - char tmp[40]; + grub_uint16_t tmp[21]; grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40)); grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8)); grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20)); @@ -377,7 +375,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? /* Print/dump IDENTIFY. */ if (ident || dumpid) { - char buf[GRUB_DISK_SECTOR_SIZE]; + grub_uint16_t buf[GRUB_DISK_SECTOR_SIZE / 2]; if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE, 0, 0, buf, sizeof (buf))) grub_printf ("Cannot read ATA IDENTIFY data\n"); @@ -386,7 +384,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? if (ident) grub_hdparm_print_identify (buf); if (dumpid) - hexdump (0, buf, sizeof (buf)); + hexdump (0, (char *) buf, sizeof (buf)); } } diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 330635f57..50559a815 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -29,29 +29,27 @@ static grub_ata_dev_t grub_ata_dev_list; /* Byteorder has to be changed before strings can be read. */ static void -grub_ata_strncpy (char *dst, char *src, grub_size_t len) +grub_ata_strncpy (grub_uint16_t *dst16, grub_uint16_t *src16, grub_size_t len) { - grub_uint16_t *src16 = (grub_uint16_t *) src; - grub_uint16_t *dst16 = (grub_uint16_t *) dst; unsigned int i; for (i = 0; i < len / 2; i++) *(dst16++) = grub_be_to_cpu16 (*(src16++)); - dst[len] = '\0'; + dst16[i] = 0; } static void -grub_ata_dumpinfo (struct grub_ata *dev, char *info) +grub_ata_dumpinfo (struct grub_ata *dev, grub_uint16_t *info) { - char text[41]; + grub_uint16_t text[21]; /* The device information was read, dump it for debugging. */ - grub_ata_strncpy (text, info + 20, 20); - grub_dprintf ("ata", "Serial: %s\n", text); - grub_ata_strncpy (text, info + 46, 8); - grub_dprintf ("ata", "Firmware: %s\n", text); - grub_ata_strncpy (text, info + 54, 40); - grub_dprintf ("ata", "Model: %s\n", text); + grub_ata_strncpy (text, info + 10, 20); + grub_dprintf ("ata", "Serial: %s\n", (char *) text); + grub_ata_strncpy (text, info + 23, 8); + grub_dprintf ("ata", "Firmware: %s\n", (char *) text); + grub_ata_strncpy (text, info + 27, 40); + grub_dprintf ("ata", "Model: %s\n", (char *) text); if (! dev->atapi) { @@ -65,7 +63,7 @@ static grub_err_t grub_atapi_identify (struct grub_ata *dev) { struct grub_disk_ata_pass_through_parms parms; - char *info; + grub_uint16_t *info; grub_err_t err; info = grub_malloc (GRUB_DISK_SECTOR_SIZE); @@ -105,17 +103,19 @@ static grub_err_t grub_ata_identify (struct grub_ata *dev) { struct grub_disk_ata_pass_through_parms parms; - char *info; + grub_uint64_t *info64; + grub_uint32_t *info32; grub_uint16_t *info16; grub_err_t err; - info = grub_malloc (GRUB_DISK_SECTOR_SIZE); - if (! info) + info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE); + info32 = (grub_uint32_t *) info64; + info16 = (grub_uint16_t *) info64; + if (! info16) return grub_errno; - info16 = (grub_uint16_t *) info; grub_memset (&parms, 0, sizeof (parms)); - parms.buffer = info; + parms.buffer = info16; parms.size = GRUB_DISK_SECTOR_SIZE; parms.taskfile.disk = 0xE0; @@ -126,7 +126,7 @@ grub_ata_identify (struct grub_ata *dev) if (err || parms.size != GRUB_DISK_SECTOR_SIZE) { grub_uint8_t sts = parms.taskfile.status; - grub_free (info); + grub_free (info16); grub_errno = GRUB_ERR_NONE; if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR @@ -167,14 +167,14 @@ grub_ata_identify (struct grub_ata *dev) /* Determine the amount of sectors. */ if (dev->addr != GRUB_ATA_LBA48) - dev->size = grub_le_to_cpu32(*((grub_uint32_t *) &info16[60])); + dev->size = grub_le_to_cpu32 (info32[30]); else - dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100])); + dev->size = grub_le_to_cpu64 (info64[25]); if (info16[106] & (1 << 12)) { grub_uint32_t secsize; - secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117])); + secsize = grub_le_to_cpu32 (grub_get_unaligned32 (&info16[117])); if (secsize & (secsize - 1) || !secsize || secsize > 1048576) secsize = 256; @@ -191,9 +191,9 @@ grub_ata_identify (struct grub_ata *dev) dev->heads = info16[3]; dev->sectors_per_track = info16[6]; - grub_ata_dumpinfo (dev, info); + grub_ata_dumpinfo (dev, info16); - grub_free(info); + grub_free (info16); return 0; } From d1c501ee949d64bea8fa54ab52a1ce044317c86d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 15:03:06 +0100 Subject: [PATCH 613/673] * include/grub/net.h (grub_net_network_level_interfaces): Remove redundant declaration. (FOR_NET_NETWORK_LEVEL_INTERFACES): Move to appropriate place. --- ChangeLog | 6 ++++++ include/grub/net.h | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 55230a081..74bc77345 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/net.h (grub_net_network_level_interfaces): Remove + redundant declaration. + (FOR_NET_NETWORK_LEVEL_INTERFACES): Move to appropriate place. + 2011-12-13 Vladimir Serbinenko * grub-core/commands/hdparm.c (le16_to_char): Make src and dest uint16 * diff --git a/include/grub/net.h b/include/grub/net.h index 03af637b5..2ec89e191 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -302,6 +302,7 @@ grub_net_add_addr (const char *name, grub_net_interface_flags_t flags); extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) extern grub_net_app_level_t grub_net_app_level_list; @@ -423,9 +424,6 @@ void grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf); -extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) - #define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next) void From 2019d09ef08866e4f26adaac8659ca6dc5fab321 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 15:04:07 +0100 Subject: [PATCH 614/673] * include/grub/i386/qemu/memory.h (grub_machine_mmap_init): Remove redundant declaration. --- ChangeLog | 5 +++++ include/grub/i386/qemu/memory.h | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 74bc77345..a2a8609ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/i386/qemu/memory.h (grub_machine_mmap_init): Remove + redundant declaration. + 2011-12-13 Vladimir Serbinenko * include/grub/net.h (grub_net_network_level_interfaces): Remove diff --git a/include/grub/i386/qemu/memory.h b/include/grub/i386/qemu/memory.h index 2003e4934..f152cd782 100644 --- a/include/grub/i386/qemu/memory.h +++ b/include/grub/i386/qemu/memory.h @@ -33,10 +33,4 @@ #define GRUB_MEMORY_MACHINE_UPPER_START 0x100000 /* 1 MiB */ #define GRUB_MEMORY_MACHINE_LOWER_SIZE GRUB_MEMORY_MACHINE_UPPER_START -#ifndef ASM_FILE - -void grub_machine_mmap_init (void); - -#endif - #endif /* ! _GRUB_MEMORY_MACHINE_HEADER */ From 02a2bf83840959729f45895bae5452654f9cfbc5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 15:13:51 +0100 Subject: [PATCH 615/673] Add noreturn attributes and remove unreachable code. * grub-core/bus/cs5536.c (grub_cs5536_smbus_wait): Remove unreachable code. * grub-core/commands/halt.c (grub_cmd_halt): Remove unreachable code. Mark as noreturn. * grub-core/commands/minicmd.c (grub_mini_cmd_exit): Likewise. * grub-core/commands/reboot.c (grub_cmd_reboot): Likewise. * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Remove unreachable code. * grub-core/kern/main.c (grub_main): Mark as noreturn. * grub-core/kern/rescue_reader.c (grub_rescue_run): Likewise. * grub-core/lib/posix_wrap/stdlib.h (abort): Likewise. * grub-core/normal/menu.c (run_menu): Remove unreachable code. * include/grub/kernel.h (grub_main): Mark as noreturn. * include/grub/reader.h (grub_rescue_run): Likewise. --- ChangeLog | 19 +++++++++++++++++++ grub-core/bus/cs5536.c | 2 -- grub-core/commands/halt.c | 3 +-- grub-core/commands/minicmd.c | 4 ++-- grub-core/commands/reboot.c | 3 +-- grub-core/disk/efi/efidisk.c | 2 -- grub-core/kern/main.c | 2 +- grub-core/kern/rescue_reader.c | 2 +- grub-core/lib/posix_wrap/stdlib.h | 2 +- grub-core/normal/menu.c | 1 - include/grub/kernel.h | 2 +- include/grub/reader.h | 2 +- 12 files changed, 28 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index a2a8609ab..f62cc0ba6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-12-13 Vladimir Serbinenko + + Add noreturn attributes and remove unreachable code. + + * grub-core/bus/cs5536.c (grub_cs5536_smbus_wait): Remove unreachable + code. + * grub-core/commands/halt.c (grub_cmd_halt): Remove unreachable + code. Mark as noreturn. + * grub-core/commands/minicmd.c (grub_mini_cmd_exit): Likewise. + * grub-core/commands/reboot.c (grub_cmd_reboot): Likewise. + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Remove + unreachable code. + * grub-core/kern/main.c (grub_main): Mark as noreturn. + * grub-core/kern/rescue_reader.c (grub_rescue_run): Likewise. + * grub-core/lib/posix_wrap/stdlib.h (abort): Likewise. + * grub-core/normal/menu.c (run_menu): Remove unreachable code. + * include/grub/kernel.h (grub_main): Mark as noreturn. + * include/grub/reader.h (grub_rescue_run): Likewise. + 2011-12-13 Vladimir Serbinenko * include/grub/i386/qemu/memory.h (grub_machine_mmap_init): Remove diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 1aae7852e..9e7796ea1 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -97,8 +97,6 @@ grub_cs5536_smbus_wait (grub_port_t smbbase) if (grub_get_time_ms () > start + 40) return grub_error (GRUB_ERR_IO, "SM stalled"); } - - return GRUB_ERR_NONE; } grub_err_t diff --git a/grub-core/commands/halt.c b/grub-core/commands/halt.c index 317f7753f..f8596ecdc 100644 --- a/grub-core/commands/halt.c +++ b/grub-core/commands/halt.c @@ -24,13 +24,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t __attribute__ ((noreturn)) grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { grub_halt (); - return 0; } static grub_command_t cmd; diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 1bb0147df..f436cd55d 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -165,13 +165,13 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), } /* exit */ -static grub_err_t +static grub_err_t __attribute__ ((noreturn)) grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { grub_exit (); - return 0; + /* Not reached. */ } static grub_command_t cmd_cat, cmd_help; diff --git a/grub-core/commands/reboot.c b/grub-core/commands/reboot.c index 8e18083c0..46d364c99 100644 --- a/grub-core/commands/reboot.c +++ b/grub-core/commands/reboot.c @@ -24,13 +24,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t __attribute__ ((noreturn)) grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { grub_reboot (); - return 0; } static grub_command_t cmd; diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 0baeb8e4b..bbb8c93b1 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -791,6 +791,4 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) grub_disk_close (parent); return device_name; } - - return 0; } diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index bf2789860..185230c5c 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -190,7 +190,7 @@ grub_load_normal_mode (void) } /* The main routine. */ -void +void __attribute__ ((noreturn)) grub_main (void) { /* First of all, initialize the machine. */ diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c index a81008579..4587b944f 100644 --- a/grub-core/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c @@ -74,7 +74,7 @@ grub_rescue_read_line (char **line, int cont) return 0; } -void +void __attribute__ ((noreturn)) grub_rescue_run (void) { grub_printf ("Entering rescue mode...\n"); diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h index 4c725f6e2..b35e21bb8 100644 --- a/grub-core/lib/posix_wrap/stdlib.h +++ b/grub-core/lib/posix_wrap/stdlib.h @@ -46,7 +46,7 @@ realloc (void *ptr, grub_size_t size) return grub_realloc (ptr, size); } -static inline void +static inline void __attribute__ ((noreturn)) abort (void) { grub_abort (); diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index b75e9f523..ae8e3e681 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -666,7 +666,6 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) } /* Never reach here. */ - return -1; } /* Callback invoked immediately before a menu entry is executed. */ diff --git a/include/grub/kernel.h b/include/grub/kernel.h index f9fc817db..f587de514 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -82,7 +82,7 @@ extern grub_addr_t EXPORT_VAR (grub_modbase); grub_addr_t grub_modules_get_end (void); /* The start point of the C code. */ -void grub_main (void); +void grub_main (void) __attribute__ ((noreturn)); /* The machine-specific initialization. This must initialize memory. */ void grub_machine_init (void); diff --git a/include/grub/reader.h b/include/grub/reader.h index fd72a3252..cd92df8f2 100644 --- a/include/grub/reader.h +++ b/include/grub/reader.h @@ -24,6 +24,6 @@ typedef grub_err_t (*grub_reader_getline_t) (char **, int); -void grub_rescue_run (void); +void grub_rescue_run (void) __attribute__ ((noreturn)); #endif /* ! GRUB_READER_HEADER */ From b70b6d11073ed0f10a04fb007c38cd896cea92b6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 15:55:36 +0100 Subject: [PATCH 616/673] * grub-core/disk/pata.c (grub_pata_pio_read): Handle unaligned buffer. (grub_pata_pio_write): Likewise. --- ChangeLog | 5 +++++ grub-core/disk/pata.c | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index f62cc0ba6..06572f7a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/disk/pata.c (grub_pata_pio_read): Handle unaligned buffer. + (grub_pata_pio_write): Likewise. + 2011-12-13 Vladimir Serbinenko Add noreturn attributes and remove unreachable code. diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index c54fe91ab..ff76cc1fb 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -116,12 +116,13 @@ grub_pata_wait (void) static void grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) { - grub_uint16_t *buf16 = (grub_uint16_t *) buf; unsigned int i; /* Read in the data, word by word. */ for (i = 0; i < size / 2; i++) - buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); + grub_set_unaligned16 (buf + 2 * i, + grub_le_to_cpu16 (grub_inw(dev->ioaddress + + GRUB_ATA_REG_DATA))); if (size & 1) buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); @@ -130,12 +131,11 @@ grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) static void grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size) { - grub_uint16_t *buf16 = (grub_uint16_t *) buf; unsigned int i; /* Write the data, word by word. */ for (i = 0; i < size / 2; i++) - grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); + grub_outw(grub_cpu_to_le16 (grub_get_unaligned16 (buf + 2 * i)), dev->ioaddress + GRUB_ATA_REG_DATA); } /* ATA pass through support, used by hdparm.mod. */ From c2e777777b6c4d4c0d37fc2d005e7dc47d0a6077 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 16:20:25 +0100 Subject: [PATCH 617/673] * grub-core/loader/i386/xnu.c (grub_xnu_devprop_remove_property): Fix incorrect pointer. --- ChangeLog | 5 +++++ grub-core/loader/i386/xnu.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 06572f7a9..0ef874d70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/loader/i386/xnu.c (grub_xnu_devprop_remove_property): Fix + incorrect pointer. + 2011-12-13 Vladimir Serbinenko * grub-core/disk/pata.c (grub_pata_pio_read): Handle unaligned buffer. diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index 1df8dc4c0..4d3678ea1 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -226,7 +226,7 @@ grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor *dev char *name) { struct property_descriptor *prop; - prop = grub_named_list_find (GRUB_AS_NAMED_LIST_P (&dev->properties), name); + prop = grub_named_list_find (GRUB_AS_NAMED_LIST (dev->properties), name); if (!prop) return GRUB_ERR_NONE; From 0c6087a8c9d0b0ef4ad79829fe1ec58997f77166 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 16:22:44 +0100 Subject: [PATCH 618/673] * grub-core/loader/multiboot_mbi2.c (grub_multiboot_add_elfsyms): Reserve alignment invariants. (grub_multiboot_load): Likewise. (retrieve_video_parameters): Likewise. (grub_multiboot_make_mbi): Likewise. --- ChangeLog | 8 ++++ grub-core/loader/multiboot_mbi2.c | 78 ++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ef874d70..fd260b57e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_add_elfsyms): + Reserve alignment invariants. + (grub_multiboot_load): Likewise. + (retrieve_video_parameters): Likewise. + (grub_multiboot_make_mbi): Likewise. + 2011-12-13 Vladimir Serbinenko * grub-core/loader/i386/xnu.c (grub_xnu_devprop_remove_property): Fix diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 05f581bb6..9a81afe8e 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -78,7 +78,7 @@ grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, grub_err_t grub_multiboot_load (grub_file_t file) { - char *buffer; + grub_properly_aligned_t *buffer; grub_ssize_t len; struct multiboot_header *header; grub_err_t err; @@ -101,11 +101,13 @@ grub_multiboot_load (grub_file_t file) return grub_error (GRUB_ERR_BAD_OS, "file too small"); } + COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0); + /* Look for the multiboot header in the buffer. The header should be at least 12 bytes and aligned on a 4-byte boundary. */ for (header = (struct multiboot_header *) buffer; - ((char *) header <= buffer + len - 12) || (header = 0); - header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN)) + ((char *) header <= (char *) buffer + len - 12) || (header = 0); + header = (struct multiboot_header *) ((grub_uint32_t *) header + MULTIBOOT_HEADER_ALIGN / 4)) { if (header->magic == MULTIBOOT_HEADER_MAGIC && !(header->magic + header->architecture @@ -120,9 +122,11 @@ grub_multiboot_load (grub_file_t file) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found"); } + COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % 4 == 0); + for (tag = (struct multiboot_header_tag *) (header + 1); tag->type != MULTIBOOT_TAG_TYPE_END; - tag = (struct multiboot_header_tag *) ((char *) tag + tag->size)) + tag = (struct multiboot_header_tag *) ((grub_uint32_t *) tag + ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) / 4)) switch (tag->type) { case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST: @@ -208,7 +212,7 @@ grub_multiboot_load (grub_file_t file) if (addr_tag) { - int offset = ((char *) header - buffer - + int offset = ((char *) header - (char *) buffer - (addr_tag->header_addr - addr_tag->load_addr)); int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset : addr_tag->load_end_addr - addr_tag->load_addr); @@ -415,7 +419,7 @@ fill_vbe_tag (struct multiboot_tag_vbe *tag) #endif static grub_err_t -retrieve_video_parameters (grub_uint8_t **ptrorig) +retrieve_video_parameters (grub_properly_aligned_t **ptrorig) { grub_err_t err; struct grub_video_mode_info mode_info; @@ -493,7 +497,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT; tag->common.size = sizeof (tag->common); tag->common.reserved = 0; - *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN); + *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } return GRUB_ERR_NONE; } @@ -508,7 +513,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) fill_vbe_tag (tag_vbe); - *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN); + *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #endif @@ -559,7 +565,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6; } - *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN); + *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); return GRUB_ERR_NONE; } @@ -567,14 +574,16 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) grub_err_t grub_multiboot_make_mbi (grub_uint32_t *target) { - grub_uint8_t *ptrorig; - grub_uint8_t *mbistart; + grub_properly_aligned_t *ptrorig; + grub_properly_aligned_t *mbistart; grub_err_t err; grub_size_t bufsize; grub_relocator_chunk_t ch; bufsize = grub_multiboot_get_mbi_size (); + COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0); + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0, 0xffffffff - bufsize, bufsize, MULTIBOOT_TAG_ALIGN, @@ -592,14 +601,19 @@ grub_multiboot_make_mbi (grub_uint32_t *target) #endif mbistart = ptrorig; - ptrorig += 2 * sizeof (grub_uint32_t); + COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t)) + % sizeof (grub_properly_aligned_t) == 0); + COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN + % sizeof (grub_properly_aligned_t) == 0); + ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t); { struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_CMDLINE; tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; grub_memcpy (tag->string, cmdline, cmdline_size); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -607,7 +621,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME; tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING); grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING)); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #ifdef GRUB_MACHINE_PCBIOS @@ -630,7 +645,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->cseg_16_len = info.cseg_16_len; tag->version = info.version; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } #endif @@ -648,14 +664,16 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->mod_start = cur->start; tag->mod_end = tag->mod_start + cur->size; grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } { struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig; grub_fill_multiboot_mmap (tag); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -668,7 +686,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->num = elf_sec_num; tag->entsize = elf_sec_entsize; tag->shndx = elf_sec_shstrndx; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -680,7 +699,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) /* Convert from bytes to kilobytes. */ tag->mem_lower = grub_mmap_get_lower () / 1024; tag->mem_upper = grub_mmap_get_upper () / 1024; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } if (bootdev_set) @@ -693,7 +713,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->biosdev = biosdev; tag->slice = slice; tag->part = part; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -711,7 +732,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_EFI64; tag->size = sizeof (*tag); tag->pointer = (grub_addr_t) grub_efi_system_table; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #endif @@ -721,7 +743,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_EFI32; tag->size = sizeof (*tag); tag->pointer = (grub_addr_t) grub_efi_system_table; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #endif @@ -735,7 +758,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD; tag->size = sizeof (*tag) + sizeof (*a); grub_memcpy (tag->rsdp, a, sizeof (*a)); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } @@ -748,7 +772,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW; tag->size = sizeof (*tag) + a->length; grub_memcpy (tag->rsdp, a, a->length); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } #endif @@ -757,10 +782,11 @@ grub_multiboot_make_mbi (grub_uint32_t *target) struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_END; tag->size = sizeof (struct multiboot_tag); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } - ((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart; + ((grub_uint32_t *) mbistart)[0] = (char *) ptrorig - (char *) mbistart; ((grub_uint32_t *) mbistart)[1] = 0; return GRUB_ERR_NONE; From 30dd48c2b02a8808d1c164010d3cf28c793681d7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 16:29:15 +0100 Subject: [PATCH 619/673] * include/grub/kernel.h (FOR_MODULES): Preserve alignment invariants. --- ChangeLog | 4 ++++ include/grub/kernel.h | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index fd260b57e..574f63cb4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-13 Vladimir Serbinenko + + * include/grub/kernel.h (FOR_MODULES): Preserve alignment invariants. + 2011-12-13 Vladimir Serbinenko * grub-core/loader/multiboot_mbi2.c (grub_multiboot_add_elfsyms): diff --git a/include/grub/kernel.h b/include/grub/kernel.h index f587de514..c9a549675 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -71,13 +71,15 @@ struct grub_module_info64 extern grub_addr_t EXPORT_VAR (grub_modbase); -#define FOR_MODULES(var) for (\ - var = grub_modbase ? (struct grub_module_header *) \ +#define FOR_MODULES(var) for (var = grub_modbase ? (struct grub_module_header *) \ (grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\ var && (grub_addr_t) var \ < (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \ var = (struct grub_module_header *) \ - ((char *) var + ((struct grub_module_header *) var)->size)) + ((grub_uint32_t *) var \ + + ((((struct grub_module_header *) var)->size \ + + sizeof (grub_uint32_t) - 1) \ + / sizeof (grub_uint32_t)))) grub_addr_t grub_modules_get_end (void); From dc71319397a1e24763bea5495e89f56237ce2185 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 16:33:27 +0100 Subject: [PATCH 620/673] * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Force inlining of add_part to workaround compiler bug. --- ChangeLog | 5 +++++ grub-core/fs/iso9660.c | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 574f63cb4..8f30b557a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Force inlining of + add_part to workaround compiler bug. + 2011-12-13 Vladimir Serbinenko * include/grub/kernel.h (FOR_MODULES): Preserve alignment invariants. diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 7b1e32f7c..048c361a6 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -533,10 +533,12 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, grub_off_t len; char *symlink = 0; - auto void add_part (const char *part, int len); - /* Extend the symlink. */ - void add_part (const char *part, int len2) + auto inline void __attribute__ ((always_inline)) add_part (const char *part, + int len2); + + auto inline void __attribute__ ((always_inline)) add_part (const char *part, + int len2) { int size = symlink ? grub_strlen (symlink) : 0; From 9b4baaa4ee24a54d354f64cf294dd4b9a35947bd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 16:35:12 +0100 Subject: [PATCH 621/673] * grub-core/fs/iso9660.c (grub_iso9660_convert_string): Make first argument a u8 pointer. All users updated. Handle unaligned buffers. --- ChangeLog | 6 ++++++ grub-core/fs/iso9660.c | 14 +++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8f30b557a..833d80a8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_convert_string): Make first + argument a u8 pointer. All users updated. + Handle unaligned buffers. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Force inlining of diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 048c361a6..fb5da2aa7 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -331,19 +331,20 @@ grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, } static char * -grub_iso9660_convert_string (grub_uint16_t *us, int len) +grub_iso9660_convert_string (grub_uint8_t *us, int len) { char *p; int i; + grub_uint16_t t[len]; - p = grub_malloc (len * 4 + 1); + p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! p) return p; for (i=0; i> 1); + ((grub_uint8_t *) oldname, dirent.namelen >> 1); semicolon = grub_strrchr (filename, ';'); if (semicolon) @@ -978,8 +979,7 @@ grub_iso9660_label (grub_device_t device, char **label) if (data) { if (data->joliet) - *label = grub_iso9660_convert_string - ((grub_uint16_t *) &data->voldesc.volname, 16); + *label = grub_iso9660_convert_string (data->voldesc.volname, 16); else *label = grub_strndup ((char *) data->voldesc.volname, 32); if (*label) From e59b7857f88e3aac8a9a8e516aa9bf2079000ceb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 19:53:57 +0100 Subject: [PATCH 622/673] * grub-core/commands/videotest.c (grub_cmd_videotest): Check that allocation succeeded. --- ChangeLog | 5 +++++ grub-core/commands/videotest.c | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index 833d80a8a..7ea8d1001 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/commands/videotest.c (grub_cmd_videotest): Check that + allocation succeeded. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/iso9660.c (grub_iso9660_convert_string): Make first diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index dc7a6485f..11949a6fc 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -74,6 +74,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_create_render_target (&text_layer, width, height, GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_ALPHA); + if (!text_layer) + goto fail; grub_video_set_active_render_target (text_layer); @@ -191,6 +193,11 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_errno = GRUB_ERR_NONE; return grub_errno; + + fail: + grub_video_delete_render_target (text_layer); + grub_video_restore (); + return grub_errno; } static grub_command_t cmd; From fd261d7300a25e4f4de9e2016147ee686d455f29 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 19:55:27 +0100 Subject: [PATCH 623/673] * grub-core/kern/misc.c (grub_vsnprintf_real): Fix fmt2 parsing. --- ChangeLog | 4 ++++ grub-core/kern/misc.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7ea8d1001..53d151b62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Fix fmt2 parsing. + 2011-12-13 Vladimir Serbinenko * grub-core/commands/videotest.c (grub_cmd_videotest): Check that diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 128139dc8..0d2ae4bd6 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -749,6 +749,12 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a while (*fmt && grub_isdigit (*fmt)) fmt++; + if (*fmt && *fmt =='.') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + p = fmt; if (*fmt && *fmt == '$') From ace96609b6c5460202f482342f6b3d039a6d4dbb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 19:56:50 +0100 Subject: [PATCH 624/673] * grub-core/kern/sparc64/dl.c (grub_arch_dl_relocate_symbols): Support HH22 and HM10 relocations. --- ChangeLog | 5 +++++ grub-core/kern/sparc64/dl.c | 9 ++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 53d151b62..784b4a25e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/sparc64/dl.c (grub_arch_dl_relocate_symbols): Support + HH22 and HM10 relocations. + 2011-12-13 Vladimir Serbinenko * grub-core/kern/misc.c (grub_vsnprintf_real): Fix fmt2 parsing. diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c index 7b6266cac..e1be5d9ec 100644 --- a/grub-core/kern/sparc64/dl.c +++ b/grub-core/kern/sparc64/dl.c @@ -111,10 +111,13 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (((grub_int32_t) ((value - (Elf_Addr) addr) >> 2)) & 0x3FFFFFFF); break; + case R_SPARC_HH22: /* 9 V-imm22 */ + *addr = (*addr & 0xFFC00000) | ((value >> 42) & 0x3FFFFF); + break; + case R_SPARC_HM10: /* 12 T-simm13 */ + *addr = (*addr & 0xFFFFFC00) | ((value >> 32) & 0x3FF); + break; case R_SPARC_HI22: /* 9 V-imm22 */ - if (((grub_int32_t) value) & 0xFF00000000) - return grub_error (GRUB_ERR_BAD_MODULE, - "high address out of 22 bits range"); *addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF); break; case R_SPARC_LO10: /* 12 T-simm13 */ From 12e9d4d15273af048f333cef72e0944689a0e148 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 20:07:33 +0100 Subject: [PATCH 625/673] Fix video on platforms where unaligned access is forbidden. Make several optimisations while on it. * grub-core/video/fb/fbblit.c (grub_video_fbblit_replace_directN): Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. (grub_video_fbblit_replace_32bit_1bit): Likewise. (grub_video_fbblit_replace_24bit_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: Disable. (grub_video_fbblit_replace_16bit_1bit): Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. (grub_video_fbblit_replace_8bit_1bit): Likewise. (grub_video_fbblit_replace_BGRX8888_RGBX8888): Likewise. (grub_video_fbblit_replace_BGRX8888_RGB888): Likewise. (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. (grub_video_fbblit_replace_BGR888_RGB888): Likewise. (grub_video_fbblit_replace_RGBX8888_RGB88): Likewise. (grub_video_fbblit_replace_RGB888_RGBX888): Likewise. (grub_video_fbblit_replace_RGB888_RGBX8888): Likewise. (grub_video_fbblit_replace_index_RGBX8888): Likewise. (grub_video_fbblit_replace_index_RGB888): Likewise. (grub_video_fbblit_blend_BGRA8888_RGBA8888): Likewise. (grub_video_fbblit_blend_BGR888_RGBA8888): Likewise. (grub_video_fbblit_blend_RGBA8888_RGBA8888): Likewise. (grub_video_fbblit_blend_RGB888_RGBA8888): Likewise. (grub_video_fbblit_blend_index_RGBA8888): Likewise. (grub_video_fbblit_blend_XXXA8888_1bit): Likewise. (grub_video_fbblit_blend_XXX888_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: Disable. (grub_video_fbblit_blend_XXX565_1bit): Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. * grub-core/video/fb/fbfill.c (grub_video_fbfill_direct32): Likewise. * grub-core/video/fb/fbutil.c (grub_video_fb_get_video_ptr): Return void *. * grub-core/video/fb/video_fb.c (common_blitter) [!GRUB_HAVE_UNALIGNED_ACCESS]: Skip disabled blitters. (grub_video_fb_create_render_target_from_pointer) [!GRUB_HAVE_UNALIGNED_ACCESS]: Check alignment. * include/grub/fbutil.h (grub_video_fb_get_video_ptr): Return void *. * include/grub/i386/types.h (GRUB_HAVE_UNALIGNED_ACCESS): New definition. * include/grub/x86_64/types.h (GRUB_HAVE_UNALIGNED_ACCESS): Likewise. --- ChangeLog | 45 ++++++++ grub-core/video/fb/fbblit.c | 204 +++++++++++++++++++++------------- grub-core/video/fb/fbfill.c | 10 +- grub-core/video/fb/fbutil.c | 2 +- grub-core/video/fb/video_fb.c | 13 +++ include/grub/fbutil.h | 13 ++- include/grub/i386/types.h | 2 + include/grub/x86_64/types.h | 2 + 8 files changed, 206 insertions(+), 85 deletions(-) diff --git a/ChangeLog b/ChangeLog index 784b4a25e..2134b481a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +2011-12-13 Vladimir Serbinenko + + Fix video on platforms where unaligned access is forbidden. + Make several optimisations while on it. + + * grub-core/video/fb/fbblit.c (grub_video_fbblit_replace_directN): + Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. + (grub_video_fbblit_replace_32bit_1bit): Likewise. + (grub_video_fbblit_replace_24bit_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: + Disable. + (grub_video_fbblit_replace_16bit_1bit): + Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. + (grub_video_fbblit_replace_8bit_1bit): Likewise. + (grub_video_fbblit_replace_BGRX8888_RGBX8888): Likewise. + (grub_video_fbblit_replace_BGRX8888_RGB888): Likewise. + (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. + (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. + (grub_video_fbblit_replace_BGR888_RGB888): Likewise. + (grub_video_fbblit_replace_RGBX8888_RGB88): Likewise. + (grub_video_fbblit_replace_RGB888_RGBX888): Likewise. + (grub_video_fbblit_replace_RGB888_RGBX8888): Likewise. + (grub_video_fbblit_replace_index_RGBX8888): Likewise. + (grub_video_fbblit_replace_index_RGB888): Likewise. + (grub_video_fbblit_blend_BGRA8888_RGBA8888): Likewise. + (grub_video_fbblit_blend_BGR888_RGBA8888): Likewise. + (grub_video_fbblit_blend_RGBA8888_RGBA8888): Likewise. + (grub_video_fbblit_blend_RGB888_RGBA8888): Likewise. + (grub_video_fbblit_blend_index_RGBA8888): Likewise. + (grub_video_fbblit_blend_XXXA8888_1bit): Likewise. + (grub_video_fbblit_blend_XXX888_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: + Disable. + (grub_video_fbblit_blend_XXX565_1bit): + Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. + * grub-core/video/fb/fbfill.c (grub_video_fbfill_direct32): Likewise. + * grub-core/video/fb/fbutil.c (grub_video_fb_get_video_ptr): Return + void *. + * grub-core/video/fb/video_fb.c (common_blitter) + [!GRUB_HAVE_UNALIGNED_ACCESS]: Skip disabled blitters. + (grub_video_fb_create_render_target_from_pointer) + [!GRUB_HAVE_UNALIGNED_ACCESS]: Check alignment. + * include/grub/fbutil.h (grub_video_fb_get_video_ptr): Return void *. + * include/grub/i386/types.h (GRUB_HAVE_UNALIGNED_ACCESS): New + definition. + * include/grub/x86_64/types.h (GRUB_HAVE_UNALIGNED_ACCESS): Likewise. + 2011-12-13 Vladimir Serbinenko * grub-core/kern/sparc64/dl.c (grub_arch_dl_relocate_symbols): Support diff --git a/grub-core/video/fb/fbblit.c b/grub-core/video/fb/fbblit.c index 15797be97..4d262d710 100644 --- a/grub-core/video/fb/fbblit.c +++ b/grub-core/video/fb/fbblit.c @@ -80,13 +80,14 @@ grub_video_fbblit_replace_directN (struct grub_video_fbblit_info *dst, int bpp; bpp = src->mode_info->bytes_per_pixel; + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - grub_memmove (dstptr, srcptr, width * bpp); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, src->mode_info->pitch); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dst->mode_info->pitch); } } @@ -101,7 +102,7 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint32_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -117,7 +118,7 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -134,9 +135,9 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, for (i = 0; i < width; i++) { if (*srcptr & srcmask) - *(grub_uint32_t *) dstptr = fgcolor; + *dstptr = fgcolor; else - *(grub_uint32_t *) dstptr = bgcolor; + *dstptr = bgcolor; srcmask >>= 1; if (!srcmask) { @@ -144,7 +145,7 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 4; + dstptr++; } srcptr += srcrowskipbyte; @@ -155,11 +156,12 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } +#ifdef GRUB_HAVE_UNALIGNED_ACCESS /* Optimized replacing blitter for 1-bit to 24-bit. */ void grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst, @@ -187,7 +189,7 @@ grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -247,6 +249,7 @@ grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst, dstptr += dstrowskip; } } +#endif /* Optimized replacing blitter for 1-bit to 16-bit. */ void @@ -259,7 +262,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint16_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -275,7 +278,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -292,9 +295,9 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, for (i = 0; i < width; i++) { if (*srcptr & srcmask) - *(grub_uint16_t *) dstptr = fgcolor; + *dstptr = fgcolor; else - *(grub_uint16_t *) dstptr = bgcolor; + *dstptr = bgcolor; srcmask >>= 1; if (!srcmask) { @@ -302,7 +305,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 2; + dstptr++; } srcptr += srcrowskipbyte; @@ -313,7 +316,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -344,7 +347,7 @@ grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -361,9 +364,9 @@ grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst, for (i = 0; i < width; i++) { if (*srcptr & srcmask) - *(grub_uint8_t *) dstptr = fgcolor; + *dstptr = fgcolor; else - *(grub_uint8_t *) dstptr = bgcolor; + *dstptr = bgcolor; srcmask >>= 1; if (!srcmask) { @@ -406,8 +409,8 @@ grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -449,8 +452,8 @@ grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -493,8 +496,8 @@ grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -516,7 +519,7 @@ grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst, *dstptr++ = sr; } - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); dstptr += dstrowskip; } } @@ -541,8 +544,8 @@ grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -578,12 +581,16 @@ grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 3 * width; + dstrowskip = dst->mode_info->pitch - 4 * width; + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { sr = *srcptr++; @@ -595,6 +602,8 @@ grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst, *dstptr++ = color; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -614,12 +623,16 @@ grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - 3 * width; for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -632,6 +645,8 @@ grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst, *dstptr++ = sg; *dstptr++ = sb; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -651,12 +666,17 @@ grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -668,6 +688,8 @@ grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst, color = grub_video_fb_map_rgb(sr, sg, sb); *dstptr++ = color & 0xFF; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -687,12 +709,17 @@ grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 3 * width; + dstrowskip = dst->mode_info->pitch - width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { sr = *srcptr++; @@ -703,6 +730,8 @@ grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst, *dstptr++ = color & 0xFF; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -787,8 +816,8 @@ grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -843,8 +872,8 @@ grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = color; } - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); - dstptr = (grub_uint32_t *) (((grub_uint8_t *) dstptr) + dstrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -868,8 +897,8 @@ grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -924,7 +953,7 @@ grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = dr; } - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); dstptr += dstrowskip; } } @@ -949,12 +978,17 @@ grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst, unsigned int dr; unsigned int dg; unsigned int db; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - 4 * width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -991,6 +1025,8 @@ grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = color; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -1014,12 +1050,17 @@ grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst, unsigned int dr; unsigned int dg; unsigned int db; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - 3 * width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -1057,6 +1098,8 @@ grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = dg; *dstptr++ = db; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -1081,12 +1124,17 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst, unsigned char dg; unsigned char db; unsigned char da; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -1120,6 +1168,8 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = color & 0xFF; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -1134,7 +1184,7 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint32_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -1150,7 +1200,7 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -1181,23 +1231,22 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, } if (a == 255) - *(grub_uint32_t *) dstptr = color; + *dstptr = color; else if (a != 0) { grub_uint8_t s1 = (color >> 0) & 0xFF; grub_uint8_t s2 = (color >> 8) & 0xFF; grub_uint8_t s3 = (color >> 16) & 0xFF; - grub_uint8_t d1 = (*(grub_uint32_t *) dstptr >> 0) & 0xFF; - grub_uint8_t d2 = (*(grub_uint32_t *) dstptr >> 8) & 0xFF; - grub_uint8_t d3 = (*(grub_uint32_t *) dstptr >> 16) & 0xFF; + grub_uint8_t d1 = (*dstptr >> 0) & 0xFF; + grub_uint8_t d2 = (*dstptr >> 8) & 0xFF; + grub_uint8_t d3 = (*dstptr >> 16) & 0xFF; d1 = (d1 * (255 - a) + s1 * a) / 255; d2 = (d2 * (255 - a) + s2 * a) / 255; d3 = (d3 * (255 - a) + s3 * a) / 255; - *(grub_uint32_t *) dstptr = (a << 24) | (d3 << 16) | (d2 << 8) - | d1; + *dstptr = (a << 24) | (d3 << 16) | (d2 << 8) | d1; } srcmask >>= 1; @@ -1207,7 +1256,7 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 4; + dstptr++; } srcptr += srcrowskipbyte; @@ -1218,11 +1267,12 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } /* Optimized blending blitter for 1-bit to XXX888. */ +#ifdef GRUB_HAVE_UNALIGNED_ACCESS void grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst, struct grub_video_fbblit_info *src, @@ -1249,7 +1299,7 @@ grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -1320,6 +1370,7 @@ grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst, dstptr += dstrowskip; } } +#endif /* Optimized blending blitter for 1-bit to XXX888. */ void @@ -1332,7 +1383,7 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint16_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -1348,7 +1399,7 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -1378,23 +1429,22 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, } if (a == 255) - *(grub_uint16_t *) dstptr = color; + *dstptr = color; else if (a != 0) { grub_uint8_t s1 = (color >> 0) & 0x1F; grub_uint8_t s2 = (color >> 5) & 0x3F; grub_uint8_t s3 = (color >> 11) & 0x1F; - grub_uint8_t d1 = (*(grub_uint16_t *) dstptr >> 0) & 0x1F; - grub_uint8_t d2 = (*(grub_uint16_t *) dstptr >> 5) & 0x3F; - grub_uint8_t d3 = (*(grub_uint16_t *) dstptr >> 11) & 0x1F; + grub_uint8_t d1 = (*dstptr >> 0) & 0x1F; + grub_uint8_t d2 = (*dstptr >> 5) & 0x3F; + grub_uint8_t d3 = (*dstptr >> 11) & 0x1F; d1 = (d1 * (255 - a) + s1 * a) / 255; d2 = (d2 * (255 - a) + s2 * a) / 255; d3 = (d3 * (255 - a) + s3 * a) / 255; - *(grub_uint16_t *) dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5) - | ((d3 & 0x1f) << 11); + *dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5) | ((d3 & 0x1f) << 11); } srcmask >>= 1; @@ -1404,7 +1454,7 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 2; + dstptr++; } srcptr += srcrowskipbyte; @@ -1415,6 +1465,6 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } diff --git a/grub-core/video/fb/fbfill.c b/grub-core/video/fb/fbfill.c index a4ca7c2a1..5f3e55fae 100644 --- a/grub-core/video/fb/fbfill.c +++ b/grub-core/video/fb/fbfill.c @@ -64,7 +64,7 @@ grub_video_fbfill_direct32 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -72,7 +72,7 @@ grub_video_fbfill_direct32 (struct grub_video_fbblit_info *dst, *dstptr++ = color; /* Advance the dest pointer to the right location on the next line. */ - dstptr = (grub_uint32_t *) (((char *) dstptr) + rowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, rowskip); } } @@ -96,7 +96,7 @@ grub_video_fbfill_direct24 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -131,7 +131,7 @@ grub_video_fbfill_direct16 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -164,7 +164,7 @@ grub_video_fbfill_direct8 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c index 511beaafc..c7fb08702 100644 --- a/grub-core/video/fb/fbutil.c +++ b/grub-core/video/fb/fbutil.c @@ -31,7 +31,7 @@ #include #include -grub_uint8_t * +void * grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, unsigned int x, unsigned int y) { diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c index 2cffcb3d9..2d9d99482 100644 --- a/grub-core/video/fb/video_fb.c +++ b/grub-core/video/fb/video_fb.c @@ -622,6 +622,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#ifdef GRUB_HAVE_UNALIGNED_ACCESS else if (target->mode_info->bpp == 24) { grub_video_fbblit_replace_24bit_1bit (target, source, @@ -629,6 +630,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#endif else if (target->mode_info->bpp == 16) { grub_video_fbblit_replace_16bit_1bit (target, source, @@ -743,6 +745,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#ifdef GRUB_HAVE_UNALIGNED_ACCESS else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888 || target->mode_info->blit_format @@ -753,6 +756,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#endif else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565 || target->mode_info->blit_format @@ -1195,6 +1199,15 @@ grub_video_fb_create_render_target_from_pointer (struct grub_video_fbrender_targ struct grub_video_fbrender_target *target; unsigned y; +#ifndef GRUB_HAVE_UNALIGNED_ACCESS + if (!(mode_info->bytes_per_pixel & (mode_info->bytes_per_pixel - 1)) + && ((grub_addr_t) ptr & (mode_info->bytes_per_pixel - 1))) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unaligned pointer"); + if (!(mode_info->bytes_per_pixel & (mode_info->bytes_per_pixel - 1)) + && (mode_info->pitch & (mode_info->bytes_per_pixel - 1))) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unaligned pitch"); +#endif + /* Allocate memory for render target. */ target = grub_malloc (sizeof (struct grub_video_fbrender_target)); if (! target) diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h index 065ccf9e3..f68db43b1 100644 --- a/include/grub/fbutil.h +++ b/include/grub/fbutil.h @@ -31,8 +31,17 @@ struct grub_video_fbblit_info grub_uint8_t *data; }; -grub_uint8_t *grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, - unsigned int x, unsigned int y); +void *grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, + unsigned int x, unsigned int y); + +/* Advance pointer by VAL bytes. If there is no unaligned access available, + VAL has to be divisible by size of pointed type. + */ +#ifdef GRUB_HAVE_UNALIGNED_ACCESS +#define GRUB_VIDEO_FB_ADVANCE_POINTER(ptr, val) ((ptr) = (typeof (ptr)) ((char *) ptr + val)) +#else +#define GRUB_VIDEO_FB_ADVANCE_POINTER(ptr, val) ((ptr) += (val) / sizeof (*(ptr))) +#endif grub_video_color_t get_pixel (struct grub_video_fbblit_info *source, unsigned int x, unsigned int y); diff --git a/include/grub/i386/types.h b/include/grub/i386/types.h index 0ac64734c..c20063f31 100644 --- a/include/grub/i386/types.h +++ b/include/grub/i386/types.h @@ -28,4 +28,6 @@ /* i386 is little-endian. */ #undef GRUB_TARGET_WORDS_BIGENDIAN +#define GRUB_HAVE_UNALIGNED_ACCESS 1 + #endif /* ! GRUB_TYPES_CPU_HEADER */ diff --git a/include/grub/x86_64/types.h b/include/grub/x86_64/types.h index bdee5a109..d53138ea3 100644 --- a/include/grub/x86_64/types.h +++ b/include/grub/x86_64/types.h @@ -28,4 +28,6 @@ /* x86_64 is little-endian. */ #undef GRUB_TARGET_WORDS_BIGENDIAN +#define GRUB_HAVE_UNALIGNED_ACCESS 1 + #endif /* ! GRUB_TYPES_CPU_HEADER */ From b453412d2f6a279b35eb6a01d4d1ae13021abdca Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 23:10:38 +0100 Subject: [PATCH 626/673] * grub-core/fs/hfs.c (grub_hfs_find_node): Handle unaligned keys. (grub_hfs_iterate_dir): Likewise. --- ChangeLog | 5 +++++ grub-core/fs/hfs.c | 7 ++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2134b481a..936e64c45 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/hfs.c (grub_hfs_find_node): Handle unaligned keys. + (grub_hfs_iterate_dir): Likewise. + 2011-12-13 Vladimir Serbinenko Fix video on platforms where unaligned access is forbidden. diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 973a2d2ef..6c5c4da3e 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -750,10 +750,7 @@ grub_hfs_find_node (struct grub_hfs_data *data, char *key, entry. In case of a non-leaf mode it will be used to lookup the rest of the tree. */ if (cmp <= 0) - { - grub_uint32_t *node = (grub_uint32_t *) rec->data; - found = grub_be_to_cpu32 (*node); - } + found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); else /* The key can not be found in the tree. */ return 1; @@ -817,7 +814,7 @@ grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx, struct grub_hfs_catalog_key *ckey = rec->key; if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0) - found = grub_be_to_cpu32 (*(grub_uint32_t *) rec->data); + found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); if (hnd->type == 0xFF && ckey->strlen > 0) { From 3c349f5a374330c67b06b1299de8d05123242ce8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 23:11:48 +0100 Subject: [PATCH 627/673] * grub-core/fs/jfs.c (grub_jfs_getent): Handle UTF16 endianness. --- ChangeLog | 4 ++++ grub-core/fs/jfs.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 936e64c45..0928450ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/jfs.c (grub_jfs_getent): Handle UTF16 endianness. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/hfs.c (grub_hfs_find_node): Handle unaligned keys. diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 3554803cb..72d6fe4c1 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -490,7 +490,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) void addstr (grub_uint16_t *name, int ulen) { while (ulen--) - filename[strpos++] = *(name++); + filename[strpos++] = grub_le_to_cpu16 (*(name++)); } /* The last node, read in more. */ From efc2616ee113b738f7bd8dffba3c533813122ea1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 23:14:25 +0100 Subject: [PATCH 628/673] * grub-core/fs/squash4.c (grub_squash_inode): Fix field sizes. (grub_squash_dirent_header): Likewise. (read_chunk): Don't double swap. (grub_squash_iterate_dir): Fix swap sizes. --- ChangeLog | 7 +++++++ grub-core/fs/squash4.c | 25 ++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0928450ba..2859e1a7b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/squash4.c (grub_squash_inode): Fix field sizes. + (grub_squash_dirent_header): Likewise. + (read_chunk): Don't double swap. + (grub_squash_iterate_dir): Fix swap sizes. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/jfs.c (grub_jfs_getent): Handle UTF16 endianness. diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 0728287b7..e14df6dbf 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -80,7 +80,8 @@ struct grub_squash_inode grub_uint32_t dummy; grub_uint32_t chunk; grub_uint32_t fragment; - grub_uint32_t offset; + grub_uint16_t offset; + grub_uint16_t dummy2; grub_uint32_t size; grub_uint32_t block_size[0]; } __attribute__ ((packed)) file; @@ -90,8 +91,9 @@ struct grub_squash_inode grub_uint64_t size; grub_uint32_t dummy2[3]; grub_uint32_t fragment; - grub_uint32_t offset; - grub_uint32_t dummy3; + grub_uint16_t offset; + grub_uint16_t dummy3; + grub_uint32_t dummy4; grub_uint32_t block_size[0]; } __attribute__ ((packed)) long_file; struct { @@ -99,8 +101,9 @@ struct grub_squash_inode grub_uint32_t chunk; grub_uint32_t dummy2; grub_uint16_t size; - grub_uint32_t offset; + grub_uint16_t offset; grub_uint16_t dummy3; + grub_uint16_t dummy4; } __attribute__ ((packed)) dir; struct { grub_uint64_t dummy; @@ -124,7 +127,8 @@ struct grub_squash_dirent_header { /* Actually the value is the number of elements - 1. */ grub_uint32_t nelems; - grub_uint64_t ino_chunk; + grub_uint32_t ino_chunk; + grub_uint32_t dummy; } __attribute__ ((packed)); struct grub_squash_dirent @@ -186,10 +190,8 @@ struct grub_fshelp_node static grub_err_t read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, - grub_uint64_t chunk, grub_off_t offset) + grub_uint64_t chunk_start, grub_off_t offset) { - grub_uint64_t chunk_start; - chunk_start = grub_le_to_cpu64 (chunk); while (len > 0) { grub_uint64_t csize; @@ -335,7 +337,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, unsigned i; /* FIXME: why - 3 ? */ - endoff = grub_le_to_cpu32 (dir->ino.dir.size) + off - 3; + endoff = grub_le_to_cpu16 (dir->ino.dir.size) + off - 3; while (off < endoff) { @@ -348,7 +350,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, if (err) return 0; off += sizeof (dh); - for (i = 0; i < (unsigned) grub_le_to_cpu16 (dh.nelems) + 1; i++) + for (i = 0; i < (unsigned) grub_le_to_cpu32 (dh.nelems) + 1; i++) { char *buf; int r; @@ -594,7 +596,8 @@ direct_read (struct grub_squash_data *data, read = grub_le_to_cpu32 (data->sb.block_size) - boff; if (read > len) read = len; - if (!(ino->block_sizes[i] & SQUASH_BLOCK_UNCOMPRESSED)) + if (!(ino->block_sizes[i] + & grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED))) err = grub_zlib_disk_read (data->disk, ino->cumulated_block_sizes[i] + a, boff, buf, read); From e7987e1b3bdea7912fdef923418c36800ba8cad7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 13 Dec 2011 23:15:56 +0100 Subject: [PATCH 629/673] * grub-core/fs/romfs.c (grub_romfs_mount): Fix pointer comparison overflow. --- ChangeLog | 5 +++++ grub-core/fs/romfs.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2859e1a7b..d3d7f0ea7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/romfs.c (grub_romfs_mount): Fix pointer comparison + overflow. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/squash4.c (grub_squash_inode): Fix field sizes. diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 76e13727d..11c844e91 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -112,7 +112,7 @@ grub_romfs_mount (grub_device_t dev) if (err) return NULL; for (ptr = sb.sb.label; (void *) ptr < (void *) (&sb + 1) - && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) + && ptr - sb.d < (grub_ssize_t) grub_be_to_cpu32 (sb.sb.total_size); ptr++) if (!*ptr) break; if ((void *) ptr == &sb + 1) @@ -124,7 +124,7 @@ grub_romfs_mount (grub_device_t dev) if (err) return NULL; for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1) - && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) + && ptr - sb.d < (grub_ssize_t) grub_be_to_cpu32 (sb.sb.total_size); ptr++) if (!*ptr) break; } From 309e5352316c1c2059cd01b4f8c61e56714df365 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 14 Dec 2011 09:52:00 +0100 Subject: [PATCH 630/673] AFFS never uses unicode. * include/grub/charset.h (GRUB_MAX_UTF8_PER_LATIN1): New const. (grub_latin1_to_utf8): New inline function. * grub-core/fs/affs.c (grub_affs_iterate_dir): Convert latin1 to UTF8. --- ChangeLog | 8 ++++++++ grub-core/fs/affs.c | 18 ++++++++++-------- include/grub/charset.h | 22 ++++++++++++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index d3d7f0ea7..2d811e710 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-12-14 Vladimir Serbinenko + + AFFS never uses unicode. + + * include/grub/charset.h (GRUB_MAX_UTF8_PER_LATIN1): New const. + (grub_latin1_to_utf8): New inline function. + * grub-core/fs/affs.c (grub_affs_iterate_dir): Convert latin1 to UTF8. + 2011-12-13 Vladimir Serbinenko * grub-core/fs/romfs.c (grub_romfs_mount): Fix pointer comparison diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 06f41c4c3..0ad5e6672 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -292,15 +293,15 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, struct grub_affs_data *data = dir->data; grub_uint32_t *hashtable; - auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, - grub_uint32_t block, + auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, const struct grub_affs_file *fil); - int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, - grub_uint32_t block, + int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, const struct grub_affs_file *fil) { int type; + grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1]; + node = grub_zalloc (sizeof (*node)); if (!node) { @@ -322,7 +323,10 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, node->di = *fil; node->parent = dir; - if (hook (name, type, node)) + *grub_latin1_to_utf8 (name_u8, fil->name, + grub_min (fil->namelen, sizeof (fil->name))) = '\0'; + + if (hook ((char *) name_u8, type, node)) { grub_free (hashtable); return 1; @@ -377,9 +381,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) goto fail; - file.name[file.namelen] = '\0'; - - if (grub_affs_create_node ((char *) (file.name), next, &file)) + if (grub_affs_create_node (next, &file)) return 1; next = grub_be_to_cpu32 (file.next); diff --git a/include/grub/charset.h b/include/grub/charset.h index c7f86a1ef..2b1f54fe8 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -118,6 +118,28 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, return dest; } +#define GRUB_MAX_UTF8_PER_LATIN1 2 + +/* Convert Latin1 to UTF-8. */ +static inline grub_uint8_t * +grub_latin1_to_utf8 (grub_uint8_t *dest, const grub_uint8_t *src, + grub_size_t size) +{ + while (size--) + { + if (!(*src & 0x80)) + *dest++ = *src; + else + { + *dest++ = (*src >> 6) | 0xC0; + *dest++ = (*src & 0x3F) | 0x80; + } + src++; + } + + return dest; +} + /* Convert UCS-4 to UTF-8. */ char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size); From cb8f88ea8220ff00d333c27af3463fd2d441f818 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 14 Dec 2011 10:01:24 +0100 Subject: [PATCH 631/673] * include/grub/charset.h (grub_utf16_to_utf8): Make src a const pointer. (grub_ucs4_to_utf8_alloc): Likewise. (grub_ucs4_to_utf8): Likewise. * grub-core/normal/charset.c (grub_ucs4_to_utf8): Likewise. (grub_ucs4_to_utf8_alloc): Likewise. --- ChangeLog | 8 ++++++++ grub-core/normal/charset.c | 6 +++--- include/grub/charset.h | 6 +++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2d811e710..90f63fb77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-12-14 Vladimir Serbinenko + + * include/grub/charset.h (grub_utf16_to_utf8): Make src a const pointer. + (grub_ucs4_to_utf8_alloc): Likewise. + (grub_ucs4_to_utf8): Likewise. + * grub-core/normal/charset.c (grub_ucs4_to_utf8): Likewise. + (grub_ucs4_to_utf8_alloc): Likewise. + 2011-12-14 Vladimir Serbinenko AFFS never uses unicode. diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c index d089843cc..ee4a7ef5f 100644 --- a/grub-core/normal/charset.c +++ b/grub-core/normal/charset.c @@ -197,7 +197,7 @@ grub_encode_utf8_character (grub_uint8_t *dest, grub_uint8_t *destend, /* Convert UCS-4 to UTF-8. */ void -grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, +grub_ucs4_to_utf8 (const grub_uint32_t *src, grub_size_t size, grub_uint8_t *dest, grub_size_t destsize) { /* Keep last char for \0. */ @@ -223,10 +223,10 @@ grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, /* Convert UCS-4 to UTF-8. */ char * -grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size) +grub_ucs4_to_utf8_alloc (const grub_uint32_t *src, grub_size_t size) { grub_size_t remaining; - grub_uint32_t *ptr; + const grub_uint32_t *ptr; grub_size_t cnt = 0; grub_uint8_t *ret; diff --git a/include/grub/charset.h b/include/grub/charset.h index 2b1f54fe8..b0960c940 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -51,7 +51,7 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, /* Convert UTF-16 to UTF-8. */ static inline grub_uint8_t * -grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, +grub_utf16_to_utf8 (grub_uint8_t *dest, const grub_uint16_t *src, grub_size_t size) { grub_uint32_t code_high = 0; @@ -141,7 +141,7 @@ grub_latin1_to_utf8 (grub_uint8_t *dest, const grub_uint8_t *src, } /* Convert UCS-4 to UTF-8. */ -char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size); +char *grub_ucs4_to_utf8_alloc (const grub_uint32_t *src, grub_size_t size); int grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize); @@ -156,7 +156,7 @@ int grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count); void -grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, +grub_ucs4_to_utf8 (const grub_uint32_t *src, grub_size_t size, grub_uint8_t *dest, grub_size_t destsize); grub_size_t grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, From e739d6988502ab3b6e77999aedd7c839d2503355 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 14 Dec 2011 11:13:14 +0100 Subject: [PATCH 632/673] * include/grub/efi/api.h (grub_efi_memory_descriptor): Add packed attribute as the structure isn't guaranteed to be properly aligned. (grub_efi_pci_device_path): Likewise. (grub_efi_pccard_device_path): Likewise. (grub_efi_memory_mapped_device_path): Likewise. Additionaly explicitly specify the size of `memory_type'. (grub_efi_vendor_device_path): Likewise. (grub_efi_controller_device_path): Likewise. (grub_efi_acpi_device_path): Likewise. (grub_efi_expanded_acpi_device_path): Likewise. (grub_efi_atapi_device_path): Likewise. (grub_efi_scsi_device_path): Likewise. (grub_efi_fibre_channel_device_path): Likewise. (grub_efi_1394_device_path): Likewise. (grub_efi_usb_device_path): Likewise. (grub_efi_usb_class_device_path): Likewise. (grub_efi_i2o_device_path): Likewise. (grub_efi_mac_address_device_path): Likewise. (grub_efi_ipv4_device_path): Likewise. (grub_efi_ipv6_device_path): Likewise. (grub_efi_infiniband_device_path): Likewise. (grub_efi_uart_device_path): Likewise. (grub_efi_vendor_messaging_device_path): Likewise. (grub_efi_hard_drive_device_path): Likewise. (grub_efi_cdrom_device_path): Likewise. (grub_efi_vendor_media_device_path): Likewise. (grub_efi_file_path_device_path): Likewise. (grub_efi_protocol_device_path): Likewise. (grub_efi_piwg_device_path): Likewise. (grub_efi_bios_device_path): Likewise. --- ChangeLog | 33 +++++++++++++++++++++++ include/grub/efi/api.h | 60 +++++++++++++++++++++--------------------- 2 files changed, 63 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 90f63fb77..3ba8b3004 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2011-12-14 Vladimir Serbinenko + + * include/grub/efi/api.h (grub_efi_memory_descriptor): Add packed + attribute as the structure isn't guaranteed to be properly aligned. + (grub_efi_pci_device_path): Likewise. + (grub_efi_pccard_device_path): Likewise. + (grub_efi_memory_mapped_device_path): Likewise. Additionaly explicitly + specify the size of `memory_type'. + (grub_efi_vendor_device_path): Likewise. + (grub_efi_controller_device_path): Likewise. + (grub_efi_acpi_device_path): Likewise. + (grub_efi_expanded_acpi_device_path): Likewise. + (grub_efi_atapi_device_path): Likewise. + (grub_efi_scsi_device_path): Likewise. + (grub_efi_fibre_channel_device_path): Likewise. + (grub_efi_1394_device_path): Likewise. + (grub_efi_usb_device_path): Likewise. + (grub_efi_usb_class_device_path): Likewise. + (grub_efi_i2o_device_path): Likewise. + (grub_efi_mac_address_device_path): Likewise. + (grub_efi_ipv4_device_path): Likewise. + (grub_efi_ipv6_device_path): Likewise. + (grub_efi_infiniband_device_path): Likewise. + (grub_efi_uart_device_path): Likewise. + (grub_efi_vendor_messaging_device_path): Likewise. + (grub_efi_hard_drive_device_path): Likewise. + (grub_efi_cdrom_device_path): Likewise. + (grub_efi_vendor_media_device_path): Likewise. + (grub_efi_file_path_device_path): Likewise. + (grub_efi_protocol_device_path): Likewise. + (grub_efi_piwg_device_path): Likewise. + (grub_efi_bios_device_path): Likewise. + 2011-12-14 Vladimir Serbinenko * include/grub/charset.h (grub_utf16_to_utf8): Make src a const pointer. diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index b20baa015..7df3602f1 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -371,7 +371,7 @@ struct grub_efi_memory_descriptor grub_efi_virtual_address_t virtual_start; grub_efi_uint64_t num_pages; grub_efi_uint64_t attribute; -}; +} __attribute__ ((packed)); typedef struct grub_efi_memory_descriptor grub_efi_memory_descriptor_t; /* Device Path definitions. */ @@ -416,7 +416,7 @@ struct grub_efi_pci_device_path grub_efi_device_path_t header; grub_efi_uint8_t function; grub_efi_uint8_t device; -}; +} __attribute__ ((packed)); typedef struct grub_efi_pci_device_path grub_efi_pci_device_path_t; #define GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE 2 @@ -425,7 +425,7 @@ struct grub_efi_pccard_device_path { grub_efi_device_path_t header; grub_efi_uint8_t function; -}; +} __attribute__ ((packed)); typedef struct grub_efi_pccard_device_path grub_efi_pccard_device_path_t; #define GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE 3 @@ -433,10 +433,10 @@ typedef struct grub_efi_pccard_device_path grub_efi_pccard_device_path_t; struct grub_efi_memory_mapped_device_path { grub_efi_device_path_t header; - grub_efi_memory_type_t memory_type; + grub_efi_uint32_t memory_type; grub_efi_physical_address_t start_address; grub_efi_physical_address_t end_address; -}; +} __attribute__ ((packed)); typedef struct grub_efi_memory_mapped_device_path grub_efi_memory_mapped_device_path_t; #define GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE 4 @@ -446,7 +446,7 @@ struct grub_efi_vendor_device_path grub_efi_device_path_t header; grub_efi_guid_t vendor_guid; grub_efi_uint8_t vendor_defined_data[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_vendor_device_path grub_efi_vendor_device_path_t; #define GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE 5 @@ -455,7 +455,7 @@ struct grub_efi_controller_device_path { grub_efi_device_path_t header; grub_efi_uint32_t controller_number; -}; +} __attribute__ ((packed)); typedef struct grub_efi_controller_device_path grub_efi_controller_device_path_t; /* ACPI Device Path. */ @@ -468,7 +468,7 @@ struct grub_efi_acpi_device_path grub_efi_device_path_t header; grub_efi_uint32_t hid; grub_efi_uint32_t uid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_acpi_device_path grub_efi_acpi_device_path_t; #define GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE 2 @@ -479,8 +479,8 @@ struct grub_efi_expanded_acpi_device_path grub_efi_uint32_t hid; grub_efi_uint32_t uid; grub_efi_uint32_t cid; - char hidstr[1]; -}; + char hidstr[0]; +} __attribute__ ((packed)); typedef struct grub_efi_expanded_acpi_device_path grub_efi_expanded_acpi_device_path_t; #define GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp) \ @@ -503,7 +503,7 @@ struct grub_efi_atapi_device_path grub_efi_uint8_t primary_secondary; grub_efi_uint8_t slave_master; grub_efi_uint16_t lun; -}; +} __attribute__ ((packed)); typedef struct grub_efi_atapi_device_path grub_efi_atapi_device_path_t; #define GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE 2 @@ -513,7 +513,7 @@ struct grub_efi_scsi_device_path grub_efi_device_path_t header; grub_efi_uint16_t pun; grub_efi_uint16_t lun; -}; +} __attribute__ ((packed)); typedef struct grub_efi_scsi_device_path grub_efi_scsi_device_path_t; #define GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE 3 @@ -524,7 +524,7 @@ struct grub_efi_fibre_channel_device_path grub_efi_uint32_t reserved; grub_efi_uint64_t wwn; grub_efi_uint64_t lun; -}; +} __attribute__ ((packed)); typedef struct grub_efi_fibre_channel_device_path grub_efi_fibre_channel_device_path_t; #define GRUB_EFI_1394_DEVICE_PATH_SUBTYPE 4 @@ -534,7 +534,7 @@ struct grub_efi_1394_device_path grub_efi_device_path_t header; grub_efi_uint32_t reserved; grub_efi_uint64_t guid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_1394_device_path grub_efi_1394_device_path_t; #define GRUB_EFI_USB_DEVICE_PATH_SUBTYPE 5 @@ -544,7 +544,7 @@ struct grub_efi_usb_device_path grub_efi_device_path_t header; grub_efi_uint8_t parent_port_number; grub_efi_uint8_t interface; -}; +} __attribute__ ((packed)); typedef struct grub_efi_usb_device_path grub_efi_usb_device_path_t; #define GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE 15 @@ -557,7 +557,7 @@ struct grub_efi_usb_class_device_path grub_efi_uint8_t device_class; grub_efi_uint8_t device_subclass; grub_efi_uint8_t device_protocol; -}; +} __attribute__ ((packed)); typedef struct grub_efi_usb_class_device_path grub_efi_usb_class_device_path_t; #define GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE 6 @@ -566,7 +566,7 @@ struct grub_efi_i2o_device_path { grub_efi_device_path_t header; grub_efi_uint32_t tid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_i2o_device_path grub_efi_i2o_device_path_t; #define GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE 11 @@ -576,7 +576,7 @@ struct grub_efi_mac_address_device_path grub_efi_device_path_t header; grub_efi_mac_address_t mac_address; grub_efi_uint8_t if_type; -}; +} __attribute__ ((packed)); typedef struct grub_efi_mac_address_device_path grub_efi_mac_address_device_path_t; #define GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE 12 @@ -590,7 +590,7 @@ struct grub_efi_ipv4_device_path grub_efi_uint16_t remote_port; grub_efi_uint16_t protocol; grub_efi_uint8_t static_ip_address; -}; +} __attribute__ ((packed)); typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t; #define GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE 13 @@ -604,7 +604,7 @@ struct grub_efi_ipv6_device_path grub_efi_uint16_t remote_port; grub_efi_uint16_t protocol; grub_efi_uint8_t static_ip_address; -}; +} __attribute__ ((packed)); typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t; #define GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE 9 @@ -617,7 +617,7 @@ struct grub_efi_infiniband_device_path grub_efi_uint64_t remote_id; grub_efi_uint64_t target_port_id; grub_efi_uint64_t device_id; -}; +} __attribute__ ((packed)); typedef struct grub_efi_infiniband_device_path grub_efi_infiniband_device_path_t; #define GRUB_EFI_UART_DEVICE_PATH_SUBTYPE 14 @@ -630,7 +630,7 @@ struct grub_efi_uart_device_path grub_efi_uint8_t data_bits; grub_efi_uint8_t parity; grub_efi_uint8_t stop_bits; -}; +} __attribute__ ((packed)); typedef struct grub_efi_uart_device_path grub_efi_uart_device_path_t; #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 @@ -640,7 +640,7 @@ struct grub_efi_vendor_messaging_device_path grub_efi_device_path_t header; grub_efi_guid_t vendor_guid; grub_efi_uint8_t vendor_defined_data[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_vendor_messaging_device_path grub_efi_vendor_messaging_device_path_t; /* Media Device Path. */ @@ -657,7 +657,7 @@ struct grub_efi_hard_drive_device_path grub_efi_uint8_t partition_signature[8]; grub_efi_uint8_t mbr_type; grub_efi_uint8_t signature_type; -}; +} __attribute__ ((packed)); typedef struct grub_efi_hard_drive_device_path grub_efi_hard_drive_device_path_t; #define GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE 2 @@ -668,7 +668,7 @@ struct grub_efi_cdrom_device_path grub_efi_uint32_t boot_entry; grub_efi_lba_t partition_start; grub_efi_lba_t partition_size; -}; +} __attribute__ ((packed)); typedef struct grub_efi_cdrom_device_path grub_efi_cdrom_device_path_t; #define GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE 3 @@ -678,7 +678,7 @@ struct grub_efi_vendor_media_device_path grub_efi_device_path_t header; grub_efi_guid_t vendor_guid; grub_efi_uint8_t vendor_defined_data[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_vendor_media_device_path grub_efi_vendor_media_device_path_t; #define GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE 4 @@ -687,7 +687,7 @@ struct grub_efi_file_path_device_path { grub_efi_device_path_t header; grub_efi_char16_t path_name[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_file_path_device_path grub_efi_file_path_device_path_t; #define GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE 5 @@ -696,7 +696,7 @@ struct grub_efi_protocol_device_path { grub_efi_device_path_t header; grub_efi_guid_t guid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_protocol_device_path grub_efi_protocol_device_path_t; #define GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE 6 @@ -705,7 +705,7 @@ struct grub_efi_piwg_device_path { grub_efi_device_path_t header; grub_efi_guid_t guid __attribute__ ((packed)); -}; +} __attribute__ ((packed)); typedef struct grub_efi_piwg_device_path grub_efi_piwg_device_path_t; @@ -720,7 +720,7 @@ struct grub_efi_bios_device_path grub_efi_uint16_t device_type; grub_efi_uint16_t status_flags; char description[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t; struct grub_efi_open_protocol_information_entry From 9f59e9fc36fb0b1efba1da06303c09c18e753934 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 14 Dec 2011 12:05:26 +0100 Subject: [PATCH 633/673] * grub-core/gfxmenu/gui_list.c (draw_menu): Don't use set in if. --- ChangeLog | 4 ++++ grub-core/gfxmenu/gui_list.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3ba8b3004..6c69ba780 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-14 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_list.c (draw_menu): Don't use set in if. + 2011-12-14 Vladimir Serbinenko * include/grub/efi/api.h (grub_efi_memory_descriptor): Add packed diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c index 2ff6e0f97..1982d9a40 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -245,6 +245,7 @@ draw_menu (list_impl_t self, int num_shown_items) visible_index++, menu_index++) { int is_selected = (menu_index == self->view->selected); + struct grub_video_bitmap *icon; if (is_selected) { @@ -256,8 +257,8 @@ draw_menu (list_impl_t self, int num_shown_items) item_top - sel_toppad); } - struct grub_video_bitmap *icon; - if ((icon = get_item_icon (self, menu_index)) != 0) + icon = get_item_icon (self, menu_index); + if (icon != 0) grub_video_blit_bitmap (icon, GRUB_VIDEO_BLIT_BLEND, sel_leftpad, item_top + (item_height - self->icon_height) / 2, From ca1b552c024d320b5e6a3bbe5d4ba4815a9755d1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 14 Dec 2011 14:20:57 +0100 Subject: [PATCH 634/673] * grub-core/gfxmenu/widget-box.c (get_left_pad): Take corners into account. (get_top_pad): Likewise. (get_right_pad): Likewise. (get_bottom_pad): Likewise. --- ChangeLog | 10 ++++++- grub-core/gfxmenu/widget-box.c | 48 +++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6c69ba780..c6fbf73f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,14 @@ 2011-12-14 Vladimir Serbinenko - * grub-core/gfxmenu/gui_list.c (draw_menu): Don't use set in if. + * grub-core/gfxmenu/widget-box.c (get_left_pad): Take corners into + account. + (get_top_pad): Likewise. + (get_right_pad): Likewise. + (get_bottom_pad): Likewise. + +2011-12-14 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_list.c (draw_menu): Don't use assignment in if. 2011-12-14 Vladimir Serbinenko diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c index 41ca7f536..8c9131a24 100644 --- a/grub-core/gfxmenu/widget-box.c +++ b/grub-core/gfxmenu/widget-box.c @@ -188,25 +188,65 @@ get_border_width (grub_gfxmenu_box_t self) static int get_left_pad (grub_gfxmenu_box_t self) { - return get_width (self->raw_pixmaps[BOX_PIXMAP_W]); + int v, c; + + v = get_width (self->raw_pixmaps[BOX_PIXMAP_W]); + c = get_width (self->raw_pixmaps[BOX_PIXMAP_NW]); + if (c > v) + v = c; + c = get_width (self->raw_pixmaps[BOX_PIXMAP_SW]); + if (c > v) + v = c; + + return v; } static int get_top_pad (grub_gfxmenu_box_t self) { - return get_height (self->raw_pixmaps[BOX_PIXMAP_N]); + int v, c; + + v = get_height (self->raw_pixmaps[BOX_PIXMAP_N]); + c = get_height (self->raw_pixmaps[BOX_PIXMAP_NW]); + if (c > v) + v = c; + c = get_height (self->raw_pixmaps[BOX_PIXMAP_NE]); + if (c > v) + v = c; + + return v; } static int get_right_pad (grub_gfxmenu_box_t self) { - return get_width (self->raw_pixmaps[BOX_PIXMAP_E]); + int v, c; + + v = get_width (self->raw_pixmaps[BOX_PIXMAP_E]); + c = get_width (self->raw_pixmaps[BOX_PIXMAP_NE]); + if (c > v) + v = c; + c = get_width (self->raw_pixmaps[BOX_PIXMAP_SE]); + if (c > v) + v = c; + + return v; } static int get_bottom_pad (grub_gfxmenu_box_t self) { - return get_height (self->raw_pixmaps[BOX_PIXMAP_S]); + int v, c; + + v = get_height (self->raw_pixmaps[BOX_PIXMAP_S]); + c = get_height (self->raw_pixmaps[BOX_PIXMAP_SW]); + if (c > v) + v = c; + c = get_height (self->raw_pixmaps[BOX_PIXMAP_SE]); + if (c > v) + v = c; + + return v; } static void From a14b16d1f95aa7fbb8e223f44b7681cec78d550f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 14 Dec 2011 23:57:35 +0100 Subject: [PATCH 635/673] * include/grub/types.h (GRUB_PROPERLY_ALIGNED_ARRAY): Add missing brackets. --- ChangeLog | 11 +++++------ include/grub/types.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index c6fbf73f0..bb00e383e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-14 Vladimir Serbinenko + + * include/grub/types.h (GRUB_PROPERLY_ALIGNED_ARRAY): Add missing + brackets. + 2011-12-14 Vladimir Serbinenko * grub-core/gfxmenu/widget-box.c (get_left_pad): Take corners into @@ -344,12 +349,6 @@ (grub_nilfs2_btree_node_dkeys): Ensure return pointer alignment. (grub_nilfs2_btree_lookup): Ensure buffer alignment. -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/ext2.c (grub_ext4_find_leaf): MAke buf as pointer to - properly aligned memory. - (grub_ext2_read_block): Ensure buffer alignment. - 2011-12-13 Vladimir Serbinenko * grub-core/fs/romfs.c (grub_romfs_iterate_dir): Properly align diff --git a/include/grub/types.h b/include/grub/types.h index e61a9a5c6..19a09895b 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -142,7 +142,7 @@ typedef grub_int32_t grub_ssize_t; typedef grub_uint64_t grub_properly_aligned_t; -#define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[(size + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] +#define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] /* The type for representing a file offset. */ typedef grub_uint64_t grub_off_t; From 7a7f7cc9c3ed7f614fb98df18f1c4035a36ce5d1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 14 Dec 2011 23:59:11 +0100 Subject: [PATCH 636/673] * include/grub/kernel.h (FOR_MODULES): Make it a bit faster. --- ChangeLog | 4 ++++ include/grub/kernel.h | 8 +++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index bb00e383e..ecc637e63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-14 Vladimir Serbinenko + + * include/grub/kernel.h (FOR_MODULES): Make it a bit faster. + 2011-12-14 Vladimir Serbinenko * include/grub/types.h (GRUB_PROPERLY_ALIGNED_ARRAY): Add missing diff --git a/include/grub/kernel.h b/include/grub/kernel.h index c9a549675..4c8b29c8b 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -71,15 +71,13 @@ struct grub_module_info64 extern grub_addr_t EXPORT_VAR (grub_modbase); -#define FOR_MODULES(var) for (var = grub_modbase ? (struct grub_module_header *) \ +#define FOR_MODULES(var) for (\ + var = grub_modbase ? (struct grub_module_header *) \ (grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\ var && (grub_addr_t) var \ < (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \ var = (struct grub_module_header *) \ - ((grub_uint32_t *) var \ - + ((((struct grub_module_header *) var)->size \ - + sizeof (grub_uint32_t) - 1) \ - / sizeof (grub_uint32_t)))) + ((grub_uint32_t *) var + ((struct grub_module_header *) var)->size / 4)) grub_addr_t grub_modules_get_end (void); From ee9c2e7a978cf5dd5f6eb84341ab356a87769bd3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 02:20:21 +0100 Subject: [PATCH 637/673] * grub-core/lib/reed_solomon.c (init_powx): Set gf_powx_inv[0] just to be deterministic. (syndroms): Compute 0 syndrom. (rs_recover): Use 0 syndrom. --- ChangeLog | 7 +++++++ grub-core/lib/reed_solomon.c | 8 +++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index ecc637e63..5a654270d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-14 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (init_powx): Set gf_powx_inv[0] just to + be deterministic. + (syndroms): Compute 0 syndrom. + (rs_recover): Use 0 syndrom. + 2011-12-14 Vladimir Serbinenko * include/grub/kernel.h (FOR_MODULES): Make it a bit faster. diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 7da5f204c..fc5443c28 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -89,6 +89,7 @@ init_powx (void) int i; grub_uint8_t cur = 1; + gf_powx_inv[0] = 0; for (i = 0; i < 255; i++) { gf_powx[i] = cur; @@ -165,7 +166,8 @@ syndroms (gf_single_t *m, grub_size_t s, grub_size_t rs, { gf_single_t xn = 1; unsigned i; - for (i = 0; i < rs; i++) + sy[0] = pol_evaluate (m, s + rs - 1, xn); + for (i = 1; i < rs; i++) { if (xn & (1 << (GF_SIZE - 1))) { @@ -344,7 +346,7 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) #endif for (j = 0; j < errnum; j++) - eq[j] = errpot[j]; + eq[j] = 1; eq[errnum] = sy[0]; for (i = 1; i < (int) rs; i++) { @@ -530,7 +532,7 @@ main (int argc, char **argv) out = fopen ("tst_rs.bin", "wb"); fwrite (buf, 1, s + rs, out); fclose (out); -#if 0 +#if 1 grub_memset (buf + 512 * 15, 0, 512); #endif From b81d609e4c9f3e8f4534c38804305979d687b2dc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:17:36 +0100 Subject: [PATCH 638/673] * grub-core/kern/i386/realmode.S: Increase alignment. * grub-core/boot/i386/pc/startup_raw.S: Likewise. --- grub-core/boot/i386/pc/startup_raw.S | 2 +- grub-core/kern/i386/realmode.S | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 9e0f23d71..3fae1e4e1 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -341,6 +341,6 @@ gate_a20_check_state: #include "lzma_decode.S" #endif - .p2align 2 + .p2align 4 LOCAL(decompressor_end): diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S index 2e16847c8..36d41e7de 100644 --- a/grub-core/kern/i386/realmode.S +++ b/grub-core/kern/i386/realmode.S @@ -46,7 +46,7 @@ * This is the area for all of the special variables. */ - .p2align 2 /* force 4-byte alignment */ + .p2align 5 /* force 4-byte alignment */ protstack: .long GRUB_MEMORY_MACHINE_PROT_STACK @@ -79,7 +79,7 @@ protstack: * description. */ - .p2align 2 /* force 4-byte alignment */ + .p2align 5 /* force 4-byte alignment */ gdt: .word 0, 0 .byte 0, 0, 0, 0 @@ -113,6 +113,7 @@ gdt: .byte 0, 0x92, 0, 0 + .p2align 5 /* this is the GDT descriptor */ gdtdesc: .word 0x27 /* limit */ From e3fd394a10a709e4935c3a64b237dada17f01b8e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:20:41 +0100 Subject: [PATCH 639/673] * grub-core/boot/i386/pc/startup_raw.S: Move realmode routines to non-RS part to avoid RS messing with GDT. * include/grub/offsets.h (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): Increase to suit in realmode routines. --- ChangeLog | 12 ++++++++++++ grub-core/boot/i386/pc/startup_raw.S | 4 ++-- include/grub/offsets.h | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5a654270d..c3c3b1c36 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/boot/i386/pc/startup_raw.S: Move realmode routines to + non-RS part to avoid RS messing with GDT. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): + Increase to suit in realmode routines. + +2011-12-15 Vladimir Serbinenko + + * grub-core/kern/i386/realmode.S: Increase alignment. + * grub-core/boot/i386/pc/startup_raw.S: Likewise. + 2011-12-14 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (init_powx): Set gf_powx_inv[0] just to diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 3fae1e4e1..ade2883b0 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -108,6 +108,8 @@ LOCAL (codestart): call EXT_C (grub_reed_solomon_recover) jmp post_reed_solomon +#include "../../../kern/i386/realmode.S" + #include .text @@ -185,8 +187,6 @@ post_reed_solomon: movl $real_to_prot, %ecx jmp *%esi -#include "../../../kern/i386/realmode.S" - /* * grub_gate_a20(int on) * diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 68ed084cb..75a46e128 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -28,7 +28,7 @@ /* Offset of reed_solomon_redundancy. */ #define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x10 -#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x6e0 +#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x7e0 /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 From 276b7a8bddaca261070b5f6658352dbbcd497f2e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:22:36 +0100 Subject: [PATCH 640/673] * grub-core/boot/i386/pc/startup_raw.S: Clear direction flag for certainety. --- ChangeLog | 5 +++++ grub-core/boot/i386/pc/startup_raw.S | 2 ++ 2 files changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index c3c3b1c36..c59df38c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/boot/i386/pc/startup_raw.S: Clear direction flag for + certainety. + 2011-12-15 Vladimir Serbinenko * grub-core/boot/i386/pc/startup_raw.S: Move realmode routines to diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index ade2883b0..9c044ffb0 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -99,12 +99,14 @@ LOCAL (codestart): .code32 incl %eax + cld call grub_gate_a20 movl LOCAL(compressed_size), %edx addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - _start), %edx movl reed_solomon_redundancy, %ecx leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax + cld call EXT_C (grub_reed_solomon_recover) jmp post_reed_solomon From 96f8caf81275c7598e5fe40a3cd40699100846a5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:27:01 +0100 Subject: [PATCH 641/673] * grub-core/lib/reed_solomon.c (decode_block): Allocate on heap and not stack. (encode_block): Likewise. --- ChangeLog | 6 ++++++ grub-core/lib/reed_solomon.c | 23 +++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c59df38c2..0063cdf04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (decode_block): Allocate on heap and not + stack. + (encode_block): Likewise. + 2011-12-15 Vladimir Serbinenko * grub-core/boot/i386/pc/startup_raw.S: Clear direction flag for diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index fc5443c28..3d8bb9e1f 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -390,12 +390,19 @@ decode_block (gf_single_t *ptr, grub_size_t s, { grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; - gf_single_t m[ds + rr]; + gf_single_t *m; /* Nothing to do. */ if (!ds || !rr) continue; +#ifndef STANDALONE + m = xmalloc (ds + rr); +#else + m = (gf_single_t *) scratch; + scratch += ds + rr; +#endif + for (j = 0; j < (int) ds; j++) m[j] = ptr[SECTOR_SIZE * j + i]; for (j = 0; j < (int) rr; j++) @@ -405,6 +412,12 @@ decode_block (gf_single_t *ptr, grub_size_t s, for (j = 0; j < (int) ds; j++) ptr[SECTOR_SIZE * j + i] = m[j]; + +#ifndef STANDALONE + free (m); +#else + scratch -= ds + rr; +#endif } } @@ -418,12 +431,18 @@ encode_block (gf_single_t *ptr, grub_size_t s, { grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; - gf_single_t m[ds + rr]; + gf_single_t *m; + + if (!ds || !rr) + continue; + + m = xmalloc (ds + rr); for (j = 0; j < ds; j++) m[j] = ptr[SECTOR_SIZE * j + i]; rs_encode (m, ds, rr); for (j = 0; j < rr; j++) rptr[SECTOR_SIZE * j + i] = m[j + ds]; + free (m); } } #endif From 384ad7cc1b08beacd709e1b51e84feaee3d2c978 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:32:41 +0100 Subject: [PATCH 642/673] * grub-core/loader/i386/bsdXX.c (grub_freebsd_load_elfmodule): Fix current address calculation. --- ChangeLog | 5 +++++ grub-core/loader/i386/bsdXX.c | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0063cdf04..2bd1aa287 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/loader/i386/bsdXX.c (grub_freebsd_load_elfmodule): Fix + current address calculation. + 2011-12-15 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (decode_block): Allocate on heap and not diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c index 92d267534..7cec7a8ef 100644 --- a/grub-core/loader/i386/bsdXX.c +++ b/grub-core/loader/i386/bsdXX.c @@ -244,16 +244,16 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, curload = module + s->sh_addr + s->sh_size; } - load (file, UINT_TO_PTR (module), 0, sizeof (e)); + load (file, (grub_uint8_t *) chunk_src + module - *kern_end, 0, sizeof (e)); if (curload < module + sizeof (e)) curload = module + sizeof (e); - load (file, UINT_TO_PTR (curload), e.e_shoff, + load (file, (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_shoff, e.e_shnum * e.e_shentsize); e.e_shoff = curload - module; curload += e.e_shnum * e.e_shentsize; - load (file, UINT_TO_PTR (curload), e.e_phoff, + load (file, (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_phoff, e.e_phnum * e.e_phentsize); e.e_phoff = curload - module; curload += e.e_phnum * e.e_phentsize; From c476e6df168aaa6b9eb3be07060cb25e3ad6dca7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:35:54 +0100 Subject: [PATCH 643/673] * grub-core/gfxmenu/gui_label.c (label_paint): Handle the case text_width > available width a bit more gracefully. --- ChangeLog | 5 +++++ grub-core/gfxmenu/gui_label.c | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2bd1aa287..ff54cfe78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_label.c (label_paint): Handle the case + text_width > available width a bit more gracefully. + 2011-12-15 Vladimir Serbinenko * grub-core/loader/i386/bsdXX.c (grub_freebsd_load_elfmodule): Fix diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c index a7dc95afc..688bea077 100644 --- a/grub-core/gfxmenu/gui_label.c +++ b/grub-core/gfxmenu/gui_label.c @@ -94,15 +94,17 @@ label_paint (void *vself, const grub_video_rect_t *region) if (self->align == align_left) left_x = 0; else if (self->align == align_center) - left_x = ((self->bounds.width - - grub_font_get_string_width (self->font, self->text)) - ) / 2; + left_x = (self->bounds.width + - grub_font_get_string_width (self->font, self->text)) / 2; else if (self->align == align_right) left_x = (self->bounds.width - grub_font_get_string_width (self->font, self->text)); else return; /* Invalid alignment. */ + if (left_x < 0 || left_x > (int) self->bounds.width) + left_x = 0; + grub_video_rect_t vpsave; grub_gui_set_viewport (&self->bounds, &vpsave); grub_font_draw_string (self->text, From 5ef5c511475d74a10ff11a9600aee559fe7ec29c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:39:41 +0100 Subject: [PATCH 644/673] * util/grub-mkimage.c (generate_image): Decrease the higher limit because of stack. * util/grub-setup.c (setup): Don't add redundancy past the higher load limit. --- ChangeLog | 7 +++++++ util/grub-mkimage.c | 6 +++--- util/grub-setup.c | 4 ++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index ff54cfe78..6931c1b55 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-15 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Decrease the higher limit + because of stack. + * util/grub-setup.c (setup): Don't add redundancy past the higher load + limit. + 2011-12-15 Vladimir Serbinenko * grub-core/gfxmenu/gui_label.c (label_paint): Handle the case diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 0ffeb909e..de43c4493 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -958,10 +958,10 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *boot_path, *boot_img; size_t boot_size; - if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > GRUB_MEMORY_I386_PC_UPPER) - grub_util_error (_("core image is too big (%p > %p)"), + if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000) + grub_util_error (_("core image is too big (0x%x > 0x%x)"), GRUB_KERNEL_I386_PC_LINK_ADDR + core_size, - GRUB_MEMORY_I386_PC_UPPER); + 0x78000); num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); if (num > 0xffff) diff --git a/util/grub-setup.c b/util/grub-setup.c index 055543f2d..d3b3b7520 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -412,6 +412,10 @@ setup (const char *dir, if (nsec > 2 * core_sectors) nsec = 2 * core_sectors; + if (nsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) + >> GRUB_DISK_SECTOR_BITS)) + nsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) + >> GRUB_DISK_SECTOR_BITS); /* Clean out the blocklists. */ block = first_block; From f2b60fbdb8f384274ea8f3b7e29469a9613d0b77 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 19:59:49 +0100 Subject: [PATCH 645/673] Replace UINT_TO_PTR and PTR_TO_UINT with explicit grub_addr_t casts. * include/grub/types.h (UINT_TO_PTR): Removed. All users switched to grub_addr_t casts. (PTR_TO_UINT64): Likewise. (PTR_TO_UINT32): Likewise. --- ChangeLog | 9 +++++++++ grub-core/commands/acpi.c | 26 +++++++++++++------------- grub-core/efiemu/mm.c | 4 ++-- grub-core/efiemu/prepare.c | 5 ++--- grub-core/efiemu/symbols.c | 14 +++++++------- grub-core/loader/i386/xnu.c | 30 +++++++++++++++--------------- grub-core/mmap/i386/mmap.c | 6 +++--- grub-core/mmap/i386/pc/mmap.c | 4 ++-- include/grub/efiemu/efiemu.h | 4 ++-- include/grub/types.h | 10 ---------- 10 files changed, 55 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6931c1b55..1ce7fce0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-12-15 Vladimir Serbinenko + + Replace UINT_TO_PTR and PTR_TO_UINT with explicit grub_addr_t casts. + + * include/grub/types.h (UINT_TO_PTR): Removed. All users switched to + grub_addr_t casts. + (PTR_TO_UINT64): Likewise. + (PTR_TO_UINT32): Likewise. + 2011-12-15 Vladimir Serbinenko * util/grub-mkimage.c (generate_image): Decrease the higher limit diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index f394e3233..2531b8e11 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -166,7 +166,7 @@ grub_acpi_create_ebda (void) return 0; } - ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4); + ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4); ebda_kb_len = *(grub_uint16_t *) ebda; if (! ebda || ebda_kb_len > 16) ebda_kb_len = 0; @@ -174,14 +174,14 @@ grub_acpi_create_ebda (void) /* FIXME: use low-memory mm allocation once it's available. */ grub_mmap_iterate (find_hook); - targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow); + targetebda = (grub_uint8_t *) (grub_addr_t) highestlow; grub_dprintf ("acpi", "creating ebda @%llx\n", (unsigned long long) highestlow); if (! highestlow) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't find space for the new EBDA"); - mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len, + mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len, GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -330,13 +330,13 @@ setup_common_tables (void) if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE, sizeof (fadt->hdr.signature)) == 0) { - fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); + fadt->dsdt_addr = (grub_addr_t) table_dsdt; fadt->facs_addr = facs_addr; /* Does a revision 2 exist at all? */ if (fadt->hdr.revision >= 3) { - fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt); + fadt->dsdt_xaddr = (grub_addr_t) table_dsdt; fadt->facs_xaddr = facs_addr; } @@ -367,7 +367,7 @@ setup_common_tables (void) rsdt->creator_rev = root_creator_rev; for (cur = acpi_tables; cur; cur = cur->next) - *(rsdt_entry++) = PTR_TO_UINT32 (cur->addr); + *(rsdt_entry++) = (grub_addr_t) cur->addr; /* Recompute checksum. */ rsdt->checksum = 0; @@ -385,7 +385,7 @@ setv1table (void) sizeof (rsdpv1_new->signature)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); rsdpv1_new->revision = 0; - rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr); + rsdpv1_new->rsdt_addr = (grub_addr_t) rsdt_addr; rsdpv1_new->checksum = 0; rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new, sizeof (*rsdpv1_new)); @@ -410,7 +410,7 @@ setv2table (void) xsdt_entry = (grub_uint64_t *)(xsdt + 1); for (cur = acpi_tables; cur; cur = cur->next) - *(xsdt_entry++) = PTR_TO_UINT64 (cur->addr); + *(xsdt_entry++) = (grub_addr_t) cur->addr; grub_memcpy (&(xsdt->signature), "XSDT", 4); xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables; xsdt->revision = 1; @@ -430,12 +430,12 @@ setv2table (void) grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid, sizeof (rsdpv2_new->rsdpv1.oemid)); rsdpv2_new->rsdpv1.revision = rev2; - rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr); + rsdpv2_new->rsdpv1.rsdt_addr = (grub_addr_t) rsdt_addr; rsdpv2_new->rsdpv1.checksum = 0; rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum (&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1)); rsdpv2_new->length = sizeof (*rsdpv2_new); - rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt); + rsdpv2_new->xsdt_addr = (grub_addr_t) xsdt; rsdpv2_new->checksum = 0; rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new, rsdpv2_new->length); @@ -507,7 +507,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) /* Set revision variables to replicate the same version as host. */ rev1 = ! rsdp->revision; rev2 = rsdp->revision; - rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr); + rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; /* Load host tables. */ for (entry_ptr = (grub_uint32_t *) (rsdt + 1); entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) @@ -517,7 +517,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) char signature[5]; struct efiemu_acpi_table *table; struct grub_acpi_table_header *curtable - = (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr); + = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; signature[4] = 0; for (i = 0; i < 4;i++) signature[i] = grub_tolower (curtable->signature[i]); @@ -541,7 +541,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) /* Load DSDT if not excluded. */ dsdt = (struct grub_acpi_table_header *) - UINT_TO_PTR (fadt->dsdt_addr); + (grub_addr_t) fadt->dsdt_addr; if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt")) && (! load_only || grub_strword (load_only, "dsdt")) && dsdt->length >= sizeof (*dsdt)) diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index 7bb7cc080..f9596f124 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -201,10 +201,10 @@ efiemu_alloc_requests (void) - (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE); if (align_overhead == GRUB_EFIEMU_PAGESIZE) align_overhead = 0; - curptr = ((grub_uint8_t *)curptr) + align_overhead; + curptr = ((grub_uint8_t *) curptr) + align_overhead; /* Add the region to memory map */ - grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart), + grub_efiemu_add_to_mmap ((grub_addr_t) typestart, curptr - typestart, reqorder[i]); } diff --git a/grub-core/efiemu/prepare.c b/grub-core/efiemu/prepare.c index 171e092c9..5c3146490 100644 --- a/grub-core/efiemu/prepare.c +++ b/grub-core/efiemu/prepare.c @@ -97,10 +97,9 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks, grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid), sizeof (cur->guid)); if (cur->get_table) - conftables[i].vendor_table - = PTR_TO_UINT64 (cur->get_table (cur->data)); + conftables[i].vendor_table = (grub_addr_t) cur->get_table (cur->data); else - conftables[i].vendor_table = PTR_TO_UINT64 (cur->data); + conftables[i].vendor_table = (grub_addr_t) cur->data; } err = SUFFIX (grub_efiemu_crc) (); diff --git a/grub-core/efiemu/symbols.c b/grub-core/efiemu/symbols.c index 4fc546b59..7137fcbd9 100644 --- a/grub-core/efiemu/symbols.c +++ b/grub-core/efiemu/symbols.c @@ -169,7 +169,7 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle, else ptv_rels[ptv_written].plustype = 0; - ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr); + ptv_rels[ptv_written].addr = (grub_addr_t) addr; ptv_rels[ptv_written].size = size; ptv_written++; @@ -179,10 +179,10 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle, /* Compute the value */ if (minus_handle) - value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle)); + value -= (grub_addr_t) grub_efiemu_mm_obtain_request (minus_handle); if (plus_handle) - value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle)); + value += (grub_addr_t) grub_efiemu_mm_obtain_request (plus_handle); /* Write the value */ switch (size) @@ -248,16 +248,16 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size, switch (cur_relloc->size) { case 8: - *((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 4: - *((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 2: - *((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 1: - *((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr; break; } } diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index 4d3678ea1..98b635911 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -734,18 +734,18 @@ grub_cpu_xnu_fill_devicetree (void) #else if (SIZEOF_OF_UINTN == 4) { - ptr = UINT_TO_PTR (((grub_efiemu_configuration_table32_t *) - SYSTEM_TABLE_PTR (configuration_table))[i] - .vendor_table); + ptr = (void *) (grub_addr_t) ((grub_efiemu_configuration_table32_t *) + SYSTEM_TABLE_PTR (configuration_table))[i] + .vendor_table; guid = ((grub_efiemu_configuration_table32_t *) SYSTEM_TABLE_PTR (configuration_table))[i].vendor_guid; } else { - ptr = UINT_TO_PTR (((grub_efiemu_configuration_table64_t *) - SYSTEM_TABLE_PTR (configuration_table))[i] - .vendor_table); + ptr = (void *) (grub_addr_t) ((grub_efiemu_configuration_table64_t *) + SYSTEM_TABLE_PTR (configuration_table))[i] + .vendor_table; guid = ((grub_efiemu_configuration_table64_t *) SYSTEM_TABLE_PTR (configuration_table))[i].vendor_guid; @@ -786,9 +786,9 @@ grub_cpu_xnu_fill_devicetree (void) if (! curval->data) return grub_errno; if (SIZEOF_OF_UINTN == 4) - *((grub_uint32_t *)curval->data) = PTR_TO_UINT32 (ptr); + *((grub_uint32_t *) curval->data) = (grub_addr_t) ptr; else - *((grub_uint64_t *)curval->data) = PTR_TO_UINT64 (ptr); + *((grub_uint64_t *) curval->data) = (grub_addr_t) ptr; /* Create alias. */ for (j = 0; j < sizeof (table_aliases) / sizeof (table_aliases[0]); j++) @@ -821,10 +821,10 @@ grub_cpu_xnu_fill_devicetree (void) return grub_errno; if (SIZEOF_OF_UINTN == 4) *((grub_uint32_t *) curval->data) - = PTR_TO_UINT32 (SYSTEM_TABLE_PTR (runtime_services)); + = (grub_addr_t) SYSTEM_TABLE_PTR (runtime_services); else *((grub_uint64_t *) curval->data) - = PTR_TO_UINT64 (SYSTEM_TABLE_PTR (runtime_services)); + = (grub_addr_t) SYSTEM_TABLE_PTR (runtime_services); return GRUB_ERR_NONE; } @@ -939,7 +939,7 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) params->lfb_depth = mode_info.bpp; params->lfb_line_len = mode_info.pitch; - params->lfb_base = PTR_TO_UINT32 (framebuffer); + params->lfb_base = (grub_addr_t) framebuffer; params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH : GRUB_XNU_VIDEO_TEXT_IN_VIDEO; @@ -1057,7 +1057,7 @@ grub_xnu_boot (void) if (err) return err; - bootparams->efi_system_table = PTR_TO_UINT32 (grub_autoefi_system_table); + bootparams->efi_system_table = (grub_addr_t) grub_autoefi_system_table; firstruntimepage = (((grub_addr_t) grub_xnu_heap_target_start + grub_xnu_heap_size + GRUB_XNU_PAGESIZE - 1) @@ -1077,11 +1077,11 @@ grub_xnu_boot (void) curdesc->virtual_start = curruntimepage << 12; curruntimepage += curdesc->num_pages; if (curdesc->physical_start - <= PTR_TO_UINT64 (grub_autoefi_system_table) + <= (grub_addr_t) grub_autoefi_system_table && curdesc->physical_start + (curdesc->num_pages << 12) - > PTR_TO_UINT64 (grub_autoefi_system_table)) + > (grub_addr_t) grub_autoefi_system_table) bootparams->efi_system_table - = PTR_TO_UINT64 (grub_autoefi_system_table) + = (grub_addr_t) grub_autoefi_system_table - curdesc->physical_start + curdesc->virtual_start; if (SIZEOF_OF_UINTN == 8 && grub_xnu_is_64bit) curdesc->virtual_start |= 0xffffff8000000000ULL; diff --git a/grub-core/mmap/i386/mmap.c b/grub-core/mmap/i386/mmap.c index e9c030b7b..648a7df4b 100644 --- a/grub-core/mmap/i386/mmap.c +++ b/grub-core/mmap/i386/mmap.c @@ -54,7 +54,7 @@ grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size, { /* FIXME: use low-memory mm allocation once it's available. */ grub_mmap_iterate (find_hook); - ret = UINT_TO_PTR (highestlow); + ret = (void *) (grub_addr_t) highestlow; } else ret = grub_memalign (align, size); @@ -65,7 +65,7 @@ grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size, return 0; } - *handle = grub_mmap_register (PTR_TO_UINT64 (ret), size, type); + *handle = grub_mmap_register ((grub_addr_t) ret, size, type); if (! *handle) { grub_free (ret); @@ -93,7 +93,7 @@ grub_mmap_free_and_unregister (int handle) grub_mmap_unregister (handle); if (addr >= 0x100000) - grub_free (UINT_TO_PTR (addr)); + grub_free ((void *) (grub_addr_t) addr); } #endif diff --git a/grub-core/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c index baa41aa2d..7f170b65d 100644 --- a/grub-core/mmap/i386/pc/mmap.c +++ b/grub-core/mmap/i386/pc/mmap.c @@ -101,8 +101,8 @@ preboot (int noreturn __attribute__ ((unused))) grub_memcpy (hooktarget, &grub_machine_mmaphook_start, &grub_machine_mmaphook_end - &grub_machine_mmaphook_start); - *((grub_uint16_t *) 0x4a) = PTR_TO_UINT32 (hooktarget) >> 4; - *((grub_uint16_t *) 0x56) = PTR_TO_UINT32 (hooktarget) >> 4; + *((grub_uint16_t *) 0x4a) = ((grub_addr_t) hooktarget) >> 4; + *((grub_uint16_t *) 0x56) = ((grub_addr_t) hooktarget) >> 4; *((grub_uint16_t *) 0x48) = &grub_machine_mmaphook_int12 - &grub_machine_mmaphook_start; *((grub_uint16_t *) 0x54) = &grub_machine_mmaphook_int15 diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index ec35dac5a..530e18c82 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -114,9 +114,9 @@ extern grub_efi_system_table64_t *grub_efiemu_system_table64; : (grub_efiemu_system_table32->x \ = (y))) #define GRUB_EFIEMU_SYSTEM_TABLE_PTR(x) ((grub_efiemu_sizeof_uintn_t () == 8)\ - ? UINT_TO_PTR \ + ? (void *) (grub_addr_t) \ (grub_efiemu_system_table64->x) \ - : UINT_TO_PTR \ + : (void *) (grub_addr_t) \ (grub_efiemu_system_table32->x)) #define GRUB_EFIEMU_SYSTEM_TABLE_VAR(x) ((grub_efiemu_sizeof_uintn_t () == 8) \ ? (void *) \ diff --git a/include/grub/types.h b/include/grub/types.h index 19a09895b..f8059c1ab 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -130,16 +130,6 @@ typedef grub_int32_t grub_ssize_t; # define GRUB_LONG_MIN (-2147483647L - 1) #endif -#if GRUB_CPU_SIZEOF_VOID_P == 4 -#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x)) -#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x)) -#define PTR_TO_UINT32(x) ((grub_uint32_t)(x)) -#else -#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x)) -#define PTR_TO_UINT64(x) ((grub_uint64_t)(x)) -#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x)) -#endif - typedef grub_uint64_t grub_properly_aligned_t; #define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] From 3a38c6723540a39bc3e93d2b43423d899f5422ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:04:21 +0100 Subject: [PATCH 646/673] forgotten file for previous commit --- grub-core/mmap/efi/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c index 8e5cce0d0..b34a3ba30 100644 --- a/grub-core/mmap/efi/mmap.c +++ b/grub-core/mmap/efi/mmap.c @@ -272,7 +272,7 @@ grub_mmap_malign_and_register (grub_uint64_t align __attribute__ ((unused)), overlays = curover; *handle = curover->handle; - return UINT_TO_PTR (curover->address); + return (void *) (grub_addr_t) curover->address; } void From 813c0a2be82a00d4117d8071ae9e6a074d7672f6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:05:27 +0100 Subject: [PATCH 647/673] * grub-core/loader/multiboot.c (grub_cmd_module): Fix target address. --- ChangeLog | 4 ++++ grub-core/loader/multiboot.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1ce7fce0e..009d52f08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/loader/multiboot.c (grub_cmd_module): Fix target address. + 2011-12-15 Vladimir Serbinenko Replace UINT_TO_PTR and PTR_TO_UINT with explicit grub_addr_t casts. diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 2de8e0909..f76123e67 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -309,7 +309,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), return err; } module = get_virtual_current_address (ch); - target = (grub_addr_t) get_virtual_current_address (ch); + target = get_physical_target_address (ch); } err = grub_multiboot_add_module (target, size, argc - 1, argv + 1); From 8e54b4b76ab5df4754ef31a44803e2d085dd3850 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:20:02 +0100 Subject: [PATCH 648/673] * grub-core/lib/libgcrypt/cipher/serpent.c (serpent_key_prepare): Fix misaligned access. (serpent_setkey): Likewise. (serpent_encrypt_internal): Likewise. (serpent_decrypt_internal): Likewise. (serpent_encrypt): Don't put an alignment-increasing cast. (serpent_decrypt): Likewise. (serpent_test): Likewise. --- ChangeLog | 11 +++ grub-core/lib/libgcrypt/cipher/serpent.c | 91 +++++++++--------------- 2 files changed, 45 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 009d52f08..7f44d38ed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/lib/libgcrypt/cipher/serpent.c (serpent_key_prepare): Fix + misaligned access. + (serpent_setkey): Likewise. + (serpent_encrypt_internal): Likewise. + (serpent_decrypt_internal): Likewise. + (serpent_encrypt): Don't put an alignment-increasing cast. + (serpent_decrypt): Likewise. + (serpent_test): Likewise. + 2011-12-15 Vladimir Serbinenko * grub-core/loader/multiboot.c (grub_cmd_module): Fix target address. diff --git a/grub-core/lib/libgcrypt/cipher/serpent.c b/grub-core/lib/libgcrypt/cipher/serpent.c index 6b7e655a9..b1026eafc 100644 --- a/grub-core/lib/libgcrypt/cipher/serpent.c +++ b/grub-core/lib/libgcrypt/cipher/serpent.c @@ -585,22 +585,19 @@ serpent_key_prepare (const byte *key, unsigned int key_length, int i; /* Copy key. */ - for (i = 0; i < key_length / 4; i++) - { + memcpy (key_prepared, key, key_length); #ifdef WORDS_BIGENDIAN - key_prepared[i] = byte_swap_32 (((u32 *) key)[i]); -#else - key_prepared[i] = ((u32 *) key)[i]; + for (i = 0; i < key_length / 4; i++) + key_prepared[i] = byte_swap_32 (key_prepared[i]); #endif - } - if (i < 8) + if (key_length < 32) { /* Key must be padded according to the Serpent specification. */ - key_prepared[i] = 0x00000001; + key_prepared[key_length / 4] = 0x00000001; - for (i++; i < 8; i++) + for (i = key_length / 4 + 1; i < 8; i++) key_prepared[i] = 0; } } @@ -707,21 +704,17 @@ serpent_setkey (void *ctx, static void serpent_encrypt_internal (serpent_context_t *context, - const serpent_block_t input, serpent_block_t output) + const byte *input, byte *output) { serpent_block_t b, b_next; int round = 0; + memcpy (b, input, sizeof (b)); #ifdef WORDS_BIGENDIAN - b[0] = byte_swap_32 (input[0]); - b[1] = byte_swap_32 (input[1]); - b[2] = byte_swap_32 (input[2]); - b[3] = byte_swap_32 (input[3]); -#else - b[0] = input[0]; - b[1] = input[1]; - b[2] = input[2]; - b[3] = input[3]; + b[0] = byte_swap_32 (b[0]); + b[1] = byte_swap_32 (b[1]); + b[2] = byte_swap_32 (b[2]); + b[3] = byte_swap_32 (b[3]); #endif ROUND (0, context->keys, b, b_next); @@ -759,35 +752,27 @@ serpent_encrypt_internal (serpent_context_t *context, ROUND_LAST (7, context->keys, b, b_next); #ifdef WORDS_BIGENDIAN - output[0] = byte_swap_32 (b_next[0]); - output[1] = byte_swap_32 (b_next[1]); - output[2] = byte_swap_32 (b_next[2]); - output[3] = byte_swap_32 (b_next[3]); -#else - output[0] = b_next[0]; - output[1] = b_next[1]; - output[2] = b_next[2]; - output[3] = b_next[3]; + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); #endif + memcpy (output, b_next, sizeof (b_next)); } static void serpent_decrypt_internal (serpent_context_t *context, - const serpent_block_t input, serpent_block_t output) + const byte *input, byte *output) { serpent_block_t b, b_next; int round = ROUNDS; + memcpy (b, input, sizeof (b)); #ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (input[0]); - b_next[1] = byte_swap_32 (input[1]); - b_next[2] = byte_swap_32 (input[2]); - b_next[3] = byte_swap_32 (input[3]); -#else - b_next[0] = input[0]; - b_next[1] = input[1]; - b_next[2] = input[2]; - b_next[3] = input[3]; + b[0] = byte_swap_32 (b[0]); + b[1] = byte_swap_32 (b[1]); + b[2] = byte_swap_32 (b[2]); + b[3] = byte_swap_32 (b[3]); #endif ROUND_FIRST_INVERSE (7, context->keys, b_next, b); @@ -824,18 +809,13 @@ serpent_decrypt_internal (serpent_context_t *context, ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); - #ifdef WORDS_BIGENDIAN - output[0] = byte_swap_32 (b_next[0]); - output[1] = byte_swap_32 (b_next[1]); - output[2] = byte_swap_32 (b_next[2]); - output[3] = byte_swap_32 (b_next[3]); -#else - output[0] = b_next[0]; - output[1] = b_next[1]; - output[2] = b_next[2]; - output[3] = b_next[3]; + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); #endif + memcpy (output, b_next, sizeof (b_next)); } static void @@ -843,8 +823,7 @@ serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; - serpent_encrypt_internal (context, - (const u32 *) buffer_in, (u32 *) buffer_out); + serpent_encrypt_internal (context, buffer_in, buffer_out); _gcry_burn_stack (2 * sizeof (serpent_block_t)); } @@ -853,9 +832,7 @@ serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; - serpent_decrypt_internal (context, - (const u32 *) buffer_in, - (u32 *) buffer_out); + serpent_decrypt_internal (context, buffer_in, buffer_out); _gcry_burn_stack (2 * sizeof (serpent_block_t)); } @@ -915,8 +892,8 @@ serpent_test (void) serpent_setkey_internal (&context, test_data[i].key, test_data[i].key_length); serpent_encrypt_internal (&context, - (const u32 *) test_data[i].text_plain, - (u32 *) scratch); + test_data[i].text_plain, + scratch); if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t))) switch (test_data[i].key_length) @@ -930,8 +907,8 @@ serpent_test (void) } serpent_decrypt_internal (&context, - (const u32 *) test_data[i].text_cipher, - (u32 *) scratch); + test_data[i].text_cipher, + scratch); if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t))) switch (test_data[i].key_length) { From e5f4d2607a7e6933b4dea713a921de30dda6508c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:26:17 +0100 Subject: [PATCH 649/673] * grub-core/lib/libgcrypt/cipher/md4.c (transform) [WORDS_BIGENDIAN]: Add missing const attribute. * grub-core/lib/libgcrypt/cipher/md5.c (transform) [WORDS_BIGENDIAN]: Likewise. * grub-core/lib/libgcrypt/cipher/rmd160.c (transform) [WORDS_BIGENDIAN]: Likewise. --- ChangeLog | 9 +++++++++ grub-core/lib/libgcrypt/cipher/md4.c | 3 ++- grub-core/lib/libgcrypt/cipher/md5.c | 3 ++- grub-core/lib/libgcrypt/cipher/rmd160.c | 3 ++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7f44d38ed..e3eee32c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-12-15 Vladimir Serbinenko + + * grub-core/lib/libgcrypt/cipher/md4.c (transform) [WORDS_BIGENDIAN]: + Add missing const attribute. + * grub-core/lib/libgcrypt/cipher/md5.c (transform) [WORDS_BIGENDIAN]: + Likewise. + * grub-core/lib/libgcrypt/cipher/rmd160.c (transform) [WORDS_BIGENDIAN]: + Likewise. + 2011-12-15 Vladimir Serbinenko * grub-core/lib/libgcrypt/cipher/serpent.c (serpent_key_prepare): Fix diff --git a/grub-core/lib/libgcrypt/cipher/md4.c b/grub-core/lib/libgcrypt/cipher/md4.c index 680cf87f5..aa180f0d4 100644 --- a/grub-core/lib/libgcrypt/cipher/md4.c +++ b/grub-core/lib/libgcrypt/cipher/md4.c @@ -101,7 +101,8 @@ transform ( MD4_CONTEXT *ctx, const unsigned char *data ) #ifdef WORDS_BIGENDIAN { int i; - byte *p2, *p1; + byte *p2; + const byte *p1; for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; diff --git a/grub-core/lib/libgcrypt/cipher/md5.c b/grub-core/lib/libgcrypt/cipher/md5.c index 899dce89a..3d3046df2 100644 --- a/grub-core/lib/libgcrypt/cipher/md5.c +++ b/grub-core/lib/libgcrypt/cipher/md5.c @@ -92,7 +92,8 @@ transform ( MD5_CONTEXT *ctx, const unsigned char *data ) #ifdef WORDS_BIGENDIAN { int i; - byte *p2, *p1; + byte *p2; + const byte *p1; for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; diff --git a/grub-core/lib/libgcrypt/cipher/rmd160.c b/grub-core/lib/libgcrypt/cipher/rmd160.c index 7805bf53b..73d533739 100644 --- a/grub-core/lib/libgcrypt/cipher/rmd160.c +++ b/grub-core/lib/libgcrypt/cipher/rmd160.c @@ -169,7 +169,8 @@ transform ( RMD160_CONTEXT *hd, const unsigned char *data ) u32 x[16]; { int i; - byte *p2, *p1; + byte *p2; + const byte *p1; for (i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; From 70ffcc93eeb714992b6e90b6b2ae3feeb7444006 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:29:30 +0100 Subject: [PATCH 650/673] * util/grub-mkimage.c (generate_image): Clean multiboot header to avoid confusing ipxe. --- ChangeLog | 5 +++++ util/grub-mkimage.c | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/ChangeLog b/ChangeLog index e3eee32c4..d7c458d15 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-15 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Clean multiboot header to avoid + confusing ipxe. + 2011-12-15 Vladimir Serbinenko * grub-core/lib/libgcrypt/cipher/md4.c (transform) [WORDS_BIGENDIAN]: diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index de43c4493..ca8047df6 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -971,6 +972,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], { char *pxeboot_path, *pxeboot_img; size_t pxeboot_size; + grub_uint32_t *ptr; pxeboot_path = grub_util_get_path (dir, "pxeboot.img"); pxeboot_size = grub_util_get_image_size (pxeboot_path); @@ -979,6 +981,18 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_util_write_image (pxeboot_img, pxeboot_size, out); free (pxeboot_img); free (pxeboot_path); + + /* Remove Multiboot header to avoid confusing ipxe. */ + for (ptr = (grub_uint32_t *) core_img; + ptr < (grub_uint32_t *) (core_img + MULTIBOOT_SEARCH); ptr++) + if (*ptr == grub_host_to_target32 (MULTIBOOT_HEADER_MAGIC) + && grub_target_to_host32 (ptr[0]) + + grub_target_to_host32 (ptr[1]) + + grub_target_to_host32 (ptr[2]) == 0) + { + *ptr = 0; + break; + } } boot_path = grub_util_get_path (dir, "diskboot.img"); From ff6b18b6182cbb3a16094257b89acd6b607d32ae Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:32:02 +0100 Subject: [PATCH 651/673] * util/import_gcry.py: Don't add include camellia.h to camellia.c. It's already there. --- ChangeLog | 5 +++++ util/import_gcry.py | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d7c458d15..d7523e116 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-15 Vladimir Serbinenko + + * util/import_gcry.py: Don't add include camellia.h to camellia.c. It's + already there. + 2011-12-15 Vladimir Serbinenko * util/grub-mkimage.c (generate_image): Clean multiboot header to avoid diff --git a/util/import_gcry.py b/util/import_gcry.py index ec34d16b5..ae9602db4 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -105,8 +105,6 @@ for cipher_file in cipher_files: fw.write ("/* This file was automatically imported with \n") fw.write (" import_gcry.py. Please don't modify it */\n") fw.write ("#include \n") - if cipher_file == "camellia.c": - fw.write ("#include \"camellia.h\"\n") if cipher_file == "camellia.h": fw.write ("#include \n") fw.write ("void camellia_setup128(const unsigned char *key, grub_uint32_t *subkey);\n") From c17e546ccab4b56c01cae45e27fc55ae244f5a97 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:33:32 +0100 Subject: [PATCH 652/673] * util/import_gcry.py: Skip _gcry_rmd160_mixblock and serpent_test. We don't use them. --- ChangeLog | 5 +++++ util/import_gcry.py | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d7523e116..74aa2a60d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-15 Vladimir Serbinenko + + * util/import_gcry.py: Skip _gcry_rmd160_mixblock and serpent_test. We + don't use them. + 2011-12-15 Vladimir Serbinenko * util/import_gcry.py: Don't add include camellia.h to camellia.c. It's diff --git a/util/import_gcry.py b/util/import_gcry.py index ae9602db4..e55ffd97b 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -190,8 +190,10 @@ for cipher_file in cipher_files: if hold: hold = False # We're optimising for size. - if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info)", line) is None: + if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info|_gcry_rmd160_mixblock|serpent_test)", line) is None: skip = True + if not re.match ("serpent_test", line) is None: + fw.write ("static const char *serpent_test (void) { return 0; }\n"); fname = re.match ("[a-zA-Z0-9_]*", line).group () chmsg = "(%s): Removed." % fname if nch: From 078d2b2e6853466ff84bc5fc777ac3d7305e6f8d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 15 Dec 2011 20:50:21 +0100 Subject: [PATCH 653/673] Add forgotten file --- grub-core/net/dns.c | 424 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 grub-core/net/dns.c diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c new file mode 100644 index 000000000..47eb68e01 --- /dev/null +++ b/grub-core/net/dns.c @@ -0,0 +1,424 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 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 . + */ + +#include +#include +#include +#include +#include + +struct dns_cache_element +{ + char *name; + grub_size_t naddresses; + struct grub_net_network_level_address *addresses; + struct grub_net_network_level_address *source; + grub_uint64_t limit_time; +}; + +struct dns_header +{ + grub_uint16_t id; + grub_uint8_t flags; + grub_uint8_t ra_z_r_code; + grub_uint16_t qdcount; + grub_uint16_t ancount; + grub_uint16_t nscount; + grub_uint16_t arcount; +} __attribute__ ((packed)); + +enum + { + FLAGS_RESPONSE = 0x80, + FLAGS_OPCODE = 0x78, + FLAGS_RD = 0x01 + }; + +enum + { + ERRCODE_MASK = 0x0f + }; + +enum + { + DNS_PORT = 53 + }; + +struct recv_data +{ + grub_size_t *naddresses; + struct grub_net_network_level_address **addresses; + int cache; + grub_uint16_t id; + int dns_err; + const char *name; +}; + +static int +check_name (const grub_uint8_t *name_at, const grub_uint8_t *head, + const grub_uint8_t *tail, const char *check_with) +{ + const char *readable_ptr = check_with; + const grub_uint8_t *ptr; + int bytes_processed = 0; + for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; ) + { + /* End marker. */ + if (!*ptr) + return (*readable_ptr == 0); + if (*ptr & 0xc0) + { + bytes_processed += 2; + if (ptr + 1 >= tail) + return 0; + ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]); + continue; + } + if (grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) + return 0; + if (grub_memchr (ptr + 1, 0, *ptr) + || grub_memchr (ptr + 1, '.', *ptr)) + return 0; + if (readable_ptr[*ptr] != '.' && readable_ptr[*ptr] != 0) + return 0; + bytes_processed += *ptr + 1; + readable_ptr += *ptr; + if (*readable_ptr) + readable_ptr++; + ptr += *ptr + 1; + } + return 0; +} + +static grub_err_t +recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), + struct grub_net_buff *nb, + void *data_) +{ + struct dns_header *head; + struct recv_data *data = data_; + int i, j; + grub_uint8_t *ptr; + + head = (struct dns_header *) nb->data; + ptr = (grub_uint8_t *) (head + 1); + if (ptr >= nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if (head->id != data->id) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (!(head->flags & FLAGS_RESPONSE) || (head->flags & FLAGS_OPCODE)) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (head->ra_z_r_code & ERRCODE_MASK) + { + data->dns_err = 1; + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + for (i = 0; i < grub_cpu_to_be16 (head->qdcount); i++) + { + if (ptr >= nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0)) + ptr += *ptr + 1; + if (ptr < nb->tail && (*ptr & 0xc0)) + ptr++; + ptr++; + ptr += 4; + } + *data->addresses = grub_malloc (sizeof ((*data->addresses)[0]) + * grub_cpu_to_be16 (head->ancount)); + if (!*data->addresses) + { + grub_errno = GRUB_ERR_NONE; + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + for (i = 0; i < grub_cpu_to_be16 (head->ancount); i++) + { + int ignored = 0; + int is_ipv6 = 0; + grub_uint32_t ttl = 0; + grub_uint16_t length; + if (ptr >= nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + return GRUB_ERR_NONE; + } + ignored = !check_name (ptr, nb->data, nb->tail, data->name); + while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0)) + ptr += *ptr + 1; + if (ptr < nb->tail && (*ptr & 0xc0)) + ptr++; + ptr++; + if (ptr + 10 >= nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (*ptr++ != 0) + ignored = 1; + if (*ptr != 1 && *ptr != 28) + ignored = 1; + if (*ptr == 28) + is_ipv6 = 1; + ptr++; + if (*ptr++ != 0) + ignored = 1; + if (*ptr++ != 1) + ignored = 1; + for (j = 0; j < 4; j++) + { + ttl >>= 8; + ttl = *ptr++ << 28; + } + length = *ptr++ << 8; + length |= *ptr++; + if (ptr + length > nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (!ignored && !is_ipv6 && length == 4) + { + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, + ptr, 4); + (*data->naddresses)++; + } + if (!ignored && is_ipv6 && length == 16) + { + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, + ptr, 16); + (*data->naddresses)++; + } + ptr += length; + } + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} + +grub_err_t +grub_net_dns_lookup (const char *name, + const struct grub_net_network_level_address *servers, + grub_size_t n_servers, + grub_size_t *naddresses, + struct grub_net_network_level_address **addresses, + int cache) +{ + grub_size_t send_servers = 0; + grub_size_t i, j; + struct grub_net_buff *nb; + grub_net_udp_socket_t sockets[n_servers]; + grub_uint8_t *optr; + const char *iptr; + struct dns_header *head; + static grub_uint16_t id = 1; + grub_err_t err = GRUB_ERR_NONE; + struct recv_data data = {naddresses, addresses, cache, + grub_cpu_to_be16 (id++), 0, name}; + grub_uint8_t *nbd; + int have_server = 0; + + *naddresses = 0; + /* if (cache && cache_lookup (name, servers, n_servers, addresses)) + return GRUB_ERR_NONE;*/ + + nb = grub_netbuff_alloc (GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE + + GRUB_NET_UDP_HEADER_SIZE + + sizeof (struct dns_header) + + grub_strlen (name) + 2 + 4 + + 2 + 4); + if (!nb) + return grub_errno; + grub_netbuff_reserve (nb, GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE + + GRUB_NET_UDP_HEADER_SIZE); + grub_netbuff_put (nb, sizeof (struct dns_header) + + grub_strlen (name) + 2 + 4 + 2 + 4); + head = (struct dns_header *) nb->data; + optr = (grub_uint8_t *) (head + 1); + for (iptr = name; *iptr; ) + { + const char *dot; + dot = grub_strchr (iptr, '.'); + if (!dot) + dot = iptr + grub_strlen (iptr); + if ((dot - iptr) >= 64) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "domain component is too long"); + *optr = (dot - iptr); + optr++; + grub_memcpy (optr, iptr, dot - iptr); + optr += dot - iptr; + iptr = dot; + if (*iptr) + iptr++; + } + *optr++ = 0; + + /* Type: A. */ + *optr++ = 0; + *optr++ = 1; + + /* Class. */ + *optr++ = 0; + *optr++ = 1; + + /* Compressed name. */ + *optr++ = 0xc0; + *optr++ = 0x0c; + /* Type: AAAA. */ + *optr++ = 0; + *optr++ = 28; + + /* Class. */ + *optr++ = 0; + *optr++ = 1; + + head->id = data.id; + head->flags = FLAGS_RD; + head->ra_z_r_code = 0; + head->qdcount = grub_cpu_to_be16_compile_time (2); + head->ancount = grub_cpu_to_be16_compile_time (0); + head->nscount = grub_cpu_to_be16_compile_time (0); + head->arcount = grub_cpu_to_be16_compile_time (0); + + nbd = nb->data; + + for (i = 0; i < n_servers * 4; i++) + { + /* Connect to a next server. */ + while (!(i & 1) && send_servers < n_servers) + { + sockets[send_servers] = grub_net_udp_open (servers[send_servers], + DNS_PORT, + recv_hook, + &data); + send_servers++; + if (!sockets[send_servers - 1]) + { + err = grub_errno; + grub_errno = GRUB_ERR_NONE; + } + else + { + have_server = 1; + break; + } + } + if (!have_server) + goto out; + if (*data.naddresses) + goto out; + for (j = 0; j < send_servers; j++) + { + grub_err_t err2; + if (!sockets[j]) + continue; + nb->data = nbd; + err2 = grub_net_send_udp_packet (sockets[j], nb); + if (err2) + { + grub_errno = GRUB_ERR_NONE; + err = err2; + } + if (*data.naddresses) + goto out; + } + grub_net_poll_cards (200); + } + out: + grub_netbuff_free (nb); + for (j = 0; j < send_servers; j++) + grub_net_udp_close (sockets[j]); + if (*data.naddresses) + return GRUB_ERR_NONE; + if (data.dns_err) + return grub_error (GRUB_ERR_NET_NO_DOMAIN, "no DNS domain found"); + + if (err) + { + grub_errno = err; + return err; + } + return grub_error (GRUB_ERR_TIMEOUT, "no DNS reply received"); +} + +static grub_err_t +grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t err; + struct grub_net_network_level_address server; + grub_size_t naddresses, i; + struct grub_net_network_level_address *addresses; + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected"); + err = grub_net_resolve_address (args[1], &server); + if (err) + return err; + + err = grub_net_dns_lookup (args[0], &server, 1, &naddresses, &addresses, 0); + if (err) + return err; + for (i = 0; i < naddresses; i++) + { + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_addr_to_str (&addresses[i], buf); + grub_printf ("%s\n", buf); + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +void +grub_dns_init (void) +{ + cmd = grub_register_command ("net_nslookup", grub_cmd_nslookup, + "ADDRESS DNSSERVER", + N_("perform a DNS lookup")); +} + +void +grub_dns_fini (void) +{ + grub_unregister_command (cmd); +} From 3729fcfc1ac31ec5feeba15d8e03cdd6586e2967 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Dec 2011 13:43:31 +0100 Subject: [PATCH 654/673] support cname --- grub-core/net/dns.c | 167 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 133 insertions(+), 34 deletions(-) diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index 47eb68e01..b3ea83223 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -66,21 +66,33 @@ struct recv_data int cache; grub_uint16_t id; int dns_err; - const char *name; + char *name; }; static int -check_name (const grub_uint8_t *name_at, const grub_uint8_t *head, - const grub_uint8_t *tail, const char *check_with) +check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + const grub_uint8_t *tail, const char *check_with, + int *length, char *set) { const char *readable_ptr = check_with; const grub_uint8_t *ptr; + char *optr = set; int bytes_processed = 0; + if (length) + *length = 0; for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; ) { /* End marker. */ if (!*ptr) - return (*readable_ptr == 0); + { + if (length && *length) + (*length)--; + if (optr && optr != set) + optr--; + if (optr) + *optr = 0; + return !readable_ptr || (*readable_ptr == 0); + } if (*ptr & 0xc0) { bytes_processed += 2; @@ -89,22 +101,66 @@ check_name (const grub_uint8_t *name_at, const grub_uint8_t *head, ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]); continue; } - if (grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) + if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) return 0; if (grub_memchr (ptr + 1, 0, *ptr) || grub_memchr (ptr + 1, '.', *ptr)) return 0; - if (readable_ptr[*ptr] != '.' && readable_ptr[*ptr] != 0) + if (readable_ptr) + readable_ptr += *ptr; + if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0) return 0; bytes_processed += *ptr + 1; - readable_ptr += *ptr; - if (*readable_ptr) + if (length) + *length += *ptr + 1; + if (optr) + { + grub_memcpy (optr, ptr + 1, *ptr); + optr += *ptr; + } + if (optr) + *optr++ = '.'; + if (readable_ptr && *readable_ptr) readable_ptr++; ptr += *ptr + 1; } return 0; } +static int +check_name (const grub_uint8_t *name_at, const grub_uint8_t *head, + const grub_uint8_t *tail, const char *check_with) +{ + return check_name_real (name_at, head, tail, check_with, NULL, NULL); +} + +static char * +get_name (const grub_uint8_t *name_at, const grub_uint8_t *head, + const grub_uint8_t *tail) +{ + int length; + char *ret; + + if (!check_name_real (name_at, head, tail, NULL, &length, NULL)) + return NULL; + ret = grub_malloc (length + 1); + if (!ret) + return NULL; + if (!check_name_real (name_at, head, tail, NULL, NULL, ret)) + { + grub_free (ret); + return NULL; + } + return ret; +} + +enum + { + DNS_CLASS_A = 1, + DNS_CLASS_CNAME = 5, + DNS_CLASS_AAAA = 28 + }; + static grub_err_t recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), struct grub_net_buff *nb, @@ -113,7 +169,9 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), struct dns_header *head; struct recv_data *data = data_; int i, j; - grub_uint8_t *ptr; + grub_uint8_t *ptr, *reparse_ptr; + int redirect_cnt = 0; + char *redirect_save = NULL; head = (struct dns_header *) nb->data; ptr = (grub_uint8_t *) (head + 1); @@ -161,10 +219,12 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_netbuff_free (nb); return GRUB_ERR_NONE; } - for (i = 0; i < grub_cpu_to_be16 (head->ancount); i++) + reparse_ptr = ptr; + reparse: + for (i = 0, ptr = reparse_ptr; i < grub_cpu_to_be16 (head->ancount); i++) { int ignored = 0; - int is_ipv6 = 0; + grub_uint8_t class; grub_uint32_t ttl = 0; grub_uint16_t length; if (ptr >= nb->tail) @@ -188,11 +248,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), } if (*ptr++ != 0) ignored = 1; - if (*ptr != 1 && *ptr != 28) - ignored = 1; - if (*ptr == 28) - is_ipv6 = 1; - ptr++; + class = *ptr++; if (*ptr++ != 0) ignored = 1; if (*ptr++ != 1) @@ -211,25 +267,56 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_netbuff_free (nb); return GRUB_ERR_NONE; } - if (!ignored && !is_ipv6 && length == 4) - { - (*data->addresses)[*data->naddresses].type - = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, - ptr, 4); - (*data->naddresses)++; - } - if (!ignored && is_ipv6 && length == 16) - { - (*data->addresses)[*data->naddresses].type - = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; - grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, + if (!ignored) + switch (class) + { + case DNS_CLASS_A: + if (length != 4) + break; + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, + ptr, 4); + (*data->naddresses)++; + break; + case DNS_CLASS_AAAA: + if (length != 16) + break; + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, ptr, 16); - (*data->naddresses)++; + (*data->naddresses)++; + break; + case DNS_CLASS_CNAME: + if (!(redirect_cnt & (redirect_cnt - 1))) + { + grub_free (redirect_save); + redirect_save = data->name; + } + else + grub_free (data->name); + redirect_cnt++; + data->name = get_name (ptr, nb->data, nb->tail); + if (!data->name) + { + data->dns_err = 1; + grub_errno = 0; + return GRUB_ERR_NONE; + } + grub_dprintf ("dns", "CNAME %s\n", data->name); + if (grub_strcmp (redirect_save, data->name) == 0) + { + data->dns_err = 1; + grub_free (redirect_save); + return GRUB_ERR_NONE; + } + goto reparse; } ptr += length; } grub_netbuff_free (nb); + grub_free (redirect_save); return GRUB_ERR_NONE; } @@ -251,10 +338,14 @@ grub_net_dns_lookup (const char *name, static grub_uint16_t id = 1; grub_err_t err = GRUB_ERR_NONE; struct recv_data data = {naddresses, addresses, cache, - grub_cpu_to_be16 (id++), 0, name}; + grub_cpu_to_be16 (id++), 0, 0}; grub_uint8_t *nbd; int have_server = 0; + data.name = grub_strdup (name); + if (!data.name) + return grub_errno; + *naddresses = 0; /* if (cache && cache_lookup (name, servers, n_servers, addresses)) return GRUB_ERR_NONE;*/ @@ -266,7 +357,10 @@ grub_net_dns_lookup (const char *name, + grub_strlen (name) + 2 + 4 + 2 + 4); if (!nb) - return grub_errno; + { + grub_free (data.name); + return grub_errno; + } grub_netbuff_reserve (nb, GRUB_NET_OUR_MAX_IP_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE + GRUB_NET_UDP_HEADER_SIZE); @@ -281,8 +375,11 @@ grub_net_dns_lookup (const char *name, if (!dot) dot = iptr + grub_strlen (iptr); if ((dot - iptr) >= 64) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "domain component is too long"); + { + grub_free (data.name); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "domain component is too long"); + } *optr = (dot - iptr); optr++; grub_memcpy (optr, iptr, dot - iptr); @@ -365,9 +462,11 @@ grub_net_dns_lookup (const char *name, grub_net_poll_cards (200); } out: + grub_free (data.name); grub_netbuff_free (nb); for (j = 0; j < send_servers; j++) grub_net_udp_close (sockets[j]); + if (*data.naddresses) return GRUB_ERR_NONE; if (data.dns_err) From 8d4e4fc0e58e63105ba04e6d80b0ff2c1eaea08e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Dec 2011 15:08:46 +0100 Subject: [PATCH 655/673] DNS cache support --- grub-core/net/dns.c | 169 +++++++++++++++++++++++++++++++------------- 1 file changed, 119 insertions(+), 50 deletions(-) diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index b3ea83223..93550171a 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -21,16 +21,21 @@ #include #include #include +#include struct dns_cache_element { char *name; grub_size_t naddresses; struct grub_net_network_level_address *addresses; - struct grub_net_network_level_address *source; grub_uint64_t limit_time; }; +#define DNS_CACHE_SIZE 1021 +#define DNS_HASH_BASE 423 + +static struct dns_cache_element dns_cache[DNS_CACHE_SIZE]; + struct dns_header { grub_uint16_t id; @@ -67,8 +72,25 @@ struct recv_data grub_uint16_t id; int dns_err; char *name; + const char *oname; }; +static inline int +hash (const char *str) +{ + int v = 0, xn = 1; + const char *ptr; + for (ptr = str; *ptr; ) + { + v = (v + xn * *ptr); + xn = (DNS_HASH_BASE * xn) % DNS_CACHE_SIZE; + ptr++; + if (((ptr - str) & 0x3ff) == 0) + v %= DNS_CACHE_SIZE; + } + return v % DNS_CACHE_SIZE; +} + static int check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, const grub_uint8_t *tail, const char *check_with, @@ -172,6 +194,7 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), grub_uint8_t *ptr, *reparse_ptr; int redirect_cnt = 0; char *redirect_save = NULL; + grub_uint32_t ttl_all = ~0U; head = (struct dns_header *) nb->data; ptr = (grub_uint8_t *) (head + 1); @@ -255,8 +278,8 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), ignored = 1; for (j = 0; j < 4; j++) { - ttl >>= 8; - ttl = *ptr++ << 28; + ttl <<= 8; + ttl |= *ptr++; } length = *ptr++ << 8; length |= *ptr++; @@ -268,53 +291,82 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), return GRUB_ERR_NONE; } if (!ignored) - switch (class) - { - case DNS_CLASS_A: - if (length != 4) + { + if (ttl_all > ttl) + ttl_all = ttl; + switch (class) + { + case DNS_CLASS_A: + if (length != 4) + break; + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, + ptr, 4); + (*data->naddresses)++; break; - (*data->addresses)[*data->naddresses].type - = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, - ptr, 4); - (*data->naddresses)++; - break; - case DNS_CLASS_AAAA: - if (length != 16) + case DNS_CLASS_AAAA: + if (length != 16) + break; + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, + ptr, 16); + (*data->naddresses)++; break; - (*data->addresses)[*data->naddresses].type - = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; - grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, - ptr, 16); - (*data->naddresses)++; - break; - case DNS_CLASS_CNAME: - if (!(redirect_cnt & (redirect_cnt - 1))) - { - grub_free (redirect_save); - redirect_save = data->name; - } - else - grub_free (data->name); - redirect_cnt++; - data->name = get_name (ptr, nb->data, nb->tail); - if (!data->name) - { - data->dns_err = 1; - grub_errno = 0; - return GRUB_ERR_NONE; - } - grub_dprintf ("dns", "CNAME %s\n", data->name); - if (grub_strcmp (redirect_save, data->name) == 0) - { - data->dns_err = 1; - grub_free (redirect_save); - return GRUB_ERR_NONE; - } - goto reparse; + case DNS_CLASS_CNAME: + if (!(redirect_cnt & (redirect_cnt - 1))) + { + grub_free (redirect_save); + redirect_save = data->name; + } + else + grub_free (data->name); + redirect_cnt++; + data->name = get_name (ptr, nb->data, nb->tail); + if (!data->name) + { + data->dns_err = 1; + grub_errno = 0; + return GRUB_ERR_NONE; + } + grub_dprintf ("dns", "CNAME %s\n", data->name); + if (grub_strcmp (redirect_save, data->name) == 0) + { + data->dns_err = 1; + grub_free (redirect_save); + return GRUB_ERR_NONE; + } + goto reparse; + } } ptr += length; } + if (ttl_all && *data->naddresses && data->cache) + { + int h; + grub_dprintf ("dns", "caching for %d seconds\n", ttl_all); + h = hash (data->oname); + grub_free (dns_cache[h].name); + dns_cache[h].name = 0; + grub_free (dns_cache[h].addresses); + dns_cache[h].addresses = 0; + dns_cache[h].name = grub_strdup (data->oname); + dns_cache[h].naddresses = *data->naddresses; + dns_cache[h].addresses = grub_malloc (*data->naddresses + * sizeof (dns_cache[h].addresses[0])); + dns_cache[h].limit_time = grub_get_time_ms () + 1000 * ttl_all; + if (!dns_cache[h].addresses || !dns_cache[h].name) + { + grub_free (dns_cache[h].name); + dns_cache[h].name = 0; + grub_free (dns_cache[h].addresses); + dns_cache[h].addresses = 0; + } + grub_memcpy (dns_cache[h].addresses, *data->addresses, + *data->naddresses + * sizeof (dns_cache[h].addresses[0])); + } grub_netbuff_free (nb); grub_free (redirect_save); return GRUB_ERR_NONE; @@ -338,18 +390,35 @@ grub_net_dns_lookup (const char *name, static grub_uint16_t id = 1; grub_err_t err = GRUB_ERR_NONE; struct recv_data data = {naddresses, addresses, cache, - grub_cpu_to_be16 (id++), 0, 0}; + grub_cpu_to_be16 (id++), 0, 0, name}; grub_uint8_t *nbd; int have_server = 0; + *naddresses = 0; + if (cache) + { + int h; + h = hash (name); + if (dns_cache[h].name && grub_strcmp (dns_cache[h].name, name) == 0 + && grub_get_time_ms () < dns_cache[h].limit_time) + { + grub_dprintf ("dns", "retrieved from cache\n"); + *addresses = grub_malloc (dns_cache[h].naddresses + * sizeof ((*addresses)[0])); + if (!*addresses) + return grub_errno; + *naddresses = dns_cache[h].naddresses; + grub_memcpy (*addresses, dns_cache[h].addresses, + dns_cache[h].naddresses + * sizeof ((*addresses)[0])); + return GRUB_ERR_NONE; + } + } + data.name = grub_strdup (name); if (!data.name) return grub_errno; - *naddresses = 0; - /* if (cache && cache_lookup (name, servers, n_servers, addresses)) - return GRUB_ERR_NONE;*/ - nb = grub_netbuff_alloc (GRUB_NET_OUR_MAX_IP_HEADER_SIZE + GRUB_NET_MAX_LINK_HEADER_SIZE + GRUB_NET_UDP_HEADER_SIZE From f0f4253cd2fbe207461167ad3f6d0202d2f2e396 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Dec 2011 17:12:01 +0100 Subject: [PATCH 656/673] Integrate DNS with address parsing --- grub-core/commands/i386/pc/drivemap.c | 2 +- grub-core/net/dns.c | 105 +++++++++++++++++++++++++- grub-core/net/net.c | 16 +++- include/grub/net.h | 5 ++ 4 files changed, 124 insertions(+), 4 deletions(-) diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 4f752bed5..a562b33e5 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ -static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13); +static grub_uint32_t *const int13slot = (void *) (4 * 0x13); /* Remember to update enum opt_idxs accordingly. */ static const struct grub_arg_option options[] = { diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index 93550171a..696b3ccca 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -35,6 +35,41 @@ struct dns_cache_element #define DNS_HASH_BASE 423 static struct dns_cache_element dns_cache[DNS_CACHE_SIZE]; +static struct grub_net_network_level_address *dns_servers; +static grub_size_t dns_nservers, dns_servers_alloc; + +grub_err_t +grub_net_add_dns_server (const struct grub_net_network_level_address *s) +{ + if (dns_servers_alloc <= dns_nservers) + { + int na = dns_servers_alloc * 2; + struct grub_net_network_level_address *ns; + if (na < 8) + na = 8; + ns = grub_malloc (na * sizeof (ns[0])); + if (!ns) + return grub_errno; + dns_servers_alloc = na; + dns_servers = ns; + } + dns_servers[dns_nservers++] = *s; + return GRUB_ERR_NONE; +} + +void +grub_net_remove_dns_server (const struct grub_net_network_level_address *s) +{ + grub_size_t i; + for (i = 0; i < dns_nservers; i++) + if (grub_net_addr_cmp (s, &dns_servers[i]) == 0) + break; + if (i < dns_nservers) + { + dns_servers[i] = dns_servers[dns_nservers - 1]; + dns_nservers--; + } +} struct dns_header { @@ -394,6 +429,15 @@ grub_net_dns_lookup (const char *name, grub_uint8_t *nbd; int have_server = 0; + if (!servers) + { + servers = dns_servers; + n_servers = dns_nservers; + } + + if (!n_servers) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no DNS servers"); + *naddresses = 0; if (cache) { @@ -572,10 +616,58 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)), grub_net_addr_to_str (&addresses[i], buf); grub_printf ("%s\n", buf); } + grub_free (addresses); return GRUB_ERR_NONE; } -static grub_command_t cmd; +static grub_err_t +grub_cmd_list_dns (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_size_t i; + for (i = 0; i < dns_nservers; i++) + { + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_addr_to_str (&dns_servers[i], buf); + grub_printf ("%s\n", buf); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_add_dns (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t err; + struct grub_net_network_level_address server; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "1 argument expected"); + err = grub_net_resolve_address (args[0], &server); + if (err) + return err; + + return grub_net_add_dns_server (&server); +} + +static grub_err_t +grub_cmd_del_dns (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t err; + struct grub_net_network_level_address server; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "1 argument expected"); + err = grub_net_resolve_address (args[1], &server); + if (err) + return err; + + return grub_net_add_dns_server (&server); +} + +static grub_command_t cmd, cmd_add, cmd_del, cmd_list; void grub_dns_init (void) @@ -583,10 +675,21 @@ grub_dns_init (void) cmd = grub_register_command ("net_nslookup", grub_cmd_nslookup, "ADDRESS DNSSERVER", N_("perform a DNS lookup")); + cmd_add = grub_register_command ("net_add_dns", grub_cmd_add_dns, + "DNSSERVER", + N_("add a DNS server")); + cmd_del = grub_register_command ("net_del_dns", grub_cmd_del_dns, + "DNSSERVER", + N_("remove a DNS server")); + cmd_list = grub_register_command ("net_del_dns", grub_cmd_list_dns, + NULL, N_("remove a DNS server")); } void grub_dns_fini (void) { grub_unregister_command (cmd); + grub_unregister_command (cmd_add); + grub_unregister_command (cmd_del); + grub_unregister_command (cmd_list); } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index ed6229807..d64206432 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -501,6 +501,10 @@ grub_net_resolve_address (const char *name, grub_net_network_level_address_t *addr) { const char *rest; + grub_err_t err; + grub_size_t naddresses; + struct grub_net_network_level_address *addresses; + if (parse_ip (name, &addr->ipv4, &rest) && *rest == 0) { addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; @@ -511,8 +515,16 @@ grub_net_resolve_address (const char *name, addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), - name); + err = grub_net_dns_lookup (name, 0, 0, &naddresses, &addresses, 1); + if (err) + return err; + if (!naddresses) + grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unresolvable address %s"), + name); + /* FIXME: use other results as well. */ + *addr = addresses[0]; + grub_free (addresses); + return GRUB_ERR_NONE; } grub_err_t diff --git a/include/grub/net.h b/include/grub/net.h index 6b2ba7ed2..dd566354d 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -483,6 +483,11 @@ grub_net_dns_lookup (const char *name, grub_size_t *naddresses, struct grub_net_network_level_address **addresses, int cache); +grub_err_t +grub_net_add_dns_server (const struct grub_net_network_level_address *s); +void +grub_net_remove_dns_server (const struct grub_net_network_level_address *s); + extern char *grub_net_default_server; From aa7d205236d311af61181aee7e9882d6f97df7af Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Dec 2011 17:37:47 +0100 Subject: [PATCH 657/673] Retrieve DNS names from DHCP/BOOTP --- grub-core/net/bootp.c | 27 ++++++++++++++++++++------- grub-core/net/dns.c | 10 +++++----- include/grub/net.h | 12 ++++++++++++ 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index f84d4ff66..ea8943a32 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -68,18 +68,18 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) tagtype = *ptr++; /* Pad tag. */ - if (tagtype == 0) + if (tagtype == GRUB_NET_BOOTP_PAD) continue; /* End tag. */ - if (tagtype == 0xff) + if (tagtype == GRUB_NET_BOOTP_END) return; taglength = *ptr++; switch (tagtype) { - case 3: + case GRUB_NET_BOOTP_ROUTER: if (taglength == 4) { grub_net_network_level_netaddress_t target; @@ -95,19 +95,32 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) grub_net_add_route_gw (rname, target, gw); } break; - case 12: + case GRUB_NET_BOOTP_DNS: + { + int i; + for (i = 0; i < taglength / 4; i++) + { + struct grub_net_network_level_address s; + s.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + s.ipv4 = grub_get_unaligned32 (ptr); + grub_net_add_dns_server (&s); + ptr += 4; + } + } + break; + case GRUB_NET_BOOTP_HOSTNAME: set_env_limn_ro (name, "hostname", (char *) ptr, taglength); break; - case 15: + case GRUB_NET_BOOTP_DOMAIN: set_env_limn_ro (name, "domain", (char *) ptr, taglength); break; - case 17: + case GRUB_NET_BOOTP_ROOT_PATH: set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); break; - case 18: + case GRUB_NET_BOOTP_EXTENSIONS_PATH: set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); break; diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c index 696b3ccca..bad2745a7 100644 --- a/grub-core/net/dns.c +++ b/grub-core/net/dns.c @@ -674,15 +674,15 @@ grub_dns_init (void) { cmd = grub_register_command ("net_nslookup", grub_cmd_nslookup, "ADDRESS DNSSERVER", - N_("perform a DNS lookup")); + N_("Perform a DNS lookup")); cmd_add = grub_register_command ("net_add_dns", grub_cmd_add_dns, "DNSSERVER", - N_("add a DNS server")); + N_("Add a DNS server")); cmd_del = grub_register_command ("net_del_dns", grub_cmd_del_dns, "DNSSERVER", - N_("remove a DNS server")); - cmd_list = grub_register_command ("net_del_dns", grub_cmd_list_dns, - NULL, N_("remove a DNS server")); + N_("Remove a DNS server")); + cmd_list = grub_register_command ("net_ls_dns", grub_cmd_list_dns, + NULL, N_("List DNS servers")); } void diff --git a/include/grub/net.h b/include/grub/net.h index dd566354d..3913272eb 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -396,6 +396,18 @@ struct grub_net_bootp_packet #define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 #define GRUB_NET_BOOTP_RFC1048_MAGIC_3 0x63 +enum + { + GRUB_NET_BOOTP_PAD = 0x00, + GRUB_NET_BOOTP_ROUTER = 0x03, + GRUB_NET_BOOTP_DNS = 0x06, + GRUB_NET_BOOTP_HOSTNAME = 0x0c, + GRUB_NET_BOOTP_DOMAIN = 0x0f, + GRUB_NET_BOOTP_ROOT_PATH = 0x11, + GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12, + GRUB_NET_BOOTP_END = 0xff + }; + struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, From 215c18008eac13ca127588d87a940cf6b2a47553 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 16 Dec 2011 17:46:28 +0100 Subject: [PATCH 658/673] * grub-core/commands/i386/pc/drivemap.c (int13slot): Replace UINT_TO_PTR with cast. --- ChangeLog | 5 +++++ grub-core/commands/i386/pc/drivemap.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 74aa2a60d..4aacc74b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-16 Vladimir Serbinenko + + * grub-core/commands/i386/pc/drivemap.c (int13slot): Replace + UINT_TO_PTR with cast. + 2011-12-15 Vladimir Serbinenko * util/import_gcry.py: Skip _gcry_rmd160_mixblock and serpent_test. We diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 4f752bed5..6e82be437 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ -static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13); +static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13); /* Remember to update enum opt_idxs accordingly. */ static const struct grub_arg_option options[] = { From 86717cbe0890ffb8a772eba3de045d4f21352e01 Mon Sep 17 00:00:00 2001 From: Keshav P R Date: Thu, 22 Dec 2011 13:05:19 +0100 Subject: [PATCH 659/673] * util/grub-mkstandalone.in: Fix minor typo errors. --- ChangeLog | 4 ++++ util/grub-mkstandalone.in | 13 +++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index a2032567b..e8588f0a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-19 Keshav P R + + * util/grub-mkstandalone.in: Fix minor typo errors. + 2011-12-20 Vladimir Serbinenko IPv6, TCP, HTTP, ICMP and DNS support. Several cleanups and bugfixes. diff --git a/util/grub-mkstandalone.in b/util/grub-mkstandalone.in index e140ecc82..b0dbf9b0e 100644 --- a/util/grub-mkstandalone.in +++ b/util/grub-mkstandalone.in @@ -31,7 +31,7 @@ pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst self=`basename $0` -source_dirrectory= +source_directory= compression=auto format= grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` @@ -86,7 +86,7 @@ do exit 0 ;; --modules) - modules=`argument $option "$@"`; shift ;; + modules=`argument $option "$@"`; shift ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; @@ -96,9 +96,9 @@ do output_image=`echo "$option" | sed 's/--output=//'` ;; --directory | -d) - source_directory=`argument $option "$@"`; shift ;; + source_directory=`argument $option "$@"`; shift ;; --directory=*) - source_directory=`echo "$option" | sed 's/--rom-directory=//'` ;; + source_directory=`echo "$option" | sed 's/--directory=//'` ;; --grub-mkimage) grub_mkimage=`argument $option "$@"`; shift ;; @@ -108,12 +108,12 @@ do --compression | -C) compression=`argument $option "$@"`; shift ;; --compression=*) - compression=`echo "${option}/" | sed 's/--xorriso=//'` ;; + compression=`echo "${option}" | sed 's/--compression=//'` ;; --format | -O) format=`argument $option "$@"`; shift ;; --format=*) - format=`echo "${option}/" | sed 's/--xorriso=//'` ;; + format=`echo "${option}" | sed 's/--format=//'` ;; *) source="${source} ${option} $@"; break ;; @@ -162,6 +162,7 @@ for file in "${source_directory}/"*.mod "${source_directory}/"efiemu32.o "${sour cp -f "$file" "${memdisk_dir}"/boot/grub/ fi done + for file in ${pkglib_DATA}; do if test -f "${source_directory}/${file}"; then cp -f "${source_directory}/${file}" "${memdisk_dir}"/boot/grub/ From dd0c91e98ed219435010dc9714f3f40137f0d418 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 22 Dec 2011 17:43:51 +0100 Subject: [PATCH 660/673] * docs/grub.texi (Loopback booting): New section. --- ChangeLog | 6 +++++- docs/grub.texi | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e8588f0a1..69ccd49fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ -2011-12-19 Keshav P R +2011-12-22 Vladimir Serbinenko + + * docs/grub.texi (Loopback booting): New section. + +2011-12-22 Keshav P R * util/grub-mkstandalone.in: Fix minor typo errors. diff --git a/docs/grub.texi b/docs/grub.texi index f2e19cc74..b8d59d7d9 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -784,6 +784,7 @@ magic. @menu * General boot methods:: How to boot OSes with GRUB generally +* Loopback booting:: Notes on booting from loopbacks * OS-specific notes:: Notes on some operating systems @end menu @@ -855,6 +856,31 @@ required. @xref{DOS/Windows}. Chain-loading is only supported on PC BIOS and EFI platforms. +@node Loopback booting +@section Loopback booting +GRUB is able to read from an image (be it one of CD or HDD) stored on +any of its accessible storages (refer to @pxref{loopback} command). +However the OS itself should be able to find its root. This usually +involves running a userspace program running before the real root +is discovered. This is achieved by GRUB loading a specially made +small image and passing it as ramdisk to the kernel. This is achieved +by commands @command{kfreebsd_module}, @command{knetbsd_module_elf}, +@command{kopenbsd_ramdisk}, @command{initrd} (@pxref{initrd}), +@command{initrd16} (@pxref{initrd}), @command{multiboot_module}, +@command{multiboot2_module} or @command{xnu_ramdisk} +depending on the loader. Note that for knetbsd the image must be put +inside miniroot.kmod and the whole miniroot.kmod has to be loaded. In +kopenbsd payload this is disabled by default. Aditionally behaviour of +initial ramdisk depends on command line options. Several distributors provide +the image for this purpose or it's integrated in their standard ramdisk and +activated by special option. Consult your kernel and distribution manual for +more details. Other loaders like appleloader, chainloader (BIOS, EFI, coreboot), +freedos, ntldr and plan9 provide no possibility of loading initial ramdisk and +as far as author is aware the payloads in question don't support either initial +ramdisk or discovering loopback boot in other way and as such not bootable this +way. Please consider alternative boot methods like copying all files +from the image to actual partition. Consult your OS documentation for +more details @node OS-specific notes @section Some caveats on OS-specific issues From 8eba9997db80230ad8de2416ca09c7eea4e9d95b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 22 Dec 2011 20:55:55 +0100 Subject: [PATCH 661/673] * docs/grub.texi (Internationalisation): New section. --- ChangeLog | 4 ++++ docs/grub.texi | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/ChangeLog b/ChangeLog index 69ccd49fe..329fccd38 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-22 Vladimir Serbinenko + + * docs/grub.texi (Internationalisation): New section. + 2011-12-22 Vladimir Serbinenko * docs/grub.texi (Loopback booting): New section. diff --git a/docs/grub.texi b/docs/grub.texi index b8d59d7d9..45bda95d5 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -89,6 +89,7 @@ This edition documents version @value{VERSION}. * Interface:: The menu and the command-line * Environment:: GRUB environment variables * Commands:: The list of available builtin commands +* Internationalisation:: Topics relating to language support * Security:: Authentication and authorisation * Supported kernels:: The list of supported kernels * Troubleshooting:: Error messages produced by GRUB @@ -3893,6 +3894,65 @@ Unset the environment variable @var{envvar}. This command is not yet implemented for GRUB 2, although it is planned. +@node Internationalisation +@chapter Charset +GRUB uses UTF-8 internally other than in rendering where some GRUB-specific +appropriate representation is used. All text files (including config) are +assumed to be encoded in UTF-8. + +@chapter Filesystems +NTFS, JFS, UDF, HFS+, exFAT, long filesnames in FAT, Joliet part of +ISO9660 are treated as UTF-16 as per specification. BFS is read as UTF-8, +again according to specification. BtrFS, cpio, tar, squash4, minix, minix2, +minix3, ROMFS, ReiserFS, XFS, ext2, ext3, ext4, FAT (short names), +ISO9660 (plain and RockRidge), nilfs2, UFS1, UFS2 and ZFS are assumed +to be UTF-8. This might be false on systems configured with legacy charset +but as long as the charset used is superset of ASCII you should be able to +access ASCII-named files. And it's recommended to configure your system to use +UTF-8 to access the filesystem, convmv may help with migration. AFFS and HFS +never use unicode and GRUB assumes them to be in Latin1 and MacRoman +respectively. NTFS, HFS+, FAT and exFAT are case-insensitive however no +attempt is performed at case conversion of international characters so e.g. +a file named lowercase greek alpha is treated as different from the one named +as uppercase alpha. Also similar to POSIX systems GRUB make no attempt at check +of canonical equivalence so a file name u-diaresis is treated as distinct from +u+combining diaresis. This however means that in order to access file on +HFS+ its name must be specified in normalisation form D. On ZFS subvolumes +marked as case insensitive files containing lowercase international characters +are inaccessible. + +@chapter Output terminal +Firmware output console ``console'' on ARC and IEEE1275 are limited to ASCII. +BIOS firmware console and VGA text are limited to ASCII and some pseudographics. +None of above mentioned is appropriate for displaying international and any +unsupported character is replaced with question mark except pseudographics +which we attempt to approximate with ASCII. EFI console on the other hand +nominally supports UTF-16 but actual language coverage depends on firmware and +may be very limited. The encoding used on serial can be chosen with +@command{terminfo} as either ASCII, UTF-8 or ``visual UTF-8''. Last one is +against the specification but results in correct rendering of right-to-left +on some readers which don't have own bidi implementation. When using gfxterm +or gfxmenu GRUB itself is responsible for rendering the text. In this case +GRUB is limited by loaded fonts. If fonts contain all required characters +then bidirectional text, cursive variants and combining marks other than +enclosing ones. Ligatures aren't supported though. This should cover +European, Middle Eastern (if you don't mind lack of la-alef ligature in +Arabic) and East Asian scripts. Notable unsupported scripts are Brahmic family +and derived as well as Mongolian and Tifinagh. If you can complete either of +two lists or, better, propose a patch to improve rendering, please contact +developper team. + +@chapter Input terminal +Firmware console on BIOS, IEEE1275 and ARC doesn't allow you to enter non-ASCII +characters. EFI specification allows for such but author is unaware of any +actual implementations. Serial input is currently limited for latin1 (unlikely +to change). Own keyboard implementations (at_keyboard and usb_keyboard) can +support any characters but work on one-char-per-keystroke. So no dead keys or +advanced input method. Also there is no keymap change hotkey. In practice it +makes difficult to enter any text using non-Latin alphabet. + +@chapter Gettext +GRUB supports being translated. For this you need to have language *.mo files in $prefix/locale, load gettext module and set ``lang'' variable. @node Security @chapter Authentication and authorisation From 1f0b1a7730d65650c9f5976b99be7514f955b26f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 10:21:27 +0100 Subject: [PATCH 662/673] * grub-core/boot/i386/pc/startup_raw.S: Add missing argument for _LzmaDecodeA. --- ChangeLog | 5 +++++ grub-core/boot/i386/pc/startup_raw.S | 3 +++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 329fccd38..34d7e26c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-23 Vladimir Serbinenko + + * grub-core/boot/i386/pc/startup_raw.S: Add missing argument for + _LzmaDecodeA. + 2011-12-22 Vladimir Serbinenko * docs/grub.texi (Internationalisation): New section. diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 9c044ffb0..0e6794f56 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -179,7 +179,10 @@ post_reed_solomon: pushl %edi movl LOCAL (uncompressed_size), %ecx leal (%edi, %ecx), %ebx + /* Don't remove this push: it's an argument. */ + push %ecx call _LzmaDecodeA + pop %ecx /* _LzmaDecodeA clears DF, so no need to run cld */ popl %esi #endif From 31355584f165f30adf972e7af23073e7f102f6f8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 10:23:41 +0100 Subject: [PATCH 663/673] * grub-core/lib/reed_solomon.c (grub_reed_solomon_add_redundancy): Add an assert. * util/grub-setup.c (setup): Likewise. --- grub-core/lib/reed_solomon.c | 11 +++++++++++ util/grub-setup.c | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 3d8bb9e1f..0257342d0 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -25,6 +25,10 @@ #define grub_memcpy memcpy #endif +#ifndef STANDALONE +#include +#endif + #ifndef STANDALONE #ifdef TEST typedef unsigned int grub_size_t; @@ -456,6 +460,10 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, grub_size_t rs = redundancy; gf_single_t *ptr = buffer; gf_single_t *rptr = ptr + s; + void *tmp; + + tmp = xmalloc (data_size); + grub_memcpy (tmp, buffer, data_size); /* Nothing to do. */ if (!rs) @@ -481,6 +489,9 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, s -= cs; rs -= crs; } + + assert (grub_memcmp (tmp, buffer, data_size) == 0); + free (tmp); } #endif diff --git a/util/grub-setup.c b/util/grub-setup.c index d3b3b7520..8965143c5 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -448,10 +448,14 @@ setup (const char *dir, + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY) = grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size); + void *tmp = xmalloc (core_size); + grub_memcpy (tmp, core_img, core_size); grub_reed_solomon_add_redundancy (core_img + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + GRUB_DISK_SECTOR_SIZE, core_size - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - GRUB_DISK_SECTOR_SIZE, nsec * GRUB_DISK_SECTOR_SIZE - core_size); + assert (grub_memcmp (tmp, core_img, core_size) == 0); + free (tmp); /* Make sure that the second blocklist is a terminator. */ block = first_block - 1; From 6209239517b711c9c15a243915edfe033d1bc1e5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 10:24:08 +0100 Subject: [PATCH 664/673] missing ChangeLog --- ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 34d7e26c2..b7320a9d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-12-23 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (grub_reed_solomon_add_redundancy): Add + an assert. + * util/grub-setup.c (setup): Likewise. + 2011-12-23 Vladimir Serbinenko * grub-core/boot/i386/pc/startup_raw.S: Add missing argument for From 66a2ecd12338a823920c79112e99d4bd76eb6b9b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 10:24:34 +0100 Subject: [PATCH 665/673] Remove empty directories From b87f7ef26b1f56b6987022c7c9115d88ff5c65ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 11:36:31 +0100 Subject: [PATCH 666/673] * util/getroot.c (ESCAPED_PATH_MAX): New define. (mountinfo_entry): Increase the field size to take escaping into account. (find_root_device_from_libzfs): Add one byte to size of strings for security. --- ChangeLog | 8 ++++++++ util/getroot.c | 11 +++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index b7320a9d9..9236d27f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-12-23 Vladimir Serbinenko + + * util/getroot.c (ESCAPED_PATH_MAX): New define. + (mountinfo_entry): Increase the field size to take escaping into + account. + (find_root_device_from_libzfs): Add one byte to size of strings for + security. + 2011-12-23 Vladimir Serbinenko * grub-core/lib/reed_solomon.c (grub_reed_solomon_add_redundancy): Add diff --git a/util/getroot.c b/util/getroot.c index 05bee4964..a4bc9f0af 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -117,12 +117,13 @@ xgetcwd (void) #ifdef __linux__ +#define ESCAPED_PATH_MAX (4 * PATH_MAX) struct mountinfo_entry { int id; int major, minor; - char enc_root[PATH_MAX], enc_path[PATH_MAX]; - char fstype[PATH_MAX], device[PATH_MAX]; + char enc_root[ESCAPED_PATH_MAX + 1], enc_path[ESCAPED_PATH_MAX + 1]; + char fstype[ESCAPED_PATH_MAX + 1], device[ESCAPED_PATH_MAX + 1]; }; /* Statting something on a btrfs filesystem always returns a virtual device @@ -352,7 +353,8 @@ find_root_device_from_libzfs (const char *dir) size_t len; int st; - char name[PATH_MAX], state[256], readlen[256], writelen[256], cksum[256], notes[256]; + char name[PATH_MAX + 1], state[257], readlen[257], writelen[257]; + char cksum[257], notes[257]; unsigned int dummy; cmd = xasprintf ("zpool status %s", poolname); @@ -367,7 +369,8 @@ find_root_device_from_libzfs (const char *dir) if (ret == -1) goto fail; - if (sscanf (line, " %s %256s %256s %256s %256s %256s", name, state, readlen, writelen, cksum, notes) >= 5) + if (sscanf (line, " %s %256s %256s %256s %256s %256s", + name, state, readlen, writelen, cksum, notes) >= 5) switch (st) { case 0: From 3ea1ca46c1a43b69e713cc83ee872740927d1717 Mon Sep 17 00:00:00 2001 From: Seth Goldberg Date: Fri, 23 Dec 2011 11:39:30 +0100 Subject: [PATCH 667/673] * grub-core/Makefile.core.def (lzma_decompress): Add missing TARGET_IMG_LDFLAGS. --- ChangeLog | 5 +++++ grub-core/Makefile.core.def | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9236d27f8..d76f07ac4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-23 Seth Goldberg + + * grub-core/Makefile.core.def (lzma_decompress): Add missing + TARGET_IMG_LDFLAGS. + 2011-12-23 Vladimir Serbinenko * util/getroot.c (ESCAPED_PATH_MAX): New define. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index c00773446..218f3df64 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -373,7 +373,7 @@ image = { i386_pc = boot/i386/pc/startup_raw.S; objcopyflags = '-O binary'; - ldflags = '-Wl,-Ttext,0x8200'; + ldflags = '$(TARGET_IMG_LDFLAGS) -Wl,-Ttext,0x8200'; enable = i386_pc; }; From a93964ce11ac01fe2e23a4e77a8ccfb507bdef8f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 11:54:08 +0100 Subject: [PATCH 668/673] * grub-core/net/net.c (grub_cmd_delroute): Add missing out condition. --- ChangeLog | 4 ++++ grub-core/net/net.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index d76f07ac4..3c2966134 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-23 Vladimir Serbinenko + + * grub-core/net/net.c (grub_cmd_delroute): Add missing out condition. + 2011-12-23 Seth Goldberg * grub-core/Makefile.core.def (lzma_decompress): Add missing diff --git a/grub-core/net/net.c b/grub-core/net/net.c index d64206432..347a95afd 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -934,6 +934,8 @@ grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), *prev = route->next; grub_free (route->name); grub_free (route); + if (!*prev) + break; } return GRUB_ERR_NONE; From a6120aca2e6e522da576e12f62bd4ba37a5b620e Mon Sep 17 00:00:00 2001 From: Lukas Anzinger Date: Fri, 23 Dec 2011 12:01:25 +0100 Subject: [PATCH 669/673] * util/grub-mkconfig_lib.in (version_test_gt): Fix variable names. --- ChangeLog | 4 ++++ util/grub-mkconfig_lib.in | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3c2966134..979acdf47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-23 Lukas Anzinger + + * util/grub-mkconfig_lib.in (version_test_gt): Fix variable names. + 2011-12-23 Vladimir Serbinenko * grub-core/net/net.c (grub_cmd_delroute): Add missing out condition. diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 5a9bf90c0..f03fb2b53 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -198,8 +198,8 @@ version_test_gt () fi case "$version_test_gt_a:$version_test_gt_b" in *.old:*.old) ;; - *.old:*) version_test_gt_a="`echo -n "$version_test_gt_a" | sed -e 's/\.old$//'`" ; cmp=gt ;; - *:*.old) version_test_gt_b="`echo -n "$version_test_gt_b" | sed -e 's/\.old$//'`" ; cmp=ge ;; + *.old:*) version_test_gt_a="`echo -n "$version_test_gt_a" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=gt ;; + *:*.old) version_test_gt_b="`echo -n "$version_test_gt_b" | sed -e 's/\.old$//'`" ; version_test_gt_cmp=ge ;; esac version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b" return "$?" From a54a0e1270a06a780259f2fdf2c90de12f73d5ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 13:38:21 +0100 Subject: [PATCH 670/673] * grub-core/fs/cpio.c (grub_cpio_find_file): Fix handling of names occupying the whole field size. --- ChangeLog | 5 +++++ grub-core/fs/cpio.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 979acdf47..de2ec0406 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-12-23 Vladimir Serbinenko + + * grub-core/fs/cpio.c (grub_cpio_find_file): Fix handling of names + occupying the whole field size. + 2011-12-23 Lukas Anzinger * util/grub-mkconfig_lib.in (version_test_gt): Fix variable names. diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 63a1d1f43..a40d4f0a2 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -225,7 +225,7 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, if (!have_longname) { - *name = grub_strdup (hd.name); + *name = grub_strndup (hd.name, sizeof (hd.name)); if (*name == NULL) return grub_errno; } From 58eba9eec7f815f8e6f320c527c8e62db6583e9f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 14:11:31 +0100 Subject: [PATCH 671/673] Fix handling of tar numbers occupying the whole field. * grub-core/fs/cpio.c (read_number): New function. (grub_cpio_find_file): Use read_number instead of strtoull. --- ChangeLog | 7 +++++++ grub-core/fs/cpio.c | 19 ++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index de2ec0406..8a9e25f70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2011-12-23 Vladimir Serbinenko + + Fix handling of tar numbers occupying the whole field. + + * grub-core/fs/cpio.c (read_number): New function. + (grub_cpio_find_file): Use read_number instead of strtoull. + 2011-12-23 Vladimir Serbinenko * grub-core/fs/cpio.c (grub_cpio_find_file): Fix handling of names diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index a40d4f0a2..cfa1b555b 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -108,6 +108,15 @@ canonicalize (char *name) *optr = 0; } +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + long long ret = 0; + while (size-- && *str >= '0' && *str <= '7') + ret = (ret << 3) | (*str++ & ~'0'); + return ret; +} + static grub_err_t grub_cpio_find_file (struct grub_cpio_data *data, char **name, grub_int32_t *mtime, grub_disk_addr_t *ofs, @@ -178,7 +187,7 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, if (hd.typeflag == 'L') { grub_err_t err; - grub_size_t namesize = grub_strtoull (hd.size, NULL, 8); + grub_size_t namesize = read_number (hd.size, sizeof (hd.size)); *name = grub_malloc (namesize + 1); if (*name == NULL) return grub_errno; @@ -198,7 +207,7 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, if (hd.typeflag == 'K') { grub_err_t err; - grub_size_t linksize = grub_strtoull (hd.size, NULL, 8); + grub_size_t linksize = read_number (hd.size, sizeof (hd.size)); if (data->linkname_alloc < linksize + 1) { char *n; @@ -230,15 +239,15 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, return grub_errno; } - data->size = grub_strtoull (hd.size, NULL, 8); + data->size = read_number (hd.size, sizeof (hd.size)); data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & ~(GRUB_DISK_SECTOR_SIZE - 1)); if (mtime) - *mtime = grub_strtoul (hd.mtime, NULL, 8); + *mtime = read_number (hd.mtime, sizeof (hd.mtime)); if (mode) { - *mode = grub_strtoul (hd.mode, NULL, 8); + *mode = read_number (hd.mode, sizeof (hd.mode)); switch (hd.typeflag) { case '2': From a1a8b1b90ab4cb0cdd82e0b318a72e01a65b9944 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 16:15:18 +0100 Subject: [PATCH 672/673] Support odc, newc and bigendian cpio formats. * Makefile.util.def (libgrubmods): Add odc.c, newc.c and cpio_be.c. * grub-core/Makefile.core.def (newc): New module. (odc): Likewise. (cpio_be): Likewise. * grub-core/fs/cpio.c (ALIGN_CPIO): New macro. (MAGIC): Likewise. (MAGIC2): Likewise. (head) [MODE_ODC]: Adapt for the format. (head) [MODE_NEWC]: Likewise. (head) [!MODE_*]: Write fields of interest as arrays. (MAGIC_USTAR): Removed. (read_number) [MODE_NEWC]: Change to hex. (read_number) [!MODE_*]: Parse binary arrays. (grub_cpio_find_file): Factor out the code for better structure and always use read_number. (grub_cpio_mount): Use MAGIC and MAGIC2. (grub_cpio_dir): Exit on first hook non-0 return. (grub_cpio_fs) [MODE_ODC]: Set name to odc. (grub_cpio_fs) [MODE_NEWC]: Set name to newc. (GRUB_MOD_INIT) [MODE_ODC]: Set name to odc. (GRUB_MOD_INIT) [MODE_NEWC]: Set name to newc. (GRUB_MOD_FINI) [MODE_ODC]: Set name to odc. (GRUB_MOD_FINI) [MODE_NEWC]: Set name to newc. * grub-core/fs/newc.c: New file. * grub-core/fs/odc.c: Likewise. * grub-core/fs/cpio_be.c: Likewise. --- ChangeLog | 31 +++++++ Makefile.util.def | 3 + grub-core/Makefile.core.def | 15 ++++ grub-core/fs/cpio.c | 162 ++++++++++++++++++++++++++++-------- grub-core/fs/cpio_be.c | 2 + grub-core/fs/newc.c | 2 + grub-core/fs/odc.c | 2 + 7 files changed, 181 insertions(+), 36 deletions(-) create mode 100644 grub-core/fs/cpio_be.c create mode 100644 grub-core/fs/newc.c create mode 100644 grub-core/fs/odc.c diff --git a/ChangeLog b/ChangeLog index 8a9e25f70..220892a75 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2011-12-23 Vladimir Serbinenko + + Support odc, newc and bigendian cpio formats. + + * Makefile.util.def (libgrubmods): Add odc.c, newc.c and cpio_be.c. + * grub-core/Makefile.core.def (newc): New module. + (odc): Likewise. + (cpio_be): Likewise. + * grub-core/fs/cpio.c (ALIGN_CPIO): New macro. + (MAGIC): Likewise. + (MAGIC2): Likewise. + (head) [MODE_ODC]: Adapt for the format. + (head) [MODE_NEWC]: Likewise. + (head) [!MODE_*]: Write fields of interest as arrays. + (MAGIC_USTAR): Removed. + (read_number) [MODE_NEWC]: Change to hex. + (read_number) [!MODE_*]: Parse binary arrays. + (grub_cpio_find_file): Factor out the code for better structure and + always use read_number. + (grub_cpio_mount): Use MAGIC and MAGIC2. + (grub_cpio_dir): Exit on first hook non-0 return. + (grub_cpio_fs) [MODE_ODC]: Set name to odc. + (grub_cpio_fs) [MODE_NEWC]: Set name to newc. + (GRUB_MOD_INIT) [MODE_ODC]: Set name to odc. + (GRUB_MOD_INIT) [MODE_NEWC]: Set name to newc. + (GRUB_MOD_FINI) [MODE_ODC]: Set name to odc. + (GRUB_MOD_FINI) [MODE_NEWC]: Set name to newc. + * grub-core/fs/newc.c: New file. + * grub-core/fs/odc.c: Likewise. + * grub-core/fs/cpio_be.c: Likewise. + 2011-12-23 Vladimir Serbinenko Fix handling of tar numbers occupying the whole field. diff --git a/Makefile.util.def b/Makefile.util.def index b52b5db9c..6e026db7e 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -59,6 +59,9 @@ library = { common = grub-core/fs/bfs.c; common = grub-core/fs/btrfs.c; common = grub-core/fs/cpio.c; + common = grub-core/fs/cpio_be.c; + common = grub-core/fs/odc.c; + common = grub-core/fs/newc.c; common = grub-core/fs/ext2.c; common = grub-core/fs/fat.c; common = grub-core/fs/exfat.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 218f3df64..e183f884c 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1014,6 +1014,21 @@ module = { common = fs/cpio.c; }; +module = { + name = cpio_be; + common = fs/cpio_be.c; +}; + +module = { + name = newc; + common = fs/newc.c; +}; + +module = { + name = odc; + common = fs/odc.c; +}; + module = { name = ext2; common = fs/ext2.c; diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index cfa1b555b..3107d0194 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -30,28 +30,69 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define ATTR_DIR 0040000 #define ATTR_LNK 0120000 -#ifndef MODE_USTAR -/* cpio support */ -#define MAGIC_BCPIO 070707 +#ifdef MODE_ODC +#define ALIGN_CPIO(x) x +#define MAGIC "070707" struct head { - grub_uint16_t magic; + char magic[6]; + char dev[6]; + char ino[6]; + char mode[6]; + char uid[6]; + char gid[6]; + char nlink[6]; + char rdev[6]; + char mtime[11]; + char namesize[6]; + char filesize[11]; +} __attribute__ ((packed)); +#elif defined (MODE_NEWC) +#define ALIGN_CPIO(x) (ALIGN_UP ((x), 4)) +#define MAGIC "070701" +#define MAGIC2 "070702" +struct head +{ + char magic[6]; + char ino[8]; + char mode[8]; + char uid[8]; + char gid[8]; + char nlink[8]; + char mtime[8]; + char filesize[8]; + char devmajor[8]; + char devminor[8]; + char rdevmajor[8]; + char rdevminor[8]; + char namesize[8]; + char check[8]; +} __attribute__ ((packed)); +#elif !defined (MODE_USTAR) +/* cpio support */ +#define ALIGN_CPIO(x) (ALIGN_UP ((x), 2)) +#ifdef MODE_BIGENDIAN +#define MAGIC "\x71\xc7" +#else +#define MAGIC "\xc7\x71" +#endif +struct head +{ + grub_uint16_t magic[1]; grub_uint16_t dev; grub_uint16_t ino; - grub_uint16_t mode; + grub_uint16_t mode[1]; grub_uint16_t uid; grub_uint16_t gid; grub_uint16_t nlink; grub_uint16_t rdev; - grub_uint16_t mtime_1; - grub_uint16_t mtime_2; - grub_uint16_t namesize; - grub_uint16_t filesize_1; - grub_uint16_t filesize_2; + grub_uint16_t mtime[2]; + grub_uint16_t namesize[1]; + grub_uint16_t filesize[2]; } __attribute__ ((packed)); #else /* tar support */ -#define MAGIC_USTAR "ustar" +#define MAGIC "ustar" struct head { char name[100]; @@ -108,14 +149,48 @@ canonicalize (char *name) *optr = 0; } +#if defined (MODE_ODC) || defined (MODE_USTAR) static inline unsigned long long read_number (const char *str, grub_size_t size) { - long long ret = 0; + unsigned long long ret = 0; while (size-- && *str >= '0' && *str <= '7') - ret = (ret << 3) | (*str++ & ~'0'); + ret = (ret << 3) | (*str++ & 0xf); return ret; } +#elif defined (MODE_NEWC) +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + unsigned long long ret = 0; + while (size-- && grub_isxdigit (*str)) + { + char dig = *str++; + if (dig >= '0' && dig <= '9') + dig &= 0xf; + else if (dig >= 'a' && dig <= 'f') + dig -= 'a' - 10; + else + dig -= 'A' - 10; + ret = (ret << 4) | (dig); + } + return ret; +} +#else +static inline unsigned long long +read_number (const grub_uint16_t *arr, grub_size_t size) +{ + long long ret = 0; +#ifdef MODE_BIGENDIAN + while (size--) + ret = (ret << 16) | grub_be_to_cpu16 (*arr++); +#else + while (size--) + ret = (ret << 16) | grub_le_to_cpu16 (*arr++); +#endif + return ret; +} +#endif static grub_err_t grub_cpio_find_file (struct grub_cpio_data *data, char **name, @@ -124,35 +199,40 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, { #ifndef MODE_USTAR struct head hd; + grub_size_t namesize; + grub_uint32_t modeval; if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) return grub_errno; - if (hd.magic != MAGIC_BCPIO) + if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0 +#ifdef MAGIC2 + && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0 +#endif + ) return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); - - data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; + data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize)); if (mtime) - *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; + *mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime)); + modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode)); + namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize)); + if (mode) - *mode = hd.mode; + *mode = modeval; - if (hd.namesize & 1) - hd.namesize++; - - *name = grub_malloc (hd.namesize + 1); + *name = grub_malloc (namesize + 1); if (*name == NULL) return grub_errno; if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), - hd.namesize, *name)) + namesize, *name)) { grub_free (*name); return grub_errno; } - (*name)[hd.namesize] = 0; + (*name)[namesize] = 0; - if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1 + if (data->size == 0 && modeval == 0 && namesize == 11 && grub_memcmp(*name, "TRAILER!!!", 11) == 0) { *ofs = 0; @@ -162,10 +242,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, canonicalize (*name); - data->dofs = data->hofs + sizeof (hd) + hd.namesize; - *ofs = data->dofs + data->size; - if (data->size & 1) - (*ofs)++; + data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize); + *ofs = data->dofs + ALIGN_CPIO (data->size); #else struct head hd; int reread = 0, have_longname = 0, have_longlink = 0; @@ -181,7 +259,7 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, return GRUB_ERR_NONE; } - if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)) return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); if (hd.typeflag == 'L') @@ -293,12 +371,11 @@ grub_cpio_mount (grub_disk_t disk) if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) goto fail; -#ifndef MODE_USTAR - if (hd.magic != MAGIC_BCPIO) -#else - if (grub_memcmp (hd.magic, MAGIC_USTAR, - sizeof (MAGIC_USTAR) - 1)) + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1) +#ifdef MAGIC2 + && grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1) #endif + ) goto fail; data = (struct grub_cpio_data *) grub_zalloc (sizeof (*data)); @@ -469,7 +546,8 @@ grub_cpio_dir (grub_device_t device, const char *path_in, info.mtime = mtime; info.mtimeset = 1; - hook (n, &info); + if (hook (n, &info)) + goto fail; grub_free (prev); prev = name; } @@ -623,6 +701,10 @@ grub_cpio_close (grub_file_t file) static struct grub_fs grub_cpio_fs = { #ifdef MODE_USTAR .name = "tarfs", +#elif defined (MODE_ODC) + .name = "odc", +#elif defined (MODE_NEWC) + .name = "newc", #else .name = "cpiofs", #endif @@ -637,6 +719,10 @@ static struct grub_fs grub_cpio_fs = { #ifdef MODE_USTAR GRUB_MOD_INIT (tar) +#elif defined (MODE_ODC) +GRUB_MOD_INIT (odc) +#elif defined (MODE_NEWC) +GRUB_MOD_INIT (newc) #else GRUB_MOD_INIT (cpio) #endif @@ -647,6 +733,10 @@ GRUB_MOD_INIT (cpio) #ifdef MODE_USTAR GRUB_MOD_FINI (tar) +#elif defined (MODE_ODC) +GRUB_MOD_FINI (odc) +#elif defined (MODE_NEWC) +GRUB_MOD_FINI (newc) #else GRUB_MOD_FINI (cpio) #endif diff --git a/grub-core/fs/cpio_be.c b/grub-core/fs/cpio_be.c new file mode 100644 index 000000000..8bad314cd --- /dev/null +++ b/grub-core/fs/cpio_be.c @@ -0,0 +1,2 @@ +#define MODE_BIGENDIAN 1 +#include "cpio.c" diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c new file mode 100644 index 000000000..fdcc160e8 --- /dev/null +++ b/grub-core/fs/newc.c @@ -0,0 +1,2 @@ +#define MODE_NEWC 1 +#include "cpio.c" diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c new file mode 100644 index 000000000..5fa88e3f9 --- /dev/null +++ b/grub-core/fs/odc.c @@ -0,0 +1,2 @@ +#define MODE_ODC 1 +#include "cpio.c" From edddb7f9b2ff889cfc7138cbed2e3377cd84377a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 23 Dec 2011 17:05:36 +0100 Subject: [PATCH 673/673] * docs/grub.texi (Filesystems): Update. --- ChangeLog | 4 +++ docs/grub.texi | 82 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 220892a75..8a409fabc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-12-23 Vladimir Serbinenko + + * docs/grub.texi (Filesystems): Update. + 2011-12-23 Vladimir Serbinenko Support odc, newc and bigendian cpio formats. diff --git a/docs/grub.texi b/docs/grub.texi index 45bda95d5..1078a2183 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -341,11 +341,17 @@ devices, partitions, and files in a directory depending on context. @item Support multiple filesystem types Support multiple filesystem types transparently, plus a useful explicit blocklist notation. The currently supported filesystem types are @dfn{Amiga -Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, @dfn{cpio}, @dfn{Linux -ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{HFS}, @dfn{HFS+}, -@dfn{ISO9660}, @dfn{JFS}, @dfn{Minix fs}, @dfn{nilfs2}, @dfn{NTFS}, -@dfn{ReiserFS}, @dfn{Amiga Smart FileSystem (SFS)}, @dfn{tar}, @dfn{UDF}, -@dfn{BSD UFS/UFS2}, and @dfn{XFS}. @xref{Filesystem}, for more information. +Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, +@dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo), +@dfn{cpio} (little- and big-endian bin, odc and newc variants), +@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS}, +@dfn{HFS+}, @dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files), +@dfn{JFS}, @dfn{Minix fs} (versions 1, 2 and 3), @dfn{nilfs2}, +@dfn{NTFS} (including compression), @dfn{ReiserFS}, @dfn{ROMFS}, +@dfn{Amiga Smart FileSystem (SFS)}, @dfn{Squash4}, @dfn{tar}, @dfn{UDF}, +@dfn{BSD UFS/UFS2}, @dfn{XFS}, and @dfn{ZFS} (including lzjb, gzip, +zle, mirror, stripe, raidz1/2/3 and encryption in AES-CCM and AES-GCM). +@xref{Filesystem}, for more information. @item Support automatic decompression Can decompress files which were compressed by @command{gzip} or @@ -2230,42 +2236,64 @@ you see the files in a device or use the command @command{search} The device syntax is like this: @example -@code{(@var{device}[,@var{part-num}][,@var{bsd-subpart-letter}])} +@code{(@var{device}[,@var{partmap-name1}@var{part-num1}[,@var{partmap-name2}@var{part-num2}[,...]]])} @end example -@samp{[]} means the parameter is optional. @var{device} should be -either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}. -But you can also set @var{device} to a hexadecimal or a decimal number -which is a BIOS drive number, so the following are equivalent: +@samp{[]} means the parameter is optional. @var{device} depends on the disk +driver in use. BIOS and EFI disks use either @samp{fd} or @samp{hd} followed +by a digit, like @samp{fd0}, or @samp{cd}. +AHCI, PATA (ata), crypto, USB use the name of driver followed by a number. +Memdisk and host are limited to one disk and so it's refered just by driver +name. +RAID (md), ofdisk (ieee1275), LVM (lv) and arcdisk (arc) use intrinsic name +of disk prefixed by driver name. Conflicts are solved by suffixing a number +if necessarry. Commas need to be escaped. +Loopback uses whatever name specified to @command{loopback} command. +For crypto and RAID (md) additionally you can use the syntax +uuid/ @example +(fd0) (hd0) -(0x80) -(128) +(cd) +(ahci0) +(ata0) +(crypto0) +(usb0) +(cryptouuid/123456789abcdef0123456789abcdef0) +(mduuid/123456789abcdef0123456789abcdef0) +(lv/system-root) +(md/myraid) +(md/0) +(ieee1275/disk) +(memdisk) +(host) +(myloop) @end example @var{part-num} represents the partition number of @var{device}, starting -from one for primary partitions and from five for extended partitions, -and @var{bsd-subpart-letter} represents the BSD disklabel subpartition, -such as @samp{a} or @samp{e}. - -A shortcut for specifying BSD subpartitions is -@code{(@var{device},@var{bsd-subpart-letter})}, in this case, GRUB -searches for the first PC partition containing a BSD disklabel, then -finds the subpartition @var{bsd-subpart-letter}. Here is an example: - -@example -(hd0,a) -@end example +from one. @var{partname} is optional but is recommended since disk may have +several top-level partmaps. Specifying third and later component you can access +to subpartitions. The syntax @samp{(hd0)} represents using the entire disk (or the MBR when installing GRUB), while the syntax @samp{(hd0,1)} represents using the first partition of the disk (or the boot sector of the partition when installing GRUB). -If you enabled the network support, the special drive @samp{(pxe)} is -also available. Before using the network drive, you must initialize the -network. @xref{Network}, for more information. +@example +(hd0,msdos1) +(hd0,msdos1,msdos5) +(hd0,msdos1,bsd3) +(hd0,netbsd1) +(hd0,gpt1) +(hd0,1,3) +@end example + +If you enabled the network support, the special drives @samp{(tftp)}, +@samp{(http)} and so on ars also available. +Before using the network drive, you must initialize the network. +@xref{Network}, for more information. If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making a GRUB bootable CD-ROM}, for details.