+++ /dev/null
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/Makefile compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/Makefile
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/Makefile 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/Makefile 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,6 @@
-+obj-$(CONFIG_LIBERTAS_UAP) += uap8xxx.o
-+
-+uap8xxx-y += uap_main.o uap_sdio_mmc.o
-+uap8xxx-$(CONFIG_PROC_FS) += uap_proc.o uap_debug.o
-+
-+EXTRA_CFLAGS += -DFPNUM='"52"' -DPXA3XX_DMA_ALIGN -DDEBUG_LEVEL1
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_debug.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_debug.c
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_debug.c 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_debug.c 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,261 @@
-+/** @file uap_debug.c
-+ * @brief This file contains functions for debug proc file.
-+ *
-+ * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+#ifdef CONFIG_PROC_FS
-+#include "uap_headers.h"
-+
-+/********************************************************
-+ Local Variables
-+********************************************************/
-+
-+#define item_size(n) (sizeof ((uap_adapter *)0)->n)
-+#define item_addr(n) ((u32) &((uap_adapter *)0)->n)
-+
-+#define item_dbg_size(n) (sizeof (((uap_adapter *)0)->dbg.n))
-+#define item_dbg_addr(n) ((u32) &(((uap_adapter *)0)->dbg.n))
-+
-+#define item_dev_size(n) (sizeof ((uap_dev_t *)0)->n)
-+#define item_dev_addr(n) ((u32) &((uap_dev_t *)0)->n)
-+
-+/** MicroAp device offset */
-+#define OFFSET_UAP_DEV 0x01
-+/** Bluetooth adapter offset */
-+#define OFFSET_UAP_ADAPTER 0x02
-+
-+struct debug_data
-+{
-+ /** Name */
-+ char name[32];
-+ /** Size */
-+ u32 size;
-+ /** Address */
-+ u32 addr;
-+ /** Offset */
-+ u32 offset;
-+ /** Flag */
-+ u32 flag;
-+};
-+
-+/* To debug any member of uap_adapter, simply add one line here.
-+ */
-+static struct debug_data items[] = {
-+ {"cmd_sent", item_dev_size(cmd_sent), 0, item_dev_addr(cmd_sent),
-+ OFFSET_UAP_DEV},
-+ {"data_sent", item_dev_size(data_sent), 0, item_dev_addr(data_sent),
-+ OFFSET_UAP_DEV},
-+ {"IntCounter", item_size(IntCounter), 0, item_addr(IntCounter),
-+ OFFSET_UAP_ADAPTER},
-+ {"cmd_pending", item_size(cmd_pending), 0, item_addr(cmd_pending),
-+ OFFSET_UAP_ADAPTER},
-+ {"num_cmd_h2c_fail", item_dbg_size(num_cmd_host_to_card_failure), 0,
-+ item_dbg_addr(num_cmd_host_to_card_failure), OFFSET_UAP_ADAPTER},
-+ {"num_tx_h2c_fail", item_dbg_size(num_tx_host_to_card_failure), 0,
-+ item_dbg_addr(num_tx_host_to_card_failure), OFFSET_UAP_ADAPTER},
-+ {"psmode", item_size(psmode), 0, item_addr(psmode), OFFSET_UAP_ADAPTER},
-+ {"ps_state", item_size(ps_state), 0, item_addr(ps_state),
-+ OFFSET_UAP_ADAPTER},
-+#ifdef DEBUG_LEVEL1
-+ {"drvdbg", sizeof(drvdbg), (u32) & drvdbg, 0, 0}
-+#endif
-+};
-+
-+static int num_of_items = sizeof(items) / sizeof(items[0]);
-+
-+/********************************************************
-+ Global Variables
-+********************************************************/
-+
-+/********************************************************
-+ Local Functions
-+********************************************************/
-+/**
-+ * @brief proc read function
-+ *
-+ * @param page pointer to buffer
-+ * @param s read data starting position
-+ * @param off offset
-+ * @param cnt counter
-+ * @param eof end of file flag
-+ * @param data data to output
-+ * @return number of output data
-+ */
-+static int
-+uap_debug_read(char *page, char **s, off_t off, int cnt, int *eof, void *data)
-+{
-+ int val = 0;
-+ char *p = page;
-+ int i;
-+
-+ struct debug_data *d = (struct debug_data *) data;
-+
-+ if (MODULE_GET == 0)
-+ return UAP_STATUS_FAILURE;
-+
-+ for (i = 0; i < num_of_items; i++) {
-+ if (d[i].size == 1)
-+ val = *((u8 *) d[i].addr);
-+ else if (d[i].size == 2)
-+ val = *((u16 *) d[i].addr);
-+ else if (d[i].size == 4)
-+ val = *((u32 *) d[i].addr);
-+
-+ p += sprintf(p, "%s=%d\n", d[i].name, val);
-+ }
-+ MODULE_PUT;
-+ return p - page;
-+}
-+
-+/**
-+ * @brief proc write function
-+ *
-+ * @param f file pointer
-+ * @param buf pointer to data buffer
-+ * @param cnt data number to write
-+ * @param data data to write
-+ * @return number of data
-+ */
-+static int
-+uap_debug_write(struct file *f, const char *buf, unsigned long cnt, void *data)
-+{
-+ int r, i;
-+ char *pdata;
-+ char *p;
-+ char *p0;
-+ char *p1;
-+ char *p2;
-+ struct debug_data *d = (struct debug_data *) data;
-+
-+ if (MODULE_GET == 0)
-+ return UAP_STATUS_FAILURE;
-+
-+ pdata = (char *) kmalloc(cnt, GFP_KERNEL);
-+ if (pdata == NULL) {
-+ MODULE_PUT;
-+ return 0;
-+ }
-+
-+ if (copy_from_user(pdata, buf, cnt)) {
-+ PRINTM(INFO, "Copy from user failed\n");
-+ kfree(pdata);
-+ MODULE_PUT;
-+ return 0;
-+ }
-+
-+ p0 = pdata;
-+ for (i = 0; i < num_of_items; i++) {
-+ do {
-+ p = strstr(p0, d[i].name);
-+ if (p == NULL)
-+ break;
-+ p1 = strchr(p, '\n');
-+ if (p1 == NULL)
-+ break;
-+ p0 = p1++;
-+ p2 = strchr(p, '=');
-+ if (!p2)
-+ break;
-+ p2++;
-+ r = string_to_number(p2);
-+ if (d[i].size == 1)
-+ *((u8 *) d[i].addr) = (u8) r;
-+ else if (d[i].size == 2)
-+ *((u16 *) d[i].addr) = (u16) r;
-+ else if (d[i].size == 4)
-+ *((u32 *) d[i].addr) = (u32) r;
-+ break;
-+ } while (TRUE);
-+ }
-+ kfree(pdata);
-+#ifdef DEBUG_LEVEL1
-+ printk(KERN_ALERT "drvdbg = 0x%x\n", drvdbg);
-+ printk(KERN_ALERT "INFO (%08lx) %s\n", DBG_INFO,
-+ (drvdbg & DBG_INFO) ? "X" : "");
-+ printk(KERN_ALERT "WARN (%08lx) %s\n", DBG_WARN,
-+ (drvdbg & DBG_WARN) ? "X" : "");
-+ printk(KERN_ALERT "ENTRY (%08lx) %s\n", DBG_ENTRY,
-+ (drvdbg & DBG_ENTRY) ? "X" : "");
-+ printk(KERN_ALERT "CMD_D (%08lx) %s\n", DBG_CMD_D,
-+ (drvdbg & DBG_CMD_D) ? "X" : "");
-+ printk(KERN_ALERT "DAT_D (%08lx) %s\n", DBG_DAT_D,
-+ (drvdbg & DBG_DAT_D) ? "X" : "");
-+ printk(KERN_ALERT "CMND (%08lx) %s\n", DBG_CMND,
-+ (drvdbg & DBG_CMND) ? "X" : "");
-+ printk(KERN_ALERT "DATA (%08lx) %s\n", DBG_DATA,
-+ (drvdbg & DBG_DATA) ? "X" : "");
-+ printk(KERN_ALERT "ERROR (%08lx) %s\n", DBG_ERROR,
-+ (drvdbg & DBG_ERROR) ? "X" : "");
-+ printk(KERN_ALERT "FATAL (%08lx) %s\n", DBG_FATAL,
-+ (drvdbg & DBG_FATAL) ? "X" : "");
-+ printk(KERN_ALERT "MSG (%08lx) %s\n", DBG_MSG,
-+ (drvdbg & DBG_MSG) ? "X" : "");
-+#endif
-+ MODULE_PUT;
-+ return cnt;
-+}
-+
-+/********************************************************
-+ Global Functions
-+********************************************************/
-+/**
-+ * @brief create debug proc file
-+ *
-+ * @param priv pointer uap_private
-+ * @param dev pointer net_device
-+ * @return N/A
-+ */
-+void
-+uap_debug_entry(uap_private * priv, struct net_device *dev)
-+{
-+ int i;
-+ struct proc_dir_entry *r;
-+
-+ if (priv->proc_entry == NULL)
-+ return;
-+
-+ for (i = 0; i < num_of_items; i++) {
-+ if (items[i].flag & OFFSET_UAP_ADAPTER)
-+ items[i].addr = items[i].offset + (u32) priv->adapter;
-+ if (items[i].flag & OFFSET_UAP_DEV)
-+ items[i].addr = items[i].offset + (u32) & priv->uap_dev;
-+ }
-+ r = create_proc_entry("debug", 0644, priv->proc_entry);
-+ if (r == NULL)
-+ return;
-+
-+ r->data = &items[0];
-+ r->read_proc = uap_debug_read;
-+ r->write_proc = uap_debug_write;
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
-+ r->owner = THIS_MODULE;
-+#endif
-+}
-+
-+/**
-+ * @brief remove proc file
-+ *
-+ * @param priv pointer uap_private
-+ * @return N/A
-+ */
-+void
-+uap_debug_remove(uap_private * priv)
-+{
-+ remove_proc_entry("debug", priv->proc_entry);
-+}
-+
-+#endif
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_drv.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_drv.h
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_drv.h 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_drv.h 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,667 @@
-+/** @file uap_drv.h
-+ * @brief This file contains Linux OS related definitions and
-+ * declarations, uAP driver
-+ *
-+ * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+
-+#ifndef _UAP_DRV_H
-+#define _UAP_DRV_H
-+
-+/** Driver release version */
-+#define DRIVER_VERSION "26146"
-+
-+/** True */
-+#ifndef TRUE
-+#define TRUE 1
-+#endif
-+/** False */
-+#ifndef FALSE
-+#define FALSE 0
-+#endif
-+
-+/** Bit definitions */
-+#ifndef BIT
-+#define BIT(x) (1UL << (x))
-+#endif
-+
-+/** Dma addresses are 32-bits wide. */
-+#ifndef __ATTRIB_ALIGN__
-+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
-+#endif
-+
-+/** attribute pack */
-+#ifndef __ATTRIB_PACK__
-+#define __ATTRIB_PACK__ __attribute__ ((packed))
-+#endif
-+
-+/** Debug Macro definition*/
-+#ifdef DEBUG_LEVEL1
-+
-+extern u32 drvdbg;
-+
-+/** Debug message control bit definition for drvdbg */
-+/** Debug message */
-+#define DBG_MSG BIT(0)
-+/** Debug fatal message */
-+#define DBG_FATAL BIT(1)
-+/** Debug error message */
-+#define DBG_ERROR BIT(2)
-+/** Debug data message */
-+#define DBG_DATA BIT(3)
-+/** Debug command message */
-+#define DBG_CMND BIT(4)
-+
-+/** Debug data */
-+#define DBG_DAT_D BIT(16)
-+/** Debug command */
-+#define DBG_CMD_D BIT(17)
-+
-+/** Debug entry */
-+#define DBG_ENTRY BIT(28)
-+/** Debug warning */
-+#define DBG_WARN BIT(29)
-+/** Debug info */
-+#define DBG_INFO BIT(30)
-+
-+/** Print info */
-+#define PRINTM_INFO(msg...) {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);}
-+/** Print warn message */
-+#define PRINTM_WARN(msg...) {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);}
-+/** Print entry */
-+#define PRINTM_ENTRY(msg...) {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);}
-+/** Print cmd_d */
-+#define PRINTM_CMD_D(msg...) {if (drvdbg & DBG_CMD_D) printk(KERN_DEBUG msg);}
-+/** Print data_d */
-+#define PRINTM_DAT_D(msg...) {if (drvdbg & DBG_DAT_D) printk(KERN_DEBUG msg);}
-+/** Print command */
-+#define PRINTM_CMND(msg...) {if (drvdbg & DBG_CMND) printk(KERN_DEBUG msg);}
-+/** Print data */
-+#define PRINTM_DATA(msg...) {if (drvdbg & DBG_DATA) printk(KERN_DEBUG msg);}
-+/** Print error message */
-+#define PRINTM_ERROR(msg...) {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);}
-+/** Print fatal message */
-+#define PRINTM_FATAL(msg...) {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);}
-+/** Print message */
-+#define PRINTM_MSG(msg...) {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);}
-+/** Print level */
-+#define PRINTM(level,msg...) PRINTM_##level(msg)
-+
-+#else
-+
-+#define PRINTM(level,msg...) do {} while (0)
-+
-+#endif /* DEBUG_LEVEL1 */
-+
-+/** Wait until a condition becomes true */
-+#define ASSERT(cond) \
-+do { \
-+ if (!(cond)) \
-+ PRINTM(INFO, "ASSERT: %s, %s:%i\n", \
-+ __FUNCTION__, __FILE__, __LINE__); \
-+} while(0)
-+
-+/** Log enrty point for debugging */
-+#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \
-+ __FILE__, __LINE__)
-+/** Log exit point for debugging */
-+#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \
-+ __FILE__, __LINE__)
-+
-+#ifdef DEBUG_LEVEL1
-+/** Dump buffer length */
-+#define DBG_DUMP_BUF_LEN 64
-+/** Maximum dump per line */
-+#define MAX_DUMP_PER_LINE 16
-+/** Data dump length */
-+#define DATA_DUMP_LEN 32
-+
-+static inline void
-+hexdump(char *prompt, u8 * buf, int len)
-+{
-+ int i;
-+ char dbgdumpbuf[DBG_DUMP_BUF_LEN];
-+ char *ptr = dbgdumpbuf;
-+
-+ printk(KERN_DEBUG "%s:\n", prompt);
-+ for (i = 1; i <= len; i++) {
-+ ptr += sprintf(ptr, "%02x ", *buf);
-+ buf++;
-+ if (i % MAX_DUMP_PER_LINE == 0) {
-+ *ptr = 0;
-+ printk(KERN_DEBUG "%s\n", dbgdumpbuf);
-+ ptr = dbgdumpbuf;
-+ }
-+ }
-+ if (len % MAX_DUMP_PER_LINE) {
-+ *ptr = 0;
-+ printk(KERN_DEBUG "%s\n", dbgdumpbuf);
-+ }
-+}
-+
-+/** Debug command */
-+#define DBG_HEXDUMP_CMD_D(x,y,z) {if (drvdbg & DBG_CMD_D) hexdump(x,y,z);}
-+/** Debug data */
-+#define DBG_HEXDUMP_DAT_D(x,y,z) {if (drvdbg & DBG_DAT_D) hexdump(x,y,z);}
-+/** Debug hexdump */
-+#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z)
-+/** hexdump */
-+#define HEXDUMP(x,y,z) {if (drvdbg & DBG_INFO) hexdump(x,y,z);}
-+#else
-+/** Do nothing since debugging is not turned on */
-+#define DBG_HEXDUMP(level,x,y,z) do {} while (0)
-+/** Do nothing since debugging is not turned on */
-+#define HEXDUMP(x,y,z) do {} while (0)
-+#endif
-+
-+/**
-+ * Typedefs
-+ */
-+/** Unsigned char */
-+typedef u8 BOOLEAN;
-+
-+/*
-+ * OS macro definitions
-+ */
-+/** OS macro to get time */
-+#define os_time_get() jiffies
-+
-+/** OS macro to update transfer start time */
-+#define UpdateTransStart(dev) { \
-+ dev->trans_start = jiffies; \
-+}
-+
-+/** Try to get a reference to the module */
-+#define MODULE_GET try_module_get(THIS_MODULE)
-+/** Decrease module reference count */
-+#define MODULE_PUT module_put(THIS_MODULE)
-+
-+/** OS macro to initialize semaphore */
-+#define OS_INIT_SEMAPHORE(x) sema_init(x,1)
-+/** OS macro to acquire blocking semaphore */
-+#define OS_ACQ_SEMAPHORE_BLOCK(x) down_interruptible(x)
-+/** OS macro to acquire non-blocking semaphore */
-+#define OS_ACQ_SEMAPHORE_NOBLOCK(x) down_trylock(x)
-+/** OS macro to release semaphore */
-+#define OS_REL_SEMAPHORE(x) up(x)
-+
-+static inline void
-+os_sched_timeout(u32 millisec)
-+{
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout((millisec * HZ) / 1000);
-+}
-+
-+/** Maximum size of ethernet packet */
-+#define MRVDRV_MAXIMUM_ETH_PACKET_SIZE 1514
-+
-+/** Maximum size of multicast list */
-+#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
-+
-+/** Find minimum */
-+#ifndef MIN
-+#define MIN(a,b) ((a) < (b) ? (a) : (b))
-+#endif
-+
-+/** Find maximum */
-+#ifndef MAX
-+#define MAX(a,b) ((a) > (b) ? (a) : (b))
-+#endif
-+
-+/** Find number of elements */
-+#ifndef NELEMENTS
-+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
-+#endif
-+
-+/** Buffer Constants */
-+
-+/** Size of command buffer */
-+#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
-+
-+/** Length of device length */
-+#define DEV_NAME_LEN 32
-+
-+/** Length of ethernet address */
-+#ifndef ETH_ALEN
-+#define ETH_ALEN 6
-+#endif
-+
-+/** Default watchdog timeout */
-+#define MRVDRV_DEFAULT_WATCHDOG_TIMEOUT (2 * HZ)
-+
-+/** Success */
-+#define UAP_STATUS_SUCCESS (0)
-+/** Failure */
-+#define UAP_STATUS_FAILURE (-1)
-+/** Not accepted */
-+#define UAP_STATUS_NOT_ACCEPTED (-2)
-+
-+/** Max loop count (* 100ms) for waiting device ready at init time */
-+#define MAX_WAIT_DEVICE_READY_COUNT 50
-+
-+/** Tx high watermark. Stop Tx queue after this is crossed */
-+#define TX_HIGH_WATERMARK 4
-+/** Tx low watermark. Restart Tx queue after this is crossed */
-+#define TX_LOW_WATERMARK 2
-+
-+/** Netlink protocol number */
-+#define NETLINK_MARVELL (MAX_LINKS - 1)
-+/** Netlink maximum payload size */
-+#define NL_MAX_PAYLOAD 1024
-+/** Netlink multicast group number */
-+#define NL_MULTICAST_GROUP 1
-+
-+/** 20 seconds */
-+#define MRVDRV_TIMER_20S 20000
-+
-+/** Host Command option for wait till Send */
-+#define HostCmd_OPTION_WAITFORSEND 0x0001
-+/** Host Command option for wait for RSP */
-+#define HostCmd_OPTION_WAITFORRSP 0x0002
-+/** Host Command option for wait for RSP or Timeout */
-+#define HostCmd_OPTION_WAITFORRSP_TIMEOUT 0x0003
-+/** Host Command option for wait for RSP of sleep confirm */
-+#define HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM 0x0004
-+
-+/** Sleep until a condition gets true or a timeout elapses */
-+#define os_wait_interruptible_timeout(waitq, cond, timeout) \
-+ wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
-+
-+/** Private command ID to Host command */
-+#define UAPHOSTCMD (SIOCDEVPRIVATE + 1)
-+
-+/** Private command ID to Power Mode */
-+#define UAP_POWER_MODE (SIOCDEVPRIVATE + 3)
-+/** sleep_param */
-+typedef struct _ps_sleep_param
-+{
-+ /** control bitmap */
-+ u32 ctrl_bitmap;
-+ /** minimum sleep period (micro second) */
-+ u32 min_sleep;
-+ /** maximum sleep period (micro second) */
-+ u32 max_sleep;
-+} ps_sleep_param;
-+
-+/** inactivity sleep_param */
-+typedef struct _inact_sleep_param
-+{
-+ /** inactivity timeout (micro second) */
-+ u32 inactivity_to;
-+ /** miniumu awake period (micro second) */
-+ u32 min_awake;
-+ /** maximum awake period (micro second) */
-+ u32 max_awake;
-+} inact_sleep_param;
-+
-+/** flag for ps mode */
-+#define PS_FLAG_PS_MODE 1
-+/** flag for sleep param */
-+#define PS_FLAG_SLEEP_PARAM 2
-+/** flag for inactivity sleep param */
-+#define PS_FLAG_INACT_SLEEP_PARAM 4
-+
-+/** Disable power mode */
-+#define PS_MODE_DISABLE 0
-+/** Enable periodic dtim ps */
-+#define PS_MODE_PERIODIC_DTIM 1
-+/** Enable inactivity ps */
-+#define PS_MODE_INACTIVITY 2
-+
-+/** sleep parameter */
-+#define SLEEP_PARAMETER 1
-+/** inactivity sleep parameter */
-+#define INACTIVITY_SLEEP_PARAMETER 2
-+/** ps_mgmt */
-+typedef struct _ps_mgmt
-+{
-+ /** flags for valid field */
-+ u16 flags;
-+ /** power mode */
-+ u16 ps_mode;
-+ /** sleep param */
-+ ps_sleep_param sleep_param;
-+ /** inactivity sleep param */
-+ inact_sleep_param inact_param;
-+} ps_mgmt;
-+
-+/** Semaphore structure */
-+typedef struct semaphore SEMAPHORE;
-+
-+/** Global Varibale Declaration */
-+/** Private data structure of the device */
-+typedef struct _uap_private uap_private;
-+/** Adapter data structure of the device */
-+typedef struct _uap_adapter uap_adapter;
-+/** private structure */
-+extern uap_private *uappriv;
-+
-+/** ENUM definition*/
-+
-+/** Hardware status codes */
-+typedef enum _HARDWARE_STATUS
-+{
-+ HWReady,
-+ HWInitializing,
-+ HWReset,
-+ HWClosing,
-+ HWNotReady
-+} HARDWARE_STATUS;
-+
-+/** info for debug purpose */
-+typedef struct _uap_dbg
-+{
-+ /** Number of host to card command failures */
-+ u32 num_cmd_host_to_card_failure;
-+ /** Number of host to card Tx failures */
-+ u32 num_tx_host_to_card_failure;
-+} uap_dbg;
-+
-+/** Set thread state */
-+#define OS_SET_THREAD_STATE(x) set_current_state(x)
-+
-+typedef struct
-+{
-+ /** Task */
-+ struct task_struct *task;
-+ /** Queue */
-+ wait_queue_head_t waitQ;
-+ /** PID */
-+ pid_t pid;
-+ /** Private structure */
-+ void *priv;
-+} uap_thread;
-+
-+static inline void
-+uap_activate_thread(uap_thread * thr)
-+{
-+ /** Record the thread pid */
-+ thr->pid = current->pid;
-+
-+ /** Initialize the wait queue */
-+ init_waitqueue_head(&thr->waitQ);
-+}
-+
-+static inline void
-+uap_deactivate_thread(uap_thread * thr)
-+{
-+ thr->pid = 0;
-+ return;
-+}
-+
-+static inline void
-+uap_create_thread(int (*uapfunc) (void *), uap_thread * thr, char *name)
-+{
-+ thr->task = kthread_run(uapfunc, thr, "%s", name);
-+}
-+
-+static inline int
-+uap_terminate_thread(uap_thread * thr)
-+{
-+ /* Check if the thread is active or not */
-+ if (!thr->pid)
-+ return -1;
-+ kthread_stop(thr->task);
-+ return 0;
-+}
-+
-+/** Data structure for the Marvell uAP device */
-+typedef struct _uap_dev
-+{
-+ /** device name */
-+ char name[DEV_NAME_LEN];
-+ /** card pointer */
-+ void *card;
-+ /** IO port */
-+ u32 ioport;
-+ /** Rx unit */
-+ u8 rx_unit;
-+ /** Data sent:
-+ TRUE - Data is sent to fw, no Tx Done received
-+ FALSE - Tx done received for previous Tx */
-+ BOOLEAN data_sent;
-+ /** CMD sent:
-+ TRUE - CMD is sent to fw, no CMD Done received
-+ FALSE - CMD done received for previous CMD */
-+ BOOLEAN cmd_sent;
-+ /** netdev pointer */
-+ struct net_device *netdev;
-+} uap_dev_t, *puap_dev_t;
-+
-+/** Private structure for the MV device */
-+struct _uap_private
-+{
-+ /** Device open */
-+ int open;
-+
-+ /** Device adapter structure */
-+ uap_adapter *adapter;
-+ /** Device structure */
-+ uap_dev_t uap_dev;
-+
-+ /** Net device statistics structure */
-+ struct net_device_stats stats;
-+
-+ /** Number of Tx timeouts */
-+ u32 num_tx_timeout;
-+
-+ /** Media connection status */
-+ BOOLEAN MediaConnected;
-+
-+#ifdef CONFIG_PROC_FS
-+ struct proc_dir_entry *proc_uap;
-+ struct proc_dir_entry *proc_entry;
-+#endif /* CONFIG_PROC_FS */
-+
-+ /** Firmware helper */
-+ const struct firmware *fw_helper;
-+ /** Firmware */
-+ const struct firmware *firmware;
-+ /** Hotplug device */
-+ struct device *hotplug_device;
-+ /** thread to service interrupts */
-+ uap_thread MainThread;
-+ /** Driver lock */
-+ spinlock_t driver_lock;
-+ /** Driver lock flags */
-+ ulong driver_flags;
-+
-+};
-+
-+/** PS_CMD_ConfirmSleep */
-+typedef struct _PS_CMD_ConfirmSleep
-+{
-+ /** SDIO Length */
-+ u16 SDLen;
-+ /** SDIO Type */
-+ u16 SDType;
-+ /** Command */
-+ u16 Command;
-+ /** Size */
-+ u16 Size;
-+ /** Sequence number */
-+ u16 SeqNum;
-+ /** Result */
-+ u16 Result;
-+} __ATTRIB_PACK__ PS_CMD_ConfirmSleep, *PPS_CMD_ConfirmSleep;
-+
-+/** Wlan Adapter data structure*/
-+struct _uap_adapter
-+{
-+ /** Power save confirm sleep command */
-+ PS_CMD_ConfirmSleep PSConfirmSleep;
-+ /** Device status */
-+ HARDWARE_STATUS HardwareStatus;
-+ /** Interrupt counter */
-+ u32 IntCounter;
-+ /** Tx packet queue */
-+ struct sk_buff_head tx_queue;
-+ /** Cmd packet queue */
-+ struct sk_buff_head cmd_queue;
-+ /** Command sequence number */
-+ u16 SeqNum;
-+ /** Command buffer */
-+ u8 *CmdBuf;
-+ /** cmd pending flag */
-+ u8 cmd_pending;
-+ /** cmd wait option */
-+ u8 cmd_wait_option;
-+ /** Command buffer length */
-+ u32 CmdSize;
-+ /** Command wait queue */
-+ wait_queue_head_t cmdwait_q __ATTRIB_ALIGN__;
-+ /** Command wait queue state flag */
-+ u8 CmdWaitQWoken;
-+ /** PnP support */
-+ BOOLEAN SurpriseRemoved;
-+ /** Debug */
-+ uap_dbg dbg;
-+ /** Netlink kernel socket */
-+ struct sock *nl_sk;
-+ /** Semaphore for CMD */
-+ SEMAPHORE CmdSem;
-+ /** Power Save mode */
-+ u8 psmode;
-+ /** Power Save state */
-+ u8 ps_state;
-+ /** Number of wakeup tries */
-+ u32 WakeupTries;
-+};
-+
-+static inline int
-+os_upload_rx_packet(uap_private * priv, struct sk_buff *skb)
-+{
-+ skb->dev = priv->uap_dev.netdev;
-+ skb->protocol = eth_type_trans(skb, priv->uap_dev.netdev);
-+ skb->ip_summed = CHECKSUM_UNNECESSARY;
-+ if (in_interrupt())
-+ netif_rx(skb);
-+ else
-+ netif_rx_ni(skb);
-+ return 0;
-+}
-+
-+/*
-+ * netif carrier_on/off and start(wake)/stop_queue handling
-+ */
-+static inline void
-+os_carrier_on(uap_private * priv)
-+{
-+ if (!netif_carrier_ok(priv->uap_dev.netdev) &&
-+ (priv->MediaConnected == TRUE)) {
-+ netif_carrier_on(priv->uap_dev.netdev);
-+ }
-+}
-+
-+static inline void
-+os_carrier_off(uap_private * priv)
-+{
-+ if (netif_carrier_ok(priv->uap_dev.netdev)) {
-+ netif_carrier_off(priv->uap_dev.netdev);
-+ }
-+}
-+
-+static inline void
-+os_start_queue(uap_private * priv)
-+{
-+ if (netif_queue_stopped(priv->uap_dev.netdev) &&
-+ (priv->MediaConnected == TRUE)) {
-+ netif_wake_queue(priv->uap_dev.netdev);
-+ }
-+}
-+
-+static inline void
-+os_stop_queue(uap_private * priv)
-+{
-+ if (!netif_queue_stopped(priv->uap_dev.netdev)) {
-+ netif_stop_queue(priv->uap_dev.netdev);
-+ }
-+}
-+
-+/** Interface specific header */
-+#define INTF_HEADER_LEN 4
-+
-+/** headroom alignment for tx packet */
-+#define HEADER_ALIGNMENT 8
-+
-+/** The number of times to try when polling for status bits */
-+#define MAX_POLL_TRIES 100
-+
-+/** Length of SNAP header */
-+#define MRVDRV_SNAP_HEADER_LEN 8
-+
-+/** Extra length of Tx packet buffer */
-+#define EXTRA_LEN 36
-+
-+/** Buffer size for ethernet Tx packets */
-+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
-+ (ETH_FRAME_LEN + sizeof(TxPD) + EXTRA_LEN)
-+
-+/** Buffer size for ethernet Rx packets */
-+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
-+ (ETH_FRAME_LEN + sizeof(RxPD) \
-+ + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
-+
-+/** Packet type: data, command & event */
-+typedef enum _mv_type
-+{
-+ MV_TYPE_DAT = 0,
-+ MV_TYPE_CMD = 1,
-+ MV_TYPE_EVENT = 3
-+} mv_type;
-+
-+/** Disable interrupt */
-+#define OS_INT_DISABLE spin_lock_irqsave(&priv->driver_lock, priv->driver_flags)
-+/** Enable interrupt */
-+#define OS_INT_RESTORE spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags)
-+
-+int uap_process_rx_packet(uap_private * priv, struct sk_buff *skb);
-+void uap_interrupt(uap_private * priv);
-+uap_private *uap_add_card(void *card);
-+int uap_remove_card(void *card);
-+int uap_process_event(uap_private * priv, u8 * payload, uint len);
-+int uap_soft_reset(uap_private * priv);
-+int uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len);
-+
-+#ifdef CONFIG_PROC_FS
-+/** The proc fs interface */
-+void uap_proc_entry(uap_private * priv, struct net_device *dev);
-+void uap_proc_remove(uap_private * priv);
-+int string_to_number(char *s);
-+void uap_debug_entry(uap_private * priv, struct net_device *dev);
-+void uap_debug_remove(uap_private * priv);
-+#endif /* CONFIG_PROC_FS */
-+
-+int sbi_register(void);
-+
-+void sbi_unregister(void);
-+int sbi_register_dev(uap_private * priv);
-+int sbi_unregister_dev(uap_private * priv);
-+int sbi_prog_fw_w_helper(uap_private *);
-+
-+int sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb);
-+int sbi_enable_host_int(uap_private * priv);
-+int sbi_disable_host_int(uap_private * priv);
-+
-+int sbi_get_int_status(uap_private * priv, u8 * ireg);
-+/** Check firmware status */
-+int sbi_check_fw_status(uap_private *, int);
-+int sbi_prog_helper(uap_private *);
-+
-+int sbi_wakeup_firmware(uap_private * priv);
-+
-+#endif /* _UAP_DRV_H */
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_fw.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_fw.h
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_fw.h 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_fw.h 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,359 @@
-+/** @file uap_fw.h
-+ *
-+ * @brief This file contains firmware specific defines.
-+ *
-+ * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+/********************************************************
-+Change log:
-+ 02/26/08: Initial creation
-+********************************************************/
-+
-+#ifndef _UAP_FW_H
-+#define _UAP_FW_H
-+
-+/** uap upload size */
-+#define UAP_UPLD_SIZE 2312
-+/** Packet type Micro AP */
-+#define PKT_TYPE_MICROAP 1
-+/** Packet type client */
-+#define PKT_TYPE_CLIENT 0
-+
-+/** TxPD descriptor */
-+typedef struct _TxPD
-+{
-+ /** Bss Type */
-+ u8 BssType;
-+ /** Bss num */
-+ u8 BssNum;
-+ /** Tx packet length */
-+ u16 TxPktLength;
-+ /** Tx packet offset */
-+ u16 TxPktOffset;
-+ /** Tx packet type */
-+ u16 TxPktType;
-+ /** Tx Control */
-+ u32 TxControl;
-+ /** reserved */
-+ u32 reserved[2];
-+} __ATTRIB_PACK__ TxPD, *PTxPD;
-+
-+/** RxPD Descriptor */
-+typedef struct _RxPD
-+{
-+ /** Bss Type */
-+ u8 BssType;
-+ /** Bss Num */
-+ u8 BssNum;
-+ /** Tx packet length */
-+ u16 RxPktLength;
-+ /** Tx packet offset */
-+ u16 RxPktOffset;
-+} __ATTRIB_PACK__ RxPD, *PRxPD;
-+
-+#ifdef BIG_ENDIAN
-+/** Convert from 16 bit little endian format to CPU format */
-+#define uap_le16_to_cpu(x) le16_to_cpu(x)
-+/** Convert from 32 bit little endian format to CPU format */
-+#define uap_le32_to_cpu(x) le32_to_cpu(x)
-+/** Convert from 64 bit little endian format to CPU format */
-+#define uap_le64_to_cpu(x) le64_to_cpu(x)
-+/** Convert to 16 bit little endian format from CPU format */
-+#define uap_cpu_to_le16(x) cpu_to_le16(x)
-+/** Convert to 32 bit little endian format from CPU format */
-+#define uap_cpu_to_le32(x) cpu_to_le32(x)
-+/** Convert to 64 bit little endian format from CPU format */
-+#define uap_cpu_to_le64(x) cpu_to_le64(x)
-+
-+/** Convert TxPD to little endian format from CPU format */
-+#define endian_convert_TxPD(x); \
-+ { \
-+ (x)->TxPktLength = uap_cpu_to_le16((x)->TxPktLength); \
-+ (x)->TxPktOffset = uap_cpu_to_le32((x)->TxPktOffset); \
-+ (x)->TxControl = uap_cpu_to_le32((x)->TxControl); \
-+ (x)->TxPktType = uap_cpu_to_le32((x)->TxPktType); \
-+ }
-+
-+/** Convert RxPD from little endian format to CPU format */
-+#define endian_convert_RxPD(x); \
-+ { \
-+ (x)->RxPktLength = uap_le16_to_cpu((x)->RxPktLength); \
-+ (x)->RxPktOffset = uap_le32_to_cpu((x)->RxPktOffset); \
-+ }
-+#else /* BIG_ENDIAN */
-+/** Do nothing */
-+#define uap_le16_to_cpu(x) x
-+/** Do nothing */
-+#define uap_le32_to_cpu(x) x
-+/** Do nothing */
-+#define uap_le64_to_cpu(x) x
-+/** Do nothing */
-+#define uap_cpu_to_le16(x) x
-+/** Do nothing */
-+#define uap_cpu_to_le32(x) x
-+/** Do nothing */
-+#define uap_cpu_to_le64(x) x
-+
-+/** Do nothing */
-+#define endian_convert_TxPD(x)
-+/** Do nothing */
-+#define endian_convert_RxPD(x)
-+#endif /* BIG_ENDIAN */
-+
-+/** Host Command ID : Function initialization */
-+#define HostCmd_CMD_FUNC_INIT 0x00a9
-+/** Host Command ID : Function shutdown */
-+#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa
-+
-+/** Host Command id: SYS_INFO */
-+#define HOST_CMD_APCMD_SYS_INFO 0x00ae
-+/** Host Command id: SYS_RESET */
-+#define HOST_CMD_APCMD_SYS_RESET 0x00af
-+/** Host Command id: SYS_CONFIGURE */
-+#define HOST_CMD_APCMD_SYS_CONFIGURE 0x00b0
-+/** Host Command id: BSS_START */
-+#define HOST_CMD_APCMD_BSS_START 0x00b1
-+/** Host Command id: SYS_STOP */
-+#define HOST_CMD_APCMD_BSS_STOP 0x00b2
-+/** Host Command id: STA_LIST */
-+#define HOST_CMD_APCMD_STA_LIST 0x00b3
-+/** Host Command id: STA_FILTER_TABLE */
-+#define HOST_CMD_APCMD_STA_FILTER_TABLE 0x00b4
-+/** Host Command id: STA_DEAUTH */
-+#define HOST_CMD_APCMD_STA_DEAUTH 0x00b5
-+/** Host Command id: SOFT_RESET */
-+#define HOST_CMD_APCMD_SOFT_RESET 0x00d5
-+/** Host Command id: POWER_MGMT_EXT */
-+#define HOST_CMD_POWER_MGMT_EXT 0x00ef
-+/** Host Command id: SLEEP_CONFIRM*/
-+#define HOST_CMD_SLEEP_CONFIRM 0x00d8
-+
-+/** TLV type : SSID */
-+#define TLV_TYPE_SSID 0x0000
-+/** TLV type : Rates */
-+#define TLV_TYPE_RATES 0x0001
-+/** TLV type : PHY DS */
-+#define TLV_TYPE_PHY_DS 0x0003
-+
-+/** TLV Id : Base id */
-+#define PROPRIETARY_TLV_BASE_ID 0x0100
-+/** TLV Id : AP_MAC_ADDRESS */
-+#define MRVL_AP_MAC_ADDRESS_TLV_ID (PROPRIETARY_TLV_BASE_ID + 43)
-+/** TLV Id : Beacon period */
-+#define MRVL_BEACON_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 44)
-+/** TLV Id : Dtim period */
-+#define MRVL_DTIM_PERIOD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 45)
-+/** TLV Id : Basic rates */
-+#define MRVL_BASIC_RATES_TLV_ID (PROPRIETARY_TLV_BASE_ID + 46)
-+/** TLV Id : Tx Power */
-+#define MRVL_TX_POWER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 47)
-+/** TLV Id : Broadcast SSID control */
-+#define MRVL_BCAST_SSID_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 48)
-+/** TLV Id : Preamble control */
-+#define MRVL_PREAMBLE_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 49)
-+/** TLV Id : Antenna control */
-+#define MRVL_ANTENNA_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 50)
-+/** TLV Id : RTS threshold */
-+#define MRVL_RTS_THRESHOLD_TLV_ID (PROPRIETARY_TLV_BASE_ID + 51)
-+/** TLV Id : Radio control */
-+#define MRVL_RADIO_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 52)
-+/** TLV Id : TX data rate */
-+#define MRVL_TX_DATA_RATE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 53)
-+/** TLV Id : Packet forward control */
-+#define MRVL_PKT_FWD_CTL_TLV_ID (PROPRIETARY_TLV_BASE_ID + 54)
-+/** TLV Id : STA info */
-+#define MRVL_STA_INFO_TLV_ID (PROPRIETARY_TLV_BASE_ID + 55)
-+/** TLV Id : STA MAC address filter */
-+#define MRVL_STA_MAC_ADDR_FILTER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 56)
-+/** TLV Id : STA ageout timer */
-+#define MRVL_STA_AGEOUT_TIMER_TLV_ID (PROPRIETARY_TLV_BASE_ID + 57)
-+/** TLV Id : Security config */
-+#define MRVL_SECURITY_CFG_TLV_ID (PROPRIETARY_TLV_BASE_ID + 58)
-+/** TLV Id : WEP KEY */
-+#define MRVL_WEP_KEY_TLV_ID (PROPRIETARY_TLV_BASE_ID + 59)
-+/** TLV Id : WPA Passphrase */
-+#define MRVL_WPA_PASSPHRASE_TLV_ID (PROPRIETARY_TLV_BASE_ID + 60)
-+
-+/** Action get */
-+#define ACTION_GET 0
-+/** Action set */
-+#define ACTION_SET 1
-+/** Length of ethernet address */
-+#ifndef ETH_ALEN
-+#define ETH_ALEN 6
-+#endif
-+
-+/** HostCmd_DS_GEN */
-+typedef struct
-+{
-+ /** Command */
-+ u16 Command;
-+ /** Size */
-+ u16 Size;
-+ /** Sequence number */
-+ u16 SeqNum;
-+ /** Result */
-+ u16 Result;
-+} __ATTRIB_PACK__ HostCmd_DS_GEN;
-+
-+/** Size of HostCmd_DS_GEN */
-+#define S_DS_GEN sizeof(HostCmd_DS_GEN)
-+
-+/** _HostCmd_HEADER*/
-+typedef struct
-+{
-+ /** Command Header : Command */
-+ u16 Command;
-+ /** Command Header : Size */
-+ u16 Size;
-+} __ATTRIB_PACK__ HostCmd_HEADER;
-+
-+/** HostCmd_SYS_CONFIG */
-+typedef struct _HostCmd_SYS_CONFIG
-+{
-+ /** CMD Action GET/SET*/
-+ u16 Action;
-+ /** Tlv buffer */
-+ u8 TlvBuffer[0];
-+} __ATTRIB_PACK__ HostCmd_SYS_CONFIG;
-+
-+/** HostCmd_DS_POWER_MGMT_EXT */
-+typedef struct _HostCmd_DS_POWER_MGMT_EXT
-+{
-+ /** CMD Action Get/Set*/
-+ u16 action;
-+ /** power mode */
-+ u16 power_mode;
-+} __ATTRIB_PACK__ HostCmd_DS_POWER_MGMT_EXT;
-+
-+/** _HostCmd_DS_COMMAND*/
-+typedef struct _HostCmd_DS_COMMAND
-+{
-+
-+ /** Command Header : Command */
-+ u16 Command;
-+ /** Command Header : Size */
-+ u16 Size;
-+ /** Command Header : Sequence number */
-+ u16 SeqNum;
-+ /** Command Header : Result */
-+ u16 Result;
-+ /** Command Body */
-+ union
-+ {
-+ HostCmd_SYS_CONFIG sys_config;
-+ HostCmd_DS_POWER_MGMT_EXT pm_cfg;
-+
-+ } params;
-+} __ATTRIB_PACK__ HostCmd_DS_COMMAND;
-+
-+/** MrvlIEtypesHeader_*/
-+typedef struct _MrvlIEtypesHeader
-+{
-+ /** Header type */
-+ u16 Type;
-+ /** Header length */
-+ u16 Len;
-+} __ATTRIB_PACK__ MrvlIEtypesHeader_t;
-+
-+/** MrvlIEtypes_Data_t */
-+typedef struct _MrvlIEtypes_Data_t
-+{
-+ /** Header */
-+ MrvlIEtypesHeader_t Header;
-+ /** Data */
-+ u8 Data[1];
-+} __ATTRIB_PACK__ MrvlIEtypes_Data_t;
-+
-+/** MrvlIEtypes_ChanListParamSet_t */
-+typedef struct _MrvlIEtypes_MacAddr_t
-+{
-+ /** Header */
-+ MrvlIEtypesHeader_t Header;
-+ /** AP MAC address */
-+ u8 ApMacAddr[ETH_ALEN];
-+} __ATTRIB_PACK__ MrvlIEtypes_MacAddr_t;
-+
-+/** Event ID: BSS started */
-+#define MICRO_AP_EV_ID_BSS_START 46
-+
-+/** Event ID: BSS idle event */
-+#define MICRO_AP_EV_BSS_IDLE 67
-+
-+/** Event ID: BSS active event */
-+#define MICRO_AP_EV_BSS_ACTIVE 68
-+
-+/** Event ID: PS_AWAKE */
-+#define EVENT_PS_AWAKE 0x0a
-+
-+/** Event ID: PS_SLEEP */
-+#define EVENT_PS_SLEEP 0x0b
-+
-+/** PS_STATE */
-+typedef enum _PS_STATE
-+{
-+ PS_STATE_AWAKE,
-+ PS_STATE_PRE_SLEEP,
-+ PS_STATE_SLEEP
-+} PS_STATE;
-+
-+/** TLV type: AP Sleep param */
-+#define TLV_TYPE_AP_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 106)
-+/** TLV type: AP Inactivity Sleep param */
-+#define TLV_TYPE_AP_INACT_SLEEP_PARAM (PROPRIETARY_TLV_BASE_ID + 107)
-+
-+/** MrvlIEtypes_sleep_param_t */
-+typedef struct _MrvlIEtypes_sleep_param_t
-+{
-+ /** Header */
-+ MrvlIEtypesHeader_t header;
-+ /** control bitmap */
-+ u32 ctrl_bitmap;
-+ /** min_sleep */
-+ u32 min_sleep;
-+ /** max_sleep */
-+ u32 max_sleep;
-+} __ATTRIB_PACK__ MrvlIEtypes_sleep_param_t;
-+
-+/** MrvlIEtypes_inact_sleep_param_t */
-+typedef struct _MrvlIEtypes_inact_sleep_param_t
-+{
-+ /** Header */
-+ MrvlIEtypesHeader_t header;
-+ /** inactivity timeout */
-+ u32 inactivity_to;
-+ /** min_awake */
-+ u32 min_awake;
-+ /** max_awake */
-+ u32 max_awake;
-+} __ATTRIB_PACK__ MrvlIEtypes_inact_sleep_param_t;
-+
-+/** AP_Event */
-+typedef struct _AP_Event
-+{
-+ /** Event ID */
-+ u32 EventId;
-+ /*
-+ * Reserved for STA_ASSOCIATED event and contains
-+ * status information for the MIC_COUNTERMEASURES event.
-+ */
-+ /** Reserved/status */
-+ u16 status;
-+ /** AP MAC address */
-+ u8 MacAddr[ETH_ALEN];
-+} __ATTRIB_PACK__ AP_Event;
-+#endif /* _UAP_FW_H */
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_headers.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_headers.h
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_headers.h 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_headers.h 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,64 @@
-+/** @file uap_headers.h
-+ *
-+ * @brief This file contains all the necessary include file.
-+ *
-+ * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+#ifndef _UAP_HEADERS_H
-+#define _UAP_HEADERS_H
-+
-+/* Linux header files */
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/version.h>
-+#include <linux/param.h>
-+#include <linux/types.h>
-+#include <linux/interrupt.h>
-+#include <linux/proc_fs.h>
-+#include <linux/kthread.h>
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-+#include <linux/semaphore.h>
-+#else
-+#include <asm/semaphore.h>
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
-+#include <linux/config.h>
-+#endif
-+
-+/* Net header files */
-+#include <linux/netdevice.h>
-+#include <linux/net.h>
-+#include <linux/skbuff.h>
-+#include <linux/if_ether.h>
-+#include <linux/etherdevice.h>
-+#include <net/sock.h>
-+#include <linux/netlink.h>
-+#include <linux/firmware.h>
-+#include <linux/delay.h>
-+
-+#include "uap_drv.h"
-+#include "uap_fw.h"
-+
-+#include <linux/mmc/sdio.h>
-+#include <linux/mmc/sdio_ids.h>
-+#include <linux/mmc/sdio_func.h>
-+#include <linux/mmc/card.h>
-+#include "uap_sdio_mmc.h"
-+
-+#endif /* _UAP_HEADERS_H */
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_main.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_main.c
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_main.c 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_main.c 2012-07-31 14:25:28.473230753 +0200
-@@ -0,0 +1,1815 @@
-+/** @file uap_main.c
-+ * @brief This file contains the major functions in uAP
-+ * driver. It includes init, exit etc..
-+ * This file also contains the initialization for SW,
-+ * FW and HW
-+ *
-+ * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+/**
-+ * @mainpage uAP Linux Driver
-+ *
-+ * @section overview_sec Overview
-+ *
-+ * This is Linux reference driver for Marvell uAP.
-+ *
-+ * @section copyright_sec Copyright
-+ *
-+ * Copyright (C) 2008, Marvell International Ltd.
-+ *
-+ */
-+
-+#include "uap_headers.h"
-+
-+/**
-+ * the global variable of a pointer to uap_private
-+ * structure variable
-+ */
-+uap_private *uappriv = NULL;
-+#ifdef DEBUG_LEVEL1
-+#define DEFAULT_DEBUG_MASK (DBG_MSG | DBG_FATAL | DBG_ERROR)
-+u32 drvdbg = DEFAULT_DEBUG_MASK;
-+#endif
-+/** Helper name */
-+char *helper_name = NULL;
-+/** Firmware name */
-+char *fw_name = NULL;
-+
-+/** Semaphore for add/remove card */
-+SEMAPHORE AddRemoveCardSem;
-+
-+/********************************************************
-+ Local Functions
-+********************************************************/
-+/**
-+ * @brief This function send sleep confirm command to firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_dnld_sleep_confirm_cmd(uap_private * priv)
-+{
-+ uap_adapter *Adapter = priv->adapter;
-+ int ret = UAP_STATUS_SUCCESS;
-+ ENTER();
-+ PRINTM(CMND, "Sleep confirm\n");
-+ Adapter->cmd_pending = TRUE;
-+ Adapter->cmd_wait_option = HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM;
-+ ret =
-+ sbi_host_to_card(priv, (u8 *) & Adapter->PSConfirmSleep,
-+ sizeof(PS_CMD_ConfirmSleep));
-+ if (ret != UAP_STATUS_SUCCESS) {
-+ Adapter->ps_state = PS_STATE_AWAKE;
-+ Adapter->cmd_pending = FALSE;
-+ Adapter->cmd_wait_option = FALSE;
-+ }
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function process sleep confirm resp from firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param resp A pointer to resp buf
-+ * @param resp_len resp buf len
-+ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
-+ */
-+int
-+uap_process_sleep_confirm_resp(uap_private * priv, u8 * resp, int resp_len)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ HostCmd_DS_COMMAND *cmd;
-+ uap_adapter *Adapter = priv->adapter;
-+ ENTER();
-+ PRINTM(CMND, "Sleep confirm resp\n");
-+ if (!resp_len) {
-+ PRINTM(ERROR, "Cmd Size is 0\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ cmd = (HostCmd_DS_COMMAND *) resp;
-+ cmd->Result = uap_le16_to_cpu(cmd->Result);
-+ if (cmd->Result != UAP_STATUS_SUCCESS) {
-+ PRINTM(ERROR, "HOST_CMD_APCMD_PS_SLEEP_CONFIRM fail=%x\n", cmd->Result);
-+ ret = -EFAULT;
-+ }
-+ done:
-+ if (ret == UAP_STATUS_SUCCESS)
-+ Adapter->ps_state = PS_STATE_SLEEP;
-+ else
-+ Adapter->ps_state = PS_STATE_AWAKE;
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function checks condition and prepares to
-+ * send sleep confirm command to firmware if OK.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return n/a
-+ */
-+static void
-+uap_ps_cond_check(uap_private * priv)
-+{
-+ uap_adapter *Adapter = priv->adapter;
-+
-+ ENTER();
-+ if (!priv->uap_dev.cmd_sent &&
-+ !Adapter->cmd_pending && !Adapter->IntCounter) {
-+ uap_dnld_sleep_confirm_cmd(priv);
-+ } else {
-+ PRINTM(INFO, "Delay Sleep Confirm (%s%s%s)\n",
-+ (priv->uap_dev.cmd_sent) ? "D" : "",
-+ (Adapter->cmd_pending) ? "C" : "",
-+ (Adapter->IntCounter) ? "I" : "");
-+ }
-+ LEAVE();
-+}
-+
-+/**
-+ * @brief This function add cmd to cmdQ and waiting for response
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param skb A pointer to the skb for process
-+ * @param wait_option Wait option
-+ * @return UAP_STATUS_SUCCESS for success otherwise UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_process_cmd(uap_private * priv, struct sk_buff *skb, u8 wait_option)
-+{
-+ uap_adapter *Adapter = priv->adapter;
-+ int ret = UAP_STATUS_SUCCESS;
-+ HostCmd_DS_COMMAND *cmd;
-+ u8 *headptr;
-+ ENTER();
-+ if (Adapter->HardwareStatus != HWReady) {
-+ PRINTM(ERROR, "Hw not ready, uap_process_cmd\n");
-+ kfree(skb);
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ skb->cb[0] = wait_option;
-+ headptr = skb->data;
-+ *(u16 *) & headptr[0] = uap_cpu_to_le16(skb->len);
-+ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_CMD);
-+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+ Adapter->SeqNum++;
-+ cmd->SeqNum = uap_cpu_to_le16(Adapter->SeqNum);
-+ PRINTM(CMND, "process_cmd: %x\n", cmd->Command);
-+ DBG_HEXDUMP(CMD_D, "process_cmd", (u8 *) cmd, cmd->Size);
-+ if (!wait_option) {
-+ skb_queue_tail(&priv->adapter->cmd_queue, skb);
-+ wake_up_interruptible(&priv->MainThread.waitQ);
-+ LEAVE();
-+ return ret;
-+ }
-+ if (OS_ACQ_SEMAPHORE_BLOCK(&Adapter->CmdSem)) {
-+ PRINTM(ERROR, "Acquire semaphore error, uap_prepare_cmd\n");
-+ kfree(skb);
-+ LEAVE();
-+ return -EBUSY;
-+ }
-+ skb_queue_tail(&priv->adapter->cmd_queue, skb);
-+ Adapter->CmdWaitQWoken = FALSE;
-+ wake_up_interruptible(&priv->MainThread.waitQ);
-+ /* Sleep until response is generated by FW */
-+ if (wait_option == HostCmd_OPTION_WAITFORRSP_TIMEOUT) {
-+ if (!os_wait_interruptible_timeout
-+ (Adapter->cmdwait_q, Adapter->CmdWaitQWoken, MRVDRV_TIMER_20S)) {
-+ PRINTM(ERROR, "Cmd timeout\n");
-+ Adapter->cmd_pending = FALSE;
-+ ret = -EFAULT;
-+ }
-+ } else
-+ wait_event_interruptible(Adapter->cmdwait_q, Adapter->CmdWaitQWoken);
-+ OS_REL_SEMAPHORE(&Adapter->CmdSem);
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief Inspect the response buffer for pointers to expected TLVs
-+ *
-+ *
-+ * @param pTlv Pointer to the start of the TLV buffer to parse
-+ * @param tlvBufSize Size of the TLV buffer
-+ * @param reqTlvType request tlv's tlvtype
-+ * @param ppTlv Output parameter: Pointer to the request TLV if found
-+ *
-+ * @return void
-+ */
-+static void
-+uap_get_tlv_ptrs(MrvlIEtypes_Data_t * pTlv, int tlvBufSize,
-+ u16 reqTlvType, MrvlIEtypes_Data_t ** ppTlv)
-+{
-+ MrvlIEtypes_Data_t *pCurrentTlv;
-+ int tlvBufLeft;
-+ u16 tlvType;
-+ u16 tlvLen;
-+
-+ ENTER();
-+ pCurrentTlv = pTlv;
-+ tlvBufLeft = tlvBufSize;
-+ *ppTlv = NULL;
-+ PRINTM(INFO, "uap_get_tlv: tlvBufSize = %d, reqTlvType=%x\n", tlvBufSize,
-+ reqTlvType);
-+ while (tlvBufLeft >= sizeof(MrvlIEtypesHeader_t)) {
-+ tlvType = uap_le16_to_cpu(pCurrentTlv->Header.Type);
-+ tlvLen = uap_le16_to_cpu(pCurrentTlv->Header.Len);
-+ if (reqTlvType == tlvType)
-+ *ppTlv = (MrvlIEtypes_Data_t *) pCurrentTlv;
-+ if (*ppTlv) {
-+ HEXDUMP("TLV Buf", (u8 *) * ppTlv, tlvLen);
-+ break;
-+ }
-+ tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen);
-+ pCurrentTlv = (MrvlIEtypes_Data_t *) (pCurrentTlv->Data + tlvLen);
-+ } /* while */
-+ LEAVE();
-+}
-+
-+/**
-+ * @brief This function get mac
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int
-+uap_get_mac_address(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u32 CmdSize;
-+ HostCmd_DS_COMMAND *cmd;
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb;
-+ MrvlIEtypes_MacAddr_t *pMacAddrTlv;
-+ MrvlIEtypes_Data_t *pTlv;
-+ u16 tlvBufSize;
-+ ENTER();
-+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+ if (!skb) {
-+ PRINTM(ERROR, "No free skb\n");
-+ ret = -ENOMEM;
-+ goto done;
-+ }
-+ CmdSize =
-+ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
-+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
-+ cmd->Size = uap_cpu_to_le16(CmdSize);
-+ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_GET);
-+ pMacAddrTlv =
-+ (MrvlIEtypes_MacAddr_t *) (skb->data + INTF_HEADER_LEN + S_DS_GEN +
-+ sizeof(HostCmd_SYS_CONFIG));
-+ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
-+ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
-+ skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+ PRINTM(ERROR, "Fail to process cmd SYS_CONFIGURE Query\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ if (!Adapter->CmdSize) {
-+ PRINTM(ERROR, "Cmd Size is 0\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
-+ cmd->Result = uap_le16_to_cpu(cmd->Result);
-+ if (cmd->Result != UAP_STATUS_SUCCESS) {
-+ PRINTM(ERROR, "uap_get_mac_address fail=%x\n", cmd->Result);
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ pTlv =
-+ (MrvlIEtypes_Data_t *) (Adapter->CmdBuf + S_DS_GEN +
-+ sizeof(HostCmd_SYS_CONFIG));
-+ tlvBufSize = Adapter->CmdSize - S_DS_GEN - sizeof(HostCmd_SYS_CONFIG);
-+ uap_get_tlv_ptrs(pTlv, tlvBufSize, MRVL_AP_MAC_ADDRESS_TLV_ID,
-+ (MrvlIEtypes_Data_t **) & pMacAddrTlv);
-+ if (pMacAddrTlv) {
-+ memcpy(priv->uap_dev.netdev->dev_addr, pMacAddrTlv->ApMacAddr,
-+ ETH_ALEN);
-+ HEXDUMP("Original MAC addr", priv->uap_dev.netdev->dev_addr, ETH_ALEN);
-+ }
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function checks the conditions and sends packet to device
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param skb A pointer to the skb for process
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_process_tx(uap_private * priv, struct sk_buff *skb)
-+{
-+ uap_adapter *Adapter = priv->adapter;
-+ int ret = UAP_STATUS_SUCCESS;
-+ TxPD *pLocalTxPD;
-+ u8 *headptr;
-+ struct sk_buff *newskb;
-+ int newheadlen;
-+ ENTER();
-+ ASSERT(skb);
-+ if (!skb) {
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+ if (skb_headroom(skb) < (sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT)) {
-+ newheadlen = sizeof(TxPD) + INTF_HEADER_LEN + HEADER_ALIGNMENT;
-+ PRINTM(WARN, "Tx: Insufficient skb headroom %d\n", skb_headroom(skb));
-+ /* Insufficient skb headroom - allocate a new skb */
-+ newskb = skb_realloc_headroom(skb, newheadlen);
-+ if (unlikely(newskb == NULL)) {
-+ PRINTM(ERROR, "Tx: Cannot allocate skb\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ kfree_skb(skb);
-+ skb = newskb;
-+ PRINTM(INFO, "new skb headroom %d\n", skb_headroom(skb));
-+ }
-+ /* headptr should be aligned */
-+ headptr = skb->data - sizeof(TxPD) - INTF_HEADER_LEN;
-+ headptr = (u8 *) ((u32) headptr & ~((u32) (HEADER_ALIGNMENT - 1)));
-+
-+ pLocalTxPD = (TxPD *) (headptr + INTF_HEADER_LEN);
-+ memset(pLocalTxPD, 0, sizeof(TxPD));
-+ pLocalTxPD->BssType = PKT_TYPE_MICROAP;
-+ pLocalTxPD->TxPktLength = skb->len;
-+ /* offset of actual data */
-+ pLocalTxPD->TxPktOffset = (long) skb->data - (long) pLocalTxPD;
-+ endian_convert_TxPD(pLocalTxPD);
-+ *(u16 *) & headptr[0] =
-+ uap_cpu_to_le16(skb->len + ((long) skb->data - (long) headptr));
-+ *(u16 *) & headptr[2] = uap_cpu_to_le16(MV_TYPE_DAT);
-+ ret =
-+ sbi_host_to_card(priv, headptr,
-+ skb->len + ((long) skb->data - (long) headptr));
-+ if (ret) {
-+ PRINTM(ERROR, "uap_process_tx Error: sbi_host_to_card failed: 0x%X\n",
-+ ret);
-+ Adapter->dbg.num_tx_host_to_card_failure++;
-+ goto done;
-+ }
-+ PRINTM(DATA, "Data => FW\n");
-+ DBG_HEXDUMP(DAT_D, "Tx", headptr,
-+ MIN(skb->len + sizeof(TxPD), DATA_DUMP_LEN));
-+ done:
-+ /* Freed skb */
-+ kfree_skb(skb);
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function initializes the adapter structure
-+ * and set default value to the member of adapter.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_init_sw(uap_private * priv)
-+{
-+ uap_adapter *Adapter = priv->adapter;
-+
-+ ENTER();
-+
-+ if (!(Adapter->CmdBuf = kmalloc(MRVDRV_SIZE_OF_CMD_BUFFER, GFP_KERNEL))) {
-+ PRINTM(INFO, "Failed to allocate command buffer!\n");
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+
-+ Adapter->cmd_pending = FALSE;
-+ Adapter->CmdWaitQWoken = FALSE;
-+ Adapter->ps_state = PS_STATE_AWAKE;
-+ Adapter->WakeupTries = 0;
-+
-+ memset(&Adapter->PSConfirmSleep, 0, sizeof(PS_CMD_ConfirmSleep));
-+ /** SDIO header */
-+ Adapter->PSConfirmSleep.SDLen =
-+ uap_cpu_to_le16(sizeof(PS_CMD_ConfirmSleep));
-+ Adapter->PSConfirmSleep.SDType = uap_cpu_to_le16(MV_TYPE_CMD);
-+ Adapter->PSConfirmSleep.SeqNum = 0;
-+ Adapter->PSConfirmSleep.Command = uap_cpu_to_le16(HOST_CMD_SLEEP_CONFIRM);
-+ Adapter->PSConfirmSleep.Size = uap_cpu_to_le16(sizeof(HostCmd_DS_GEN));
-+ Adapter->PSConfirmSleep.Result = 0;
-+
-+ init_waitqueue_head(&Adapter->cmdwait_q);
-+ OS_INIT_SEMAPHORE(&Adapter->CmdSem);
-+
-+ skb_queue_head_init(&Adapter->tx_queue);
-+ skb_queue_head_init(&Adapter->cmd_queue);
-+
-+ /* Status variable */
-+ Adapter->HardwareStatus = HWInitializing;
-+
-+ /* PnP support */
-+ Adapter->SurpriseRemoved = FALSE;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
-+ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
-+ NL_MULTICAST_GROUP, NULL,
-+ THIS_MODULE);
-+#else
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-+ Adapter->nl_sk = netlink_kernel_create(NETLINK_MARVELL,
-+ NL_MULTICAST_GROUP, NULL, NULL,
-+ THIS_MODULE);
-+#else
-+ Adapter->nl_sk = netlink_kernel_create(&init_net, NETLINK_MARVELL,
-+ NL_MULTICAST_GROUP, NULL, NULL,
-+ THIS_MODULE);
-+#endif
-+#endif
-+ if (!Adapter->nl_sk) {
-+ PRINTM(ERROR,
-+ "Could not initialize netlink event passing mechanism!\n");
-+ }
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ * @brief This function sends FUNC_INIT command to firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int
-+uap_func_init(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u32 CmdSize;
-+ HostCmd_DS_GEN *cmd;
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb;
-+ ENTER();
-+ if (Adapter->HardwareStatus != HWReady) {
-+ PRINTM(ERROR, "uap_func_init:Hardware is not ready!\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+ if (!skb) {
-+ PRINTM(ERROR, "No free skb\n");
-+ ret = -ENOMEM;
-+ goto done;
-+ }
-+ CmdSize = sizeof(HostCmd_DS_GEN);
-+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_INIT);
-+ cmd->Size = uap_cpu_to_le16(CmdSize);
-+ skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+ PRINTM(CMND, "HostCmd_CMD_FUNC_INIT\n");
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_INIT\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function sends FUNC_SHUTDOWN command to firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int __exit
-+uap_func_shutdown(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u32 CmdSize;
-+ HostCmd_DS_GEN *cmd;
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb;
-+ ENTER();
-+ if (Adapter->HardwareStatus != HWReady) {
-+ PRINTM(ERROR, "uap_func_shutdown:Hardware is not ready!\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+ if (!skb) {
-+ PRINTM(ERROR, "No free skb\n");
-+ ret = -ENOMEM;
-+ goto done;
-+ }
-+ CmdSize = sizeof(HostCmd_DS_GEN);
-+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+ cmd->Command = uap_cpu_to_le16(HostCmd_CMD_FUNC_SHUTDOWN);
-+ cmd->Size = uap_cpu_to_le16(CmdSize);
-+ skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+ PRINTM(CMND, "HostCmd_CMD_FUNC_SHUTDOWN\n");
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+ PRINTM(ERROR, "Fail to process cmd HostCmd_CMD_FUNC_SHUTDOWN\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function initializes firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_init_fw(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ ENTER();
-+ sbi_disable_host_int(priv);
-+ /* Check if firmware is already running */
-+ if (sbi_check_fw_status(priv, 1) == UAP_STATUS_SUCCESS) {
-+ PRINTM(MSG, "UAP FW already running! Skip FW download\n");
-+ } else {
-+ if ((ret = request_firmware(&priv->fw_helper, helper_name,
-+ priv->hotplug_device)) < 0) {
-+ PRINTM(FATAL,
-+ "request_firmware() failed (helper), error code = %#x\n",
-+ ret);
-+ goto done;
-+ }
-+
-+ /* Download the helper */
-+ ret = sbi_prog_helper(priv);
-+
-+ if (ret) {
-+ PRINTM(FATAL,
-+ "Bootloader in invalid state! Helper download failed!\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ if ((ret = request_firmware(&priv->firmware, fw_name,
-+ priv->hotplug_device)) < 0) {
-+ PRINTM(FATAL, "request_firmware() failed, error code = %#x\n", ret);
-+ goto done;
-+ }
-+
-+ /* Download the main firmware via the helper firmware */
-+ if (sbi_prog_fw_w_helper(priv)) {
-+ PRINTM(FATAL, "UAP FW download failed!\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ /* Check if the firmware is downloaded successfully or not */
-+ if (sbi_check_fw_status(priv, MAX_FIRMWARE_POLL_TRIES) ==
-+ UAP_STATUS_FAILURE) {
-+ PRINTM(FATAL, "FW failed to be active in time!\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ PRINTM(MSG, "UAP FW is active\n");
-+ }
-+ sbi_enable_host_int(priv);
-+ priv->adapter->HardwareStatus = HWReady;
-+ if (uap_func_init(priv) != UAP_STATUS_SUCCESS) {
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ done:
-+ if (priv->fw_helper)
-+ release_firmware(priv->fw_helper);
-+ if (priv->firmware)
-+ release_firmware(priv->firmware);
-+ LEAVE();
-+ return ret;
-+
-+}
-+
-+/**
-+ * @brief This function frees the structure of adapter
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return n/a
-+ */
-+static void
-+uap_free_adapter(uap_private * priv)
-+{
-+ uap_adapter *Adapter = priv->adapter;
-+
-+ ENTER();
-+
-+ if (Adapter) {
-+ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
-+ sock_release((Adapter->nl_sk)->sk_socket);
-+ Adapter->nl_sk = NULL;
-+ }
-+ if (Adapter->CmdBuf)
-+ kfree(Adapter->CmdBuf);
-+ skb_queue_purge(&priv->adapter->tx_queue);
-+ skb_queue_purge(&priv->adapter->cmd_queue);
-+ /* Free the adapter object itself */
-+ kfree(Adapter);
-+ priv->adapter = NULL;
-+ }
-+
-+ LEAVE();
-+}
-+
-+/**
-+ * @brief This function handles the major job in uap driver.
-+ * it handles the event generated by firmware, rx data received
-+ * from firmware and tx data sent from kernel.
-+ *
-+ * @param data A pointer to uap_thread structure
-+ * @return BT_STATUS_SUCCESS
-+ */
-+static int
-+uap_service_main_thread(void *data)
-+{
-+ uap_thread *thread = data;
-+ uap_private *priv = thread->priv;
-+ uap_adapter *Adapter = priv->adapter;
-+ wait_queue_t wait;
-+ u8 ireg = 0;
-+ struct sk_buff *skb;
-+ ENTER();
-+ uap_activate_thread(thread);
-+ init_waitqueue_entry(&wait, current);
-+ current->flags |= PF_NOFREEZE;
-+
-+ for (;;) {
-+ add_wait_queue(&thread->waitQ, &wait);
-+ OS_SET_THREAD_STATE(TASK_INTERRUPTIBLE);
-+ if ((Adapter->WakeupTries) ||
-+ (!Adapter->IntCounter && Adapter->ps_state == PS_STATE_PRE_SLEEP) ||
-+ (!priv->adapter->IntCounter
-+ && (priv->uap_dev.data_sent ||
-+ skb_queue_empty(&priv->adapter->tx_queue))
-+ && (priv->uap_dev.cmd_sent || Adapter->cmd_pending ||
-+ skb_queue_empty(&priv->adapter->cmd_queue))
-+ )) {
-+ PRINTM(INFO, "Main: Thread sleeping...\n");
-+ schedule();
-+ }
-+ OS_SET_THREAD_STATE(TASK_RUNNING);
-+ remove_wait_queue(&thread->waitQ, &wait);
-+ if (kthread_should_stop() || Adapter->SurpriseRemoved) {
-+ PRINTM(INFO, "main-thread: break from main thread: "
-+ "SurpriseRemoved=0x%x\n", Adapter->SurpriseRemoved);
-+ /* Cancel pending command */
-+ if (Adapter->cmd_pending == TRUE) {
-+ /* Wake up cmd Q */
-+ Adapter->CmdWaitQWoken = TRUE;
-+ wake_up_interruptible(&Adapter->cmdwait_q);
-+ }
-+ break;
-+ }
-+
-+ PRINTM(INFO, "Main: Thread waking up...\n");
-+ if (priv->adapter->IntCounter) {
-+ OS_INT_DISABLE;
-+ Adapter->IntCounter = 0;
-+ OS_INT_RESTORE;
-+ sbi_get_int_status(priv, &ireg);
-+ } else if ((priv->adapter->ps_state == PS_STATE_SLEEP) &&
-+ (!skb_queue_empty(&priv->adapter->cmd_queue) ||
-+ !skb_queue_empty(&priv->adapter->tx_queue))) {
-+ priv->adapter->WakeupTries++;
-+ PRINTM(CMND, "%lu : Wakeup device...\n", os_time_get());
-+ sbi_wakeup_firmware(priv);
-+ continue;
-+ }
-+ if (Adapter->ps_state == PS_STATE_PRE_SLEEP)
-+ uap_ps_cond_check(priv);
-+
-+ /* The PS state is changed during processing of Sleep Request event
-+ above */
-+ if ((Adapter->ps_state == PS_STATE_SLEEP) ||
-+ (Adapter->ps_state == PS_STATE_PRE_SLEEP))
-+ continue;
-+ /* Execute the next command */
-+ if (!priv->uap_dev.cmd_sent && !Adapter->cmd_pending &&
-+ (Adapter->HardwareStatus == HWReady)) {
-+ if (!skb_queue_empty(&priv->adapter->cmd_queue)) {
-+ skb = skb_dequeue(&priv->adapter->cmd_queue);
-+ if (skb) {
-+ Adapter->CmdSize = 0;
-+ Adapter->cmd_pending = TRUE;
-+ Adapter->cmd_wait_option = skb->cb[0];
-+ if (sbi_host_to_card(priv, skb->data, skb->len)) {
-+ PRINTM(ERROR, "Cmd:sbi_host_to_card failed!\n");
-+ Adapter->cmd_pending = FALSE;
-+ Adapter->dbg.num_cmd_host_to_card_failure++;
-+ /* Wake up cmd Q */
-+ Adapter->CmdWaitQWoken = TRUE;
-+ wake_up_interruptible(&Adapter->cmdwait_q);
-+ } else {
-+ if (Adapter->cmd_wait_option ==
-+ HostCmd_OPTION_WAITFORSEND) {
-+ /* Wake up cmd Q */
-+ Adapter->CmdWaitQWoken = TRUE;
-+ wake_up_interruptible(&Adapter->cmdwait_q);
-+ Adapter->cmd_wait_option = FALSE;
-+ }
-+ }
-+ kfree_skb(skb);
-+ }
-+ }
-+ }
-+ if (!priv->uap_dev.data_sent && (Adapter->HardwareStatus == HWReady)) {
-+ if (!skb_queue_empty(&priv->adapter->tx_queue)) {
-+ skb = skb_dequeue(&priv->adapter->tx_queue);
-+ if (skb) {
-+ if (uap_process_tx(priv, skb)) {
-+ priv->stats.tx_dropped++;
-+ priv->stats.tx_errors++;
-+ os_start_queue(priv);
-+ } else {
-+ priv->stats.tx_packets++;
-+ priv->stats.tx_bytes += skb->len;
-+ }
-+
-+ }
-+ }
-+ }
-+ }
-+ uap_deactivate_thread(thread);
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ * @brief uap hostcmd ioctl handler
-+ *
-+ * @param dev A pointer to net_device structure
-+ * @param req A pointer to ifreq structure
-+ * @return UAP_STATUS_SUCCESS --success, otherwise fail
-+ */
-+/********* format of ifr_data *************/
-+/* buf_len + Hostcmd_body */
-+/* buf_len: 4 bytes */
-+/* the length of the buf which */
-+/* can be used to return data */
-+/* to application */
-+/* Hostcmd_body */
-+/*******************************************/
-+static int
-+uap_hostcmd_ioctl(struct net_device *dev, struct ifreq *req)
-+{
-+ u32 buf_len;
-+ HostCmd_HEADER head;
-+ uap_private *priv = (uap_private *) netdev_priv(dev);
-+ uap_adapter *Adapter = priv->adapter;
-+ int ret = UAP_STATUS_SUCCESS;
-+ struct sk_buff *skb;
-+
-+ ENTER();
-+
-+ /* Sanity check */
-+ if (req->ifr_data == NULL) {
-+ PRINTM(ERROR, "uap_hostcmd_ioctl() corrupt data\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ if (copy_from_user(&buf_len, req->ifr_data, sizeof(buf_len))) {
-+ PRINTM(ERROR, "Copy from user failed\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ memset(&head, 0, sizeof(HostCmd_HEADER));
-+ /* Get the command size from user space */
-+ if (copy_from_user
-+ (&head, req->ifr_data + sizeof(buf_len), sizeof(HostCmd_HEADER))) {
-+ PRINTM(ERROR, "Copy from user failed\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ head.Size = uap_le16_to_cpu(head.Size);
-+ if (head.Size > MRVDRV_SIZE_OF_CMD_BUFFER) {
-+ PRINTM(ERROR, "CmdSize too big=%d\n", head.Size);
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ PRINTM(CMND, "ioctl: hostcmd=%x, size=%d,buf_len=%d\n", head.Command,
-+ head.Size, buf_len);
-+ skb = dev_alloc_skb(head.Size + INTF_HEADER_LEN);
-+ if (!skb) {
-+ PRINTM(ERROR, "No free skb\n");
-+ LEAVE();
-+ return -ENOMEM;
-+ }
-+
-+ /* Get the command from user space */
-+ if (copy_from_user
-+ (skb->data + INTF_HEADER_LEN, req->ifr_data + sizeof(buf_len),
-+ head.Size)) {
-+ PRINTM(ERROR, "Copy from user failed\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ skb_put(skb, head.Size + INTF_HEADER_LEN);
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
-+ PRINTM(ERROR, "Fail to process cmd\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ if (!Adapter->CmdSize) {
-+ PRINTM(ERROR, "Cmd Size is 0\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ if (Adapter->CmdSize > buf_len) {
-+ PRINTM(ERROR, "buf_len is too small\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ /* Copy to user */
-+ if (copy_to_user
-+ (req->ifr_data + sizeof(buf_len), Adapter->CmdBuf, Adapter->CmdSize)) {
-+ PRINTM(ERROR, "Copy to user failed!\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief uap power mode ioctl handler
-+ *
-+ * @param dev A pointer to net_device structure
-+ * @param req A pointer to ifreq structure
-+ * @return UAP_STATUS_SUCCESS --success, otherwise fail
-+ */
-+static int
-+uap_power_mode_ioctl(struct net_device *dev, struct ifreq *req)
-+{
-+ ps_mgmt pm_cfg;
-+ int ret = UAP_STATUS_SUCCESS;
-+ uap_private *priv = (uap_private *) netdev_priv(dev);
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb = NULL;
-+ HostCmd_DS_COMMAND *cmd;
-+ u32 CmdSize;
-+ u8 *tlv = NULL;
-+ MrvlIEtypes_sleep_param_t *sleep_tlv = NULL;
-+ MrvlIEtypes_inact_sleep_param_t *inact_tlv = NULL;
-+ u16 tlv_buf_left = 0;
-+ MrvlIEtypesHeader_t *tlvbuf = NULL;
-+ u16 tlv_type = 0;
-+ u16 tlv_len = 0;
-+
-+ ENTER();
-+
-+ /* Sanity check */
-+ if (req->ifr_data == NULL) {
-+ PRINTM(ERROR, "uap_power_mode_ioctl() corrupt data\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+
-+ memset(&pm_cfg, 0, sizeof(ps_mgmt));
-+ if (copy_from_user(&pm_cfg, req->ifr_data, sizeof(ps_mgmt))) {
-+ PRINTM(ERROR, "Copy from user failed\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ PRINTM(CMND,
-+ "ioctl power: flag=0x%x ps_mode=%d ctrl_bitmap=%d min_sleep=%d max_sleep=%d "
-+ "inact_to=%d min_awake=%d max_awake=%d\n", pm_cfg.flags,
-+ (int) pm_cfg.ps_mode, (int) pm_cfg.sleep_param.ctrl_bitmap,
-+ (int) pm_cfg.sleep_param.min_sleep,
-+ (int) pm_cfg.sleep_param.max_sleep,
-+ (int) pm_cfg.inact_param.inactivity_to,
-+ (int) pm_cfg.inact_param.min_awake,
-+ (int) pm_cfg.inact_param.max_awake);
-+
-+ if (pm_cfg.
-+ flags & ~(PS_FLAG_PS_MODE | PS_FLAG_SLEEP_PARAM |
-+ PS_FLAG_INACT_SLEEP_PARAM)) {
-+ PRINTM(ERROR, "Invalid parameter: flags = 0x%x\n", pm_cfg.flags);
-+ ret = -EINVAL;
-+ goto done;
-+ }
-+ if (pm_cfg.ps_mode > PS_MODE_INACTIVITY) {
-+ PRINTM(ERROR, "Invalid parameter: ps_mode = %d\n", (int) pm_cfg.flags);
-+ ret = -EINVAL;
-+ goto done;
-+ }
-+
-+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+ if (!skb) {
-+ PRINTM(INFO, "No free skb\n");
-+ ret = -ENOMEM;
-+ goto done;
-+ }
-+
-+ CmdSize = S_DS_GEN + sizeof(HostCmd_DS_POWER_MGMT_EXT);
-+
-+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+ cmd->Command = uap_cpu_to_le16(HOST_CMD_POWER_MGMT_EXT);
-+ if (!pm_cfg.flags) {
-+ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_GET);
-+ } else {
-+ cmd->params.pm_cfg.action = uap_cpu_to_le16(ACTION_SET);
-+ cmd->params.pm_cfg.power_mode = uap_cpu_to_le16(pm_cfg.ps_mode);
-+ tlv = (u8 *) & cmd->params.pm_cfg + sizeof(HostCmd_DS_POWER_MGMT_EXT);
-+
-+ if ((pm_cfg.ps_mode) && (pm_cfg.flags & PS_FLAG_SLEEP_PARAM)) {
-+ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlv;
-+ sleep_tlv->header.Type = uap_cpu_to_le16(TLV_TYPE_AP_SLEEP_PARAM);
-+ sleep_tlv->header.Len =
-+ uap_cpu_to_le16(sizeof(MrvlIEtypes_sleep_param_t) -
-+ sizeof(MrvlIEtypesHeader_t));
-+ sleep_tlv->ctrl_bitmap =
-+ uap_cpu_to_le32(pm_cfg.sleep_param.ctrl_bitmap);
-+ sleep_tlv->min_sleep =
-+ uap_cpu_to_le32(pm_cfg.sleep_param.min_sleep);
-+ sleep_tlv->max_sleep =
-+ uap_cpu_to_le32(pm_cfg.sleep_param.max_sleep);
-+ CmdSize += sizeof(MrvlIEtypes_sleep_param_t);
-+ tlv += sizeof(MrvlIEtypes_sleep_param_t);
-+ }
-+ if ((pm_cfg.ps_mode == PS_MODE_INACTIVITY) &&
-+ (pm_cfg.flags & PS_FLAG_INACT_SLEEP_PARAM)) {
-+ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlv;
-+ inact_tlv->header.Type =
-+ uap_cpu_to_le16(TLV_TYPE_AP_INACT_SLEEP_PARAM);
-+ inact_tlv->header.Len =
-+ uap_cpu_to_le16(sizeof(MrvlIEtypes_inact_sleep_param_t) -
-+ sizeof(MrvlIEtypesHeader_t));
-+ inact_tlv->inactivity_to =
-+ uap_cpu_to_le32(pm_cfg.inact_param.inactivity_to);
-+ inact_tlv->min_awake =
-+ uap_cpu_to_le32(pm_cfg.inact_param.min_awake);
-+ inact_tlv->max_awake =
-+ uap_cpu_to_le32(pm_cfg.inact_param.max_awake);
-+ CmdSize += sizeof(MrvlIEtypes_inact_sleep_param_t);
-+ tlv += sizeof(MrvlIEtypes_inact_sleep_param_t);
-+ }
-+ }
-+ cmd->Size = uap_cpu_to_le16(CmdSize);
-+ skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP)) {
-+ PRINTM(ERROR, "Fail to process cmd POWER_MODE\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ if (!Adapter->CmdSize) {
-+ PRINTM(ERROR, "Cmd Size is 0\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
-+ cmd->Result = uap_le16_to_cpu(cmd->Result);
-+ if (cmd->Result != UAP_STATUS_SUCCESS) {
-+ PRINTM(ERROR, "HOST_CMD_APCMD_POWER_MODE fail=%x\n", cmd->Result);
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ if (pm_cfg.flags) {
-+ Adapter->psmode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
-+ } else {
-+ pm_cfg.flags = PS_FLAG_PS_MODE;
-+ pm_cfg.ps_mode = uap_le16_to_cpu(cmd->params.pm_cfg.power_mode);
-+ tlv_buf_left =
-+ cmd->Size - (sizeof(HostCmd_DS_POWER_MGMT_EXT) + S_DS_GEN);
-+ tlvbuf =
-+ (MrvlIEtypesHeader_t *) ((u8 *) & cmd->params.pm_cfg +
-+ sizeof(HostCmd_DS_POWER_MGMT_EXT));
-+ while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
-+ tlv_type = uap_le16_to_cpu(tlvbuf->Type);
-+ tlv_len = uap_le16_to_cpu(tlvbuf->Len);
-+ switch (tlv_type) {
-+ case TLV_TYPE_AP_SLEEP_PARAM:
-+ sleep_tlv = (MrvlIEtypes_sleep_param_t *) tlvbuf;
-+ pm_cfg.flags |= PS_FLAG_SLEEP_PARAM;
-+ pm_cfg.sleep_param.ctrl_bitmap =
-+ uap_le32_to_cpu(sleep_tlv->ctrl_bitmap);
-+ pm_cfg.sleep_param.min_sleep =
-+ uap_le32_to_cpu(sleep_tlv->min_sleep);
-+ pm_cfg.sleep_param.max_sleep =
-+ uap_le32_to_cpu(sleep_tlv->max_sleep);
-+ break;
-+ case TLV_TYPE_AP_INACT_SLEEP_PARAM:
-+ inact_tlv = (MrvlIEtypes_inact_sleep_param_t *) tlvbuf;
-+ pm_cfg.flags |= PS_FLAG_INACT_SLEEP_PARAM;
-+ pm_cfg.inact_param.inactivity_to =
-+ uap_le32_to_cpu(inact_tlv->inactivity_to);
-+ pm_cfg.inact_param.min_awake =
-+ uap_le32_to_cpu(inact_tlv->min_awake);
-+ pm_cfg.inact_param.max_awake =
-+ uap_le32_to_cpu(inact_tlv->max_awake);
-+ break;
-+ }
-+ tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
-+ tlvbuf =
-+ (MrvlIEtypesHeader_t *) ((u8 *) tlvbuf + tlv_len +
-+ sizeof(MrvlIEtypesHeader_t));
-+ }
-+ /* Copy to user */
-+ if (copy_to_user(req->ifr_data, &pm_cfg, sizeof(ps_mgmt))) {
-+ PRINTM(ERROR, "Copy to user failed!\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ }
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function send bss_stop command to firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+static int
-+uap_bss_stop(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u32 CmdSize;
-+ HostCmd_DS_GEN *cmd;
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb;
-+ ENTER();
-+ if (Adapter->HardwareStatus != HWReady) {
-+ PRINTM(ERROR, "uap_bss_stop:Hardware is not ready!\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+ if (!skb) {
-+ PRINTM(ERROR, "No free skb\n");
-+ ret = -ENOMEM;
-+ goto done;
-+ }
-+ CmdSize = sizeof(HostCmd_DS_GEN);
-+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_BSS_STOP);
-+ cmd->Size = uap_cpu_to_le16(CmdSize);
-+ skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+ PRINTM(CMND, "APCMD_BSS_STOP\n");
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+ PRINTM(ERROR, "Fail to process cmd BSS_STOP\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/********************************************************
-+ Global Functions
-+********************************************************/
-+/**
-+ * @brief This function send soft_reset command to firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS on success, otherwise failure code
-+ */
-+int
-+uap_soft_reset(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u32 CmdSize;
-+ HostCmd_DS_GEN *cmd;
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb;
-+ ENTER();
-+ ret = uap_bss_stop(priv);
-+ if (ret != UAP_STATUS_SUCCESS)
-+ goto done;
-+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+ if (!skb) {
-+ PRINTM(ERROR, "No free skb\n");
-+ ret = -ENOMEM;
-+ goto done;
-+ }
-+ CmdSize = sizeof(HostCmd_DS_GEN);
-+ cmd = (HostCmd_DS_GEN *) (skb->data + INTF_HEADER_LEN);
-+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SOFT_RESET);
-+ cmd->Size = uap_cpu_to_le16(CmdSize);
-+ skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+ PRINTM(CMND, "APCMD_SOFT_RESET\n");
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORSEND)) {
-+ PRINTM(ERROR, "Fail to process cmd SOFT_RESET\n");
-+ ret = -EFAULT;
-+ goto done;
-+ }
-+ Adapter->SurpriseRemoved = TRUE;
-+ /* delay to allow hardware complete reset */
-+ os_sched_timeout(5);
-+ if (priv->MediaConnected == TRUE) {
-+ os_stop_queue(priv);
-+ os_carrier_off(priv);
-+ priv->MediaConnected = FALSE;
-+ }
-+ Adapter->CmdSize = 0;
-+ Adapter->CmdWaitQWoken = TRUE;
-+ wake_up_interruptible(&Adapter->cmdwait_q);
-+ skb_queue_purge(&priv->adapter->tx_queue);
-+ skb_queue_purge(&priv->adapter->cmd_queue);
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function processes received packet and forwards it
-+ * to kernel/upper layer
-+ *
-+ * @param priv A pointer to uap_private
-+ * @param skb A pointer to skb which includes the received packet
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_process_rx_packet(uap_private * priv, struct sk_buff *skb)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ RxPD *pRxPD;
-+ ENTER();
-+ priv->adapter->ps_state = PS_STATE_AWAKE;
-+ pRxPD = (RxPD *) skb->data;
-+ endian_convert_RxPD(pRxPD);
-+ DBG_HEXDUMP(DAT_D, "Rx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
-+ skb_pull(skb, pRxPD->RxPktOffset);
-+ priv->stats.rx_packets++;
-+ priv->stats.rx_bytes += skb->len;
-+ os_upload_rx_packet(priv, skb);
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function opens the network device
-+ *
-+ * @param dev A pointer to net_device structure
-+ * @return UAP_STATUS_SUCCESS
-+ */
-+static int
-+uap_open(struct net_device *dev)
-+{
-+ uap_private *priv = (uap_private *) (uap_private *) netdev_priv(dev);
-+ uap_adapter *Adapter = priv->adapter;
-+ int i = 0;
-+
-+ ENTER();
-+
-+ /* On some systems the device open handler will be called before HW ready. */
-+ /* Use the following flag check and wait function to work around the issue. */
-+ while ((Adapter->HardwareStatus != HWReady) &&
-+ (i < MAX_WAIT_DEVICE_READY_COUNT)) {
-+ i++;
-+ os_sched_timeout(100);
-+ }
-+ if (i >= MAX_WAIT_DEVICE_READY_COUNT) {
-+ PRINTM(FATAL, "HW not ready, uap_open() return failure\n");
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+
-+ if (MODULE_GET == 0)
-+ return UAP_STATUS_FAILURE;
-+
-+ priv->open = TRUE;
-+ if (priv->MediaConnected == TRUE) {
-+ os_carrier_on(priv);
-+ os_start_queue(priv);
-+ } else {
-+ os_stop_queue(priv);
-+ os_carrier_off(priv);
-+ }
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ * @brief This function closes the network device
-+ *
-+ * @param dev A pointer to net_device structure
-+ * @return UAP_STATUS_SUCCESS
-+ */
-+static int
-+uap_close(struct net_device *dev)
-+{
-+ uap_private *priv = (uap_private *) netdev_priv(dev);
-+
-+ ENTER();
-+ skb_queue_purge(&priv->adapter->tx_queue);
-+ os_stop_queue(priv);
-+ os_carrier_off(priv);
-+
-+ MODULE_PUT;
-+ priv->open = FALSE;
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ * @brief This function returns the network statistics
-+ *
-+ * @param dev A pointer to uap_private structure
-+ * @return A pointer to net_device_stats structure
-+ */
-+static struct net_device_stats *
-+uap_get_stats(struct net_device *dev)
-+{
-+ uap_private *priv = (uap_private *) netdev_priv(dev);
-+
-+ return &priv->stats;
-+}
-+
-+/**
-+ * @brief This function sets the MAC address to firmware.
-+ *
-+ * @param dev A pointer to uap_private structure
-+ * @param addr MAC address to set
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_set_mac_address(struct net_device *dev, void *addr)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ uap_private *priv = (uap_private *) netdev_priv(dev);
-+ struct sockaddr *pHwAddr = (struct sockaddr *) addr;
-+ u32 CmdSize;
-+ HostCmd_DS_COMMAND *cmd;
-+ MrvlIEtypes_MacAddr_t *pMacAddrTlv;
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb;
-+
-+ ENTER();
-+
-+ /* Dump MAC address */
-+ DBG_HEXDUMP(CMD_D, "Original MAC addr", dev->dev_addr, ETH_ALEN);
-+ DBG_HEXDUMP(CMD_D, "New MAC addr", pHwAddr->sa_data, ETH_ALEN);
-+ if (priv->open && (priv->MediaConnected == TRUE)) {
-+ os_carrier_on(priv);
-+ os_start_queue(priv);
-+ }
-+ skb = dev_alloc_skb(MRVDRV_SIZE_OF_CMD_BUFFER);
-+ if (!skb) {
-+ PRINTM(ERROR, "No free skb\n");
-+ LEAVE();
-+ return -ENOMEM;
-+ }
-+ CmdSize =
-+ S_DS_GEN + sizeof(HostCmd_SYS_CONFIG) + sizeof(MrvlIEtypes_MacAddr_t);
-+ cmd = (HostCmd_DS_COMMAND *) (skb->data + INTF_HEADER_LEN);
-+ cmd->Command = uap_cpu_to_le16(HOST_CMD_APCMD_SYS_CONFIGURE);
-+ cmd->Size = uap_cpu_to_le16(CmdSize);
-+ cmd->params.sys_config.Action = uap_cpu_to_le16(ACTION_SET);
-+ pMacAddrTlv =
-+ (MrvlIEtypes_MacAddr_t *) ((u8 *) cmd + S_DS_GEN +
-+ sizeof(HostCmd_SYS_CONFIG));
-+ pMacAddrTlv->Header.Type = uap_cpu_to_le16(MRVL_AP_MAC_ADDRESS_TLV_ID);
-+ pMacAddrTlv->Header.Len = uap_cpu_to_le16(ETH_ALEN);
-+ memcpy(pMacAddrTlv->ApMacAddr, pHwAddr->sa_data, ETH_ALEN);
-+ skb_put(skb, CmdSize + INTF_HEADER_LEN);
-+ PRINTM(CMND, "set_mac_address\n");
-+ if (UAP_STATUS_SUCCESS !=
-+ uap_process_cmd(priv, skb, HostCmd_OPTION_WAITFORRSP_TIMEOUT)) {
-+ PRINTM(ERROR, "Fail to set mac address\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ if (!Adapter->CmdSize) {
-+ PRINTM(ERROR, "Cmd Size is 0\n");
-+ LEAVE();
-+ return -EFAULT;
-+ }
-+ cmd = (HostCmd_DS_COMMAND *) Adapter->CmdBuf;
-+ cmd->Result = uap_cpu_to_le16(cmd->Result);
-+ if (cmd->Result != UAP_STATUS_SUCCESS) {
-+ PRINTM(ERROR, "set mac addrress fail,cmd result=%x\n", cmd->Result);
-+ ret = -EFAULT;
-+ } else
-+ memcpy(dev->dev_addr, pHwAddr->sa_data, ETH_ALEN);
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function handles the timeout of packet
-+ * transmission
-+ *
-+ * @param dev A pointer to net_device structure
-+ * @return n/a
-+ */
-+static void
-+uap_tx_timeout(struct net_device *dev)
-+{
-+ uap_private *priv = (uap_private *) netdev_priv(dev);
-+
-+ ENTER();
-+
-+ PRINTM(DATA, "Tx timeout\n");
-+ UpdateTransStart(dev);
-+ priv->num_tx_timeout++;
-+ priv->adapter->IntCounter++;
-+ wake_up_interruptible(&priv->MainThread.waitQ);
-+
-+ LEAVE();
-+}
-+
-+/**
-+ * @brief This function handles packet transmission
-+ *
-+ * @param skb A pointer to sk_buff structure
-+ * @param dev A pointer to net_device structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-+{
-+ uap_private *priv = (uap_private *) netdev_priv(dev);
-+ int ret = UAP_STATUS_SUCCESS;
-+
-+ ENTER();
-+ PRINTM(DATA, "Data <= kernel\n");
-+ DBG_HEXDUMP(DAT_D, "Tx", skb->data, MIN(skb->len, DATA_DUMP_LEN));
-+ /* skb sanity check */
-+ if (!skb->len || (skb->len > MRVDRV_MAXIMUM_ETH_PACKET_SIZE)) {
-+ PRINTM(ERROR, "Tx Error: Bad skb length %d : %d\n", skb->len,
-+ MRVDRV_MAXIMUM_ETH_PACKET_SIZE);
-+ priv->stats.tx_dropped++;
-+ kfree(skb);
-+ goto done;
-+ }
-+ skb_queue_tail(&priv->adapter->tx_queue, skb);
-+ wake_up_interruptible(&priv->MainThread.waitQ);
-+ if (skb_queue_len(&priv->adapter->tx_queue) > TX_HIGH_WATERMARK) {
-+ UpdateTransStart(dev);
-+ os_stop_queue(priv);
-+ }
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief ioctl function - entry point
-+ *
-+ * @param dev A pointer to net_device structure
-+ * @param req A pointer to ifreq structure
-+ * @param cmd command
-+ * @return UAP_STATUS_SUCCESS--success, otherwise fail
-+ */
-+static int
-+uap_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+
-+ ENTER();
-+
-+ PRINTM(CMND, "uap_do_ioctl: ioctl cmd = 0x%x\n", cmd);
-+
-+ switch (cmd) {
-+ case UAPHOSTCMD:
-+ ret = uap_hostcmd_ioctl(dev, req);
-+ break;
-+ case UAP_POWER_MODE:
-+ ret = uap_power_mode_ioctl(dev, req);
-+ break;
-+ default:
-+ ret = -EINVAL;
-+ break;
-+ }
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function handles events generated by firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param payload A pointer to payload buffer
-+ * @param len Length of the payload
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_process_event(uap_private * priv, u8 * payload, uint len)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ uap_adapter *Adapter = priv->adapter;
-+ struct sk_buff *skb = NULL;
-+ struct nlmsghdr *nlh = NULL;
-+ struct sock *sk = Adapter->nl_sk;
-+ AP_Event *pEvent;
-+
-+ ENTER();
-+ Adapter->ps_state = PS_STATE_AWAKE;
-+ if (len > NL_MAX_PAYLOAD) {
-+ PRINTM(ERROR, "event size is too big!!! len=%d\n", len);
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ pEvent = (AP_Event *) payload;
-+ PRINTM(CMND, "Event: %d\n", pEvent->EventId);
-+ switch (pEvent->EventId) {
-+ case MICRO_AP_EV_ID_BSS_START:
-+ memcpy(priv->uap_dev.netdev->dev_addr, pEvent->MacAddr, ETH_ALEN);
-+ DBG_HEXDUMP(CMD_D, "BSS MAC addr", priv->uap_dev.netdev->dev_addr,
-+ ETH_ALEN);
-+ break;
-+ case MICRO_AP_EV_BSS_ACTIVE:
-+ // carrier on
-+ priv->MediaConnected = TRUE;
-+ os_carrier_on(priv);
-+ os_start_queue(priv);
-+ break;
-+ case MICRO_AP_EV_BSS_IDLE:
-+ os_stop_queue(priv);
-+ os_carrier_off(priv);
-+ priv->MediaConnected = FALSE;
-+ break;
-+ case EVENT_PS_AWAKE:
-+ PRINTM(CMND, "UAP: PS_AWAKE\n");
-+ Adapter->ps_state = PS_STATE_AWAKE;
-+ Adapter->WakeupTries = 0;
-+ break;
-+ case EVENT_PS_SLEEP:
-+ PRINTM(CMND, "UAP: PS_SLEEP\n");
-+ Adapter->ps_state = PS_STATE_PRE_SLEEP;
-+ break;
-+ default:
-+ break;
-+ }
-+ if ((pEvent->EventId == EVENT_PS_AWAKE) ||
-+ (pEvent->EventId == EVENT_PS_SLEEP))
-+ goto done;
-+ if (sk) {
-+ /* Allocate skb */
-+ if (!(skb = alloc_skb(NLMSG_SPACE(NL_MAX_PAYLOAD), GFP_ATOMIC))) {
-+ PRINTM(ERROR, "Could not allocate skb for netlink.\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ nlh = (struct nlmsghdr *) skb->data;
-+ nlh->nlmsg_len = NLMSG_SPACE(len);
-+
-+ /* From kernel */
-+ nlh->nlmsg_pid = 0;
-+ nlh->nlmsg_flags = 0;
-+
-+ /* Data */
-+ skb_put(skb, nlh->nlmsg_len);
-+ memcpy(NLMSG_DATA(nlh), payload, len);
-+
-+ /* From Kernel */
-+ NETLINK_CB(skb).pid = 0;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
-+ /* Multicast message */
-+ NETLINK_CB(skb).dst_pid = 0;
-+#endif
-+
-+ /* Multicast group number */
-+ NETLINK_CB(skb).dst_group = NL_MULTICAST_GROUP;
-+
-+ /* Send message */
-+ netlink_broadcast(sk, skb, 0, NL_MULTICAST_GROUP, GFP_KERNEL);
-+
-+ ret = UAP_STATUS_SUCCESS;
-+ } else {
-+ PRINTM(ERROR, "Could not send event through NETLINK. Link down.\n");
-+ ret = UAP_STATUS_FAILURE;
-+ }
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function handles the interrupt. it will change PS
-+ * state if applicable. it will wake up main_thread to handle
-+ * the interrupt event as well.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return n/a
-+ */
-+void
-+uap_interrupt(uap_private * priv)
-+{
-+ ENTER();
-+ priv->adapter->IntCounter++;
-+ priv->adapter->WakeupTries = 0;
-+ PRINTM(INFO, "*\n");
-+ wake_up_interruptible(&priv->MainThread.waitQ);
-+
-+ LEAVE();
-+
-+}
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
-+/** Network device handlers */
-+static const struct net_device_ops uap_netdev_ops = {
-+ .ndo_open = uap_open,
-+ .ndo_start_xmit = uap_hard_start_xmit,
-+ .ndo_stop = uap_close,
-+ .ndo_do_ioctl = uap_do_ioctl,
-+ .ndo_set_mac_address = uap_set_mac_address,
-+ .ndo_tx_timeout = uap_tx_timeout,
-+ .ndo_get_stats = uap_get_stats,
-+};
-+#endif
-+
-+/**
-+ * @brief This function adds the card. it will probe the
-+ * card, allocate the uap_priv and initialize the device.
-+ *
-+ * @param card A pointer to card
-+ * @return A pointer to uap_private structure
-+ */
-+uap_private *
-+uap_add_card(void *card)
-+{
-+ struct net_device *dev = NULL;
-+ uap_private *priv = NULL;
-+
-+ ENTER();
-+
-+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
-+ goto exit_sem_err;
-+
-+ /* Allocate an Ethernet device */
-+ if (!(dev = alloc_etherdev(sizeof(uap_private)))) {
-+ PRINTM(FATAL, "Init ethernet device failed!\n");
-+ goto error;
-+ }
-+ priv = (uap_private *) netdev_priv(dev);
-+
-+ /* Allocate name */
-+ if (dev_alloc_name(dev, "uap%d") < 0) {
-+ PRINTM(ERROR, "Could not allocate device name!\n");
-+ goto error;
-+ }
-+
-+ /* Allocate buffer for uap_adapter */
-+ if (!(priv->adapter = kmalloc(sizeof(uap_adapter), GFP_KERNEL))) {
-+ PRINTM(FATAL, "Allocate buffer for uap_adapter failed!\n");
-+ goto error;
-+ }
-+ memset(priv->adapter, 0, sizeof(uap_adapter));
-+
-+ priv->uap_dev.netdev = dev;
-+ priv->uap_dev.card = card;
-+ priv->MediaConnected = FALSE;
-+ uappriv = priv;
-+ ((struct sdio_mmc_card *) card)->priv = priv;
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
-+ SET_MODULE_OWNER(dev);
-+#endif
-+
-+ /* Setup the OS Interface to our functions */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
-+ dev->open = uap_open;
-+ dev->stop = uap_close;
-+ dev->hard_start_xmit = uap_hard_start_xmit;
-+ dev->tx_timeout = uap_tx_timeout;
-+ dev->get_stats = uap_get_stats;
-+ dev->do_ioctl = uap_do_ioctl;
-+ dev->set_mac_address = uap_set_mac_address;
-+ dev->set_multicast_list = uap_set_multicast_list;
-+#else
-+ dev->netdev_ops = &uap_netdev_ops;
-+#endif
-+ dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
-+ dev->hard_header_len += sizeof(TxPD) + INTF_HEADER_LEN;
-+ dev->hard_header_len += HEADER_ALIGNMENT;
-+#define NETIF_F_DYNALLOC 16
-+ dev->features |= NETIF_F_DYNALLOC;
-+ dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-+
-+ /* Init SW */
-+ if (uap_init_sw(priv)) {
-+ PRINTM(FATAL, "Software Init Failed\n");
-+ goto error;
-+ }
-+
-+ PRINTM(INFO, "Starting kthread...\n");
-+ priv->MainThread.priv = priv;
-+ spin_lock_init(&priv->driver_lock);
-+ uap_create_thread(uap_service_main_thread, &priv->MainThread,
-+ "uap_main_service");
-+ while (priv->MainThread.pid == 0) {
-+ os_sched_timeout(2);
-+ }
-+
-+ /* Register the device */
-+ if (sbi_register_dev(priv) < 0) {
-+ PRINTM(FATAL, "Failed to register uap device!\n");
-+ goto err_registerdev;
-+ }
-+#ifdef FW_DNLD_NEEDED
-+ SET_NETDEV_DEV(dev, priv->hotplug_device);
-+#endif
-+
-+ /* Init FW and HW */
-+ if (uap_init_fw(priv)) {
-+ PRINTM(FATAL, "Firmware Init Failed\n");
-+ goto err_init_fw;
-+ }
-+
-+ priv->uap_dev.cmd_sent = FALSE;
-+ priv->uap_dev.data_sent = FALSE;
-+
-+ /* Get mac address from firmware */
-+ if (uap_get_mac_address(priv)) {
-+ PRINTM(FATAL, "Fail to get mac address\n");
-+ goto err_init_fw;
-+ }
-+ /* Register network device */
-+ if (register_netdev(dev)) {
-+ printk(KERN_ERR "Cannot register network device!\n");
-+ goto err_init_fw;
-+ }
-+#ifdef CONFIG_PROC_FS
-+ uap_proc_entry(priv, dev);
-+ uap_debug_entry(priv, dev);
-+#endif /* CPNFIG_PROC_FS */
-+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+
-+ LEAVE();
-+ return priv;
-+ err_init_fw:
-+ sbi_unregister_dev(priv);
-+ err_registerdev:
-+ ((struct sdio_mmc_card *) card)->priv = NULL;
-+ /* Stop the thread servicing the interrupts */
-+ priv->adapter->SurpriseRemoved = TRUE;
-+ wake_up_interruptible(&priv->MainThread.waitQ);
-+ while (priv->MainThread.pid) {
-+ os_sched_timeout(1);
-+ }
-+ error:
-+ if (dev) {
-+ if (dev->reg_state == NETREG_REGISTERED)
-+ unregister_netdev(dev);
-+ if (priv->adapter)
-+ uap_free_adapter(priv);
-+ free_netdev(dev);
-+ uappriv = NULL;
-+ }
-+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+ exit_sem_err:
-+ LEAVE();
-+ return NULL;
-+}
-+
-+/**
-+ * @brief This function removes the card.
-+ *
-+ * @param card A pointer to card
-+ * @return UAP_STATUS_SUCCESS
-+ */
-+int
-+uap_remove_card(void *card)
-+{
-+ uap_private *priv = uappriv;
-+ uap_adapter *Adapter;
-+ struct net_device *dev;
-+
-+ ENTER();
-+
-+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
-+ goto exit_sem_err;
-+
-+ if (!priv || !(Adapter = priv->adapter)) {
-+ goto exit_remove;
-+ }
-+ Adapter->SurpriseRemoved = TRUE;
-+ if (Adapter->cmd_pending == TRUE) {
-+ /* Wake up cmd Q */
-+ Adapter->CmdWaitQWoken = TRUE;
-+ wake_up_interruptible(&Adapter->cmdwait_q);
-+ }
-+ dev = priv->uap_dev.netdev;
-+ if (priv->MediaConnected == TRUE) {
-+ os_stop_queue(priv);
-+ os_carrier_off(priv);
-+ priv->MediaConnected = FALSE;
-+ }
-+ Adapter->CmdSize = 0;
-+ Adapter->CmdWaitQWoken = TRUE;
-+ wake_up_interruptible(&Adapter->cmdwait_q);
-+ skb_queue_purge(&priv->adapter->tx_queue);
-+ skb_queue_purge(&priv->adapter->cmd_queue);
-+
-+ /* Disable interrupts on the card */
-+ sbi_disable_host_int(priv);
-+ PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name,
-+ (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style");
-+ unregister_netdev(dev);
-+ PRINTM(INFO, "Unregister finish\n");
-+ wake_up_interruptible(&priv->MainThread.waitQ);
-+ while (priv->MainThread.pid) {
-+ os_sched_timeout(1);
-+ }
-+
-+ if ((Adapter->nl_sk) && ((Adapter->nl_sk)->sk_socket)) {
-+ sock_release((Adapter->nl_sk)->sk_socket);
-+ Adapter->nl_sk = NULL;
-+ }
-+#ifdef CONFIG_PROC_FS
-+ uap_debug_remove(priv);
-+ uap_proc_remove(priv);
-+#endif
-+ sbi_unregister_dev(priv);
-+ PRINTM(INFO, "Free Adapter\n");
-+ uap_free_adapter(priv);
-+ priv->uap_dev.netdev = NULL;
-+ free_netdev(dev);
-+ uappriv = NULL;
-+
-+ exit_remove:
-+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+ exit_sem_err:
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ * @brief This function initializes module.
-+ *
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int __init
-+uap_init_module(void)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ ENTER();
-+
-+ OS_INIT_SEMAPHORE(&AddRemoveCardSem);
-+ ret = sbi_register();
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function cleans module
-+ *
-+ * @return n/a
-+ */
-+static void __exit
-+uap_cleanup_module(void)
-+{
-+ ENTER();
-+
-+ if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
-+ goto exit_sem_err;
-+
-+ if ((uappriv) && (uappriv->adapter)) {
-+ uap_func_shutdown(uappriv);
-+ }
-+ OS_REL_SEMAPHORE(&AddRemoveCardSem);
-+ exit_sem_err:
-+ sbi_unregister();
-+ LEAVE();
-+}
-+
-+module_init(uap_init_module);
-+module_exit(uap_cleanup_module);
-+module_param(helper_name, charp, 0);
-+MODULE_PARM_DESC(helper_name, "Helper name");
-+module_param(fw_name, charp, 0);
-+MODULE_PARM_DESC(fw_name, "Firmware name");
-+
-+MODULE_DESCRIPTION("M-UAP Driver");
-+MODULE_AUTHOR("Marvell International Ltd.");
-+MODULE_VERSION(DRIVER_VERSION);
-+MODULE_LICENSE("GPL");
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_proc.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_proc.c
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_proc.c 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_proc.c 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,296 @@
-+/** @file uap_proc.c
-+ * @brief This file contains functions for proc file.
-+ *
-+ * Copyright (C) 2008-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+#ifdef CONFIG_PROC_FS
-+#include "uap_headers.h"
-+
-+/** /proc directory root */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
-+#define PROC_DIR NULL
-+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
-+#define PROC_DIR &proc_root
-+#else
-+#define PROC_DIR proc_net
-+#endif
-+
-+/********************************************************
-+ Local Variables
-+********************************************************/
-+
-+/********************************************************
-+ Global Variables
-+********************************************************/
-+
-+/********************************************************
-+ Local Functions
-+********************************************************/
-+
-+/**
-+ * @brief proc read function
-+ *
-+ * @param page pointer to buffer
-+ * @param start read data starting position
-+ * @param offset offset
-+ * @param count counter
-+ * @param eof end of file flag
-+ * @param data data to output
-+ * @return number of output data
-+ */
-+static int
-+uap_proc_read(char *page, char **start, off_t offset,
-+ int count, int *eof, void *data)
-+{
-+ int i;
-+ char *p = page;
-+ struct net_device *netdev = data;
-+ struct netdev_hw_addr *ha;
-+ char fmt[64];
-+ uap_private *priv = (uap_private *) netdev_priv(netdev);
-+
-+ if (offset != 0) {
-+ *eof = 1;
-+ goto exit;
-+ }
-+
-+ strcpy(fmt, DRIVER_VERSION);
-+
-+ p += sprintf(p, "driver_name = " "\"uap\"\n");
-+ p += sprintf(p, "driver_version = %s-(FP%s)", fmt, FPNUM);
-+ p += sprintf(p, "\nInterfaceName=\"%s\"\n", netdev->name);
-+ p += sprintf(p, "State=\"%s\"\n",
-+ ((priv->MediaConnected ==
-+ FALSE) ? "Disconnected" : "Connected"));
-+ p += sprintf(p, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
-+ netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
-+ netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
-+ i = 0;
-+ netdev_for_each_mc_addr(ha, netdev) {
-+ ++i;
-+ }
-+ p += sprintf(p, "MCCount=\"%d\"\n", i);
-+
-+ /*
-+ * Put out the multicast list
-+ */
-+ i = 0;
-+ netdev_for_each_mc_addr(ha, netdev) {
-+ p += sprintf(p,
-+ "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n",
-+ i++,
-+ ha->addr[0], ha->addr[1],
-+ ha->addr[2], ha->addr[3],
-+ ha->addr[4], ha->addr[5]);
-+ }
-+
-+ p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
-+ p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
-+ p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
-+ p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
-+ p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
-+ p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
-+ p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
-+ p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
-+ p += sprintf(p, "num_tx_timeout = %u\n", priv->num_tx_timeout);
-+ p += sprintf(p, "carrier %s\n",
-+ ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off"));
-+ p += sprintf(p, "tx queue %s\n",
-+ ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" :
-+ "started"));
-+
-+ exit:
-+ return (p - page);
-+}
-+
-+/**
-+ * @brief hwstatus proc write function
-+ *
-+ * @param f file pointer
-+ * @param buf pointer to data buffer
-+ * @param cnt data number to write
-+ * @param data data to write
-+ * @return number of data
-+ */
-+static int
-+uap_hwstatus_write(struct file *f, const char *buf, unsigned long cnt,
-+ void *data)
-+{
-+ struct net_device *netdev = data;
-+ uap_private *priv = (uap_private *) netdev_priv(netdev);
-+ char databuf[10];
-+ int hwstatus;
-+ MODULE_GET;
-+ if (cnt > 10) {
-+ MODULE_PUT;
-+ return cnt;
-+ }
-+ if (copy_from_user(databuf, buf, cnt)) {
-+ MODULE_PUT;
-+ return 0;
-+ }
-+ hwstatus = string_to_number(databuf);
-+ switch (hwstatus) {
-+ case HWReset:
-+ PRINTM(MSG, "reset hw\n");
-+ uap_soft_reset(priv);
-+ priv->adapter->HardwareStatus = HWReset;
-+ break;
-+ default:
-+ break;
-+ }
-+ MODULE_PUT;
-+ return cnt;
-+}
-+
-+/**
-+ * @brief hwstatus proc read function
-+ *
-+ * @param page pointer to buffer
-+ * @param s read data starting position
-+ * @param off offset
-+ * @param cnt counter
-+ * @param eof end of file flag
-+ * @param data data to output
-+ * @return number of output data
-+ */
-+static int
-+uap_hwstatus_read(char *page, char **s, off_t off, int cnt, int *eof,
-+ void *data)
-+{
-+ char *p = page;
-+ struct net_device *netdev = data;
-+ uap_private *priv = (uap_private *) netdev_priv(netdev);
-+ MODULE_GET;
-+ p += sprintf(p, "%d\n", priv->adapter->HardwareStatus);
-+ MODULE_PUT;
-+ return p - page;
-+}
-+
-+/********************************************************
-+ Global Functions
-+********************************************************/
-+/**
-+ * @brief create uap proc file
-+ *
-+ * @param priv pointer uap_private
-+ * @param dev pointer net_device
-+ * @return N/A
-+ */
-+void
-+uap_proc_entry(uap_private * priv, struct net_device *dev)
-+{
-+ struct proc_dir_entry *r = PROC_DIR;
-+
-+ PRINTM(INFO, "Creating Proc Interface\n");
-+ /* Check if uap directory already exists */
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
-+ for (r = r->subdir; r; r = r->next) {
-+ if (r->namelen && !strcmp("uap", r->name)) {
-+ /* Directory exists */
-+ PRINTM(WARN, "proc directory already exists!\n");
-+ priv->proc_uap = r;
-+ break;
-+ }
-+ }
-+#endif
-+ if (!priv->proc_uap) {
-+ priv->proc_uap = proc_mkdir("uap", PROC_DIR);
-+ if (!priv->proc_uap)
-+ return;
-+ else
-+ atomic_set(&priv->proc_uap->count, 1);
-+ } else {
-+ atomic_inc(&priv->proc_uap->count);
-+ }
-+ priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap);
-+
-+ if (priv->proc_entry) {
-+ r = create_proc_read_entry("info", 0, priv->proc_entry, uap_proc_read,
-+ dev);
-+ r = create_proc_entry("hwstatus", 0644, priv->proc_entry);
-+ if (r) {
-+ r->data = dev;
-+ r->read_proc = uap_hwstatus_read;
-+ r->write_proc = uap_hwstatus_write;
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
-+ r->owner = THIS_MODULE;
-+#endif
-+ } else
-+ PRINTM(MSG, "Fail to create proc hwstatus\n");
-+ }
-+}
-+
-+/**
-+ * @brief remove proc file
-+ *
-+ * @param priv pointer uap_private
-+ * @return N/A
-+ */
-+void
-+uap_proc_remove(uap_private * priv)
-+{
-+ if (priv->proc_uap) {
-+ if (priv->proc_entry) {
-+ remove_proc_entry("info", priv->proc_entry);
-+ remove_proc_entry("hwstatus", priv->proc_entry);
-+ }
-+ remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap);
-+ atomic_dec(&priv->proc_uap->count);
-+ if (atomic_read(&(priv->proc_uap->count)) == 0)
-+ remove_proc_entry("uap", PROC_DIR);
-+ }
-+}
-+
-+/**
-+ * @brief convert string to number
-+ *
-+ * @param s pointer to numbered string
-+ * @return converted number from string s
-+ */
-+int
-+string_to_number(char *s)
-+{
-+ int r = 0;
-+ int base = 0;
-+ int pn = 1;
-+
-+ if (strncmp(s, "-", 1) == 0) {
-+ pn = -1;
-+ s++;
-+ }
-+ if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) {
-+ base = 16;
-+ s += 2;
-+ } else
-+ base = 10;
-+
-+ for (s = s; *s != 0; s++) {
-+ if ((*s >= '0') && (*s <= '9'))
-+ r = (r * base) + (*s - '0');
-+ else if ((*s >= 'A') && (*s <= 'F'))
-+ r = (r * base) + (*s - 'A' + 10);
-+ else if ((*s >= 'a') && (*s <= 'f'))
-+ r = (r * base) + (*s - 'a' + 10);
-+ else
-+ break;
-+ }
-+
-+ return (r * pn);
-+}
-+
-+#endif
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.c 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,1428 @@
-+/** @file uap_sdio_mmc.c
-+ * @brief This file contains SDIO IF (interface) module
-+ * related functions.
-+ *
-+ * Copyright (C) 2007-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+/****************************************************
-+Change log:
-+****************************************************/
-+
-+#include "uap_sdio_mmc.h"
-+
-+#include <linux/firmware.h>
-+
-+/** define SDIO block size */
-+/* We support up to 480-byte block size due to FW buffer limitation. */
-+#define SD_BLOCK_SIZE 256
-+
-+/** define allocated buffer size */
-+#define ALLOC_BUF_SIZE (((MAX(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, \
-+ MRVDRV_SIZE_OF_CMD_BUFFER) + INTF_HEADER_LEN \
-+ + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
-+
-+/** Max retry number of CMD53 write */
-+#define MAX_WRITE_IOMEM_RETRY 2
-+
-+/********************************************************
-+ Local Variables
-+********************************************************/
-+
-+/** SDIO Rx unit */
-+static u8 sdio_rx_unit = 0;
-+
-+/**Interrupt status */
-+static u8 sd_ireg = 0;
-+/********************************************************
-+ Global Variables
-+********************************************************/
-+extern u8 *helper_name;
-+extern u8 *fw_name;
-+/** Default helper name */
-+#define DEFAULT_HELPER_NAME "mrvl/helper_sd.bin"
-+/** Default firmware name */
-+#define DEFAULT_FW_NAME "mrvl/sd8688_ap.bin"
-+
-+/********************************************************
-+ Local Functions
-+********************************************************/
-+/**
-+ * @brief This function reads the IO register.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param reg register to be read
-+ * @param dat A pointer to variable that keeps returned value
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sbi_read_ioreg(uap_private * priv, u32 reg, u8 * dat)
-+{
-+ struct sdio_mmc_card *card;
-+ int ret = UAP_STATUS_FAILURE;
-+
-+ ENTER();
-+
-+ card = priv->uap_dev.card;
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "sbi_read_ioreg(): card or function is NULL!\n");
-+ goto done;
-+ }
-+
-+ *dat = sdio_readb(card->func, reg, &ret);
-+ if (ret) {
-+ PRINTM(ERROR, "sbi_read_ioreg(): sdio_readb failed! ret=%d\n", ret);
-+ goto done;
-+ }
-+
-+ PRINTM(INFO, "sbi_read_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
-+ card->func->num, reg, *dat);
-+
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function writes the IO register.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param reg register to be written
-+ * @param dat the value to be written
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sbi_write_ioreg(uap_private * priv, u32 reg, u8 dat)
-+{
-+ struct sdio_mmc_card *card;
-+ int ret = UAP_STATUS_FAILURE;
-+
-+ ENTER();
-+
-+ card = priv->uap_dev.card;
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "sbi_write_ioreg(): card or function is NULL!\n");
-+ goto done;
-+ }
-+
-+ PRINTM(INFO, "sbi_write_ioreg() priv=%p func=%d reg=%#x dat=%#x\n", priv,
-+ card->func->num, reg, dat);
-+
-+ sdio_writeb(card->func, dat, reg, &ret);
-+ if (ret) {
-+ PRINTM(ERROR, "sbi_write_ioreg(): sdio_readb failed! ret=%d\n", ret);
-+ goto done;
-+ }
-+
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function get rx_unit value
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_get_rx_unit(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u8 reg;
-+
-+ ENTER();
-+
-+ ret = sbi_read_ioreg(priv, CARD_RX_UNIT_REG, ®);
-+ if (ret == UAP_STATUS_SUCCESS)
-+ sdio_rx_unit = reg;
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function reads rx length
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param dat A pointer to keep returned data
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_read_rx_len(uap_private * priv, u16 * dat)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u8 reg;
-+
-+ ENTER();
-+
-+ ret = sbi_read_ioreg(priv, CARD_RX_LEN_REG, ®);
-+ if (ret == UAP_STATUS_SUCCESS)
-+ *dat = (u16) reg << sdio_rx_unit;
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function reads fw status registers
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param dat A pointer to keep returned data
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_read_firmware_status(uap_private * priv, u16 * dat)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u8 fws0;
-+ u8 fws1;
-+
-+ ENTER();
-+
-+ ret = sbi_read_ioreg(priv, CARD_FW_STATUS0_REG, &fws0);
-+ if (ret < 0) {
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+
-+ ret = sbi_read_ioreg(priv, CARD_FW_STATUS1_REG, &fws1);
-+ if (ret < 0) {
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+
-+ *dat = (((u16) fws1) << 8) | fws0;
-+
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ * @brief This function polls the card status register.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param bits the bit mask
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+mv_sdio_poll_card_status(uap_private * priv, u8 bits)
-+{
-+ int tries;
-+ u8 cs;
-+
-+ ENTER();
-+
-+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-+ if (sbi_read_ioreg(priv, CARD_STATUS_REG, &cs) < 0)
-+ break;
-+ else if ((cs & bits) == bits) {
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+ }
-+ udelay(10);
-+ }
-+
-+ PRINTM(WARN, "mv_sdio_poll_card_status failed, tries = %d\n", tries);
-+
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+}
-+
-+/**
-+ * @brief This function set the sdio bus width.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param mode 1--1 bit mode, 4--4 bit mode
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+#if 0
-+static int
-+sdio_set_bus_width(uap_private * priv, u8 mode)
-+{
-+ ENTER();
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+#endif
-+
-+/**
-+ * @brief This function reads data from the card.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+sd_card_to_host(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u16 buf_len = 0;
-+ int buf_block_len;
-+ int blksz;
-+ struct sk_buff *skb = NULL;
-+ u16 type;
-+ u8 *payload = NULL;
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "card or function is NULL!\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto exit;
-+ }
-+
-+ /* Read the length of data to be transferred */
-+ ret = sd_read_rx_len(priv, &buf_len);
-+ if (ret < 0) {
-+ PRINTM(ERROR, "card_to_host, read scratch reg failed\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto exit;
-+ }
-+
-+ /* Allocate buffer */
-+ blksz = SD_BLOCK_SIZE;
-+ buf_block_len = (buf_len + blksz - 1) / blksz;
-+ if (buf_len <= INTF_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
-+ PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len);
-+ ret = UAP_STATUS_FAILURE;
-+ goto exit;
-+ }
-+#ifdef PXA3XX_DMA_ALIGN
-+ skb = dev_alloc_skb(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT);
-+#else
-+ skb = dev_alloc_skb(buf_block_len * blksz);
-+#endif
-+ if (skb == NULL) {
-+ PRINTM(WARN, "No free skb\n");
-+ goto exit;
-+ }
-+#ifdef PXA3XX_DMA_ALIGN
-+ if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) {
-+ skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
-+ skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
-+ }
-+#endif /* PXA3XX_DMA_ALIGN */
-+
-+ payload = skb->tail;
-+ ret = sdio_readsb(card->func, payload, priv->uap_dev.ioport,
-+ buf_block_len * blksz);
-+ if (ret < 0) {
-+ PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret);
-+ ret = UAP_STATUS_FAILURE;
-+ goto exit;
-+ }
-+ HEXDUMP("SDIO Blk Rd", payload, blksz * buf_block_len);
-+ /*
-+ * This is SDIO specific header
-+ * u16 length,
-+ * u16 type (MV_TYPE_DAT = 0, MV_TYPE_CMD = 1, MV_TYPE_EVENT = 3)
-+ */
-+ buf_len = uap_le16_to_cpu(*(u16 *) & payload[0]);
-+ type = uap_le16_to_cpu(*(u16 *) & payload[2]);
-+ switch (type) {
-+ case MV_TYPE_EVENT:
-+ skb_put(skb, buf_len);
-+ skb_pull(skb, INTF_HEADER_LEN);
-+ uap_process_event(priv, skb->data, skb->len);
-+ kfree_skb(skb);
-+ skb = NULL;
-+ break;
-+ case MV_TYPE_CMD:
-+ skb_put(skb, buf_len);
-+ skb_pull(skb, INTF_HEADER_LEN);
-+ priv->adapter->cmd_pending = FALSE;
-+ if (priv->adapter->cmd_wait_option ==
-+ HostCmd_OPTION_WAITFORRSP_SLEEPCONFIRM) {
-+ priv->adapter->cmd_wait_option = FALSE;
-+ uap_process_sleep_confirm_resp(priv, skb->data, skb->len);
-+ } else if (priv->adapter->cmd_wait_option) {
-+ memcpy(priv->adapter->CmdBuf, skb->data, skb->len);
-+ priv->adapter->CmdSize = skb->len;
-+ priv->adapter->cmd_wait_option = FALSE;
-+ priv->adapter->CmdWaitQWoken = TRUE;
-+ wake_up_interruptible(&priv->adapter->cmdwait_q);
-+ }
-+ kfree_skb(skb);
-+ skb = NULL;
-+ break;
-+ case MV_TYPE_DAT:
-+ skb_put(skb, buf_len);
-+ skb_pull(skb, INTF_HEADER_LEN);
-+ uap_process_rx_packet(priv, skb);
-+ break;
-+ default:
-+ priv->stats.rx_errors++;
-+ priv->stats.rx_dropped++;
-+ /* Driver specified event and command resp should be handle here */
-+ PRINTM(INFO, "Unknown PKT type:%d\n", type);
-+ kfree_skb(skb);
-+ skb = NULL;
-+ break;
-+ }
-+ exit:
-+ if (ret) {
-+ if (skb)
-+ kfree_skb(skb);
-+ }
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function enables the host interrupts mask
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param mask the interrupt mask
-+ * @return UAP_STATUS_SUCCESS
-+ */
-+static int
-+enable_host_int_mask(uap_private * priv, u8 mask)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+
-+ ENTER();
-+
-+ /* Simply write the mask to the register */
-+ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, mask);
-+
-+ if (ret) {
-+ PRINTM(WARN, "Unable to enable the host interrupt!\n");
-+ ret = UAP_STATUS_FAILURE;
-+ }
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/** @brief This function disables the host interrupts mask.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param mask the interrupt mask
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+disable_host_int_mask(uap_private * priv, u8 mask)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u8 host_int_mask;
-+
-+ ENTER();
-+
-+ /* Read back the host_int_mask register */
-+ ret = sbi_read_ioreg(priv, HOST_INT_MASK_REG, &host_int_mask);
-+ if (ret) {
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+
-+ /* Update with the mask and write back to the register */
-+ host_int_mask &= ~mask;
-+ ret = sbi_write_ioreg(priv, HOST_INT_MASK_REG, host_int_mask);
-+ if (ret < 0) {
-+ PRINTM(WARN, "Unable to diable the host interrupt!\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/********************************************************
-+ Global Functions
-+********************************************************/
-+
-+/**
-+ * @brief This function handles the interrupt.
-+ *
-+ * @param func A pointer to sdio_func structure.
-+ * @return n/a
-+ */
-+static void
-+sbi_interrupt(struct sdio_func *func)
-+{
-+ struct sdio_mmc_card *card;
-+ uap_private *priv;
-+ u8 ireg = 0;
-+ int ret = UAP_STATUS_SUCCESS;
-+
-+ ENTER();
-+
-+ card = sdio_get_drvdata(func);
-+ if (!card || !card->priv) {
-+ PRINTM(MSG, "%s: sbi_interrupt(%p) card or priv is NULL, card=%p\n",
-+ __FUNCTION__, func, card);
-+ LEAVE();
-+ return;
-+ }
-+ priv = card->priv;
-+#ifdef FW_WAKEUP_TIME
-+ if ((priv->adapter->wt_pwrup_sending != 0L) &&
-+ (priv->adapter->wt_int == 0L))
-+ priv->adapter->wt_int = get_utimeofday();
-+#endif
-+
-+ ireg = sdio_readb(card->func, HOST_INTSTATUS_REG, &ret);
-+ if (ret) {
-+ PRINTM(WARN, "sdio_read_ioreg: read int status register failed\n");
-+ goto done;
-+ }
-+ if (ireg != 0) {
-+ /*
-+ * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS
-+ * Clear the interrupt status register and re-enable the interrupt
-+ */
-+ PRINTM(INFO, "sdio_ireg = 0x%x\n", ireg);
-+ sdio_writeb(card->func,
-+ ~(ireg) & (DN_LD_HOST_INT_STATUS | UP_LD_HOST_INT_STATUS),
-+ HOST_INTSTATUS_REG, &ret);
-+ if (ret) {
-+ PRINTM(WARN,
-+ "sdio_write_ioreg: clear int status register failed\n");
-+ goto done;
-+ }
-+ }
-+ OS_INT_DISABLE;
-+ sd_ireg |= ireg;
-+ OS_INT_RESTORE;
-+
-+ uap_interrupt(priv);
-+ done:
-+ LEAVE();
-+}
-+
-+/**
-+ * @brief This function probe the card
-+ *
-+ * @param func A pointer to sdio_func structure
-+ * @param id A pointer to structure sd_device_id
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+static int
-+uap_probe(struct sdio_func *func, const struct sdio_device_id *id)
-+{
-+ int ret = UAP_STATUS_FAILURE;
-+ struct sdio_mmc_card *card = NULL;
-+
-+ ENTER();
-+
-+ PRINTM(MSG, "%s: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
-+ __FUNCTION__, func->vendor, func->device, func->class, func->num);
-+
-+ card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
-+ if (!card) {
-+ ret = -ENOMEM;
-+ goto done;
-+ }
-+
-+ card->func = func;
-+
-+ if (!uap_add_card(card)) {
-+ PRINTM(ERROR, "%s: uap_add_callback failed\n", __FUNCTION__);
-+ kfree(card);
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+
-+ ret = UAP_STATUS_SUCCESS;
-+
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function removes the card
-+ *
-+ * @param func A pointer to sdio_func structure
-+ * @return N/A
-+ */
-+static void
-+uap_remove(struct sdio_func *func)
-+{
-+ struct sdio_mmc_card *card;
-+
-+ ENTER();
-+
-+ if (func) {
-+ card = sdio_get_drvdata(func);
-+ if (card) {
-+ uap_remove_card(card);
-+ kfree(card);
-+ }
-+ }
-+
-+ LEAVE();
-+}
-+
-+#ifdef CONFIG_PM
-+/**
-+ * @brief This function handles client driver suspend
-+ *
-+ * @param func A pointer to sdio_func structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_suspend(struct sdio_func *func)
-+{
-+ ENTER();
-+ LEAVE();
-+ return 0;
-+}
-+
-+/**
-+ * @brief This function handles client driver resume
-+ *
-+ * @param func A pointer to sdio_func structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+uap_resume(struct sdio_func *func)
-+{
-+ ENTER();
-+ LEAVE();
-+ return 0;
-+}
-+#endif
-+
-+/** Device ID for SD8688 */
-+#define SD_DEVICE_ID_8688_UAP 0x9104
-+/** UAP IDs */
-+static const struct sdio_device_id uap_ids[] = {
-+ {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SD_DEVICE_ID_8688_UAP)},
-+ {},
-+};
-+
-+MODULE_DEVICE_TABLE(sdio, uap_ids);
-+
-+static struct sdio_driver uap_sdio = {
-+ .name = "uap_sdio",
-+ .id_table = uap_ids,
-+ .probe = uap_probe,
-+ .remove = uap_remove,
-+#ifdef CONFIG_PM
-+/* .suspend = uap_suspend, */
-+/* .resume = uap_resume, */
-+#endif
-+
-+};
-+
-+/**
-+ * @brief This function registers the IF module in bus driver.
-+ *
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int __init
-+sbi_register()
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+
-+ ENTER();
-+
-+ /* SDIO Driver Registration */
-+ if (sdio_register_driver(&uap_sdio) != 0) {
-+ PRINTM(FATAL, "SDIO Driver Registration Failed \n");
-+ ret = UAP_STATUS_FAILURE;
-+ }
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function de-registers the IF module in bus driver.
-+ *
-+ * @return n/a
-+ */
-+void __exit
-+sbi_unregister(void)
-+{
-+ ENTER();
-+
-+ /* SDIO Driver Unregistration */
-+ sdio_unregister_driver(&uap_sdio);
-+
-+ LEAVE();
-+}
-+
-+/**
-+ * @brief This function checks the interrupt status and handle it accordingly.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param ireg A pointer to variable that keeps returned value
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_get_int_status(uap_private * priv, u8 * ireg)
-+{
-+ int ret = UAP_STATUS_SUCCESS;
-+ u8 sdio_ireg = 0;
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+
-+ ENTER();
-+
-+ *ireg = 0;
-+ OS_INT_DISABLE;
-+ sdio_ireg = sd_ireg;
-+ sd_ireg = 0;
-+ OS_INT_RESTORE;
-+
-+ sdio_claim_host(card->func);
-+
-+ if (sdio_ireg & DN_LD_HOST_INT_STATUS) { /* tx_done INT */
-+ if (!priv->uap_dev.cmd_sent) { /* tx_done already received */
-+ PRINTM(INFO,
-+ "warning: tx_done already received: tx_dnld_rdy=0x%x int status=0x%x\n",
-+ priv->uap_dev.cmd_sent, sdio_ireg);
-+ } else {
-+ priv->uap_dev.cmd_sent = FALSE;
-+ priv->uap_dev.data_sent = FALSE;
-+ if ( (priv->uap_dev.netdev->reg_state == NETREG_REGISTERED) && (skb_queue_len(&priv->adapter->tx_queue) < TX_LOW_WATERMARK)) {
-+ os_start_queue(priv);
-+ }
-+ }
-+ }
-+ if (sdio_ireg & UP_LD_HOST_INT_STATUS) {
-+ sd_card_to_host(priv);
-+ }
-+
-+ *ireg = sdio_ireg;
-+ ret = UAP_STATUS_SUCCESS;
-+ sdio_release_host(card->func);
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function disables the host interrupts.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_disable_host_int(uap_private * priv)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ int ret;
-+
-+ ENTER();
-+
-+ sdio_claim_host(card->func);
-+ ret = disable_host_int_mask(priv, HIM_DISABLE);
-+ sdio_release_host(card->func);
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function enables the host interrupts.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS
-+ */
-+int
-+sbi_enable_host_int(uap_private * priv)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ int ret;
-+
-+ ENTER();
-+
-+ sdio_claim_host(card->func);
-+ ret = enable_host_int_mask(priv, HIM_ENABLE);
-+ sdio_release_host(card->func);
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function de-registers the device.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS
-+ */
-+int
-+sbi_unregister_dev(uap_private * priv)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "Error: card or function is NULL!\n");
-+ goto done;
-+ }
-+
-+ sdio_claim_host(card->func);
-+ sdio_release_irq(card->func);
-+ sdio_disable_func(card->func);
-+ sdio_release_host(card->func);
-+
-+ sdio_set_drvdata(card->func, NULL);
-+
-+ done:
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+
-+/**
-+ * @brief This function registers the device.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_register_dev(uap_private * priv)
-+{
-+ int ret = UAP_STATUS_FAILURE;
-+ u8 reg;
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ struct sdio_func *func;
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "Error: card or function is NULL!\n");
-+ goto done;
-+ }
-+
-+ func = card->func;
-+
-+ /* Initialize the private structure */
-+ priv->uap_dev.ioport = 0;
-+
-+ sdio_claim_host(func);
-+
-+ ret = sdio_enable_func(func);
-+ if (ret) {
-+ PRINTM(FATAL, "sdio_enable_func() failed: ret=%d\n", ret);
-+ goto release_host;
-+ }
-+
-+ ret = sdio_claim_irq(func, sbi_interrupt);
-+ if (ret) {
-+ PRINTM(FATAL, "sdio_claim_irq failed: ret=%d\n", ret);
-+ goto disable_func;
-+ }
-+
-+ /* Read the IO port */
-+ ret = sbi_read_ioreg(priv, IO_PORT_0_REG, ®);
-+ if (ret)
-+ goto release_irq;
-+ else
-+ priv->uap_dev.ioport |= reg;
-+
-+ ret = sbi_read_ioreg(priv, IO_PORT_1_REG, ®);
-+ if (ret)
-+ goto release_irq;
-+ else
-+ priv->uap_dev.ioport |= (reg << 8);
-+
-+ ret = sbi_read_ioreg(priv, IO_PORT_2_REG, ®);
-+ if (ret)
-+ goto release_irq;
-+ else
-+ priv->uap_dev.ioport |= (reg << 16);
-+
-+ PRINTM(INFO, "SDIO FUNC #%d IO port: 0x%x\n", func->num,
-+ priv->uap_dev.ioport);
-+
-+ ret = sdio_set_block_size(card->func, SD_BLOCK_SIZE);
-+ if (ret) {
-+ PRINTM(ERROR, "%s: cannot set SDIO block size\n", __FUNCTION__);
-+ ret = UAP_STATUS_FAILURE;
-+ goto release_irq;
-+ }
-+ priv->hotplug_device = &func->dev;
-+
-+ if (helper_name == NULL) {
-+ helper_name = DEFAULT_HELPER_NAME;
-+ }
-+ if (fw_name == NULL) {
-+ fw_name = DEFAULT_FW_NAME;
-+ }
-+ sdio_release_host(func);
-+
-+ sdio_set_drvdata(func, card);
-+
-+ ret = UAP_STATUS_SUCCESS;
-+ goto done;
-+
-+ release_irq:
-+ sdio_release_irq(func);
-+ disable_func:
-+ sdio_disable_func(func);
-+ release_host:
-+ sdio_release_host(func);
-+
-+ done:
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function sends data to the card.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param payload A pointer to the data/cmd buffer
-+ * @param nb the length of data/cmd
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_host_to_card(uap_private * priv, u8 * payload, u16 nb)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ int ret = UAP_STATUS_SUCCESS;
-+ int buf_block_len;
-+ int blksz;
-+ int i = 0;
-+ u8 *buf = NULL;
-+#ifdef PXA3XX_DMA_ALIGN
-+ void *tmpbuf = NULL;
-+ int tmpbufsz;
-+#endif
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "card or function is NULL!\n");
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+ buf = payload;
-+#ifdef PXA3XX_DMA_ALIGN
-+ if ((u32) payload & (PXA3XX_DMA_ALIGNMENT - 1)) {
-+ tmpbufsz = ALIGN_SZ(nb, PXA3XX_DMA_ALIGNMENT);
-+ tmpbuf = kmalloc(tmpbufsz, GFP_KERNEL);
-+ memset(tmpbuf, 0, tmpbufsz);
-+ /* Ensure 8-byte aligned CMD buffer */
-+ buf = (u8 *) ALIGN_ADDR(tmpbuf, PXA3XX_DMA_ALIGNMENT);
-+ memcpy(buf, payload, nb);
-+ }
-+#endif
-+ /* Allocate buffer and copy payload */
-+ blksz = SD_BLOCK_SIZE;
-+ buf_block_len = (nb + blksz - 1) / blksz;
-+ sdio_claim_host(card->func);
-+#define MAX_WRITE_IOMEM_RETRY 2
-+ priv->uap_dev.cmd_sent = TRUE;
-+ priv->uap_dev.data_sent = TRUE;
-+ do {
-+ /* Transfer data to card */
-+ ret = sdio_writesb(card->func, priv->uap_dev.ioport, buf,
-+ buf_block_len * blksz);
-+ if (ret < 0) {
-+ i++;
-+ PRINTM(ERROR, "host_to_card, write iomem (%d) failed: %d\n", i,
-+ ret);
-+ ret = UAP_STATUS_FAILURE;
-+ if (i > MAX_WRITE_IOMEM_RETRY)
-+ goto exit;
-+ } else {
-+ HEXDUMP("SDIO Blk Wr", payload, nb);
-+ }
-+ } while (ret == UAP_STATUS_FAILURE);
-+ exit:
-+ sdio_release_host(card->func);
-+#ifdef PXA3XX_DMA_ALIGN
-+ if (tmpbuf)
-+ kfree(tmpbuf);
-+#endif
-+ if (ret == UAP_STATUS_FAILURE) {
-+ priv->uap_dev.cmd_sent = FALSE;
-+ priv->uap_dev.data_sent = FALSE;
-+ }
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function reads CIS information.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param cisinfo A pointer to CIS information output buffer
-+ * @param cislen A pointer to length of CIS info output buffer
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+#if 0
-+static int
-+sbi_get_cis_info(uap_private * priv, void *cisinfo, int *cislen)
-+{
-+#define CIS_PTR (0x8000)
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ unsigned int i, cis_ptr = CIS_PTR;
-+ int ret = UAP_STATUS_FAILURE;
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "sbi_get_cis_info(): card or function is NULL!\n");
-+ goto exit;
-+ }
-+#define MAX_SDIO_CIS_INFO_LEN (256)
-+ if (!cisinfo || (*cislen < MAX_SDIO_CIS_INFO_LEN)) {
-+ PRINTM(WARN, "ERROR! get_cis_info: insufficient buffer passed\n");
-+ goto exit;
-+ }
-+
-+ *cislen = MAX_SDIO_CIS_INFO_LEN;
-+
-+ sdio_claim_host(card->func);
-+
-+ PRINTM(INFO, "cis_ptr=%#x\n", cis_ptr);
-+
-+ /* Read the Tuple Data */
-+ for (i = 0; i < *cislen; i++) {
-+ ((unsigned char *) cisinfo)[i] =
-+ sdio_readb(card->func, cis_ptr + i, &ret);
-+ if (ret) {
-+ PRINTM(WARN, "get_cis_info error: ret=%d\n", ret);
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ PRINTM(INFO, "cisinfo[%d]=%#x\n", i, ((unsigned char *) cisinfo)[i]);
-+ }
-+
-+ done:
-+ sdio_release_host(card->func);
-+ exit:
-+ LEAVE();
-+ return ret;
-+}
-+#endif
-+/**
-+ * @brief This function downloads helper image to the card.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_prog_helper(uap_private * priv)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ u8 *helper = NULL;
-+ int helperlen;
-+ int ret = UAP_STATUS_SUCCESS;
-+ void *tmphlprbuf = NULL;
-+ int tmphlprbufsz;
-+ u8 *hlprbuf;
-+ int hlprblknow;
-+ u32 tx_len;
-+#ifdef FW_DOWNLOAD_SPEED
-+ u32 tv1, tv2;
-+#endif
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "sbi_prog_helper(): card or function is NULL!\n");
-+ goto done;
-+ }
-+
-+ if (priv->fw_helper) {
-+ helper = (u8 *) priv->fw_helper->data;
-+ helperlen = priv->fw_helper->size;
-+ } else {
-+ PRINTM(MSG, "No helper image found! Terminating download.\n");
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+
-+ PRINTM(INFO, "Downloading helper image (%d bytes), block size %d bytes\n",
-+ helperlen, SD_BLOCK_SIZE);
-+
-+#ifdef FW_DOWNLOAD_SPEED
-+ tv1 = get_utimeofday();
-+#endif
-+
-+#ifdef PXA3XX_DMA_ALIGN
-+ tmphlprbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
-+#else /* !PXA3XX_DMA_ALIGN */
-+ tmphlprbufsz = UAP_UPLD_SIZE;
-+#endif /* !PXA3XX_DMA_ALIGN */
-+ tmphlprbuf = kmalloc(tmphlprbufsz, GFP_KERNEL);
-+ if (!tmphlprbuf) {
-+ PRINTM(ERROR,
-+ "Unable to allocate buffer for helper. Terminating download\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ memset(tmphlprbuf, 0, tmphlprbufsz);
-+#ifdef PXA3XX_DMA_ALIGN
-+ hlprbuf = (u8 *) ALIGN_ADDR(tmphlprbuf, PXA3XX_DMA_ALIGNMENT);
-+#else /* !PXA3XX_DMA_ALIGN */
-+ hlprbuf = (u8 *) tmphlprbuf;
-+#endif /* !PXA3XX_DMA_ALIGN */
-+
-+ sdio_claim_host(card->func);
-+
-+ /* Perform helper data transfer */
-+ tx_len = (FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE) - INTF_HEADER_LEN;
-+ hlprblknow = 0;
-+ do {
-+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
-+ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
-+ if (ret < 0) {
-+ PRINTM(FATAL, "Helper download poll status timeout @ %d\n",
-+ hlprblknow);
-+ goto done;
-+ }
-+
-+ /* More data? */
-+ if (hlprblknow >= helperlen)
-+ break;
-+
-+ /* Set blocksize to transfer - checking for last block */
-+ if (helperlen - hlprblknow < tx_len)
-+ tx_len = helperlen - hlprblknow;
-+
-+ /* Set length to the 4-byte header */
-+ *(u32 *) hlprbuf = uap_cpu_to_le32(tx_len);
-+
-+ /* Copy payload to buffer */
-+ memcpy(&hlprbuf[INTF_HEADER_LEN], &helper[hlprblknow], tx_len);
-+
-+ PRINTM(INFO, ".");
-+
-+ /* Send data */
-+ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
-+ hlprbuf, FIRMWARE_TRANSFER_NBLOCK * SD_BLOCK_SIZE);
-+
-+ if (ret < 0) {
-+ PRINTM(FATAL, "IO error during helper download @ %d\n", hlprblknow);
-+ goto done;
-+ }
-+
-+ hlprblknow += tx_len;
-+ } while (TRUE);
-+
-+#ifdef FW_DOWNLOAD_SPEED
-+ tv2 = get_utimeofday();
-+ PRINTM(INFO, "helper: %ld.%03ld.%03ld ", tv1 / 1000000,
-+ (tv1 % 1000000) / 1000, tv1 % 1000);
-+ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000, (tv2 % 1000000) / 1000,
-+ tv2 % 1000);
-+ tv2 -= tv1;
-+ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000, (tv2 % 1000000) / 1000,
-+ tv2 % 1000);
-+#endif
-+
-+ /* Write last EOF data */
-+ PRINTM(INFO, "\nTransferring helper image EOF block\n");
-+ memset(hlprbuf, 0x0, SD_BLOCK_SIZE);
-+ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
-+ hlprbuf, SD_BLOCK_SIZE);
-+
-+ if (ret < 0) {
-+ PRINTM(FATAL, "IO error in writing helper image EOF block\n");
-+ goto done;
-+ }
-+
-+ ret = UAP_STATUS_SUCCESS;
-+
-+ done:
-+ sdio_release_host(card->func);
-+ if (tmphlprbuf)
-+ kfree(tmphlprbuf);
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function downloads firmware image to the card.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_prog_fw_w_helper(uap_private * priv)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ u8 *firmware = NULL;
-+ int firmwarelen;
-+ u8 base0;
-+ u8 base1;
-+ int ret = UAP_STATUS_SUCCESS;
-+ int offset;
-+ void *tmpfwbuf = NULL;
-+ int tmpfwbufsz;
-+ u8 *fwbuf;
-+ u16 len;
-+ int txlen = 0;
-+ int tx_blocks = 0;
-+ int i = 0;
-+ int tries = 0;
-+#ifdef FW_DOWNLOAD_SPEED
-+ u32 tv1, tv2;
-+#endif
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "sbi_prog_fw_w_helper(): card or function is NULL!\n");
-+ goto done;
-+ }
-+
-+ if (priv->firmware) {
-+ firmware = (u8 *) priv->firmware->data;
-+ firmwarelen = priv->firmware->size;
-+ } else {
-+ PRINTM(MSG, "No firmware image found! Terminating download.\n");
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+
-+ PRINTM(INFO, "Downloading FW image (%d bytes)\n", firmwarelen);
-+
-+#ifdef FW_DOWNLOAD_SPEED
-+ tv1 = get_utimeofday();
-+#endif
-+
-+#ifdef PXA3XX_DMA_ALIGN
-+ tmpfwbufsz = ALIGN_SZ(UAP_UPLD_SIZE, PXA3XX_DMA_ALIGNMENT);
-+#else /* PXA3XX_DMA_ALIGN */
-+ tmpfwbufsz = UAP_UPLD_SIZE;
-+#endif /* PXA3XX_DMA_ALIGN */
-+ tmpfwbuf = kmalloc(tmpfwbufsz, GFP_KERNEL);
-+ if (!tmpfwbuf) {
-+ PRINTM(ERROR,
-+ "Unable to allocate buffer for firmware. Terminating download.\n");
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ memset(tmpfwbuf, 0, tmpfwbufsz);
-+#ifdef PXA3XX_DMA_ALIGN
-+ /* Ensure 8-byte aligned firmware buffer */
-+ fwbuf = (u8 *) ALIGN_ADDR(tmpfwbuf, PXA3XX_DMA_ALIGNMENT);
-+#else /* PXA3XX_DMA_ALIGN */
-+ fwbuf = (u8 *) tmpfwbuf;
-+#endif /* PXA3XX_DMA_ALIGN */
-+
-+ sdio_claim_host(card->func);
-+
-+ /* Perform firmware data transfer */
-+ offset = 0;
-+ do {
-+ /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY bits */
-+ ret = mv_sdio_poll_card_status(priv, CARD_IO_READY | DN_LD_CARD_RDY);
-+ if (ret < 0) {
-+ PRINTM(FATAL, "FW download with helper poll status timeout @ %d\n",
-+ offset);
-+ goto done;
-+ }
-+
-+ /* More data? */
-+ if (offset >= firmwarelen)
-+ break;
-+
-+ for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
-+ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_0, &base0)) < 0) {
-+ PRINTM(WARN, "Dev BASE0 register read failed:"
-+ " base0=0x%04X(%d). Terminating download.\n", base0,
-+ base0);
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ if ((ret = sbi_read_ioreg(priv, HOST_F1_RD_BASE_1, &base1)) < 0) {
-+ PRINTM(WARN, "Dev BASE1 register read failed:"
-+ " base1=0x%04X(%d). Terminating download.\n", base1,
-+ base1);
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ len = (((u16) base1) << 8) | base0;
-+
-+ /* For SD8688 wait until the length is not 0, 1 or 2 before
-+ downloading the first FW block, since BOOT code writes the
-+ register to indicate the helper/FW download winner, the value
-+ could be 1 or 2 (Func1 or Func2). */
-+ if ((len && offset) || (len > 2))
-+ break;
-+ udelay(10);
-+ }
-+
-+ if (len == 0)
-+ break;
-+ else if (len > UAP_UPLD_SIZE) {
-+ PRINTM(FATAL, "FW download failure @ %d, invalid length %d\n",
-+ offset, len);
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+
-+ txlen = len;
-+
-+ if (len & BIT(0)) {
-+ i++;
-+ if (i > MAX_WRITE_IOMEM_RETRY) {
-+ PRINTM(FATAL,
-+ "FW download failure @ %d, over max retry count\n",
-+ offset);
-+ ret = UAP_STATUS_FAILURE;
-+ goto done;
-+ }
-+ PRINTM(ERROR, "FW CRC error indicated by the helper:"
-+ " len = 0x%04X, txlen = %d\n", len, txlen);
-+ len &= ~BIT(0);
-+ /* Setting this to 0 to resend from same offset */
-+ txlen = 0;
-+ } else {
-+ i = 0;
-+
-+ /* Set blocksize to transfer - checking for last block */
-+ if (firmwarelen - offset < txlen) {
-+ txlen = firmwarelen - offset;
-+ }
-+ PRINTM(INFO, ".");
-+
-+ tx_blocks = (txlen + SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE;
-+
-+ /* Copy payload to buffer */
-+ memcpy(fwbuf, &firmware[offset], txlen);
-+ }
-+
-+ /* Send data */
-+ ret = sdio_writesb(card->func, priv->uap_dev.ioport,
-+ fwbuf, tx_blocks * SD_BLOCK_SIZE);
-+
-+ if (ret < 0) {
-+ PRINTM(ERROR, "FW download, write iomem (%d) failed @ %d\n", i,
-+ offset);
-+ if (sbi_write_ioreg(priv, CONFIGURATION_REG, 0x04) < 0) {
-+ PRINTM(ERROR, "write ioreg failed (CFG)\n");
-+ }
-+ }
-+
-+ offset += txlen;
-+ } while (TRUE);
-+
-+ PRINTM(INFO, "\nFW download over, size %d bytes\n", offset);
-+
-+ ret = UAP_STATUS_SUCCESS;
-+ done:
-+#ifdef FW_DOWNLOAD_SPEED
-+ tv2 = get_utimeofday();
-+ PRINTM(INFO, "FW: %ld.%03ld.%03ld ", tv1 / 1000000,
-+ (tv1 % 1000000) / 1000, tv1 % 1000);
-+ PRINTM(INFO, " -> %ld.%03ld.%03ld ", tv2 / 1000000,
-+ (tv2 % 1000000) / 1000, tv2 % 1000);
-+ tv2 -= tv1;
-+ PRINTM(INFO, " == %ld.%03ld.%03ld\n", tv2 / 1000000,
-+ (tv2 % 1000000) / 1000, tv2 % 1000);
-+#endif
-+ sdio_release_host(card->func);
-+ if (tmpfwbuf)
-+ kfree(tmpfwbuf);
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function checks if the firmware is ready to accept
-+ * command or not.
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param pollnum Poll number
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_check_fw_status(uap_private * priv, int pollnum)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ int ret = UAP_STATUS_SUCCESS;
-+ u16 firmwarestat;
-+ int tries;
-+
-+ ENTER();
-+
-+ sdio_claim_host(card->func);
-+
-+ /* Wait for firmware initialization event */
-+ for (tries = 0; tries < pollnum; tries++) {
-+ if ((ret = sd_read_firmware_status(priv, &firmwarestat)) < 0)
-+ continue;
-+ if (firmwarestat == FIRMWARE_READY) {
-+ ret = UAP_STATUS_SUCCESS;
-+ break;
-+ } else {
-+ mdelay(10);
-+ ret = UAP_STATUS_FAILURE;
-+ }
-+ }
-+
-+ if (ret < 0)
-+ goto done;
-+
-+ ret = UAP_STATUS_SUCCESS;
-+ sd_get_rx_unit(priv);
-+
-+ done:
-+ sdio_release_host(card->func);
-+
-+ LEAVE();
-+ return ret;
-+}
-+
-+/**
-+ * @brief This function set bus clock on/off
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @param option TRUE--on , FALSE--off
-+ * @return UAP_STATUS_SUCCESS
-+ */
-+#if 0
-+static int
-+sbi_set_bus_clock(uap_private * priv, u8 option)
-+{
-+ ENTER();
-+ LEAVE();
-+ return UAP_STATUS_SUCCESS;
-+}
-+#endif
-+
-+/**
-+ * @brief This function wakeup firmware
-+ *
-+ * @param priv A pointer to uap_private structure
-+ * @return UAP_STATUS_SUCCESS or UAP_STATUS_FAILURE
-+ */
-+int
-+sbi_wakeup_firmware(uap_private * priv)
-+{
-+ struct sdio_mmc_card *card = priv->uap_dev.card;
-+ int ret = UAP_STATUS_SUCCESS;
-+
-+ ENTER();
-+
-+ if (!card || !card->func) {
-+ PRINTM(ERROR, "card or function is NULL!\n");
-+ LEAVE();
-+ return UAP_STATUS_FAILURE;
-+ }
-+ sdio_claim_host(card->func);
-+ sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
-+ sdio_release_host(card->func);
-+ LEAVE();
-+ return ret;
-+}
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 1970-01-01 01:00:00.000000000 +0100
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/libertas_uap/uap_sdio_mmc.h 2012-07-31 14:23:04.000000000 +0200
-@@ -0,0 +1,136 @@
-+/** @file uap_sdio_mmc.h
-+ * @brief This file contains SDIO IF (interface) module
-+ * related macros, enum, and structure.
-+ *
-+ * Copyright (C) 2007-2009, Marvell International Ltd.
-+ *
-+ * This software file (the "File") is distributed by Marvell International
-+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
-+ * (the "License"). You may use, redistribute and/or modify this File in
-+ * accordance with the terms and conditions of the License, a copy of which
-+ * is available along with the File in the gpl.txt file or by writing to
-+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
-+ *
-+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
-+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
-+ * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
-+ * this warranty disclaimer.
-+ *
-+ */
-+/****************************************************
-+Change log:
-+ 10/10/07: initial version
-+****************************************************/
-+
-+#ifndef _UAP_SDIO_MMC_H
-+#define _UAP_SDIO_MMC_H
-+
-+#include <linux/mmc/sdio.h>
-+#include <linux/mmc/sdio_ids.h>
-+#include <linux/mmc/sdio_func.h>
-+#include <linux/mmc/card.h>
-+
-+#include "uap_headers.h"
-+
-+/** The number of times to try when waiting for downloaded firmware to
-+ become active. (polling the scratch register). */
-+#define MAX_FIRMWARE_POLL_TRIES 100
-+
-+/** Firmware ready */
-+#define FIRMWARE_READY 0xfedc
-+
-+/** Number of firmware blocks to transfer */
-+#define FIRMWARE_TRANSFER_NBLOCK 2
-+
-+/* Host Control Registers */
-+/** Host Control Registers : I/O port 0 */
-+#define IO_PORT_0_REG 0x00
-+/** Host Control Registers : I/O port 1 */
-+#define IO_PORT_1_REG 0x01
-+/** Host Control Registers : I/O port 2 */
-+#define IO_PORT_2_REG 0x02
-+
-+/** Host Control Registers : Configuration */
-+#define CONFIGURATION_REG 0x03
-+/** Host Control Registers : Host without Command 53 finish host */
-+#define HOST_WO_CMD53_FINISH_HOST (0x1U << 2)
-+/** Host Control Registers : Host power up */
-+#define HOST_POWER_UP (0x1U << 1)
-+/** Host Control Registers : Host power down */
-+#define HOST_POWER_DOWN (0x1U << 0)
-+
-+/** Host Control Registers : Host interrupt mask */
-+#define HOST_INT_MASK_REG 0x04
-+/** Host Control Registers : Upload host interrupt mask */
-+#define UP_LD_HOST_INT_MASK (0x1U)
-+/** Host Control Registers : Download host interrupt mask */
-+#define DN_LD_HOST_INT_MASK (0x2U)
-+/** Enable Host interrupt mask */
-+#define HIM_ENABLE (UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK)
-+/** Disable Host interrupt mask */
-+#define HIM_DISABLE 0xff
-+
-+/** Host Control Registers : Host interrupt status */
-+#define HOST_INTSTATUS_REG 0x05
-+/** Host Control Registers : Upload host interrupt status */
-+#define UP_LD_HOST_INT_STATUS (0x1U)
-+/** Host Control Registers : Download host interrupt status */
-+#define DN_LD_HOST_INT_STATUS (0x2U)
-+
-+/** Host F1 read base 0 */
-+#define HOST_F1_RD_BASE_0 0x10
-+/** Host F1 read base 1 */
-+#define HOST_F1_RD_BASE_1 0x11
-+
-+/** Card Control Registers : Card status register */
-+#define CARD_STATUS_REG 0x20
-+/** Card Control Registers : Card I/O ready */
-+#define CARD_IO_READY (0x1U << 3)
-+/** Card Control Registers : CIS card ready */
-+#define CIS_CARD_RDY (0x1U << 2)
-+/** Card Control Registers : Upload card ready */
-+#define UP_LD_CARD_RDY (0x1U << 1)
-+/** Card Control Registers : Download card ready */
-+#define DN_LD_CARD_RDY (0x1U << 0)
-+
-+/** Card Control Registers : Card OCR 0 register */
-+#define CARD_OCR_0_REG 0x34
-+/** Card Control Registers : Card OCR 1 register */
-+#define CARD_OCR_1_REG 0x35
-+
-+/** Firmware status 0 register */
-+#define CARD_FW_STATUS0_REG 0x40
-+/** Firmware status 1 register */
-+#define CARD_FW_STATUS1_REG 0x41
-+/** Rx length register */
-+#define CARD_RX_LEN_REG 0x42
-+/** Rx unit register */
-+#define CARD_RX_UNIT_REG 0x43
-+
-+/** Chip Id Register 0 */
-+#define CARD_CHIP_ID_0_REG 0x801c
-+/** Chip Id Register 1 */
-+#define CARD_CHIP_ID_1_REG 0x801d
-+
-+#ifdef PXA3XX_DMA_ALIGN
-+/** DMA alignment value for PXA3XX platforms */
-+#define PXA3XX_DMA_ALIGNMENT 8
-+/** Macros for Data Alignment : size */
-+#define ALIGN_SZ(p, a) \
-+ (((p) + ((a) - 1)) & ~((a) - 1))
-+
-+/** Macros for Data Alignment : address */
-+#define ALIGN_ADDR(p, a) \
-+ ((((u32)(p)) + (((u32)(a)) - 1)) & ~(((u32)(a)) - 1))
-+#endif /* PXA3XX_DMA_ALIGN */
-+
-+struct sdio_mmc_card
-+{
-+ /** sdio_func structure pointer */
-+ struct sdio_func *func;
-+ /** uap_private structure pointer */
-+ uap_private *priv;
-+};
-+
-+#endif /* _UAP_SDIO_MMC_H */
-diff -Naur compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/Makefile compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/Makefile
---- compat-wireless-3.5-rc5-1-snpc.org/drivers/net/wireless/Makefile 2012-07-05 03:48:01.000000000 +0200
-+++ compat-wireless-3.5-rc5-1-snpc/drivers/net/wireless/Makefile 2012-07-31 14:20:01.343608619 +0200
-@@ -22,6 +22,8 @@
-
- obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
-
-+obj-$(CONFIG_LIBERTAS_UAP) += libertas_uap/
-+
- obj-$(CONFIG_ADM8211) += adm8211.o
-
- obj-$(CONFIG_MWL8K) += mwl8k.o
+++ /dev/null
-diff -Nur grub-0.97/acinclude.m4 grub-0.97-patched/acinclude.m4
---- grub-0.97/acinclude.m4 2004-04-27 22:48:06.000000000 +0200
-+++ grub-0.97-patched/acinclude.m4 2012-11-11 17:07:12.710729053 +0100
-@@ -57,7 +57,7 @@
- fi
- grub_cv_prog_objcopy_absolute=yes
- for link_addr in 2000 8000 7C00; do
-- if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then :
-+ if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} ${LDFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec]); then :
- else
- AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr])
- fi
-diff -Nur grub-0.97/ChangeLog grub-0.97-patched/ChangeLog
---- grub-0.97/ChangeLog 2005-05-08 04:47:02.000000000 +0200
-+++ grub-0.97-patched/ChangeLog 2012-11-11 17:07:12.708728989 +0100
-@@ -1,3 +1,127 @@
-+2008-05-20 Robert Millan <rmh@aybabtu.com>
-+
-+ * netboot/cs89x0.c: Fix license violation.
-+ * netboot/cs89x0.h: Likewise.
-+
-+2008-04-10 Pavel Roskin <proski@gnu.org>
-+
-+ * configure.ac: Always use "_cv_" in cache variables for
-+ compatibility with Autoconf 2.62.
-+
-+2008-03-28 Robert Millan <rmh@aybabtu.com>
-+
-+ Surpass 1 TiB disk addressing limit. Note: there are no plans to handle
-+ the 2 TiB disk limit in GRUB Legacy, since that would need considerable
-+ rework. If you have >2TiB disks, use GRUB 2 instead.
-+
-+ * grub/asmstub.c (biosdisk): Add unsigned qualifier to `sector'.
-+ * stage2/bios.c (biosdisk): Likewise.
-+ * stage2/disk_io.c (rawread, devread, rawwrite, devwrite): Likewise.
-+ * stage2/shared.h (rawread, devread, rawwrite, devwrite): Likewise.
-+ * lib/device.c (get_drive_geometry): Replace BLKGETSIZE with
-+ BLKGETSIZE64.
-+
-+2007-10-29 Pavel Roskin <proski@gnu.org>
-+
-+ * configure.ac: Test if '--build-id=none' is supported by the
-+ linker and add it to LDFLAGS if possible. Build ID causes
-+ objcopy to generate huge binary files.
-+ * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): Use LDFLAGS when
-+ linking, so that build ID doesn't break the test.
-+ * stage1/Makefile.am: Preserve LDFLAGS, use stage1_exec_LDFLAGS.
-+
-+2007-02-22 Pavel Roskin <proski@gnu.org>
-+
-+ * stage2/iso9660.h: Remove unnecessary packed attributes.
-+
-+2007-02-22 Robert Millan <rmh@aybabtu.com>
-+
-+ * util/mkbimage: Update my email address, and remove my name from
-+ some places where unnecessary credit is given.
-+
-+2006-09-10 Pavel Roskin <proski@gnu.org>
-+
-+ * netboot/natsemi.c: Fix compile error with gcc 4.1.1. Cast
-+ cannot make a variable volatile - it should be declared as such.
-+ * netboot/sis900.c: Likewise.
-+
-+2006-09-08 Pavel Roskin <proski@gnu.org>
-+
-+ * netboot/etherboot.h: Remove incorrect extern declarations of
-+ the variables later declared static. Move BOOTP_DATA_ADDR ...
-+ * netboot/main.c: ... here. Eliminate end_of_rfc1533 - it's
-+ write-only.
-+
-+2006-06-24 Yoshinori K. Okuji <okuji@enbug.org>
-+
-+ * docs/grub.texi: Changed the license term to the GNU Free
-+ Documentation License 1.2.
-+
-+ * docs/multiboot.texi: Reformatted to show the license term
-+ and the version number explicitly.
-+
-+ * docs/fdl.texi: New file.
-+
-+ * docs/Makefile.am (grub_TEXINFOS): Added fdl.texi.
-+
-+2006-06-24 Robert Millan <robertmh@gnu.org>
-+
-+ * lib/device.c (write_to_partition): /dev/ataraid/ and /dev/rd/
-+ partitions have a "p" prefix. Add it.
-+
-+2006-06-24 Robert Millan <robertmh@gnu.org>
-+
-+ * lib/device.c (get_i2o_disk_name): New function.
-+ (init_device_map) [__linux__]: Add support for I2O devices.
-+
-+2006-05-02 Pavel Roskin <proski@gnu.org>
-+
-+ * stage2/stage2.c (run_menu): Fix "savedefault" to save only top
-+ level menu positions. Remember current position when calling a
-+ submenu. Don't recalculate it when booting from a submenu.
-+
-+ * grub/main.c (main): Make sure the boot drive number doesn't
-+ exceed 255.
-+
-+2006-05-02 Vesa Jaaskelainen <chaac@nic.fi>
-+
-+ * stage2/shared.h (vbe_mode): Back ported aligment fix from GRUB 2
-+ to GRUB Legacy. Problem reported by Gerardo Richarte.
-+
-+2006-04-23 Robert Millan <robertmh@gnu.org>
-+
-+ * grub/asmstub.c (get_diskinfo): Optimize sysctl routine.
-+
-+2006-04-20 Robert Millan <robertmh@gnu.org>
-+
-+ Fixes for kernel of FreeBSD:
-+ * grub/asmstub.c (get_diskinfo): Toggle "kern.geom.debugflags" sysctl
-+ before opening a device for writing.
-+ * util/grub-install.in: Devices don't have this "r" prefix anymore.
-+
-+2006-04-16 Yoshinori K. Okuji <okuji@enbug.org>
-+
-+ * docs/multiboot.texi: Correct the offset of address
-+ fields. Reported by Jeroen Dekkers.
-+
-+2006-03-21 Yoshinori K. Okuji <okuji@enbug.org>
-+
-+ * stage2/builtins.c (setup_func): Specify the size of DEVICE to
-+ grub_strncat instead of a strange number 256. Reported by Vitaly
-+ Fertman <vitaly@namesys.com>.
-+
-+2005-09-29 Yoshinori K. Okuji <okuji@enbug.org>
-+
-+ * docs/multiboot.texi: Fix a bug in the byte order of
-+ boot_device. I hope this won't affect any OS image.
-+ Increased the version number to 0.6.94.
-+
-+2005-09-28 Yoshinori K. Okuji <okuji@enbug.org>
-+
-+ * stage2/boot.c (load_image): Even if an OS image is an ELF
-+ object, use the a.out kludge if MULTIBOOT_AOUT_KLUDGE is
-+ specified.
-+
- 2005-05-08 Yoshinori K. Okuji <okuji@enbug.org>
-
- * configure.ac (AC_INIT): Upgraded to 0.97.
-diff -Nur grub-0.97/configure.ac grub-0.97-patched/configure.ac
---- grub-0.97/configure.ac 2005-05-08 04:36:03.000000000 +0200
-+++ grub-0.97-patched/configure.ac 2012-11-11 17:07:12.752730394 +0100
-@@ -21,8 +21,12 @@
- AC_CANONICAL_HOST
-
- case "$host_cpu" in
--i[[3456]]86) host_cpu=i386 ;;
--x86_64) host_cpu=x86_64 ;;
-+i[[3456]]86)
-+ STAGE_MARCH="-march=$host_cpu"
-+ host_cpu=i386 ;;
-+x86_64)
-+ STAGE_MARCH="-march=i686"
-+ host_cpu=x86_64 ;;
- *) AC_MSG_ERROR([unsupported CPU type]) ;;
- esac
-
-@@ -56,12 +60,7 @@
-
- AC_CHECK_TOOL(CC, gcc)
- AC_PROG_CC
--# We need this for older versions of Autoconf.
--_AM_DEPENDENCIES(CC)
--
--dnl Because recent automake complains about AS, set it here.
--CCAS="$CC"
--AC_SUBST(CCAS)
-+AM_PROG_AS
-
- AC_ARG_WITH(binutils,
- [ --with-binutils=DIR search the directory DIR to find binutils])
-@@ -86,13 +85,13 @@
- fi
- STAGE1_CFLAGS="-O2"
- GRUB_CFLAGS="-O2"
-- AC_CACHE_CHECK([whether optimization for size works], size_flag, [
-+ AC_CACHE_CHECK([whether optimization for size works], grub_cv_cc_Os, [
- saved_CFLAGS=$CFLAGS
- CFLAGS="-Os -g"
-- AC_TRY_COMPILE(, , size_flag=yes, size_flag=no)
-+ AC_TRY_COMPILE(, , grub_cv_cc_Os=yes, grub_cv_cc_Os=no)
- CFLAGS=$saved_CFLAGS
- ])
-- if test "x$size_flag" = xyes; then
-+ if test "x$grub_cv_cc_Os" = xyes; then
- STAGE2_CFLAGS="-Os"
- else
- STAGE2_CFLAGS="-O2 -fno-strength-reduce -fno-unroll-loops"
-@@ -100,21 +99,38 @@
- # OpenBSD has a GCC extension for protecting applications from
- # stack smashing attacks, but GRUB doesn't want this feature.
- AC_CACHE_CHECK([whether gcc has -fno-stack-protector],
-- no_stack_protector_flag, [
-+ grub_cv_cc_no_stack_protector, [
- saved_CFLAGS=$CFLAGS
- CFLAGS="-fno-stack-protector"
- AC_TRY_COMPILE(,
- ,
-- no_stack_protector_flag=yes,
-- no_stack_protector_flag=no)
-+ grub_cv_cc_no_stack_protector=yes,
-+ grub_cv_cc_no_stack_protector=no)
- CFLAGS=$saved_CFLAGS
- ])
-- if test "x$no_stack_protector_flag" = xyes; then
-+ if test "x$grub_cv_cc_no_stack_protector" = xyes; then
- STAGE2_CFLAGS="$STAGE2_CFLAGS -fno-stack-protector"
- fi
-+ # Position Independent Executables, but GRUB doesn't want this feature.
-+ AC_CACHE_CHECK([whether gcc has -fPIE on as default], grub_cv_cc_fpie, [
-+ AC_TRY_COMPILE(,[
-+ #if ! defined (__PIC__) || ! defined (__PIE__)
-+ #error
-+ #endif
-+ ],
-+ grub_cv_cc_fpie=yes,
-+ grub_cv_cc_fpie=no)
-+ ])
-+ if test "x$grub_cv_cc_fpie" = xyes; then
-+ STAGE1_CFLAGS="$STAGE1_CFLAGS -nopie"
-+ STAGE2_CFLAGS="$STAGE2_CFLAGS -nopie"
-+ fi
- fi
- fi
-
-+STAGE1_CFLAGS="$STAGE1_CFLAGS -fno-strict-aliasing $STAGE_MARCH"
-+STAGE2_CFLAGS="$STAGE2_CFLAGS -fno-strict-aliasing $STAGE_MARCH"
-+GRUB_CFLAGS="$GRUB_CFLAGS -fno-strict-aliasing"
- AC_SUBST(STAGE1_CFLAGS)
- AC_SUBST(STAGE2_CFLAGS)
- AC_SUBST(GRUB_CFLAGS)
-@@ -123,33 +139,44 @@
- CPPFLAGS="$CPPFLAGS -Wall -Wmissing-prototypes -Wunused -Wshadow"
- CPPFLAGS="$CPPFLAGS -Wpointer-arith"
-
--AC_CACHE_CHECK([whether -Wundef works], undef_flag, [
-+AC_CACHE_CHECK([whether -Wundef works], grub_cv_cc_Wundef, [
- saved_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="-Wundef"
-- AC_TRY_COMPILE(, , undef_flag=yes, undef_flag=no)
-+ AC_TRY_COMPILE(, , grub_cv_cc_Wundef=yes, grub_cv_cc_Wundef=no)
- CPPFLAGS="$saved_CPPFLAGS"
- ])
-
- # The options `-falign-*' are supported by gcc 3.0 or later.
- # Probably it is sufficient to only check for -falign-loops.
--AC_CACHE_CHECK([whether -falign-loops works], [falign_loop_flag], [
-+AC_CACHE_CHECK([whether -falign-loops works], [grub_cv_cc_falign_loop], [
- saved_CPPFLAGS="$CPPFLAGS"
- CPPFLAGS="-falign-loops=1"
-- AC_TRY_COMPILE(, , [falign_loop_flag=yes], [falign_loop_flag=no])
-+ AC_TRY_COMPILE(, , [grub_cv_cc_falign_loop=yes], [grub_cv_cc_falign_loop=no])
- CPPFLAGS="$saved_CPPFLAGS"
- ])
-
- # Force no alignment to save space.
--if test "x$falign_loop_flag" = xyes; then
-+if test "x$grub_cv_cc_falign_loop" = xyes; then
- CPPFLAGS="$CPPFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1"
- else
- CPPFLAGS="$CPPFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1"
- fi
-
--if test "x$undef_flag" = xyes; then
-+if test "x$grub_cv_cc_Wundef" = xyes; then
- CPPFLAGS="$CPPFLAGS -Wundef"
- fi
-
-+# Check if build ID can be disabled in the linker
-+AC_MSG_CHECKING([whether linker accepts `--build-id=none'])
-+save_LDFLAGS="$LDFLAGS"
-+LDFLAGS="$LDFLAGS -Wl,--build-id=none"
-+AC_TRY_LINK(, , build_id_flag=yes, build_id_flag=no)
-+AC_MSG_RESULT([$build_id_flag])
-+LDFLAGS="$save_LDFLAGS"
-+if test "x$build_id_flag" = xyes; then
-+ LDFLAGS="$LDFLAGS -Wl,--build-id=none"
-+fi
-+
- if test "x$with_binutils" != x; then
- dnl AC_PATH_TOOL(OBJCOPY, objcopy, , "$with_binutils:$PATH")
- AC_PATH_PROG(OBJCOPY, objcopy, , "$with_binutils:$PATH")
-@@ -595,6 +622,11 @@
- [ --enable-diskless enable diskless support])
- AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
-
-+dnl Graphical splashscreen support
-+AC_ARG_ENABLE(graphics,
-+ [ --disable-graphics disable graphics terminal support])
-+AM_CONDITIONAL(GRAPHICS_SUPPORT, test "x$enable_graphics" != xno)
-+
- dnl Hercules terminal
- AC_ARG_ENABLE(hercules,
- [ --disable-hercules disable hercules terminal support])
-diff -Nur grub-0.97/docs/fdl.texi grub-0.97-patched/docs/fdl.texi
---- grub-0.97/docs/fdl.texi 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/docs/fdl.texi 2012-11-11 17:07:12.712729117 +0100
-@@ -0,0 +1,452 @@
-+
-+@node GNU Free Documentation License
-+@appendixsec GNU Free Documentation License
-+
-+@cindex FDL, GNU Free Documentation License
-+@center Version 1.2, November 2002
-+
-+@display
-+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
-+51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
-+
-+Everyone is permitted to copy and distribute verbatim copies
-+of this license document, but changing it is not allowed.
-+@end display
-+
-+@enumerate 0
-+@item
-+PREAMBLE
-+
-+The purpose of this License is to make a manual, textbook, or other
-+functional and useful document @dfn{free} in the sense of freedom: to
-+assure everyone the effective freedom to copy and redistribute it,
-+with or without modifying it, either commercially or noncommercially.
-+Secondarily, this License preserves for the author and publisher a way
-+to get credit for their work, while not being considered responsible
-+for modifications made by others.
-+
-+This License is a kind of ``copyleft'', which means that derivative
-+works of the document must themselves be free in the same sense. It
-+complements the GNU General Public License, which is a copyleft
-+license designed for free software.
-+
-+We have designed this License in order to use it for manuals for free
-+software, because free software needs free documentation: a free
-+program should come with manuals providing the same freedoms that the
-+software does. But this License is not limited to software manuals;
-+it can be used for any textual work, regardless of subject matter or
-+whether it is published as a printed book. We recommend this License
-+principally for works whose purpose is instruction or reference.
-+
-+@item
-+APPLICABILITY AND DEFINITIONS
-+
-+This License applies to any manual or other work, in any medium, that
-+contains a notice placed by the copyright holder saying it can be
-+distributed under the terms of this License. Such a notice grants a
-+world-wide, royalty-free license, unlimited in duration, to use that
-+work under the conditions stated herein. The ``Document'', below,
-+refers to any such manual or work. Any member of the public is a
-+licensee, and is addressed as ``you''. You accept the license if you
-+copy, modify or distribute the work in a way requiring permission
-+under copyright law.
-+
-+A ``Modified Version'' of the Document means any work containing the
-+Document or a portion of it, either copied verbatim, or with
-+modifications and/or translated into another language.
-+
-+A ``Secondary Section'' is a named appendix or a front-matter section
-+of the Document that deals exclusively with the relationship of the
-+publishers or authors of the Document to the Document's overall
-+subject (or to related matters) and contains nothing that could fall
-+directly within that overall subject. (Thus, if the Document is in
-+part a textbook of mathematics, a Secondary Section may not explain
-+any mathematics.) The relationship could be a matter of historical
-+connection with the subject or with related matters, or of legal,
-+commercial, philosophical, ethical or political position regarding
-+them.
-+
-+The ``Invariant Sections'' are certain Secondary Sections whose titles
-+are designated, as being those of Invariant Sections, in the notice
-+that says that the Document is released under this License. If a
-+section does not fit the above definition of Secondary then it is not
-+allowed to be designated as Invariant. The Document may contain zero
-+Invariant Sections. If the Document does not identify any Invariant
-+Sections then there are none.
-+
-+The ``Cover Texts'' are certain short passages of text that are listed,
-+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
-+the Document is released under this License. A Front-Cover Text may
-+be at most 5 words, and a Back-Cover Text may be at most 25 words.
-+
-+A ``Transparent'' copy of the Document means a machine-readable copy,
-+represented in a format whose specification is available to the
-+general public, that is suitable for revising the document
-+straightforwardly with generic text editors or (for images composed of
-+pixels) generic paint programs or (for drawings) some widely available
-+drawing editor, and that is suitable for input to text formatters or
-+for automatic translation to a variety of formats suitable for input
-+to text formatters. A copy made in an otherwise Transparent file
-+format whose markup, or absence of markup, has been arranged to thwart
-+or discourage subsequent modification by readers is not Transparent.
-+An image format is not Transparent if used for any substantial amount
-+of text. A copy that is not ``Transparent'' is called ``Opaque''.
-+
-+Examples of suitable formats for Transparent copies include plain
-+@sc{ascii} without markup, Texinfo input format, La@TeX{} input
-+format, @acronym{SGML} or @acronym{XML} using a publicly available
-+@acronym{DTD}, and standard-conforming simple @acronym{HTML},
-+PostScript or @acronym{PDF} designed for human modification. Examples
-+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
-+@acronym{JPG}. Opaque formats include proprietary formats that can be
-+read and edited only by proprietary word processors, @acronym{SGML} or
-+@acronym{XML} for which the @acronym{DTD} and/or processing tools are
-+not generally available, and the machine-generated @acronym{HTML},
-+PostScript or @acronym{PDF} produced by some word processors for
-+output purposes only.
-+
-+The ``Title Page'' means, for a printed book, the title page itself,
-+plus such following pages as are needed to hold, legibly, the material
-+this License requires to appear in the title page. For works in
-+formats which do not have any title page as such, ``Title Page'' means
-+the text near the most prominent appearance of the work's title,
-+preceding the beginning of the body of the text.
-+
-+A section ``Entitled XYZ'' means a named subunit of the Document whose
-+title either is precisely XYZ or contains XYZ in parentheses following
-+text that translates XYZ in another language. (Here XYZ stands for a
-+specific section name mentioned below, such as ``Acknowledgements'',
-+``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title''
-+of such a section when you modify the Document means that it remains a
-+section ``Entitled XYZ'' according to this definition.
-+
-+The Document may include Warranty Disclaimers next to the notice which
-+states that this License applies to the Document. These Warranty
-+Disclaimers are considered to be included by reference in this
-+License, but only as regards disclaiming warranties: any other
-+implication that these Warranty Disclaimers may have is void and has
-+no effect on the meaning of this License.
-+
-+@item
-+VERBATIM COPYING
-+
-+You may copy and distribute the Document in any medium, either
-+commercially or noncommercially, provided that this License, the
-+copyright notices, and the license notice saying this License applies
-+to the Document are reproduced in all copies, and that you add no other
-+conditions whatsoever to those of this License. You may not use
-+technical measures to obstruct or control the reading or further
-+copying of the copies you make or distribute. However, you may accept
-+compensation in exchange for copies. If you distribute a large enough
-+number of copies you must also follow the conditions in section 3.
-+
-+You may also lend copies, under the same conditions stated above, and
-+you may publicly display copies.
-+
-+@item
-+COPYING IN QUANTITY
-+
-+If you publish printed copies (or copies in media that commonly have
-+printed covers) of the Document, numbering more than 100, and the
-+Document's license notice requires Cover Texts, you must enclose the
-+copies in covers that carry, clearly and legibly, all these Cover
-+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
-+the back cover. Both covers must also clearly and legibly identify
-+you as the publisher of these copies. The front cover must present
-+the full title with all words of the title equally prominent and
-+visible. You may add other material on the covers in addition.
-+Copying with changes limited to the covers, as long as they preserve
-+the title of the Document and satisfy these conditions, can be treated
-+as verbatim copying in other respects.
-+
-+If the required texts for either cover are too voluminous to fit
-+legibly, you should put the first ones listed (as many as fit
-+reasonably) on the actual cover, and continue the rest onto adjacent
-+pages.
-+
-+If you publish or distribute Opaque copies of the Document numbering
-+more than 100, you must either include a machine-readable Transparent
-+copy along with each Opaque copy, or state in or with each Opaque copy
-+a computer-network location from which the general network-using
-+public has access to download using public-standard network protocols
-+a complete Transparent copy of the Document, free of added material.
-+If you use the latter option, you must take reasonably prudent steps,
-+when you begin distribution of Opaque copies in quantity, to ensure
-+that this Transparent copy will remain thus accessible at the stated
-+location until at least one year after the last time you distribute an
-+Opaque copy (directly or through your agents or retailers) of that
-+edition to the public.
-+
-+It is requested, but not required, that you contact the authors of the
-+Document well before redistributing any large number of copies, to give
-+them a chance to provide you with an updated version of the Document.
-+
-+@item
-+MODIFICATIONS
-+
-+You may copy and distribute a Modified Version of the Document under
-+the conditions of sections 2 and 3 above, provided that you release
-+the Modified Version under precisely this License, with the Modified
-+Version filling the role of the Document, thus licensing distribution
-+and modification of the Modified Version to whoever possesses a copy
-+of it. In addition, you must do these things in the Modified Version:
-+
-+@enumerate A
-+@item
-+Use in the Title Page (and on the covers, if any) a title distinct
-+from that of the Document, and from those of previous versions
-+(which should, if there were any, be listed in the History section
-+of the Document). You may use the same title as a previous version
-+if the original publisher of that version gives permission.
-+
-+@item
-+List on the Title Page, as authors, one or more persons or entities
-+responsible for authorship of the modifications in the Modified
-+Version, together with at least five of the principal authors of the
-+Document (all of its principal authors, if it has fewer than five),
-+unless they release you from this requirement.
-+
-+@item
-+State on the Title page the name of the publisher of the
-+Modified Version, as the publisher.
-+
-+@item
-+Preserve all the copyright notices of the Document.
-+
-+@item
-+Add an appropriate copyright notice for your modifications
-+adjacent to the other copyright notices.
-+
-+@item
-+Include, immediately after the copyright notices, a license notice
-+giving the public permission to use the Modified Version under the
-+terms of this License, in the form shown in the Addendum below.
-+
-+@item
-+Preserve in that license notice the full lists of Invariant Sections
-+and required Cover Texts given in the Document's license notice.
-+
-+@item
-+Include an unaltered copy of this License.
-+
-+@item
-+Preserve the section Entitled ``History'', Preserve its Title, and add
-+to it an item stating at least the title, year, new authors, and
-+publisher of the Modified Version as given on the Title Page. If
-+there is no section Entitled ``History'' in the Document, create one
-+stating the title, year, authors, and publisher of the Document as
-+given on its Title Page, then add an item describing the Modified
-+Version as stated in the previous sentence.
-+
-+@item
-+Preserve the network location, if any, given in the Document for
-+public access to a Transparent copy of the Document, and likewise
-+the network locations given in the Document for previous versions
-+it was based on. These may be placed in the ``History'' section.
-+You may omit a network location for a work that was published at
-+least four years before the Document itself, or if the original
-+publisher of the version it refers to gives permission.
-+
-+@item
-+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
-+the Title of the section, and preserve in the section all the
-+substance and tone of each of the contributor acknowledgements and/or
-+dedications given therein.
-+
-+@item
-+Preserve all the Invariant Sections of the Document,
-+unaltered in their text and in their titles. Section numbers
-+or the equivalent are not considered part of the section titles.
-+
-+@item
-+Delete any section Entitled ``Endorsements''. Such a section
-+may not be included in the Modified Version.
-+
-+@item
-+Do not retitle any existing section to be Entitled ``Endorsements'' or
-+to conflict in title with any Invariant Section.
-+
-+@item
-+Preserve any Warranty Disclaimers.
-+@end enumerate
-+
-+If the Modified Version includes new front-matter sections or
-+appendices that qualify as Secondary Sections and contain no material
-+copied from the Document, you may at your option designate some or all
-+of these sections as invariant. To do this, add their titles to the
-+list of Invariant Sections in the Modified Version's license notice.
-+These titles must be distinct from any other section titles.
-+
-+You may add a section Entitled ``Endorsements'', provided it contains
-+nothing but endorsements of your Modified Version by various
-+parties---for example, statements of peer review or that the text has
-+been approved by an organization as the authoritative definition of a
-+standard.
-+
-+You may add a passage of up to five words as a Front-Cover Text, and a
-+passage of up to 25 words as a Back-Cover Text, to the end of the list
-+of Cover Texts in the Modified Version. Only one passage of
-+Front-Cover Text and one of Back-Cover Text may be added by (or
-+through arrangements made by) any one entity. If the Document already
-+includes a cover text for the same cover, previously added by you or
-+by arrangement made by the same entity you are acting on behalf of,
-+you may not add another; but you may replace the old one, on explicit
-+permission from the previous publisher that added the old one.
-+
-+The author(s) and publisher(s) of the Document do not by this License
-+give permission to use their names for publicity for or to assert or
-+imply endorsement of any Modified Version.
-+
-+@item
-+COMBINING DOCUMENTS
-+
-+You may combine the Document with other documents released under this
-+License, under the terms defined in section 4 above for modified
-+versions, provided that you include in the combination all of the
-+Invariant Sections of all of the original documents, unmodified, and
-+list them all as Invariant Sections of your combined work in its
-+license notice, and that you preserve all their Warranty Disclaimers.
-+
-+The combined work need only contain one copy of this License, and
-+multiple identical Invariant Sections may be replaced with a single
-+copy. If there are multiple Invariant Sections with the same name but
-+different contents, make the title of each such section unique by
-+adding at the end of it, in parentheses, the name of the original
-+author or publisher of that section if known, or else a unique number.
-+Make the same adjustment to the section titles in the list of
-+Invariant Sections in the license notice of the combined work.
-+
-+In the combination, you must combine any sections Entitled ``History''
-+in the various original documents, forming one section Entitled
-+``History''; likewise combine any sections Entitled ``Acknowledgements'',
-+and any sections Entitled ``Dedications''. You must delete all
-+sections Entitled ``Endorsements.''
-+
-+@item
-+COLLECTIONS OF DOCUMENTS
-+
-+You may make a collection consisting of the Document and other documents
-+released under this License, and replace the individual copies of this
-+License in the various documents with a single copy that is included in
-+the collection, provided that you follow the rules of this License for
-+verbatim copying of each of the documents in all other respects.
-+
-+You may extract a single document from such a collection, and distribute
-+it individually under this License, provided you insert a copy of this
-+License into the extracted document, and follow this License in all
-+other respects regarding verbatim copying of that document.
-+
-+@item
-+AGGREGATION WITH INDEPENDENT WORKS
-+
-+A compilation of the Document or its derivatives with other separate
-+and independent documents or works, in or on a volume of a storage or
-+distribution medium, is called an ``aggregate'' if the copyright
-+resulting from the compilation is not used to limit the legal rights
-+of the compilation's users beyond what the individual works permit.
-+When the Document is included in an aggregate, this License does not
-+apply to the other works in the aggregate which are not themselves
-+derivative works of the Document.
-+
-+If the Cover Text requirement of section 3 is applicable to these
-+copies of the Document, then if the Document is less than one half of
-+the entire aggregate, the Document's Cover Texts may be placed on
-+covers that bracket the Document within the aggregate, or the
-+electronic equivalent of covers if the Document is in electronic form.
-+Otherwise they must appear on printed covers that bracket the whole
-+aggregate.
-+
-+@item
-+TRANSLATION
-+
-+Translation is considered a kind of modification, so you may
-+distribute translations of the Document under the terms of section 4.
-+Replacing Invariant Sections with translations requires special
-+permission from their copyright holders, but you may include
-+translations of some or all Invariant Sections in addition to the
-+original versions of these Invariant Sections. You may include a
-+translation of this License, and all the license notices in the
-+Document, and any Warranty Disclaimers, provided that you also include
-+the original English version of this License and the original versions
-+of those notices and disclaimers. In case of a disagreement between
-+the translation and the original version of this License or a notice
-+or disclaimer, the original version will prevail.
-+
-+If a section in the Document is Entitled ``Acknowledgements'',
-+``Dedications'', or ``History'', the requirement (section 4) to Preserve
-+its Title (section 1) will typically require changing the actual
-+title.
-+
-+@item
-+TERMINATION
-+
-+You may not copy, modify, sublicense, or distribute the Document except
-+as expressly provided for under this License. Any other attempt to
-+copy, modify, sublicense or distribute the Document is void, and will
-+automatically terminate your rights under this License. However,
-+parties who have received copies, or rights, from you under this
-+License will not have their licenses terminated so long as such
-+parties remain in full compliance.
-+
-+@item
-+FUTURE REVISIONS OF THIS LICENSE
-+
-+The Free Software Foundation may publish new, revised versions
-+of the GNU Free Documentation License from time to time. Such new
-+versions will be similar in spirit to the present version, but may
-+differ in detail to address new problems or concerns. See
-+@uref{http://www.gnu.org/copyleft/}.
-+
-+Each version of the License is given a distinguishing version number.
-+If the Document specifies that a particular numbered version of this
-+License ``or any later version'' applies to it, you have the option of
-+following the terms and conditions either of that specified version or
-+of any later version that has been published (not as a draft) by the
-+Free Software Foundation. If the Document does not specify a version
-+number of this License, you may choose any version ever published (not
-+as a draft) by the Free Software Foundation.
-+@end enumerate
-+
-+@page
-+@appendixsubsec ADDENDUM: How to use this License for your documents
-+
-+To use this License in a document you have written, include a copy of
-+the License in the document and put the following copyright and
-+license notices just after the title page:
-+
-+@smallexample
-+@group
-+ Copyright (C) @var{year} @var{your name}.
-+ Permission is granted to copy, distribute and/or modify this document
-+ under the terms of the GNU Free Documentation License, Version 1.2
-+ or any later version published by the Free Software Foundation;
-+ with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
-+ Texts. A copy of the license is included in the section entitled ``GNU
-+ Free Documentation License''.
-+@end group
-+@end smallexample
-+
-+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
-+replace the ``with...Texts.'' line with this:
-+
-+@smallexample
-+@group
-+ with the Invariant Sections being @var{list their titles}, with
-+ the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
-+ being @var{list}.
-+@end group
-+@end smallexample
-+
-+If you have Invariant Sections without Cover Texts, or some other
-+combination of the three, merge those two alternatives to suit the
-+situation.
-+
-+If your document contains nontrivial examples of program code, we
-+recommend releasing these examples in parallel under your choice of
-+free software license, such as the GNU General Public License,
-+to permit their use in free software.
-+
-+@c Local Variables:
-+@c ispell-local-pdict: "ispell-dict"
-+@c End:
-+
-diff -Nur grub-0.97/docs/grub.8 grub-0.97-patched/docs/grub.8
---- grub-0.97/docs/grub.8 2005-05-08 04:48:56.000000000 +0200
-+++ grub-0.97-patched/docs/grub.8 2012-11-11 17:07:12.715729211 +0100
-@@ -1,5 +1,5 @@
- .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
--.TH GRUB "8" "May 2005" "grub (GNU GRUB 0.97)" FSF
-+.TH GRUB "8" "June 2006" "grub (GNU GRUB 0.97)" FSF
- .SH NAME
- grub \- the grub shell
- .SH SYNOPSIS
-diff -Nur grub-0.97/docs/grub.8.additions grub-0.97-patched/docs/grub.8.additions
---- grub-0.97/docs/grub.8.additions 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/docs/grub.8.additions 2012-11-11 17:07:12.702728798 +0100
-@@ -0,0 +1,3 @@
-+[SEE ALSO]
-+.BR update-grub (8),
-+.BR grub-install (8).
-diff -Nur grub-0.97/docs/grub-install.8 grub-0.97-patched/docs/grub-install.8
---- grub-0.97/docs/grub-install.8 2005-05-08 04:48:56.000000000 +0200
-+++ grub-0.97-patched/docs/grub-install.8 2012-11-11 17:07:12.713729149 +0100
-@@ -1,5 +1,5 @@
- .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
--.TH GRUB-INSTALL "8" "May 2005" "grub-install (GNU GRUB 0.97)" FSF
-+.TH GRUB-INSTALL "8" "June 2006" "grub-install (GNU GRUB 0.97)" FSF
- .SH NAME
- grub-install \- install GRUB on your drive
- .SH SYNOPSIS
-diff -Nur grub-0.97/docs/grub-install.8.additions grub-0.97-patched/docs/grub-install.8.additions
---- grub-0.97/docs/grub-install.8.additions 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/docs/grub-install.8.additions 2012-11-11 17:07:12.703728829 +0100
-@@ -0,0 +1,3 @@
-+[SEE ALSO]
-+.BR grub (8),
-+.BR update-grub (8).
-diff -Nur grub-0.97/docs/grub-md5-crypt.8 grub-0.97-patched/docs/grub-md5-crypt.8
---- grub-0.97/docs/grub-md5-crypt.8 2005-05-08 04:48:56.000000000 +0200
-+++ grub-0.97-patched/docs/grub-md5-crypt.8 2012-11-11 17:07:12.713729149 +0100
-@@ -1,5 +1,5 @@
- .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
--.TH GRUB-MD5-CRYPT "8" "May 2005" "grub-md5-crypt (GNU GRUB )" FSF
-+.TH GRUB-MD5-CRYPT "8" "June 2006" "grub-md5-crypt (GNU GRUB )" FSF
- .SH NAME
- grub-md5-crypt \- Encrypt a password in MD5 format
- .SH SYNOPSIS
-diff -Nur grub-0.97/docs/grub-terminfo.8 grub-0.97-patched/docs/grub-terminfo.8
---- grub-0.97/docs/grub-terminfo.8 2005-05-08 04:48:56.000000000 +0200
-+++ grub-0.97-patched/docs/grub-terminfo.8 2012-11-11 17:07:12.714729180 +0100
-@@ -1,5 +1,5 @@
- .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
--.TH GRUB-TERMINFO "8" "May 2005" "grub-terminfo (GNU GRUB 0.97)" FSF
-+.TH GRUB-TERMINFO "8" "June 2006" "grub-terminfo (GNU GRUB 0.97)" FSF
- .SH NAME
- grub-terminfo \- Generate a terminfo command from a terminfo name
- .SH SYNOPSIS
-diff -Nur grub-0.97/docs/grub.texi grub-0.97-patched/docs/grub.texi
---- grub-0.97/docs/grub.texi 2005-05-08 04:59:59.000000000 +0200
-+++ grub-0.97-patched/docs/grub.texi 2012-11-11 17:07:12.717729276 +0100
-@@ -2,22 +2,41 @@
- @c -*-texinfo-*-
- @c %**start of header
- @setfilename grub.info
--@settitle GRUB Manual
--@c %**end of header
--
- @include version.texi
--
-+@settitle GNU GRUB Manual @value{VERSION}
- @c Unify all our little indices for now.
- @syncodeindex fn cp
- @syncodeindex vr cp
- @syncodeindex ky cp
- @syncodeindex pg cp
- @syncodeindex tp cp
-+@c %**end of header
-
- @footnotestyle separate
- @paragraphindent 3
- @finalout
-
-+@copying
-+This manual is for GNU GRUB (version @value{VERSION},
-+@value{UPDATED}).
-+
-+Copyright @copyright{} 1999,2000,2001,2002,2004,2006 Free Software Foundation, Inc.
-+
-+@quotation
-+Permission is granted to copy, distribute and/or modify this document
-+under the terms of the GNU Free Documentation License, Version 1.2 or
-+any later version published by the Free Software Foundation; with no
-+Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
-+and with the Back-Cover Texts as in (a) below. A copy of the
-+license is included in the section entitled ``GNU Free Documentation
-+License.''
-+
-+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
-+this GNU Manual, like GNU software. Copies published by the Free
-+Software Foundation raise funds for GNU development.''
-+@end quotation
-+@end copying
-+
- @dircategory Kernel
- @direntry
- * GRUB: (grub). The GRand Unified Bootloader
-@@ -34,53 +53,16 @@
-
- @setchapternewpage odd
-
--@ifinfo
--Copyright @copyright{} 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
--
--Permission is granted to make and distribute verbatim copies of
--this manual provided the copyright notice and this permission notice
--are preserved on all copies.
--
--@ignore
--Permission is granted to process this file through TeX and print the
--results, provided the printed document carries a copying permission
--notice identical to this one except for the removal of this paragraph
--(this paragraph not being relevant to the printed manual).
--
--@end ignore
--
--Permission is granted to copy and distribute modified versions of this
--manual under the conditions for verbatim copying, provided also that
--the entire resulting derived work is distributed under the terms of a
--permission notice identical to this one.
--
--Permission is granted to copy and distribute translations of this manual
--into another language, under the above conditions for modified versions.
--@end ifinfo
--
- @titlepage
- @sp 10
--@title the GRUB manual
-+@title the GNU GRUB manual
- @subtitle The GRand Unified Bootloader, version @value{VERSION}, @value{UPDATED}.
- @author Gordon Matzigkeit
- @author Yoshinori K. Okuji
- @c The following two commands start the copyright page.
- @page
- @vskip 0pt plus 1filll
--Copyright @copyright{} 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
--
--Permission is granted to make and distribute verbatim copies of
--this manual provided the copyright notice and this permission notice
--are preserved on all copies.
--Permission is granted to copy and distribute modified versions of this
--manual under the conditions for verbatim copying, provided that the entire
--resulting derived work is distributed under the terms of a permission
--notice identical to this one.
--
--Permission is granted to copy and distribute translations of this manual
--into another language, under the above conditions for modified versions,
--except that this permission notice may be stated in a translation approved
--by Free Software Foundation.
-+@insertcopying
- @end titlepage
-
- @c Output the table of contents at the beginning.
-@@ -91,12 +73,14 @@
-
- @ifnottex
- @node Top
--@top GRUB manual
-+@top GNU GRUB manual
-
- This is the documentation of GNU GRUB, the GRand Unified Bootloader,
- a flexible and powerful boot loader program for @sc{pc}s.
-
- This edition documents version @value{VERSION}.
-+
-+@insertcopying
- @end ifnottex
-
- @menu
-@@ -124,6 +108,7 @@
- * Reporting bugs:: Where you should send a bug report
- * Future:: Some future plans on GRUB
- * Internals:: Hacking GRUB
-+* Copying This Manual:: Copying This Manual
- * Index::
- @end menu
-
-@@ -3965,6 +3950,16 @@
- @include internals.texi
-
-
-+@node Copying This Manual
-+@appendix Copying This Manual
-+
-+@menu
-+* GNU Free Documentation License:: License for copying this manual.
-+@end menu
-+
-+@include fdl.texi
-+
-+
- @node Index
- @unnumbered Index
-
-diff -Nur grub-0.97/docs/help2man grub-0.97-patched/docs/help2man
---- grub-0.97/docs/help2man 2003-07-09 13:45:36.000000000 +0200
-+++ grub-0.97-patched/docs/help2man 2012-11-11 17:07:12.701728766 +0100
-@@ -455,7 +455,9 @@
- $include{$sect} .= <<EOT;
- The full documentation for
- .B $program
--is maintained as a Texinfo manual. If the
-+is maintained as a Texinfo manual in the
-+.B grub-doc
-+package. If the
- .B info
- and
- .B $program
-diff -Nur grub-0.97/docs/Makefile.am grub-0.97-patched/docs/Makefile.am
---- grub-0.97/docs/Makefile.am 2003-07-09 13:45:35.000000000 +0200
-+++ grub-0.97-patched/docs/Makefile.am 2012-11-11 17:07:12.711729085 +0100
-@@ -1,5 +1,5 @@
- info_TEXINFOS = grub.texi multiboot.texi
--grub_TEXINFOS = internals.texi
-+grub_TEXINFOS = internals.texi fdl.texi
- EXAMPLES = boot.S kernel.c multiboot.h
- multiboot_TEXINFOS = boot.S.texi kernel.c.texi multiboot.h.texi
- man_MANS = grub.8 mbchk.1 grub-install.8 grub-md5-crypt.8 grub-terminfo.8
-@@ -37,14 +37,14 @@
- $(SHELL) $(srcdir)/$(SRC2TEXI) $(srcdir) $< $@
-
- if MAINTAINER_MODE
--$(srcdir)/grub.8: ../grub/grub $(srcdir)/$(HELP2MAN)
-+$(srcdir)/grub.8: ../grub/grub $(srcdir)/$(HELP2MAN) $(srcdir)/grub.8.additions
- $(PERL) $(srcdir)/$(HELP2MAN) --name="the grub shell" \
-- --section=8 --output=$@ $<
-+ --section=8 --include=$@.additions --output=$@ $<
-
--$(srcdir)/grub-install.8: ../util/grub-install $(srcdir)/$(HELP2MAN)
-+$(srcdir)/grub-install.8: ../util/grub-install $(srcdir)/$(HELP2MAN) $(srcdir)/grub-install.8.additions
- chmod 755 $<
- $(PERL) $(srcdir)/$(HELP2MAN) --name="install GRUB on your drive" \
-- --section=8 --output=$@ $<
-+ --section=8 --include=$@.additions --output=$@ $<
-
- $(srcdir)/mbchk.1: ../util/mbchk $(srcdir)/$(HELP2MAN)
- $(PERL) $(srcdir)/$(HELP2MAN) \
-diff -Nur grub-0.97/docs/mbchk.1 grub-0.97-patched/docs/mbchk.1
---- grub-0.97/docs/mbchk.1 2005-05-08 04:48:56.000000000 +0200
-+++ grub-0.97-patched/docs/mbchk.1 2012-11-11 17:07:12.717729276 +0100
-@@ -1,5 +1,5 @@
- .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
--.TH MBCHK "1" "May 2005" "mbchk (GNU GRUB 0.97)" FSF
-+.TH MBCHK "1" "June 2006" "mbchk (GNU GRUB 0.97)" FSF
- .SH NAME
- mbchk \- check the format of a Multiboot kernel
- .SH SYNOPSIS
-diff -Nur grub-0.97/docs/menu.lst grub-0.97-patched/docs/menu.lst
---- grub-0.97/docs/menu.lst 2004-05-11 14:11:17.000000000 +0200
-+++ grub-0.97-patched/docs/menu.lst 2012-11-11 17:07:07.225553829 +0100
-@@ -11,6 +11,9 @@
- # Fallback to the second entry.
- fallback 1
-
-+# Splash image to show behind grub.
-+splashimage=(hd0,0)/boot/grub/splash.xpm.gz
-+
- # For booting GNU/Hurd
- title GNU/Hurd
- root (hd0,0)
-@@ -23,6 +26,11 @@
- kernel /vmlinuz root=/dev/hdb1
- #initrd /initrd.img
-
-+# For booting Gentoo with the static rescue shell
-+title Gentoo (rescue shell)
-+root (hd1,0)
-+kernel /vmlinuz root=/dev/hdb1 init=/bin/bb
-+
- # For booting GNU/kFreeBSD
- title GNU/kFreeBSD
- root (hd0,2,a)
-diff -Nur grub-0.97/docs/menu.lst.orig grub-0.97-patched/docs/menu.lst.orig
---- grub-0.97/docs/menu.lst.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/docs/menu.lst.orig 2004-05-11 14:11:17.000000000 +0200
-@@ -0,0 +1,82 @@
-+#
-+# Sample boot menu configuration file
-+#
-+
-+# Boot automatically after 30 secs.
-+timeout 30
-+
-+# By default, boot the first entry.
-+default 0
-+
-+# Fallback to the second entry.
-+fallback 1
-+
-+# For booting GNU/Hurd
-+title GNU/Hurd
-+root (hd0,0)
-+kernel /boot/gnumach.gz root=hd0s1
-+module /boot/serverboot.gz
-+
-+# For booting GNU/Linux
-+title GNU/Linux
-+root (hd1,0)
-+kernel /vmlinuz root=/dev/hdb1
-+#initrd /initrd.img
-+
-+# For booting GNU/kFreeBSD
-+title GNU/kFreeBSD
-+root (hd0,2,a)
-+kernel /boot/loader.gz
-+
-+# For booting GNU/kNetBSD
-+title GNU/kNetBSD
-+root (hd0,2,a)
-+kernel --type=netbsd /boot/knetbsd.gz
-+
-+# For booting Mach (getting kernel from floppy)
-+title Utah Mach4 multiboot
-+root (hd0,2)
-+pause Insert the diskette now\a!!
-+kernel (fd0)/boot/kernel root=hd0s3
-+module (fd0)/boot/bootstrap
-+
-+# For booting FreeBSD
-+title FreeBSD
-+root (hd0,2,a)
-+kernel /boot/loader
-+
-+# For booting NetBSD
-+title NetBSD
-+root (hd0,2,a)
-+kernel --type=netbsd /netbsd
-+
-+# For booting OpenBSD
-+title OpenBSD
-+root (hd0,2,a)
-+kernel --type=netbsd /bsd
-+
-+# For booting OS/2
-+title OS/2
-+root (hd0,1)
-+makeactive
-+# chainload OS/2 bootloader from the first sector
-+chainloader +1
-+# This is similar to "chainload", but loads a specific file
-+#chainloader /boot/chain.os2
-+
-+# For booting Windows NT or Windows95
-+title Windows NT / Windows 95 boot menu
-+rootnoverify (hd0,0)
-+makeactive
-+chainloader +1
-+# For loading DOS if Windows NT is installed
-+# chainload /bootsect.dos
-+
-+# For installing GRUB into the hard disk
-+title Install GRUB into the hard disk
-+root (hd0,0)
-+setup (hd0)
-+
-+# Change the colors.
-+title Change the colors
-+color light-green/brown blink-red/blue
-diff -Nur grub-0.97/docs/multiboot.texi grub-0.97-patched/docs/multiboot.texi
---- grub-0.97/docs/multiboot.texi 2003-07-09 13:45:36.000000000 +0200
-+++ grub-0.97-patched/docs/multiboot.texi 2012-11-11 17:07:12.718729309 +0100
-@@ -1,32 +1,28 @@
- \input texinfo @c -*-texinfo-*-
--@c -*-texinfo-*-
- @c %**start of header
- @setfilename multiboot.info
--@settitle Multiboot Specification
--@c %**end of header
--
-+@set VERSION 0.6.95
-+@settitle Multiboot Specification version @value{VERSION}
- @c Unify all our little indices for now.
- @syncodeindex fn cp
- @syncodeindex vr cp
- @syncodeindex ky cp
- @syncodeindex pg cp
- @syncodeindex tp cp
-+@c %**end of header
-
- @footnotestyle separate
- @paragraphindent 3
- @finalout
-
-+@copying
-+Copyright @copyright{} 1995,96 Bryan Ford <baford@@cs.utah.edu>
-
--@dircategory Kernel
--@direntry
--* Multiboot Specification: (multiboot). Multiboot Specification.
--@end direntry
-+Copyright @copyright{} 1995,96 Erich Stefan Boleyn <erich@@uruk.org>
-
--@ifinfo
--Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu>
--Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org>
--Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
-+Copyright @copyright{} 1999,2000,2001,2002,2005,2006 Free Software Foundation, Inc.
-
-+@quotation
- Permission is granted to make and distribute verbatim copies of
- this manual provided the copyright notice and this permission notice
- are preserved on all copies.
-@@ -36,7 +32,6 @@
- results, provided the printed document carries a copying permission
- notice identical to this one except for the removal of this paragraph
- (this paragraph not being relevant to the printed manual).
--
- @end ignore
-
- Permission is granted to copy and distribute modified versions of this
-@@ -45,31 +40,23 @@
- permission notice identical to this one.
-
- Permission is granted to copy and distribute translations of this manual
--into another language, under the above conditions for modified versions.
--@end ifinfo
-+into another language, under the above conditions for modified
-+versions.
-+@end quotation
-+@end copying
-+
-+@dircategory Kernel
-+@direntry
-+* Multiboot Specification: (multiboot). Multiboot Specification.
-+@end direntry
-
- @titlepage
- @sp 10
--@title The Multiboot Specification
-+@title The Multiboot Specification version @value{VERSION}
- @author Yoshinori K. Okuji, Bryan Ford, Erich Stefan Boleyn, Kunihiro Ishiguro
- @page
--
- @vskip 0pt plus 1filll
--Copyright @copyright{} 1995, 96 Bryan Ford <baford@@cs.utah.edu>
--Copyright @copyright{} 1995, 96 Erich Stefan Boleyn <erich@@uruk.org>
--Copyright @copyright{} 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
--
--Permission is granted to make and distribute verbatim copies of
--this manual provided the copyright notice and this permission notice
--are preserved on all copies.
--
--Permission is granted to copy and distribute modified versions of this
--manual under the conditions for verbatim copying, provided also that
--the entire resulting derived work is distributed under the terms of a
--permission notice identical to this one.
--
--Permission is granted to copy and distribute translations of this manual
--into another language, under the above conditions for modified versions.
-+@insertcopying
- @end titlepage
-
- @finalout
-@@ -80,7 +67,9 @@
- @top Multiboot Specification
-
- This file documents Multiboot Specification, the proposal for the boot
--sequence standard. This edition documents version 0.6.93.
-+sequence standard. This edition documents version @value{VERSION}.
-+
-+@insertcopying
- @end ifnottex
-
- @menu
-@@ -426,7 +415,7 @@
- kernel.
-
- If bit 16 in the @samp{flags} word is set, then the fields at offsets
--8-24 in the Multiboot header are valid, and the boot loader should use
-+12-28 in the Multiboot header are valid, and the boot loader should use
- them instead of the fields in the actual executable header to calculate
- where to load the OS image. This information does not need to be
- provided if the kernel image is in @sc{elf} format, but it @emph{must}
-@@ -677,7 +666,7 @@
- @example
- @group
- +-------+-------+-------+-------+
--| drive | part1 | part2 | part3 |
-+| part3 | part2 | part1 | drive |
- +-------+-------+-------+-------+
- @end group
- @end example
-@@ -1197,6 +1186,17 @@
- @item
- The maintainer changes to the GNU GRUB maintainer team
- @email{bug-grub@@gnu.org}, from Bryan Ford and Erich Stefan Boleyn.
-+
-+@item
-+The byte order of the @samp{boot_device} in Multiboot information is
-+reversed. This was a mistake.
-+
-+@item
-+The offset of the address fields were wrong.
-+
-+@item
-+The format is adapted to a newer Texinfo, and the version number is
-+specified more explicitly in the title.
- @end itemize
-
- @item 0.6
-diff -Nur grub-0.97/grub/asmstub.c grub-0.97-patched/grub/asmstub.c
---- grub-0.97/grub/asmstub.c 2005-02-16 21:45:14.000000000 +0100
-+++ grub-0.97-patched/grub/asmstub.c 2012-11-11 17:07:12.719729342 +0100
-@@ -42,6 +42,7 @@
- #include <sys/time.h>
- #include <termios.h>
- #include <signal.h>
-+#include <sys/mman.h>
-
- #ifdef __linux__
- # include <sys/ioctl.h> /* ioctl */
-@@ -55,6 +56,10 @@
- # endif /* ! BLKFLSBUF */
- #endif /* __linux__ */
-
-+#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
-+# include <sys/sysctl.h>
-+#endif
-+
- /* We want to prevent any circularararity in our stubs, as well as
- libc name clashes. */
- #define WITHOUT_LIBC_STUBS 1
-@@ -79,7 +84,7 @@
- struct apm_info apm_bios_info;
-
- /* Emulation requirements. */
--char *grub_scratch_mem = 0;
-+void *grub_scratch_mem = 0;
-
- struct geometry *disks = 0;
-
-@@ -103,14 +108,62 @@
- static unsigned int serial_speed;
- #endif /* SIMULATE_SLOWNESS_OF_SERIAL */
-
-+/* This allocates page-aligned storage of the specified size, which must be
-+ * a multiple of the page size as determined by calling sysconf(_SC_PAGESIZE)
-+ */
-+#ifdef __linux__
-+static void *
-+grub_mmap_alloc(size_t len)
-+{
-+ int mmap_flags = MAP_ANONYMOUS|MAP_PRIVATE;
-+
-+#ifdef MAP_32BIT
-+ mmap_flags |= MAP_32BIT;
-+#endif
-+ /* Mark the simulated stack executable, as GCC uses stack trampolines
-+ * to implement nested functions. */
-+ return mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, mmap_flags, -1, 0);
-+}
-+#else /* !defined(__linux__) */
-+static void *
-+grub_mmap_alloc(size_t len)
-+{
-+ int fd = 0, offset = 0, ret = 0;
-+ void *pa = MAP_FAILED;
-+ char template[] = "/tmp/grub_mmap_alloc_XXXXXX";
-+ int e;
-+
-+ fd = mkstemp(template);
-+ if (fd < 0)
-+ return pa;
-+
-+ unlink(template);
-+
-+ ret = ftruncate(fd, len);
-+ if (ret < 0)
-+ return pa;
-+
-+ /* Mark the simulated stack executable, as GCC uses stack trampolines
-+ * to implement nested functions. */
-+ pa = mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC,
-+ MAP_PRIVATE, fd, offset);
-+
-+ e = errno;
-+ close(fd);
-+ errno = e;
-+ return pa;
-+}
-+#endif /* defined(__linux__) */
-+
- /* The main entry point into this mess. */
- int
- grub_stage2 (void)
- {
- /* These need to be static, because they survive our stack transitions. */
- static int status = 0;
-- static char *realstack;
-- char *scratch, *simstack;
-+ static void *realstack;
-+ void *simstack_alloc_base, *simstack;
-+ size_t simstack_size, page_size;
- int i;
-
- auto void doit (void);
-@@ -142,9 +195,35 @@
- }
-
- assert (grub_scratch_mem == 0);
-- scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
-- assert (scratch);
-- grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
-+
-+ /* Allocate enough pages for 0x100000 + EXTENDED_SIZE + 15, and
-+ * make sure the memory is aligned to a multiple of the system's
-+ * page size */
-+ page_size = sysconf (_SC_PAGESIZE);
-+ simstack_size = ( 0x100000 + EXTENDED_MEMSIZE + 15);
-+ if (simstack_size % page_size)
-+ {
-+ /* If we're not on a page_size boundary, round up to the next one */
-+ simstack_size &= ~(page_size-1);
-+ simstack_size += page_size;
-+ }
-+
-+ /* Add one for a PROT_NONE boundary page at each end. */
-+ simstack_size += 2 * page_size;
-+
-+ simstack_alloc_base = grub_mmap_alloc(simstack_size);
-+ assert (simstack_alloc_base != MAP_FAILED);
-+
-+ /* mark pages above and below our simstack area as innaccessable.
-+ * If the implementation we're using doesn't support that, then the
-+ * new protection modes are undefined. It's safe to just ignore
-+ * them, though. It'd be nice if we knew that we'd get a SEGV for
-+ * touching the area, but that's all. it'd be nice to have. */
-+ mprotect (simstack_alloc_base, page_size, PROT_NONE);
-+ mprotect ((void *)((unsigned long)simstack_alloc_base +
-+ simstack_size - page_size), page_size, PROT_NONE);
-+
-+ grub_scratch_mem = (void *)((unsigned long)simstack_alloc_base + page_size);
-
- /* FIXME: simulate the memory holes using mprot, if available. */
-
-@@ -217,7 +296,7 @@
- device_map = 0;
- free (disks);
- disks = 0;
-- free (scratch);
-+ munmap(simstack_alloc_base, simstack_size);
- grub_scratch_mem = 0;
-
- if (serial_device)
-@@ -777,7 +856,39 @@
-
- /* Open read/write, or read-only if that failed. */
- if (! read_only)
-- disks[drive].flags = open (devname, O_RDWR);
-+ {
-+/* By default, kernel of FreeBSD does not allow overwriting MBR */
-+#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
-+#define GEOM_SYSCTL "kern.geom.debugflags"
-+ int old_flags, flags;
-+ size_t sizeof_int = sizeof (int);
-+
-+ if (sysctlbyname (GEOM_SYSCTL, &old_flags, &sizeof_int, NULL, 0) != 0)
-+ grub_printf ("failed to get " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
-+
-+ if ((old_flags & 0x10) == 0)
-+ {
-+ /* "allow foot shooting", see geom(4) */
-+ flags = old_flags | 0x10;
-+
-+ if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &flags, sizeof (int)) != 0)
-+ {
-+ flags = old_flags;
-+ grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
-+ }
-+ }
-+ else
-+ flags = old_flags;
-+#endif
-+ disks[drive].flags = open (devname, O_RDWR);
-+#if defined(__FreeBSD_kernel__) || defined(__FreeBSD__)
-+ if (flags != old_flags)
-+ {
-+ if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &old_flags, sizeof (int)) != 0)
-+ grub_printf ("failed to set " GEOM_SYSCTL "sysctl: %s\n", strerror (errno));
-+ }
-+#endif
-+ }
-
- if (disks[drive].flags == -1)
- {
-@@ -926,7 +1037,7 @@
-
- int
- biosdisk (int subfunc, int drive, struct geometry *geometry,
-- int sector, int nsec, int segment)
-+ unsigned int sector, int nsec, int segment)
- {
- char *buf;
- int fd = geometry->flags;
-diff -Nur grub-0.97/grub/asmstub.c.orig grub-0.97-patched/grub/asmstub.c.orig
---- grub-0.97/grub/asmstub.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/grub/asmstub.c.orig 2005-02-16 21:45:14.000000000 +0100
-@@ -0,0 +1,1275 @@
-+/* asmstub.c - a version of shared_src/asm.S that works under Unix */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+/* Try to use glibc's transparant LFS support. */
-+#define _LARGEFILE_SOURCE 1
-+/* lseek becomes synonymous with lseek64. */
-+#define _FILE_OFFSET_BITS 64
-+
-+/* Simulator entry point. */
-+int grub_stage2 (void);
-+
-+#include <stdlib.h>
-+#include <string.h>
-+#include <ctype.h>
-+#include <assert.h>
-+#include <stdio.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
-+#include <fcntl.h>
-+#include <time.h>
-+#include <errno.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <setjmp.h>
-+#include <sys/time.h>
-+#include <termios.h>
-+#include <signal.h>
-+
-+#ifdef __linux__
-+# include <sys/ioctl.h> /* ioctl */
-+# if !defined(__GLIBC__) || \
-+ ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
-+/* Maybe libc doesn't have large file support. */
-+# include <linux/unistd.h> /* _llseek */
-+# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
-+# ifndef BLKFLSBUF
-+# define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */
-+# endif /* ! BLKFLSBUF */
-+#endif /* __linux__ */
-+
-+/* We want to prevent any circularararity in our stubs, as well as
-+ libc name clashes. */
-+#define WITHOUT_LIBC_STUBS 1
-+#include <shared.h>
-+#include <device.h>
-+#include <serial.h>
-+#include <term.h>
-+
-+/* Simulated memory sizes. */
-+#define EXTENDED_MEMSIZE (3 * 1024 * 1024) /* 3MB */
-+#define CONVENTIONAL_MEMSIZE (640 * 1024) /* 640kB */
-+
-+unsigned long install_partition = 0x20000;
-+unsigned long boot_drive = 0;
-+int saved_entryno = 0;
-+char version_string[] = VERSION;
-+char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */
-+unsigned long linux_text_len = 0;
-+char *linux_data_tmp_addr = 0;
-+char *linux_data_real_addr = 0;
-+unsigned short io_map[IO_MAP_SIZE];
-+struct apm_info apm_bios_info;
-+
-+/* Emulation requirements. */
-+char *grub_scratch_mem = 0;
-+
-+struct geometry *disks = 0;
-+
-+/* The map between BIOS drives and UNIX device file names. */
-+char **device_map = 0;
-+
-+/* The jump buffer for exiting correctly. */
-+static jmp_buf env_for_exit;
-+
-+/* The current color for console. */
-+int console_current_color = A_NORMAL;
-+
-+/* The file descriptor for a serial device. */
-+static int serial_fd = -1;
-+
-+/* The file name of a serial device. */
-+static char *serial_device = 0;
-+
-+#ifdef SIMULATE_SLOWNESS_OF_SERIAL
-+/* The speed of a serial device. */
-+static unsigned int serial_speed;
-+#endif /* SIMULATE_SLOWNESS_OF_SERIAL */
-+
-+/* The main entry point into this mess. */
-+int
-+grub_stage2 (void)
-+{
-+ /* These need to be static, because they survive our stack transitions. */
-+ static int status = 0;
-+ static char *realstack;
-+ char *scratch, *simstack;
-+ int i;
-+
-+ auto void doit (void);
-+
-+ /* We need a nested function so that we get a clean stack frame,
-+ regardless of how the code is optimized. */
-+ void doit (void)
-+ {
-+ /* Make sure our stack lives in the simulated memory area. */
-+ asm volatile ("movl %%esp, %0\n\tmovl %1, %%esp\n"
-+ : "=&r" (realstack) : "r" (simstack));
-+
-+ /* Do a setjmp here for the stop command. */
-+ if (! setjmp (env_for_exit))
-+ {
-+ /* Actually enter the generic stage2 code. */
-+ status = 0;
-+ init_bios_info ();
-+ }
-+ else
-+ {
-+ /* If ERRNUM is non-zero, then set STATUS to non-zero. */
-+ if (errnum)
-+ status = 1;
-+ }
-+
-+ /* Replace our stack before we use any local variables. */
-+ asm volatile ("movl %0, %%esp\n" : : "r" (realstack));
-+ }
-+
-+ assert (grub_scratch_mem == 0);
-+ scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15);
-+ assert (scratch);
-+ grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4);
-+
-+ /* FIXME: simulate the memory holes using mprot, if available. */
-+
-+ assert (disks == 0);
-+ disks = malloc (NUM_DISKS * sizeof (*disks));
-+ assert (disks);
-+ /* Initialize DISKS. */
-+ for (i = 0; i < NUM_DISKS; i++)
-+ disks[i].flags = -1;
-+
-+ if (! init_device_map (&device_map, device_map_file, floppy_disks))
-+ return 1;
-+
-+ /* Check some invariants. */
-+ assert ((SCRATCHSEG << 4) == SCRATCHADDR);
-+ assert ((BUFFERSEG << 4) == BUFFERADDR);
-+ assert (BUFFERADDR + BUFFERLEN == SCRATCHADDR);
-+ assert (FSYS_BUF % 16 == 0);
-+ assert (FSYS_BUF + FSYS_BUFLEN == BUFFERADDR);
-+
-+#ifdef HAVE_LIBCURSES
-+ /* Get into char-at-a-time mode. */
-+ if (use_curses)
-+ {
-+ initscr ();
-+ cbreak ();
-+ noecho ();
-+ nonl ();
-+ scrollok (stdscr, TRUE);
-+ keypad (stdscr, TRUE);
-+ wtimeout (stdscr, 100);
-+ signal (SIGWINCH, SIG_IGN);
-+ }
-+#endif
-+
-+ /* Make sure that actual writing is done. */
-+ sync ();
-+
-+ /* Set our stack, and go for it. */
-+ simstack = (char *) PROTSTACKINIT;
-+ doit ();
-+
-+ /* I don't know if this is necessary really. */
-+ sync ();
-+
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ endwin ();
-+#endif
-+
-+ /* Close off the file descriptors we used. */
-+ for (i = 0; i < NUM_DISKS; i ++)
-+ if (disks[i].flags != -1)
-+ {
-+#ifdef __linux__
-+ /* In Linux, invalidate the buffer cache. In other OSes, reboot
-+ is one of the solutions... */
-+ ioctl (disks[i].flags, BLKFLSBUF, 0);
-+#else
-+# warning "In your operating system, the buffer cache will not be flushed."
-+#endif
-+ close (disks[i].flags);
-+ }
-+
-+ if (serial_fd >= 0)
-+ close (serial_fd);
-+
-+ /* Release memory. */
-+ restore_device_map (device_map);
-+ device_map = 0;
-+ free (disks);
-+ disks = 0;
-+ free (scratch);
-+ grub_scratch_mem = 0;
-+
-+ if (serial_device)
-+ free (serial_device);
-+ serial_device = 0;
-+
-+ /* Ahh... at last we're ready to return to caller. */
-+ return status;
-+}
-+
-+/* Assign DRIVE to a device name DEVICE. */
-+void
-+assign_device_name (int drive, const char *device)
-+{
-+ /* If DRIVE is already assigned, free it. */
-+ if (device_map[drive])
-+ free (device_map[drive]);
-+
-+ /* If the old one is already opened, close it. */
-+ if (disks[drive].flags != -1)
-+ {
-+ close (disks[drive].flags);
-+ disks[drive].flags = -1;
-+ }
-+
-+ /* Assign DRIVE to DEVICE. */
-+ if (! device)
-+ device_map[drive] = 0;
-+ else
-+ device_map[drive] = strdup (device);
-+}
-+
-+void
-+stop (void)
-+{
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ endwin ();
-+#endif
-+
-+ /* Jump to doit. */
-+ longjmp (env_for_exit, 1);
-+}
-+
-+void
-+grub_reboot (void)
-+{
-+ stop ();
-+}
-+
-+void
-+grub_halt (int no_apm)
-+{
-+ stop ();
-+}
-+
-+/* calls for direct boot-loader chaining */
-+void
-+chain_stage1 (unsigned long segment, unsigned long offset,
-+ unsigned long part_table_addr)
-+{
-+ stop ();
-+}
-+
-+
-+void
-+chain_stage2 (unsigned long segment, unsigned long offset, int second_sector)
-+{
-+ stop ();
-+}
-+
-+
-+/* do some funky stuff, then boot linux */
-+void
-+linux_boot (void)
-+{
-+ stop ();
-+}
-+
-+
-+/* For bzImage kernels. */
-+void
-+big_linux_boot (void)
-+{
-+ stop ();
-+}
-+
-+
-+/* booting a multiboot executable */
-+void
-+multi_boot (int start, int mb_info)
-+{
-+ stop ();
-+}
-+
-+/* sets it to linear or wired A20 operation */
-+void
-+gateA20 (int linear)
-+{
-+ /* Nothing to do in the simulator. */
-+}
-+
-+/* Set up the int15 handler. */
-+void
-+set_int15_handler (void)
-+{
-+ /* Nothing to do in the simulator. */
-+}
-+
-+/* Restore the original int15 handler. */
-+void
-+unset_int15_handler (void)
-+{
-+ /* Nothing to do in the simulator. */
-+}
-+
-+/* The key map. */
-+unsigned short bios_key_map[KEY_MAP_SIZE + 1];
-+unsigned short ascii_key_map[KEY_MAP_SIZE + 1];
-+
-+/* Copy MAP to the drive map and set up the int13 handler. */
-+void
-+set_int13_handler (unsigned short *map)
-+{
-+ /* Nothing to do in the simulator. */
-+}
-+
-+int
-+get_code_end (void)
-+{
-+ /* Just return a little area for simulation. */
-+ return BOOTSEC_LOCATION + (60 * 1024);
-+}
-+
-+
-+/* memory probe routines */
-+int
-+get_memsize (int type)
-+{
-+ if (! type)
-+ return CONVENTIONAL_MEMSIZE >> 10;
-+ else
-+ return EXTENDED_MEMSIZE >> 10;
-+}
-+
-+
-+/* get_eisamemsize() : return packed EISA memory map, lower 16 bits is
-+ * memory between 1M and 16M in 1K parts, upper 16 bits is
-+ * memory above 16M in 64K parts. If error, return -1.
-+ */
-+int
-+get_eisamemsize (void)
-+{
-+ return (EXTENDED_MEMSIZE >> 10);
-+}
-+
-+
-+#define MMAR_DESC_TYPE_AVAILABLE 1 /* available to OS */
-+#define MMAR_DESC_TYPE_RESERVED 2 /* not available */
-+#define MMAR_DESC_TYPE_ACPI_RECLAIM 3 /* usable by OS after reading ACPI */
-+#define MMAR_DESC_TYPE_ACPI_NVS 4 /* required to save between NVS sessions */
-+
-+#define MMAR_DESC_LENGTH 20
-+
-+/* Fetch the next entry in the memory map and return the continuation
-+ value. DESC is a pointer to the descriptor buffer, and CONT is the
-+ previous continuation value (0 to get the first entry in the
-+ map). */
-+int
-+get_mmap_entry (struct mmar_desc *desc, int cont)
-+{
-+ /* Record the memory map statically. */
-+ static struct mmar_desc desc_table[] =
-+ {
-+ /* The conventional memory. */
-+ {
-+ MMAR_DESC_LENGTH,
-+ 0,
-+ CONVENTIONAL_MEMSIZE,
-+ MMAR_DESC_TYPE_AVAILABLE
-+ },
-+ /* BIOS RAM and ROM (such as video memory). */
-+ {
-+ MMAR_DESC_LENGTH,
-+ CONVENTIONAL_MEMSIZE,
-+ 0x100000 - CONVENTIONAL_MEMSIZE,
-+ MMAR_DESC_TYPE_RESERVED
-+ },
-+ /* The extended memory. */
-+ {
-+ MMAR_DESC_LENGTH,
-+ 0x100000,
-+ EXTENDED_MEMSIZE,
-+ MMAR_DESC_TYPE_AVAILABLE
-+ }
-+ };
-+
-+ int num = sizeof (desc_table) / sizeof (*desc_table);
-+
-+ if (cont < 0 || cont >= num)
-+ {
-+ /* Should not happen. */
-+ desc->desc_len = 0;
-+ }
-+ else
-+ {
-+ /* Copy the entry. */
-+ *desc = desc_table[cont++];
-+
-+ /* If the next entry exists, return the index. */
-+ if (cont < num)
-+ return cont;
-+ }
-+
-+ return 0;
-+}
-+
-+/* Track the int13 handler. */
-+void
-+track_int13 (int drive)
-+{
-+ /* Nothing to do in the simulator. */
-+}
-+
-+/* Get the ROM configuration table. */
-+unsigned long
-+get_rom_config_table (void)
-+{
-+ return 0;
-+}
-+
-+/* Get APM BIOS information. */
-+void
-+get_apm_info (void)
-+{
-+ /* Nothing to do in the simulator. */
-+}
-+
-+/* Get VBE controller information. */
-+int
-+get_vbe_controller_info (struct vbe_controller *controller)
-+{
-+ /* Always fails. */
-+ return 0;
-+}
-+
-+/* Get VBE mode information. */
-+int
-+get_vbe_mode_info (int mode_number, struct vbe_mode *mode)
-+{
-+ /* Always fails. */
-+ return 0;
-+}
-+
-+/* Set VBE mode. */
-+int
-+set_vbe_mode (int mode_number)
-+{
-+ /* Always fails. */
-+ return 0;
-+}
-+
-+/* low-level timing info */
-+int
-+getrtsecs (void)
-+{
-+ /* FIXME: exact value is not important, so just return time_t for now. */
-+ return time (0);
-+}
-+
-+int
-+currticks (void)
-+{
-+ struct timeval tv;
-+ long csecs;
-+ int ticks_per_csec, ticks_per_usec;
-+
-+ /* Note: 18.2 ticks/sec. */
-+
-+ /* Get current time. */
-+ gettimeofday (&tv, 0);
-+
-+ /* Compute centiseconds. */
-+ csecs = tv.tv_sec / 10;
-+
-+ /* Ticks per centisecond. */
-+ ticks_per_csec = csecs * 182;
-+
-+ /* Ticks per microsecond. */
-+ ticks_per_usec = (((tv.tv_sec - csecs * 10) * 1000000 + tv.tv_usec)
-+ * 182 / 10000000);
-+
-+ /* Sum them. */
-+ return ticks_per_csec + ticks_per_usec;
-+}
-+
-+/* displays an ASCII character. IBM displays will translate some
-+ characters to special graphical ones */
-+void
-+console_putchar (int c)
-+{
-+ /* Curses doesn't have VGA fonts. */
-+ switch (c)
-+ {
-+ case DISP_UL:
-+ c = ACS_ULCORNER;
-+ break;
-+ case DISP_UR:
-+ c = ACS_URCORNER;
-+ break;
-+ case DISP_LL:
-+ c = ACS_LLCORNER;
-+ break;
-+ case DISP_LR:
-+ c = ACS_LRCORNER;
-+ break;
-+ case DISP_HORIZ:
-+ c = ACS_HLINE;
-+ break;
-+ case DISP_VERT:
-+ c = ACS_VLINE;
-+ break;
-+ case DISP_LEFT:
-+ c = ACS_LARROW;
-+ break;
-+ case DISP_RIGHT:
-+ c = ACS_RARROW;
-+ break;
-+ case DISP_UP:
-+ c = ACS_UARROW;
-+ break;
-+ case DISP_DOWN:
-+ c = ACS_DARROW;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ {
-+ /* In ncurses, a newline is treated badly, so we emulate it in our
-+ own way. */
-+ if (c == '\n')
-+ {
-+ int x, y;
-+
-+ getyx (stdscr, y, x);
-+ if (y + 1 == LINES)
-+ scroll (stdscr);
-+ else
-+ move (y + 1, x);
-+ }
-+ else if (isprint (c))
-+ {
-+ int x, y;
-+
-+ getyx (stdscr, y, x);
-+ if (x + 1 == COLS)
-+ {
-+ console_putchar ('\r');
-+ console_putchar ('\n');
-+ }
-+ addch (c | console_current_color);
-+ }
-+ else
-+ {
-+ addch (c);
-+ }
-+
-+#ifdef REFRESH_IMMEDIATELY
-+ refresh ();
-+#endif
-+ }
-+ else
-+#endif
-+ {
-+ /* CR is not used in Unix. */
-+ if (c != '\r')
-+ putchar (c);
-+ }
-+}
-+
-+/* The store for ungetch simulation. This is necessary, because
-+ ncurses-1.9.9g is still used in the world and its ungetch is
-+ completely broken. */
-+#ifdef HAVE_LIBCURSES
-+static int save_char = ERR;
-+#endif
-+
-+static int
-+console_translate_key (int c)
-+{
-+ switch (c)
-+ {
-+ case KEY_LEFT:
-+ return 2;
-+ case KEY_RIGHT:
-+ return 6;
-+ case KEY_UP:
-+ return 16;
-+ case KEY_DOWN:
-+ return 14;
-+ case KEY_DC:
-+ return 4;
-+ case KEY_BACKSPACE:
-+ return 8;
-+ case KEY_HOME:
-+ return 1;
-+ case KEY_END:
-+ return 5;
-+ case KEY_PPAGE:
-+ return 7;
-+ case KEY_NPAGE:
-+ return 3;
-+ default:
-+ break;
-+ }
-+
-+ return c;
-+}
-+
-+/* like 'getkey', but doesn't wait, returns -1 if nothing available */
-+int
-+console_checkkey (void)
-+{
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ {
-+ int c;
-+
-+ /* Check for SAVE_CHAR. This should not be true, because this
-+ means checkkey is called twice continuously. */
-+ if (save_char != ERR)
-+ return save_char;
-+
-+ c = getch ();
-+ /* If C is not ERR, then put it back in the input queue. */
-+ if (c != ERR)
-+ save_char = c;
-+ return console_translate_key (c);
-+ }
-+#endif
-+
-+ /* Just pretend they hit the space bar, then read the real key when
-+ they call getkey. */
-+ return ' ';
-+}
-+
-+/* returns packed BIOS/ASCII code */
-+int
-+console_getkey (void)
-+{
-+ int c;
-+
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ {
-+ /* If checkkey has already got a character, then return it. */
-+ if (save_char != ERR)
-+ {
-+ c = save_char;
-+ save_char = ERR;
-+ return console_translate_key (c);
-+ }
-+
-+ wtimeout (stdscr, -1);
-+ c = getch ();
-+ wtimeout (stdscr, 100);
-+ }
-+ else
-+#endif
-+ c = getchar ();
-+
-+ /* Quit if we get EOF. */
-+ if (c == -1)
-+ stop ();
-+
-+ return console_translate_key (c);
-+}
-+
-+/* returns packed values, LSB+1 is x, LSB is y */
-+int
-+console_getxy (void)
-+{
-+ int y, x;
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ getyx (stdscr, y, x);
-+ else
-+#endif
-+ y = x = 0;
-+ return (x << 8) | (y & 0xff);
-+}
-+
-+void
-+console_gotoxy (int x, int y)
-+{
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ move (y, x);
-+#endif
-+}
-+
-+/* low-level character I/O */
-+void
-+console_cls (void)
-+{
-+#ifdef HAVE_LIBCURSES
-+ if (use_curses)
-+ clear ();
-+#endif
-+}
-+
-+void
-+console_setcolorstate (color_state state)
-+{
-+ console_current_color =
-+ (state == COLOR_STATE_HIGHLIGHT) ? A_REVERSE : A_NORMAL;
-+}
-+
-+void
-+console_setcolor (int normal_color, int highlight_color)
-+{
-+ /* Nothing to do. */
-+}
-+
-+int
-+console_setcursor (int on)
-+{
-+ return 1;
-+}
-+
-+/* Low-level disk I/O. Our stubbed version just returns a file
-+ descriptor, not the actual geometry. */
-+int
-+get_diskinfo (int drive, struct geometry *geometry)
-+{
-+ /* FIXME: this function is truly horrid. We try opening the device,
-+ then severely abuse the GEOMETRY->flags field to pass a file
-+ descriptor to biosdisk. Thank God nobody's looking at this comment,
-+ or my reputation would be ruined. --Gord */
-+
-+ /* See if we have a cached device. */
-+ if (disks[drive].flags == -1)
-+ {
-+ /* The unpartitioned device name: /dev/XdX */
-+ char *devname = device_map[drive];
-+ char buf[512];
-+
-+ if (! devname)
-+ return -1;
-+
-+ if (verbose)
-+ grub_printf ("Attempt to open drive 0x%x (%s)\n",
-+ drive, devname);
-+
-+ /* Open read/write, or read-only if that failed. */
-+ if (! read_only)
-+ disks[drive].flags = open (devname, O_RDWR);
-+
-+ if (disks[drive].flags == -1)
-+ {
-+ if (read_only || errno == EACCES || errno == EROFS || errno == EPERM)
-+ {
-+ disks[drive].flags = open (devname, O_RDONLY);
-+ if (disks[drive].flags == -1)
-+ {
-+ assign_device_name (drive, 0);
-+ return -1;
-+ }
-+ }
-+ else
-+ {
-+ assign_device_name (drive, 0);
-+ return -1;
-+ }
-+ }
-+
-+ /* Attempt to read the first sector. */
-+ if (read (disks[drive].flags, buf, 512) != 512)
-+ {
-+ close (disks[drive].flags);
-+ disks[drive].flags = -1;
-+ assign_device_name (drive, 0);
-+ return -1;
-+ }
-+
-+ if (disks[drive].flags != -1)
-+ get_drive_geometry (&disks[drive], device_map, drive);
-+ }
-+
-+ if (disks[drive].flags == -1)
-+ return -1;
-+
-+#ifdef __linux__
-+ /* In Linux, invalidate the buffer cache, so that left overs
-+ from other program in the cache are flushed and seen by us */
-+ ioctl (disks[drive].flags, BLKFLSBUF, 0);
-+#endif
-+
-+ *geometry = disks[drive];
-+ return 0;
-+}
-+
-+/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
-+ error occurs, otherwise return LEN. */
-+static int
-+nread (int fd, char *buf, size_t len)
-+{
-+ int size = len;
-+
-+ while (len)
-+ {
-+ int ret = read (fd, buf, len);
-+
-+ if (ret <= 0)
-+ {
-+ if (errno == EINTR)
-+ continue;
-+ else
-+ return ret;
-+ }
-+
-+ len -= ret;
-+ buf += ret;
-+ }
-+
-+ return size;
-+}
-+
-+/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
-+ error occurs, otherwise return LEN. */
-+static int
-+nwrite (int fd, char *buf, size_t len)
-+{
-+ int size = len;
-+
-+ while (len)
-+ {
-+ int ret = write (fd, buf, len);
-+
-+ if (ret <= 0)
-+ {
-+ if (errno == EINTR)
-+ continue;
-+ else
-+ return ret;
-+ }
-+
-+ len -= ret;
-+ buf += ret;
-+ }
-+
-+ return size;
-+}
-+
-+/* Dump BUF in the format of hexadecimal numbers. */
-+static void
-+hex_dump (void *buf, size_t size)
-+{
-+ /* FIXME: How to determine which length is readable? */
-+#define MAX_COLUMN 70
-+
-+ /* use unsigned char for numerical computations */
-+ unsigned char *ptr = buf;
-+ /* count the width of the line */
-+ int column = 0;
-+ /* how many bytes written */
-+ int count = 0;
-+
-+ while (size > 0)
-+ {
-+ /* high 4 bits */
-+ int hi = *ptr >> 4;
-+ /* low 4 bits */
-+ int low = *ptr & 0xf;
-+
-+ /* grub_printf does not handle prefix number, such as %2x, so
-+ format the number by hand... */
-+ grub_printf ("%x%x", hi, low);
-+ column += 2;
-+ count++;
-+ ptr++;
-+ size--;
-+
-+ /* Insert space or newline with the interval 4 bytes. */
-+ if (size != 0 && (count % 4) == 0)
-+ {
-+ if (column < MAX_COLUMN)
-+ {
-+ grub_printf (" ");
-+ column++;
-+ }
-+ else
-+ {
-+ grub_printf ("\n");
-+ column = 0;
-+ }
-+ }
-+ }
-+
-+ /* Add a newline at the end for readability. */
-+ grub_printf ("\n");
-+}
-+
-+int
-+biosdisk (int subfunc, int drive, struct geometry *geometry,
-+ int sector, int nsec, int segment)
-+{
-+ char *buf;
-+ int fd = geometry->flags;
-+
-+ /* Get the file pointer from the geometry, and make sure it matches. */
-+ if (fd == -1 || fd != disks[drive].flags)
-+ return BIOSDISK_ERROR_GEOMETRY;
-+
-+ /* Seek to the specified location. */
-+#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 * (loff_t) SECTOR_SIZE;
-+ if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
-+ return -1;
-+ }
-+#else
-+ {
-+ off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
-+
-+ if (lseek (fd, offset, SEEK_SET) != offset)
-+ return -1;
-+ }
-+#endif
-+
-+ buf = (char *) (segment << 4);
-+
-+ switch (subfunc)
-+ {
-+ case BIOSDISK_READ:
-+#ifdef __linux__
-+ if (sector == 0 && nsec > 1)
-+ {
-+ /* Work around a bug in linux's ez remapping. Linux remaps all
-+ 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, SECTOR_SIZE) != SECTOR_SIZE)
-+ return -1;
-+ buf += SECTOR_SIZE;
-+ nsec--;
-+ }
-+#endif
-+ if (nread (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
-+ return -1;
-+ break;
-+
-+ case BIOSDISK_WRITE:
-+ if (verbose)
-+ {
-+ grub_printf ("Write %d sectors starting from %d sector"
-+ " to drive 0x%x (%s)\n",
-+ nsec, sector, drive, device_map[drive]);
-+ hex_dump (buf, nsec * SECTOR_SIZE);
-+ }
-+ if (! read_only)
-+ if (nwrite (fd, buf, nsec * SECTOR_SIZE) != nsec * SECTOR_SIZE)
-+ return -1;
-+ break;
-+
-+ default:
-+ grub_printf ("unknown subfunc %d\n", subfunc);
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+void
-+stop_floppy (void)
-+{
-+ /* NOTUSED */
-+}
-+
-+/* Fetch a key from a serial device. */
-+int
-+serial_hw_fetch (void)
-+{
-+ fd_set fds;
-+ struct timeval to;
-+ char c;
-+
-+ /* Wait only for the serial device. */
-+ FD_ZERO (&fds);
-+ FD_SET (serial_fd, &fds);
-+
-+ to.tv_sec = 0;
-+ to.tv_usec = 0;
-+
-+ if (select (serial_fd + 1, &fds, 0, 0, &to) > 0)
-+ {
-+ if (nread (serial_fd, &c, 1) != 1)
-+ stop ();
-+
-+ return c;
-+ }
-+
-+ return -1;
-+}
-+
-+/* Put a character to a serial device. */
-+void
-+serial_hw_put (int c)
-+{
-+ char ch = (char) c;
-+
-+ if (nwrite (serial_fd, &ch, 1) != 1)
-+ stop ();
-+}
-+
-+void
-+serial_hw_delay (void)
-+{
-+#ifdef SIMULATE_SLOWNESS_OF_SERIAL
-+ struct timeval otv, tv;
-+
-+ gettimeofday (&otv, 0);
-+
-+ while (1)
-+ {
-+ long delta;
-+
-+ gettimeofday (&tv, 0);
-+ delta = tv.tv_usec - otv.tv_usec;
-+ if (delta < 0)
-+ delta += 1000000;
-+
-+ if (delta >= 1000000 / (serial_speed >> 3))
-+ break;
-+ }
-+#endif /* SIMULATE_SLOWNESS_OF_SERIAL */
-+}
-+
-+static speed_t
-+get_termios_speed (int speed)
-+{
-+ switch (speed)
-+ {
-+ case 2400: return B2400;
-+ case 4800: return B4800;
-+ case 9600: return B9600;
-+ case 19200: return B19200;
-+ case 38400: return B38400;
-+#ifdef B57600
-+ case 57600: return B57600;
-+#endif
-+#ifdef B115200
-+ case 115200: return B115200;
-+#endif
-+ }
-+
-+ return B0;
-+}
-+
-+/* Get the port number of the unit UNIT. In the grub shell, this doesn't
-+ make sense. */
-+unsigned short
-+serial_hw_get_port (int unit)
-+{
-+ return 0;
-+}
-+
-+/* Initialize a serial device. In the grub shell, PORT is unused. */
-+int
-+serial_hw_init (unsigned short port, unsigned int speed,
-+ int word_len, int parity, int stop_bit_len)
-+{
-+ struct termios termios;
-+ speed_t termios_speed;
-+ int i;
-+
-+ /* Check if the file name is specified. */
-+ if (! serial_device)
-+ return 0;
-+
-+ /* If a serial device is already opened, close it first. */
-+ if (serial_fd >= 0)
-+ close (serial_fd);
-+
-+ /* Open the device file. */
-+ serial_fd = open (serial_device,
-+ O_RDWR | O_NOCTTY
-+#if defined(O_SYNC)
-+ /* O_SYNC is used in Linux (and some others?). */
-+ | O_SYNC
-+#elif defined(O_FSYNC)
-+ /* O_FSYNC is used in FreeBSD. */
-+ | O_FSYNC
-+#endif
-+ );
-+ if (serial_fd < 0)
-+ return 0;
-+
-+ /* Get the termios parameters. */
-+ if (tcgetattr (serial_fd, &termios))
-+ goto fail;
-+
-+ /* Raw mode. */
-+ cfmakeraw (&termios);
-+
-+ /* Set the speed. */
-+ termios_speed = get_termios_speed (speed);
-+ if (termios_speed == B0)
-+ goto fail;
-+
-+ cfsetispeed (&termios, termios_speed);
-+ cfsetospeed (&termios, termios_speed);
-+
-+ /* Set the word length. */
-+ termios.c_cflag &= ~CSIZE;
-+ switch (word_len)
-+ {
-+ case UART_5BITS_WORD:
-+ termios.c_cflag |= CS5;
-+ break;
-+ case UART_6BITS_WORD:
-+ termios.c_cflag |= CS6;
-+ break;
-+ case UART_7BITS_WORD:
-+ termios.c_cflag |= CS7;
-+ break;
-+ case UART_8BITS_WORD:
-+ termios.c_cflag |= CS8;
-+ break;
-+ default:
-+ goto fail;
-+ }
-+
-+ /* Set the parity. */
-+ switch (parity)
-+ {
-+ case UART_NO_PARITY:
-+ termios.c_cflag &= ~PARENB;
-+ break;
-+ case UART_ODD_PARITY:
-+ termios.c_cflag |= PARENB;
-+ termios.c_cflag |= PARODD;
-+ break;
-+ case UART_EVEN_PARITY:
-+ termios.c_cflag |= PARENB;
-+ termios.c_cflag &= ~PARODD;
-+ break;
-+ default:
-+ goto fail;
-+ }
-+
-+ /* Set the length of stop bit. */
-+ switch (stop_bit_len)
-+ {
-+ case UART_1_STOP_BIT:
-+ termios.c_cflag &= ~CSTOPB;
-+ break;
-+ case UART_2_STOP_BITS:
-+ termios.c_cflag |= CSTOPB;
-+ break;
-+ default:
-+ goto fail;
-+ }
-+
-+ /* Set the parameters. */
-+ if (tcsetattr (serial_fd, TCSANOW, &termios))
-+ goto fail;
-+
-+#ifdef SIMULATE_SLOWNESS_OF_SERIAL
-+ serial_speed = speed;
-+#endif /* SIMUATE_SLOWNESS_OF_SERIAL */
-+
-+ /* Get rid of the flag TERM_NEED_INIT from the serial terminal. */
-+ for (i = 0; term_table[i].name; i++)
-+ {
-+ if (strcmp (term_table[i].name, "serial") == 0)
-+ {
-+ term_table[i].flags &= ~(TERM_NEED_INIT);
-+ break;
-+ }
-+ }
-+
-+ return 1;
-+
-+ fail:
-+ close (serial_fd);
-+ serial_fd = -1;
-+ return 0;
-+}
-+
-+/* Set the file name of a serial device (or a pty device). This is a
-+ function specific to the grub shell. */
-+void
-+serial_set_device (const char *device)
-+{
-+ if (serial_device)
-+ free (serial_device);
-+
-+ serial_device = strdup (device);
-+}
-+
-+/* There is no difference between console and hercules in the grub shell. */
-+void
-+hercules_putchar (int c)
-+{
-+ console_putchar (c);
-+}
-+
-+int
-+hercules_getxy (void)
-+{
-+ return console_getxy ();
-+}
-+
-+void
-+hercules_gotoxy (int x, int y)
-+{
-+ console_gotoxy (x, y);
-+}
-+
-+void
-+hercules_cls (void)
-+{
-+ console_cls ();
-+}
-+
-+void
-+hercules_setcolorstate (color_state state)
-+{
-+ console_setcolorstate (state);
-+}
-+
-+void
-+hercules_setcolor (int normal_color, int highlight_color)
-+{
-+ console_setcolor (normal_color, highlight_color);
-+}
-+
-+int
-+hercules_setcursor (int on)
-+{
-+ return 1;
-+}
-diff -Nur grub-0.97/grub/main.c grub-0.97-patched/grub/main.c
---- grub-0.97/grub/main.c 2003-07-09 13:45:36.000000000 +0200
-+++ grub-0.97-patched/grub/main.c 2012-11-11 17:07:12.720729374 +0100
-@@ -32,6 +32,7 @@
- #define WITHOUT_LIBC_STUBS 1
- #include <shared.h>
- #include <term.h>
-+#include <device.h>
-
- char *program_name = 0;
- int use_config_file = 1;
-@@ -140,10 +141,7 @@
- program_name = argv[0];
- default_boot_drive = boot_drive;
- default_install_partition = install_partition;
-- if (config_file)
-- default_config_file = config_file;
-- else
-- default_config_file = "NONE";
-+ default_config_file = config_file;
-
- /* Parse command-line options. */
- do
-@@ -192,6 +190,12 @@
- perror ("strtoul");
- exit (1);
- }
-+ if (boot_drive >= NUM_DISKS)
-+ {
-+ fprintf (stderr, "boot_drive should be from 0 to %d\n",
-+ NUM_DISKS - 1);
-+ exit (1);
-+ }
- break;
-
- case OPT_NO_CONFIG_FILE:
-diff -Nur grub-0.97/grub/main.c.orig grub-0.97-patched/grub/main.c.orig
---- grub-0.97/grub/main.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/grub/main.c.orig 2003-07-09 13:45:36.000000000 +0200
-@@ -0,0 +1,265 @@
-+/* main.c - experimental GRUB stage2 that runs under Unix */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 1999,2000,2001,2002 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+/* Simulator entry point. */
-+int grub_stage2 (void);
-+
-+#include <stdio.h>
-+#include <getopt.h>
-+#include <unistd.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <limits.h>
-+#include <setjmp.h>
-+
-+#define WITHOUT_LIBC_STUBS 1
-+#include <shared.h>
-+#include <term.h>
-+
-+char *program_name = 0;
-+int use_config_file = 1;
-+int use_preset_menu = 0;
-+#ifdef HAVE_LIBCURSES
-+int use_curses = 1;
-+#else
-+int use_curses = 0;
-+#endif
-+int verbose = 0;
-+int read_only = 0;
-+int floppy_disks = 1;
-+char *device_map_file = 0;
-+static int default_boot_drive;
-+static int default_install_partition;
-+static char *default_config_file;
-+
-+#define OPT_HELP -2
-+#define OPT_VERSION -3
-+#define OPT_HOLD -4
-+#define OPT_CONFIG_FILE -5
-+#define OPT_INSTALL_PARTITION -6
-+#define OPT_BOOT_DRIVE -7
-+#define OPT_NO_CONFIG_FILE -8
-+#define OPT_NO_CURSES -9
-+#define OPT_BATCH -10
-+#define OPT_VERBOSE -11
-+#define OPT_READ_ONLY -12
-+#define OPT_PROBE_SECOND_FLOPPY -13
-+#define OPT_NO_FLOPPY -14
-+#define OPT_DEVICE_MAP -15
-+#define OPT_PRESET_MENU -16
-+#define OPT_NO_PAGER -17
-+#define OPTSTRING ""
-+
-+static struct option longopts[] =
-+{
-+ {"batch", no_argument, 0, OPT_BATCH},
-+ {"boot-drive", required_argument, 0, OPT_BOOT_DRIVE},
-+ {"config-file", required_argument, 0, OPT_CONFIG_FILE},
-+ {"device-map", required_argument, 0, OPT_DEVICE_MAP},
-+ {"help", no_argument, 0, OPT_HELP},
-+ {"hold", optional_argument, 0, OPT_HOLD},
-+ {"install-partition", required_argument, 0, OPT_INSTALL_PARTITION},
-+ {"no-config-file", no_argument, 0, OPT_NO_CONFIG_FILE},
-+ {"no-curses", no_argument, 0, OPT_NO_CURSES},
-+ {"no-floppy", no_argument, 0, OPT_NO_FLOPPY},
-+ {"no-pager", no_argument, 0, OPT_NO_PAGER},
-+ {"preset-menu", no_argument, 0, OPT_PRESET_MENU},
-+ {"probe-second-floppy", no_argument, 0, OPT_PROBE_SECOND_FLOPPY},
-+ {"read-only", no_argument, 0, OPT_READ_ONLY},
-+ {"verbose", no_argument, 0, OPT_VERBOSE},
-+ {"version", no_argument, 0, OPT_VERSION},
-+ {0},
-+};
-+
-+
-+static void
-+usage (int status)
-+{
-+ if (status)
-+ fprintf (stderr, "Try ``grub --help'' for more information.\n");
-+ else
-+ printf ("\
-+Usage: grub [OPTION]...\n\
-+\n\
-+Enter the GRand Unified Bootloader command shell.\n\
-+\n\
-+ --batch turn on batch mode for non-interactive use\n\
-+ --boot-drive=DRIVE specify stage2 boot_drive [default=0x%x]\n\
-+ --config-file=FILE specify stage2 config_file [default=%s]\n\
-+ --device-map=FILE use the device map file FILE\n\
-+ --help display this message and exit\n\
-+ --hold wait until a debugger will attach\n\
-+ --install-partition=PAR specify stage2 install_partition [default=0x%x]\n\
-+ --no-config-file do not use the config file\n\
-+ --no-curses do not use curses\n\
-+ --no-floppy do not probe any floppy drive\n\
-+ --no-pager do not use internal pager\n\
-+ --preset-menu use the preset menu\n\
-+ --probe-second-floppy probe the second floppy drive\n\
-+ --read-only do not write anything to devices\n\
-+ --verbose print verbose messages\n\
-+ --version print version information and exit\n\
-+\n\
-+Report bugs to <bug-grub@gnu.org>.\n\
-+",
-+ default_boot_drive, default_config_file,
-+ default_install_partition);
-+
-+ exit (status);
-+}
-+
-+
-+int
-+main (int argc, char **argv)
-+{
-+ int c;
-+ int hold = 0;
-+
-+ /* First of all, call sync so that all in-core data is scheduled to be
-+ actually written to disks. This is very important because GRUB does
-+ not use ordinary stdio interface but raw devices. */
-+ sync ();
-+
-+ program_name = argv[0];
-+ default_boot_drive = boot_drive;
-+ default_install_partition = install_partition;
-+ if (config_file)
-+ default_config_file = config_file;
-+ else
-+ default_config_file = "NONE";
-+
-+ /* Parse command-line options. */
-+ do
-+ {
-+ c = getopt_long (argc, argv, OPTSTRING, longopts, 0);
-+ switch (c)
-+ {
-+ case EOF:
-+ /* Fall through the bottom of the loop. */
-+ break;
-+
-+ case OPT_HELP:
-+ usage (0);
-+ break;
-+
-+ case OPT_VERSION:
-+ printf ("grub (GNU GRUB " VERSION ")\n");
-+ exit (0);
-+ break;
-+
-+ case OPT_HOLD:
-+ if (! optarg)
-+ hold = -1;
-+ else
-+ hold = atoi (optarg);
-+ break;
-+
-+ case OPT_CONFIG_FILE:
-+ strncpy (config_file, optarg, 127); /* FIXME: arbitrary */
-+ config_file[127] = '\0';
-+ break;
-+
-+ case OPT_INSTALL_PARTITION:
-+ install_partition = strtoul (optarg, 0, 0);
-+ if (install_partition == ULONG_MAX)
-+ {
-+ perror ("strtoul");
-+ exit (1);
-+ }
-+ break;
-+
-+ case OPT_BOOT_DRIVE:
-+ boot_drive = strtoul (optarg, 0, 0);
-+ if (boot_drive == ULONG_MAX)
-+ {
-+ perror ("strtoul");
-+ exit (1);
-+ }
-+ break;
-+
-+ case OPT_NO_CONFIG_FILE:
-+ use_config_file = 0;
-+ break;
-+
-+ case OPT_NO_CURSES:
-+ use_curses = 0;
-+ break;
-+
-+ case OPT_NO_PAGER:
-+ use_pager = 0;
-+ break;
-+
-+ case OPT_BATCH:
-+ /* This is the same as "--no-config-file --no-curses --no-pager". */
-+ use_config_file = 0;
-+ use_curses = 0;
-+ use_pager = 0;
-+ break;
-+
-+ case OPT_READ_ONLY:
-+ read_only = 1;
-+ break;
-+
-+ case OPT_VERBOSE:
-+ verbose = 1;
-+ break;
-+
-+ case OPT_NO_FLOPPY:
-+ floppy_disks = 0;
-+ break;
-+
-+ case OPT_PROBE_SECOND_FLOPPY:
-+ floppy_disks = 2;
-+ break;
-+
-+ case OPT_DEVICE_MAP:
-+ device_map_file = strdup (optarg);
-+ break;
-+
-+ case OPT_PRESET_MENU:
-+ use_preset_menu = 1;
-+ break;
-+
-+ default:
-+ usage (1);
-+ }
-+ }
-+ while (c != EOF);
-+
-+ /* Wait until the HOLD variable is cleared by an attached debugger. */
-+ if (hold && verbose)
-+ printf ("Run \"gdb %s %d\", and set HOLD to zero.\n",
-+ program_name, (int) getpid ());
-+ while (hold)
-+ {
-+ if (hold > 0)
-+ hold--;
-+
-+ sleep (1);
-+ }
-+
-+ /* If we don't have curses (!HAVE_LIBCURSES or --no-curses or
-+ --batch) put terminal to dumb for better handling of line i/o */
-+ if (! use_curses)
-+ current_term->flags = TERM_NO_EDIT | TERM_DUMB;
-+
-+ /* Transfer control to the stage2 simulator. */
-+ exit (grub_stage2 ());
-+}
-diff -Nur grub-0.97/lib/device.c grub-0.97-patched/lib/device.c
---- grub-0.97/lib/device.c 2005-03-28 01:14:25.000000000 +0200
-+++ grub-0.97-patched/lib/device.c 2012-11-11 17:07:12.748730268 +0100
-@@ -69,9 +69,9 @@
- # ifndef CDROM_GET_CAPABILITY
- # define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
- # endif /* ! CDROM_GET_CAPABILITY */
--# ifndef BLKGETSIZE
--# define BLKGETSIZE _IO(0x12,96) /* return device size */
--# endif /* ! BLKGETSIZE */
-+# ifndef BLKGETSIZE64
-+# define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size */
-+# endif /* ! BLKGETSIZE64 */
- #endif /* __linux__ */
-
- /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
-@@ -131,6 +131,152 @@
- #include <shared.h>
- #include <device.h>
-
-+#if defined(__linux__)
-+/* The 2.6 kernel has removed all of the geometry handling for IDE drives
-+ * that did fixups for LBA, etc. This means that the geometry we get
-+ * with the ioctl has a good chance of being wrong. So, we get to
-+ * also know about partition tables and try to read what the geometry
-+ * is there. *grumble* Very closely based on code from cfdisk
-+ */
-+static void get_kernel_geometry(int fd, long long *cyl, int *heads, int *sectors) {
-+ struct hd_geometry hdg;
-+
-+ if (ioctl (fd, HDIO_GETGEO, &hdg))
-+ return;
-+
-+ *cyl = hdg.cylinders;
-+ *heads = hdg.heads;
-+ *sectors = hdg.sectors;
-+}
-+
-+struct partition {
-+ unsigned char boot_ind; /* 0x80 - active */
-+ unsigned char head; /* starting head */
-+ unsigned char sector; /* starting sector */
-+ unsigned char cyl; /* starting cylinder */
-+ unsigned char sys_ind; /* What partition type */
-+ unsigned char end_head; /* end head */
-+ unsigned char end_sector; /* end sector */
-+ unsigned char end_cyl; /* end cylinder */
-+ unsigned char start4[4]; /* starting sector counting from 0 */
-+ unsigned char size4[4]; /* nr of sectors in partition */
-+};
-+
-+#define ALIGNMENT 2
-+typedef union {
-+ struct {
-+ unsigned char align[ALIGNMENT];
-+ unsigned char b[SECTOR_SIZE];
-+ } c;
-+ struct {
-+ unsigned char align[ALIGNMENT];
-+ unsigned char buffer[0x1BE];
-+ struct partition part[4];
-+ unsigned char magicflag[2];
-+ } p;
-+} partition_table;
-+
-+#define PART_TABLE_FLAG0 0x55
-+#define PART_TABLE_FLAG1 0xAA
-+
-+static void
-+get_partition_table_geometry(partition_table *bufp, long long *cyl, int *heads,
-+ int *sectors) {
-+ struct partition *p;
-+ int i,h,s,hh,ss;
-+ int first = 1;
-+ int bad = 0;
-+
-+ if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 ||
-+ bufp->p.magicflag[1] != PART_TABLE_FLAG1) {
-+ /* Matthew Wilcox: slightly friendlier version of
-+ fatal(_("Bad signature on partition table"), 3);
-+ */
-+ fprintf(stderr, "Unknown partition table signature\n");
-+ return;
-+ }
-+
-+ hh = ss = 0;
-+ for (i=0; i<4; i++) {
-+ p = &(bufp->p.part[i]);
-+ if (p->sys_ind != 0) {
-+ h = p->end_head + 1;
-+ s = (p->end_sector & 077);
-+ if (first) {
-+ hh = h;
-+ ss = s;
-+ first = 0;
-+ } else if (hh != h || ss != s)
-+ bad = 1;
-+ }
-+ }
-+
-+ if (!first && !bad) {
-+ *heads = hh;
-+ *sectors = ss;
-+ }
-+}
-+
-+static long long my_lseek (unsigned int fd, long long offset,
-+ unsigned int origin)
-+{
-+#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);
-+
-+ if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET) < 0)
-+ return (long long) -1;
-+ return result;
-+#else
-+ return lseek(fd, offset, SEEK_SET);
-+#endif
-+}
-+
-+static void get_linux_geometry (int fd, struct geometry *geom) {
-+ long long kern_cyl = 0; int kern_head = 0, kern_sectors = 0;
-+ long long pt_cyl = 0; int pt_head = 0, pt_sectors = 0;
-+ partition_table bufp;
-+ char *buff, *buf_unaligned;
-+
-+ buf_unaligned = malloc(sizeof(partition_table) + 4095);
-+ buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
-+ (~(4096-1)));
-+
-+ get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors);
-+
-+ if (my_lseek (fd, 0*SECTOR_SIZE, SEEK_SET) < 0) {
-+ fprintf(stderr, "Unable to seek");
-+ }
-+
-+ if (read(fd, buff, SECTOR_SIZE) == SECTOR_SIZE) {
-+ memcpy(bufp.c.b, buff, SECTOR_SIZE);
-+ get_partition_table_geometry(&bufp, &pt_cyl, &pt_head, &pt_sectors);
-+ } else {
-+ fprintf(stderr, "Unable to read partition table: %s\n", strerror(errno));
-+ }
-+
-+ if (pt_head && pt_sectors) {
-+ int cyl_size;
-+
-+ geom->heads = pt_head;
-+ geom->sectors = pt_sectors;
-+ cyl_size = pt_head * pt_sectors;
-+ geom->cylinders = geom->total_sectors/cyl_size;
-+ } else {
-+ geom->heads = kern_head;
-+ geom->sectors = kern_sectors;
-+ geom->cylinders = kern_cyl;
-+ }
-+
-+ return;
-+}
-+#endif
-+
- /* Get the geometry of a drive DRIVE. */
- void
- get_drive_geometry (struct geometry *geom, char **map, int drive)
-@@ -151,20 +297,16 @@
- #if defined(__linux__)
- /* Linux */
- {
-- struct hd_geometry hdg;
-- unsigned long nr;
-+ unsigned long long nr;
-
-- if (ioctl (fd, HDIO_GETGEO, &hdg))
-- goto fail;
--
-- if (ioctl (fd, BLKGETSIZE, &nr))
-+ if (ioctl (fd, BLKGETSIZE64, &nr))
- goto fail;
-
- /* Got the geometry, so save it. */
-- geom->cylinders = hdg.cylinders;
-- geom->heads = hdg.heads;
-- geom->sectors = hdg.sectors;
-- geom->total_sectors = nr;
-+ get_linux_geometry(fd, geom);
-+ if (!geom->heads && !geom->cylinders && !geom->sectors)
-+ goto fail;
-+ geom->total_sectors = nr / 512;
-
- goto success;
- }
-@@ -403,10 +545,28 @@
- }
-
- static void
-+get_cciss_disk_name (char *name, int controller, int drive)
-+{
-+ sprintf (name, "/dev/cciss/c%dd%d", controller, drive);
-+}
-+
-+static void
-+get_ida_disk_name (char *name, int controller, int drive)
-+{
-+ sprintf (name, "/dev/ida/c%dd%d", controller, drive);
-+}
-+
-+static void
- get_ataraid_disk_name (char *name, int unit)
- {
- sprintf (name, "/dev/ataraid/d%c", unit + '0');
- }
-+
-+static void
-+get_i2o_disk_name (char *name, char unit)
-+{
-+ sprintf (name, "/dev/i2o/hd%c", unit);
-+}
- #endif
-
- /* Check if DEVICE can be read. If an error occurs, return zero,
-@@ -801,6 +961,97 @@
- }
- }
- }
-+
-+ /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
-+ {
-+ int unit;
-+
-+ for (unit = 'a'; unit < 'f'; unit++)
-+ {
-+ char name[24];
-+
-+ get_i2o_disk_name (name, unit);
-+ if (check_device (name))
-+ {
-+ (*map)[num_hd + 0x80] = strdup (name);
-+ assert ((*map)[num_hd + 0x80]);
-+
-+ /* If the device map file is opened, write the map. */
-+ if (fp)
-+ fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
-+
-+ num_hd++;
-+ }
-+ }
-+ }
-+
-+ /* This is for CCISS, its like the DAC960 - we have
-+ /dev/cciss/<controller>d<logical drive>p<partition>
-+
-+ It currently supports up to 3 controllers, 10 logical volumes
-+ and 10 partitions
-+
-+ Code gratuitously copied from DAC960 above.
-+ Horms <horms@verge.net.au> 23rd July 2004
-+ */
-+ {
-+ int controller, drive;
-+
-+ for (controller = 0; controller < 2; controller++)
-+ {
-+ for (drive = 0; drive < 9; drive++)
-+ {
-+ char name[24];
-+
-+ get_cciss_disk_name (name, controller, drive);
-+ if (check_device (name))
-+ {
-+ (*map)[num_hd + 0x80] = strdup (name);
-+ assert ((*map)[num_hd + 0x80]);
-+
-+ /* If the device map file is opened, write the map. */
-+ if (fp)
-+ fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
-+
-+ num_hd++;
-+ }
-+ }
-+ }
-+ }
-+
-+ /* This is for Compaq Smart Array, its like the DAC960 - we have
-+ /dev/ida/<controller>d<logical drive>p<partition>
-+
-+ It currently supports up to 3 controllers, 10 logical volumes
-+ and 15 partitions
-+
-+ Code gratuitously copied from DAC960 above.
-+ Piotr Roszatycki <dexter@debian.org>
-+ */
-+ {
-+ int controller, drive;
-+
-+ for (controller = 0; controller < 2; controller++)
-+ {
-+ for (drive = 0; drive < 9; drive++)
-+ {
-+ char name[24];
-+
-+ get_ida_disk_name (name, controller, drive);
-+ if (check_device (name))
-+ {
-+ (*map)[num_hd + 0x80] = strdup (name);
-+ assert ((*map)[num_hd + 0x80]);
-+
-+ /* If the device map file is opened, write the map. */
-+ if (fp)
-+ fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
-+
-+ num_hd++;
-+ }
-+ }
-+ }
-+ }
- #endif /* __linux__ */
-
- /* OK, close the device map file if opened. */
-@@ -844,6 +1095,7 @@
- {
- char dev[PATH_MAX]; /* XXX */
- int fd;
-+ off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
-
- if ((partition & 0x00FF00) != 0x00FF00)
- {
-@@ -861,6 +1113,14 @@
- if (strcmp (dev + strlen(dev) - 5, "/disc") == 0)
- strcpy (dev + strlen(dev) - 5, "/part");
- }
-+ else
-+ {
-+ if ((strncmp (dev, "/dev/ataraid/", 13) == 0) ||
-+ (strncmp (dev, "/dev/ida/", 9) == 0) ||
-+ (strncmp (dev, "/dev/cciss/", 11) == 0) ||
-+ (strncmp (dev, "/dev/rd/", 8) == 0))
-+ strcpy (dev + strlen(dev), "p");
-+ }
- sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1);
-
- /* Open the partition. */
-@@ -870,35 +1130,13 @@
- errnum = ERR_NO_PART;
- return 0;
- }
--
--#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 * (loff_t) SECTOR_SIZE;
-- if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
-- {
-- errnum = ERR_DEV_VALUES;
-- return 0;
-- }
-- }
--#else
-- {
-- off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
-
-- if (lseek (fd, offset, SEEK_SET) != offset)
-- {
-- errnum = ERR_DEV_VALUES;
-- return 0;
-- }
-- }
--#endif
-+ if (my_lseek(fd, offset, SEEK_SET) != offset)
-+ {
-+ errnum = ERR_DEV_VALUES;
-+ return 0;
-+ }
-
- if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE))
- {
-diff -Nur grub-0.97/netboot/cs89x0.c grub-0.97-patched/netboot/cs89x0.c
---- grub-0.97/netboot/cs89x0.c 2003-07-09 13:45:37.000000000 +0200
-+++ grub-0.97-patched/netboot/cs89x0.c 2012-11-11 17:07:12.722729437 +0100
-@@ -1,3 +1,21 @@
-+/**
-+ Per an email message from Russ Nelson <nelson@crynwr.com> on
-+ 18 March 2008 this file is now licensed under GPL Version 2.
-+
-+ From: Russ Nelson <nelson@crynwr.com>
-+ Date: Tue, 18 Mar 2008 12:42:00 -0400
-+ Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
-+ -- quote from email
-+ As copyright holder, if I say it doesn't conflict with the GPL,
-+ then it doesn't conflict with the GPL.
-+
-+ However, there's no point in causing people's brains to overheat,
-+ so yes, I grant permission for the code to be relicensed under the
-+ GPLv2. Please make sure that this change in licensing makes its
-+ way upstream. -russ
-+ -- quote from email
-+**/
-+
- /* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
- /*
- Permission is granted to distribute the enclosed cs89x0.[ch] driver
-diff -Nur grub-0.97/netboot/cs89x0.h grub-0.97-patched/netboot/cs89x0.h
---- grub-0.97/netboot/cs89x0.h 2003-07-09 13:45:37.000000000 +0200
-+++ grub-0.97-patched/netboot/cs89x0.h 2012-11-11 17:07:12.723729469 +0100
-@@ -1,3 +1,21 @@
-+/**
-+ Per an email message from Russ Nelson <nelson@crynwr.com> on
-+ 18 March 2008 this file is now licensed under GPL Version 2.
-+
-+ From: Russ Nelson <nelson@crynwr.com>
-+ Date: Tue, 18 Mar 2008 12:42:00 -0400
-+ Subject: Re: [Etherboot-developers] cs89x0 driver in etherboot
-+ -- quote from email
-+ As copyright holder, if I say it doesn't conflict with the GPL,
-+ then it doesn't conflict with the GPL.
-+
-+ However, there's no point in causing people's brains to overheat,
-+ so yes, I grant permission for the code to be relicensed under the
-+ GPLv2. Please make sure that this change in licensing makes its
-+ way upstream. -russ
-+ -- quote from email
-+**/
-+
- /* Copyright, 1988-1992, Russell Nelson, Crynwr Software
-
- This program is free software; you can redistribute it and/or modify
-diff -Nur grub-0.97/netboot/etherboot.h grub-0.97-patched/netboot/etherboot.h
---- grub-0.97/netboot/etherboot.h 2003-07-09 13:45:37.000000000 +0200
-+++ grub-0.97-patched/netboot/etherboot.h 2012-11-11 17:07:12.723729469 +0100
-@@ -531,9 +531,6 @@
- extern int network_ready;
- extern struct rom_info rom;
- extern struct arptable_t arptable[MAX_ARP];
--extern struct bootpd_t bootp_data;
--#define BOOTP_DATA_ADDR (&bootp_data)
--extern unsigned char *end_of_rfc1533;
-
- /* config.c */
- extern struct nic nic;
-diff -Nur grub-0.97/netboot/main.c grub-0.97-patched/netboot/main.c
---- grub-0.97/netboot/main.c 2004-05-21 00:19:33.000000000 +0200
-+++ grub-0.97-patched/netboot/main.c 2012-11-11 17:07:12.724729500 +0100
-@@ -56,7 +56,8 @@
- static unsigned long netmask;
- static struct bootpd_t bootp_data;
- static unsigned long xid;
--static unsigned char *end_of_rfc1533 = NULL;
-+
-+#define BOOTP_DATA_ADDR (&bootp_data)
-
- #ifndef NO_DHCP_SUPPORT
- #endif /* NO_DHCP_SUPPORT */
-@@ -83,7 +84,9 @@
- RFC2132_MAX_SIZE,2, /* request as much as we can */
- ETH_MAX_MTU / 256, ETH_MAX_MTU % 256,
- RFC2132_PARAM_LIST, 4, RFC1533_NETMASK, RFC1533_GATEWAY,
-- RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH
-+ RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
-+ /* Vendor class identifier */
-+ RFC2132_VENDOR_CLASS_ID, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't',
- };
-
- static const unsigned char dhcprequest[] =
-@@ -103,6 +106,8 @@
- /* Etherboot vendortags */
- RFC1533_VENDOR_MAGIC,
- RFC1533_VENDOR_CONFIGFILE,
-+ /* Vendor class identifier */
-+ RFC2132_VENDOR_CLASS_ID, 10, 'G', 'R', 'U', 'B', 'C', 'l', 'i', 'e', 'n', 't',
- };
-
- #endif /* ! NO_DHCP_SUPPORT */
-@@ -701,7 +706,7 @@
- "adcw %%ax,%0\n\t" /* add carry of previous iteration */
- "loop 1b\n\t"
- "adcw $0,%0" /* add carry of last iteration */
-- : "=b" (*sum), "=S"(start), "=c"(len)
-+ : "=r" (*sum), "=S"(start), "=c"(len)
- : "0"(*sum), "1"(start), "2"(len)
- : "ax", "cc"
- );
-@@ -967,7 +972,6 @@
-
- if (block == 0)
- {
-- end_of_rfc1533 = NULL;
- vendorext_isvalid = 0;
-
- if (grub_memcmp (p, rfc1533_cookie, 4))
-@@ -1021,7 +1025,7 @@
- }
- else if (c == RFC1533_END)
- {
-- end_of_rfc1533 = endp = p;
-+ endp = p;
- continue;
- }
- else if (c == RFC1533_NETMASK)
-diff -Nur grub-0.97/netboot/natsemi.c grub-0.97-patched/netboot/natsemi.c
---- grub-0.97/netboot/natsemi.c 2003-07-09 13:45:38.000000000 +0200
-+++ grub-0.97-patched/netboot/natsemi.c 2012-11-11 17:07:12.724729500 +0100
-@@ -608,7 +608,7 @@
- const char *p) /* Packet */
- {
- u32 status, to, nstype;
-- u32 tx_status;
-+ volatile u32 tx_status;
-
- /* Stop the transmitter */
- outl(TxOff, ioaddr + ChipCmd);
-@@ -647,7 +647,7 @@
-
- to = currticks() + TX_TIMEOUT;
-
-- while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
-+ while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
- /* wait */ ;
-
- if (currticks() >= to) {
-diff -Nur grub-0.97/netboot/pci.c grub-0.97-patched/netboot/pci.c
---- grub-0.97/netboot/pci.c 2003-07-09 13:45:38.000000000 +0200
-+++ grub-0.97-patched/netboot/pci.c 2012-11-11 17:07:07.227553894 +0100
-@@ -105,13 +105,16 @@
-
- save_flags(flags);
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
-- "lcall (%%edi)"
-+ "lcall (%%edi)\n\t"
- #else
-- "lcall *(%%edi)"
-+ "lcall *(%%edi)\n\t"
- #endif
-+ "movl %%ebx, %1\n\t" /* capture what was in %ebx */
-+ "popl %%ebx\n\t" /* restore %ebx */
- : "=a" (return_code),
-- "=b" (address),
-+ "=r" (address),
- "=c" (length),
- "=d" (entry)
- : "0" (service),
-@@ -141,18 +144,21 @@
-
- save_flags(flags);
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
-+ "movl %3, %%ebx\n\t" /* put the value into ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
- "lcall (%%esi)\n\t"
- #else
- "lcall *(%%esi)\n\t"
- #endif
- "jc 1f\n\t"
-- "xor %%ah, %%ah\n"
-+ "popl %%ebx\n\t" /* restore %ebx */
-+ "xor %%ah, %%ah\n\t"
- "1:"
- : "=c" (*value),
- "=a" (ret)
- : "1" (PCIBIOS_READ_CONFIG_BYTE),
-- "b" (bx),
-+ "r" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- restore_flags(flags);
-@@ -168,18 +174,21 @@
-
- save_flags(flags);
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
-+ "movl %3, %%ebx\n\t" /* put the value into ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
- "lcall (%%esi)\n\t"
- #else
- "lcall *(%%esi)\n\t"
- #endif
- "jc 1f\n\t"
-- "xor %%ah, %%ah\n"
-+ "popl %%ebx\n\t" /* restore %ebx */
-+ "xor %%ah, %%ah\n\t"
- "1:"
- : "=c" (*value),
- "=a" (ret)
- : "1" (PCIBIOS_READ_CONFIG_WORD),
-- "b" (bx),
-+ "r" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- restore_flags(flags);
-@@ -195,18 +204,21 @@
-
- save_flags(flags);
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
-+ "movl %3, %%ebx\n\t" /* put the value into ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
- "lcall (%%esi)\n\t"
- #else
- "lcall *(%%esi)\n\t"
- #endif
- "jc 1f\n\t"
-- "xor %%ah, %%ah\n"
-+ "popl %%ebx\n\t" /* restore %ebx */
-+ "xor %%ah, %%ah\n\t"
- "1:"
- : "=c" (*value),
- "=a" (ret)
- : "1" (PCIBIOS_READ_CONFIG_DWORD),
-- "b" (bx),
-+ "r" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- restore_flags(flags);
-@@ -222,18 +234,21 @@
-
- save_flags(flags); cli();
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
-+ "movl %3, %%ebx\n\t" /* put the value into ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
- "lcall (%%esi)\n\t"
- #else
- "lcall *(%%esi)\n\t"
- #endif
- "jc 1f\n\t"
-- "xor %%ah, %%ah\n"
-+ "popl %%ebx\n\t" /* restore %ebx */
-+ "xor %%ah, %%ah\n\t"
- "1:"
- : "=a" (ret)
- : "0" (PCIBIOS_WRITE_CONFIG_BYTE),
- "c" (value),
-- "b" (bx),
-+ "r" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- restore_flags(flags);
-@@ -249,18 +264,21 @@
-
- save_flags(flags); cli();
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
-+ "movl %3, %%ebx\n\t" /* put the value into ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
- "lcall (%%esi)\n\t"
- #else
- "lcall *(%%esi)\n\t"
- #endif
- "jc 1f\n\t"
-- "xor %%ah, %%ah\n"
-+ "popl %%ebx\n\t" /* restore %ebx */
-+ "xor %%ah, %%ah\n\t"
- "1:"
- : "=a" (ret)
- : "0" (PCIBIOS_WRITE_CONFIG_WORD),
- "c" (value),
-- "b" (bx),
-+ "r" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- restore_flags(flags);
-@@ -276,18 +294,21 @@
-
- save_flags(flags); cli();
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
-+ "movl %3, %%ebx\n\t" /* put the value into ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
- "lcall (%%esi)\n\t"
- #else
- "lcall *(%%esi)\n\t"
- #endif
- "jc 1f\n\t"
-- "xor %%ah, %%ah\n"
-+ "popl %%ebx\n\t" /* restore %ebx */
-+ "xor %%ah, %%ah\n\t"
- "1:"
- : "=a" (ret)
- : "0" (PCIBIOS_WRITE_CONFIG_DWORD),
- "c" (value),
-- "b" (bx),
-+ "r" (bx),
- "D" ((long) where),
- "S" (&pci_indirect));
- restore_flags(flags);
-@@ -308,20 +329,22 @@
-
- save_flags(flags);
- __asm__(
-+ "pushl %%ebx\n\t" /* save %ebx */
- #ifdef ABSOLUTE_WITHOUT_ASTERISK
- "lcall (%%edi)\n\t"
- #else
- "lcall *(%%edi)\n\t"
- #endif
- "jc 1f\n\t"
-- "xor %%ah, %%ah\n"
-+ "xor %%ah, %%ah\n\t"
- "1:\tshl $8, %%eax\n\t"
-- "movw %%bx, %%ax"
-+ "movw %%bx, %%ax\n\t"
-+ "popl %%ebx\n\t" /* restore %ebx */
- : "=d" (signature),
- "=a" (pack)
- : "1" (PCIBIOS_PCI_BIOS_PRESENT),
- "D" (&pci_indirect)
-- : "bx", "cx");
-+ : "cx");
- restore_flags(flags);
-
- present_status = (pack >> 16) & 0xff;
-diff -Nur grub-0.97/netboot/sis900.c grub-0.97-patched/netboot/sis900.c
---- grub-0.97/netboot/sis900.c 2003-07-09 13:45:38.000000000 +0200
-+++ grub-0.97-patched/netboot/sis900.c 2012-11-11 17:07:12.725729531 +0100
-@@ -901,7 +901,7 @@
- const char *p) /* Packet */
- {
- u32 status, to, nstype;
-- u32 tx_status;
-+ volatile u32 tx_status;
-
- /* Stop the transmitter */
- outl(TxDIS, ioaddr + cr);
-@@ -940,7 +940,7 @@
-
- to = currticks() + TX_TIMEOUT;
-
-- while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
-+ while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
- /* wait */ ;
-
- if (currticks() >= to) {
-diff -Nur grub-0.97/stage1/Makefile.am grub-0.97-patched/stage1/Makefile.am
---- grub-0.97/stage1/Makefile.am 2004-07-16 13:44:56.000000000 +0200
-+++ grub-0.97-patched/stage1/Makefile.am 2012-11-11 17:07:12.747730236 +0100
-@@ -1,11 +1,11 @@
--pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
--nodist_pkglib_DATA = stage1
-+stagedir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-+nodist_stage_DATA = stage1
-
--CLEANFILES = $(nodist_pkglib_DATA)
-+CLEANFILES = $(nodist_stage_DATA)
-
- # We can't use builtins or standard includes.
- AM_CCASFLAGS = $(STAGE1_CFLAGS) -fno-builtin -nostdinc
--LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00
-+stage1_exec_LDFLAGS = -nostdlib -Wl,-N,-Ttext,7C00
-
- noinst_PROGRAMS = stage1.exec
- stage1_exec_SOURCES = stage1.S stage1.h
-diff -Nur grub-0.97/stage2/asm.S grub-0.97-patched/stage2/asm.S
---- grub-0.97/stage2/asm.S 2004-06-19 18:55:22.000000000 +0200
-+++ grub-0.97-patched/stage2/asm.S 2012-11-11 17:07:03.850446017 +0100
-@@ -1651,7 +1651,29 @@
- jnz 3f
- ret
-
--3: /* use keyboard controller */
-+3: /*
-+ * try to switch gateA20 using PORT92, the "Fast A20 and Init"
-+ * register
-+ */
-+ mov $0x92, %dx
-+ inb %dx, %al
-+ /* skip the port92 code if it's unimplemented (read returns 0xff) */
-+ cmpb $0xff, %al
-+ jz 6f
-+
-+ /* set or clear bit1, the ALT_A20_GATE bit */
-+ movb 4(%esp), %ah
-+ testb %ah, %ah
-+ jz 4f
-+ orb $2, %al
-+ jmp 5f
-+4: and $0xfd, %al
-+
-+ /* clear the INIT_NOW bit don't accidently reset the machine */
-+5: and $0xfe, %al
-+ outb %al, %dx
-+
-+6: /* use keyboard controller */
- pushl %eax
-
- call gloop1
-@@ -1661,9 +1683,12 @@
-
- gloopint1:
- inb $K_STATUS
-+ cmpb $0xff, %al
-+ jz gloopint1_done
- andb $K_IBUF_FUL, %al
- jnz gloopint1
-
-+gloopint1_done:
- movb $KB_OUTPUT_MASK, %al
- cmpb $0, 0x8(%esp)
- jz gdoit
-@@ -1684,6 +1709,8 @@
-
- gloop1:
- inb $K_STATUS
-+ cmpb $0xff, %al
-+ jz gloop2ret
- andb $K_IBUF_FUL, %al
- jnz gloop1
-
-@@ -1991,6 +2018,11 @@
- ENTRY(console_getkey)
- push %ebp
-
-+wait_for_key:
-+ call EXT_C(console_checkkey)
-+ incl %eax
-+ jz wait_for_key
-+
- call EXT_C(prot_to_real)
- .code16
-
-@@ -2216,6 +2248,156 @@
- pop %ebx
- pop %ebp
- ret
-+
-+/* graphics mode functions */
-+#ifdef SUPPORT_GRAPHICS
-+VARIABLE(cursorX)
-+.word 0
-+VARIABLE(cursorY)
-+.word 0
-+VARIABLE(cursorCount)
-+.word 0
-+VARIABLE(cursorBuf)
-+.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-+
-+
-+/*
-+ * int set_videomode(mode)
-+ * BIOS call "INT 10H Function 0h" to set video mode
-+ * Call with %ah = 0x0
-+ * %al = video mode
-+ * Returns old videomode.
-+ */
-+ENTRY(set_videomode)
-+ push %ebp
-+ push %ebx
-+ push %ecx
-+
-+ movb 0x10(%esp), %cl
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ xorw %bx, %bx
-+ movb $0xf, %ah
-+ int $0x10 /* Get Current Video mode */
-+ movb %al, %ch
-+ xorb %ah, %ah
-+ movb %cl, %al
-+ int $0x10 /* Set Video mode */
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ xorb %ah, %ah
-+ movb %ch, %al
-+
-+ pop %ecx
-+ pop %ebx
-+ pop %ebp
-+ ret
-+
-+
-+/*
-+ * unsigned char * graphics_get_font()
-+ * BIOS call "INT 10H Function 11h" to set font
-+ * Call with %ah = 0x11
-+ */
-+ENTRY(graphics_get_font)
-+ push %ebp
-+ push %ebx
-+ push %ecx
-+ push %edx
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ movw $0x1130, %ax
-+ movb $6, %bh /* font 8x16 */
-+ int $0x10
-+ movw %bp, %dx
-+ movw %es, %cx
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ xorl %eax, %eax
-+ movw %cx, %ax
-+ shll $4, %eax
-+ movw %dx, %ax
-+
-+ pop %edx
-+ pop %ecx
-+ pop %ebx
-+ pop %ebp
-+ ret
-+
-+
-+
-+/*
-+ * graphics_set_palette(index, red, green, blue)
-+ * BIOS call "INT 10H Function 10h" to set individual dac register
-+ * Call with %ah = 0x10
-+ * %bx = register number
-+ * %ch = new value for green (0-63)
-+ * %cl = new value for blue (0-63)
-+ * %dh = new value for red (0-63)
-+ */
-+
-+ENTRY(graphics_set_palette)
-+ push %ebp
-+ push %eax
-+ push %ebx
-+ push %ecx
-+ push %edx
-+
-+ movw $0x3c8, %bx /* address write mode register */
-+
-+ /* wait vertical retrace */
-+
-+ movw $0x3da, %dx
-+l1b: inb %dx, %al /* wait vertical active display */
-+ test $8, %al
-+ jnz l1b
-+
-+l2b: inb %dx, %al /* wait vertical retrace */
-+ test $8, %al
-+ jnz l2b
-+
-+ mov %bx, %dx
-+ movb 0x18(%esp), %al /* index */
-+ outb %al, %dx
-+ inc %dx
-+
-+ movb 0x1c(%esp), %al /* red */
-+ outb %al, %dx
-+
-+ movb 0x20(%esp), %al /* green */
-+ outb %al, %dx
-+
-+ movb 0x24(%esp), %al /* blue */
-+ outb %al, %dx
-+
-+ movw 0x18(%esp), %bx
-+
-+ call EXT_C(prot_to_real)
-+ .code16
-+
-+ movb %bl, %bh
-+ movw $0x1000, %ax
-+ int $0x10
-+
-+ DATA32 call EXT_C(real_to_prot)
-+ .code32
-+
-+ pop %edx
-+ pop %ecx
-+ pop %ebx
-+ pop %eax
-+ pop %ebp
-+ ret
-+
-+#endif /* SUPPORT_GRAPHICS */
-
- /*
- * getrtsecs()
-diff -Nur grub-0.97/stage2/bios.c grub-0.97-patched/stage2/bios.c
---- grub-0.97/stage2/bios.c 2004-03-27 17:34:04.000000000 +0100
-+++ grub-0.97-patched/stage2/bios.c 2012-11-11 17:07:12.751730363 +0100
-@@ -47,7 +47,7 @@
- return the error number. Otherwise, return 0. */
- int
- biosdisk (int read, int drive, struct geometry *geometry,
-- int sector, int nsec, int segment)
-+ unsigned int sector, int nsec, int segment)
- {
- int err;
-
-@@ -60,7 +60,18 @@
- unsigned short blocks;
- unsigned long buffer;
- unsigned long long block;
-- } __attribute__ ((packed)) dap;
-+
-+ /* This structure is passed in the stack. A buggy BIOS could write
-+ * garbage data to the tail of the struct and hang the machine. So
-+ * we need this protection. - Tinybit
-+ */
-+ unsigned char dummy[16];
-+ } __attribute__ ((packed)) *dap;
-+
-+ /* Even the above protection is not enough to avoid stupid actions by
-+ * buggy BIOSes. So we do it in the 0040:0000 segment. - Tinybit
-+ */
-+ dap = (struct disk_address_packet *)0x580;
-
- /* XXX: Don't check the geometry by default, because some buggy
- BIOSes don't return the number of total sectors correctly,
-@@ -72,15 +83,15 @@
-
- /* FIXME: sizeof (DAP) must be 0x10. Should assert that the compiler
- can't add any padding. */
-- dap.length = sizeof (dap);
-- dap.block = sector;
-- dap.blocks = nsec;
-- dap.reserved = 0;
-+ dap->length = 0x10;
-+ dap->block = sector;
-+ dap->blocks = nsec;
-+ dap->reserved = 0;
- /* This is undocumented part. The address is formated in
- SEGMENT:ADDRESS. */
-- dap.buffer = segment << 16;
-+ dap->buffer = segment << 16;
-
-- err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, &dap);
-+ err = biosdisk_int13_extensions ((read + 0x42) << 8, drive, dap);
-
- /* #undef NO_INT13_FALLBACK */
- #ifndef NO_INT13_FALLBACK
-diff -Nur grub-0.97/stage2/boot.c grub-0.97-patched/stage2/boot.c
---- grub-0.97/stage2/boot.c 2004-03-30 13:44:08.000000000 +0200
-+++ grub-0.97-patched/stage2/boot.c 2012-11-11 17:07:12.727729596 +0100
-@@ -1,7 +1,7 @@
- /* boot.c - load and bootstrap a kernel */
- /*
- * GRUB -- GRand Unified Bootloader
-- * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
-+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
-@@ -96,7 +96,7 @@
- lh = (struct linux_kernel_header *) buffer;
-
- /* ELF loading supported if multiboot, FreeBSD and NetBSD. */
-- if ((type == KERNEL_TYPE_MULTIBOOT
-+ if (((type == KERNEL_TYPE_MULTIBOOT && ! (flags & MULTIBOOT_AOUT_KLUDGE))
- || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
- || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
- || suggested_type == KERNEL_TYPE_NETBSD)
-@@ -241,7 +241,7 @@
- }
-
- if (lh->version >= 0x0202)
-- lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
-+ lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_0202_PRM_OFFSET;
- else
- {
- lh->cl_magic = LINUX_CL_MAGIC;
-@@ -407,6 +407,15 @@
- while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
- *(dest++) = *(src++);
-
-+ {
-+ char *src = skip_to (0, arg);
-+ char *dest = linux_data_tmp_addr + LINUX_CL_0202_PRM_OFFSET;
-+
-+ while (dest < linux_data_tmp_addr + LINUX_CL_0202_PRM_END_OFFSET && *src)
-+ *(dest++) = *(src++);
-+ *dest = 0;
-+ }
-+
- /* Old Linux kernels have problems determining the amount of
- the available memory. To work around this problem, we add
- the "mem" option to the kernel command line. This has its
-@@ -824,8 +833,11 @@
- moveto = (mbi.mem_upper + 0x400) << 10;
-
- moveto = (moveto - len) & 0xfffff000;
-- max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
-- ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
-+ max_addr = LINUX_INITRD_MAX_ADDRESS;
-+ if (lh->header == LINUX_MAGIC_SIGNATURE &&
-+ lh->version >= 0x0203 &&
-+ lh->initrd_addr_max < max_addr)
-+ max_addr = lh->initrd_addr_max;
- if (moveto + len >= max_addr)
- moveto = (max_addr - len) & 0xfffff000;
-
-diff -Nur grub-0.97/stage2/boot.c.orig grub-0.97-patched/stage2/boot.c.orig
---- grub-0.97/stage2/boot.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/boot.c.orig 2004-03-30 13:44:08.000000000 +0200
-@@ -0,0 +1,1020 @@
-+/* boot.c - load and bootstrap a kernel */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+
-+#include "shared.h"
-+
-+#include "freebsd.h"
-+#include "imgact_aout.h"
-+#include "i386-elf.h"
-+
-+static int cur_addr;
-+entry_func entry_addr;
-+static struct mod_list mll[99];
-+static int linux_mem_size;
-+
-+/*
-+ * The next two functions, 'load_image' and 'load_module', are the building
-+ * blocks of the multiboot loader component. They handle essentially all
-+ * of the gory details of loading in a bootable image and the modules.
-+ */
-+
-+kernel_t
-+load_image (char *kernel, char *arg, kernel_t suggested_type,
-+ unsigned long load_flags)
-+{
-+ int len, i, exec_type = 0, align_4k = 1;
-+ entry_func real_entry_addr = 0;
-+ kernel_t type = KERNEL_TYPE_NONE;
-+ unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
-+ char *str = 0, *str2 = 0;
-+ struct linux_kernel_header *lh;
-+ union
-+ {
-+ struct multiboot_header *mb;
-+ struct exec *aout;
-+ Elf32_Ehdr *elf;
-+ }
-+ pu;
-+ /* presuming that MULTIBOOT_SEARCH is large enough to encompass an
-+ executable header */
-+ unsigned char buffer[MULTIBOOT_SEARCH];
-+
-+ /* sets the header pointer to point to the beginning of the
-+ buffer by default */
-+ pu.aout = (struct exec *) buffer;
-+
-+ if (!grub_open (kernel))
-+ return KERNEL_TYPE_NONE;
-+
-+ if (!(len = grub_read (buffer, MULTIBOOT_SEARCH)) || len < 32)
-+ {
-+ grub_close ();
-+
-+ if (!errnum)
-+ errnum = ERR_EXEC_FORMAT;
-+
-+ return KERNEL_TYPE_NONE;
-+ }
-+
-+ for (i = 0; i < len; i++)
-+ {
-+ if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
-+ {
-+ flags = ((struct multiboot_header *) (buffer + i))->flags;
-+ if (flags & MULTIBOOT_UNSUPPORTED)
-+ {
-+ grub_close ();
-+ errnum = ERR_BOOT_FEATURES;
-+ return KERNEL_TYPE_NONE;
-+ }
-+ type = KERNEL_TYPE_MULTIBOOT;
-+ str2 = "Multiboot";
-+ break;
-+ }
-+ }
-+
-+ /* Use BUFFER as a linux kernel header, if the image is Linux zImage
-+ or bzImage. */
-+ lh = (struct linux_kernel_header *) buffer;
-+
-+ /* ELF loading supported if multiboot, FreeBSD and NetBSD. */
-+ if ((type == KERNEL_TYPE_MULTIBOOT
-+ || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
-+ || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
-+ || suggested_type == KERNEL_TYPE_NETBSD)
-+ && len > sizeof (Elf32_Ehdr)
-+ && BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer))))
-+ {
-+ if (type == KERNEL_TYPE_MULTIBOOT)
-+ entry_addr = (entry_func) pu.elf->e_entry;
-+ else
-+ entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
-+
-+ if (entry_addr < (entry_func) 0x100000)
-+ errnum = ERR_BELOW_1MB;
-+
-+ /* don't want to deal with ELF program header at some random
-+ place in the file -- this generally won't happen */
-+ if (pu.elf->e_phoff == 0 || pu.elf->e_phnum == 0
-+ || ((pu.elf->e_phoff + (pu.elf->e_phentsize * pu.elf->e_phnum))
-+ >= len))
-+ errnum = ERR_EXEC_FORMAT;
-+ str = "elf";
-+
-+ if (type == KERNEL_TYPE_NONE)
-+ {
-+ /* At the moment, there is no way to identify a NetBSD ELF
-+ kernel, so rely on the suggested type by the user. */
-+ if (suggested_type == KERNEL_TYPE_NETBSD)
-+ {
-+ str2 = "NetBSD";
-+ type = suggested_type;
-+ }
-+ else
-+ {
-+ str2 = "FreeBSD";
-+ type = KERNEL_TYPE_FREEBSD;
-+ }
-+ }
-+ }
-+ else if (flags & MULTIBOOT_AOUT_KLUDGE)
-+ {
-+ pu.mb = (struct multiboot_header *) (buffer + i);
-+ entry_addr = (entry_func) pu.mb->entry_addr;
-+ cur_addr = pu.mb->load_addr;
-+ /* first offset into file */
-+ grub_seek (i - (pu.mb->header_addr - cur_addr));
-+
-+ /* If the load end address is zero, load the whole contents. */
-+ if (! pu.mb->load_end_addr)
-+ pu.mb->load_end_addr = cur_addr + filemax;
-+
-+ text_len = pu.mb->load_end_addr - cur_addr;
-+ data_len = 0;
-+
-+ /* If the bss end address is zero, assume that there is no bss area. */
-+ if (! pu.mb->bss_end_addr)
-+ pu.mb->bss_end_addr = pu.mb->load_end_addr;
-+
-+ bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
-+
-+ if (pu.mb->header_addr < pu.mb->load_addr
-+ || pu.mb->load_end_addr <= pu.mb->load_addr
-+ || pu.mb->bss_end_addr < pu.mb->load_end_addr
-+ || (pu.mb->header_addr - pu.mb->load_addr) > i)
-+ errnum = ERR_EXEC_FORMAT;
-+
-+ if (cur_addr < 0x100000)
-+ errnum = ERR_BELOW_1MB;
-+
-+ pu.aout = (struct exec *) buffer;
-+ exec_type = 2;
-+ str = "kludge";
-+ }
-+ else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
-+ {
-+ entry_addr = (entry_func) pu.aout->a_entry;
-+
-+ if (type == KERNEL_TYPE_NONE)
-+ {
-+ /*
-+ * If it doesn't have a Multiboot header, then presume
-+ * it is either a FreeBSD or NetBSD executable. If so,
-+ * then use a magic number of normal ordering, ZMAGIC to
-+ * determine if it is FreeBSD.
-+ *
-+ * This is all because freebsd and netbsd seem to require
-+ * masking out some address bits... differently for each
-+ * one... plus of course we need to know which booting
-+ * method to use.
-+ */
-+ entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
-+
-+ if (buffer[0] == 0xb && buffer[1] == 1)
-+ {
-+ type = KERNEL_TYPE_FREEBSD;
-+ cur_addr = (int) entry_addr;
-+ str2 = "FreeBSD";
-+ }
-+ else
-+ {
-+ type = KERNEL_TYPE_NETBSD;
-+ cur_addr = (int) entry_addr & 0xF00000;
-+ if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
-+ align_4k = 0;
-+ str2 = "NetBSD";
-+ }
-+ }
-+
-+ /* first offset into file */
-+ grub_seek (N_TXTOFF (*(pu.aout)));
-+ text_len = pu.aout->a_text;
-+ data_len = pu.aout->a_data;
-+ bss_len = pu.aout->a_bss;
-+
-+ if (cur_addr < 0x100000)
-+ errnum = ERR_BELOW_1MB;
-+
-+ exec_type = 1;
-+ str = "a.out";
-+ }
-+ else if (lh->boot_flag == BOOTSEC_SIGNATURE
-+ && lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
-+ {
-+ int big_linux = 0;
-+ int setup_sects = lh->setup_sects;
-+
-+ if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
-+ {
-+ big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
-+ lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
-+
-+ /* Put the real mode part at as a high location as possible. */
-+ linux_data_real_addr
-+ = (char *) ((mbi.mem_lower << 10) - LINUX_SETUP_MOVE_SIZE);
-+ /* But it must not exceed the traditional area. */
-+ if (linux_data_real_addr > (char *) LINUX_OLD_REAL_MODE_ADDR)
-+ linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
-+
-+ if (lh->version >= 0x0201)
-+ {
-+ lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
-+ lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
-+ }
-+
-+ if (lh->version >= 0x0202)
-+ lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
-+ else
-+ {
-+ lh->cl_magic = LINUX_CL_MAGIC;
-+ lh->cl_offset = LINUX_CL_OFFSET;
-+ lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
-+ }
-+ }
-+ else
-+ {
-+ /* Your kernel is quite old... */
-+ lh->cl_magic = LINUX_CL_MAGIC;
-+ lh->cl_offset = LINUX_CL_OFFSET;
-+
-+ setup_sects = LINUX_DEFAULT_SETUP_SECTS;
-+
-+ linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
-+ }
-+
-+ /* If SETUP_SECTS is not set, set it to the default (4). */
-+ if (! setup_sects)
-+ setup_sects = LINUX_DEFAULT_SETUP_SECTS;
-+
-+ data_len = setup_sects << 9;
-+ text_len = filemax - data_len - SECTOR_SIZE;
-+
-+ linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
-+
-+ if (! big_linux
-+ && text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
-+ {
-+ grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
-+ errnum = ERR_WONT_FIT;
-+ }
-+ else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
-+ > RAW_ADDR ((char *) (mbi.mem_lower << 10)))
-+ errnum = ERR_WONT_FIT;
-+ else
-+ {
-+ grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
-+ (big_linux ? "bzImage" : "zImage"), data_len, text_len);
-+
-+ /* Video mode selection support. What a mess! */
-+ /* NOTE: Even the word "mess" is not still enough to
-+ represent how wrong and bad the Linux video support is,
-+ but I don't want to hear complaints from Linux fanatics
-+ any more. -okuji */
-+ {
-+ char *vga;
-+
-+ /* Find the substring "vga=". */
-+ vga = grub_strstr (arg, "vga=");
-+ if (vga)
-+ {
-+ char *value = vga + 4;
-+ int vid_mode;
-+
-+ /* Handle special strings. */
-+ if (substring ("normal", value) < 1)
-+ vid_mode = LINUX_VID_MODE_NORMAL;
-+ else if (substring ("ext", value) < 1)
-+ vid_mode = LINUX_VID_MODE_EXTENDED;
-+ else if (substring ("ask", value) < 1)
-+ vid_mode = LINUX_VID_MODE_ASK;
-+ else if (safe_parse_maxint (&value, &vid_mode))
-+ ;
-+ else
-+ {
-+ /* ERRNUM is already set inside the function
-+ safe_parse_maxint. */
-+ grub_close ();
-+ return KERNEL_TYPE_NONE;
-+ }
-+
-+ lh->vid_mode = vid_mode;
-+ }
-+ }
-+
-+ /* Check the mem= option to limit memory used for initrd. */
-+ {
-+ char *mem;
-+
-+ mem = grub_strstr (arg, "mem=");
-+ if (mem)
-+ {
-+ char *value = mem + 4;
-+
-+ safe_parse_maxint (&value, &linux_mem_size);
-+ switch (errnum)
-+ {
-+ case ERR_NUMBER_OVERFLOW:
-+ /* If an overflow occurs, use the maximum address for
-+ initrd instead. This is good, because MAXINT is
-+ greater than LINUX_INITRD_MAX_ADDRESS. */
-+ linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
-+ errnum = ERR_NONE;
-+ break;
-+
-+ case ERR_NONE:
-+ {
-+ int shift = 0;
-+
-+ switch (grub_tolower (*value))
-+ {
-+ case 'g':
-+ shift += 10;
-+ case 'm':
-+ shift += 10;
-+ case 'k':
-+ shift += 10;
-+ default:
-+ break;
-+ }
-+
-+ /* Check an overflow. */
-+ if (linux_mem_size > (MAXINT >> shift))
-+ linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
-+ else
-+ linux_mem_size <<= shift;
-+ }
-+ break;
-+
-+ default:
-+ linux_mem_size = 0;
-+ errnum = ERR_NONE;
-+ break;
-+ }
-+ }
-+ else
-+ linux_mem_size = 0;
-+ }
-+
-+ /* It is possible that DATA_LEN + SECTOR_SIZE is greater than
-+ MULTIBOOT_SEARCH, so the data may have been read partially. */
-+ if (data_len + SECTOR_SIZE <= MULTIBOOT_SEARCH)
-+ grub_memmove (linux_data_tmp_addr, buffer,
-+ data_len + SECTOR_SIZE);
-+ else
-+ {
-+ grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
-+ grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
-+ data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
-+ }
-+
-+ if (lh->header != LINUX_MAGIC_SIGNATURE ||
-+ lh->version < 0x0200)
-+ /* Clear the heap space. */
-+ grub_memset (linux_data_tmp_addr + ((setup_sects + 1) << 9),
-+ 0,
-+ (64 - setup_sects - 1) << 9);
-+
-+ /* Copy command-line plus memory hack to staging area.
-+ NOTE: Linux has a bug that it doesn't handle multiple spaces
-+ between two options and a space after a "mem=" option isn't
-+ removed correctly so the arguments to init could be like
-+ {"init", "", "", NULL}. This affects some not-very-clever
-+ shells. Thus, the code below does a trick to avoid the bug.
-+ That is, copy "mem=XXX" to the end of the command-line, and
-+ avoid to copy spaces unnecessarily. Hell. */
-+ {
-+ char *src = skip_to (0, arg);
-+ char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
-+
-+ while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
-+ *(dest++) = *(src++);
-+
-+ /* Old Linux kernels have problems determining the amount of
-+ the available memory. To work around this problem, we add
-+ the "mem" option to the kernel command line. This has its
-+ own drawbacks because newer kernels can determine the
-+ memory map more accurately. Boot protocol 2.03, which
-+ appeared in Linux 2.4.18, provides a pointer to the kernel
-+ version string, so we could check it. But since kernel
-+ 2.4.18 and newer are known to detect memory reliably, boot
-+ protocol 2.03 already implies that the kernel is new
-+ enough. The "mem" option is added if neither of the
-+ following conditions is met:
-+ 1) The "mem" option is already present.
-+ 2) The "kernel" command is used with "--no-mem-option".
-+ 3) GNU GRUB is configured not to pass the "mem" option.
-+ 4) The kernel supports boot protocol 2.03 or newer. */
-+ if (! grub_strstr (arg, "mem=")
-+ && ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION)
-+ && lh->version < 0x0203 /* kernel version < 2.4.18 */
-+ && dest + 15 < linux_data_tmp_addr + LINUX_CL_END_OFFSET)
-+ {
-+ *dest++ = ' ';
-+ *dest++ = 'm';
-+ *dest++ = 'e';
-+ *dest++ = 'm';
-+ *dest++ = '=';
-+
-+ dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
-+ *dest++ = 'K';
-+ }
-+
-+ *dest = 0;
-+ }
-+
-+ /* offset into file */
-+ grub_seek (data_len + SECTOR_SIZE);
-+
-+ cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
-+ grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
-+
-+ if (errnum == ERR_NONE)
-+ {
-+ grub_close ();
-+
-+ /* Sanity check. */
-+ if (suggested_type != KERNEL_TYPE_NONE
-+ && ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX)
-+ || (! big_linux && suggested_type != KERNEL_TYPE_LINUX)))
-+ {
-+ errnum = ERR_EXEC_FORMAT;
-+ return KERNEL_TYPE_NONE;
-+ }
-+
-+ /* Ugly hack. */
-+ linux_text_len = text_len;
-+
-+ return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
-+ }
-+ }
-+ }
-+ else /* no recognizable format */
-+ errnum = ERR_EXEC_FORMAT;
-+
-+ /* return if error */
-+ if (errnum)
-+ {
-+ grub_close ();
-+ return KERNEL_TYPE_NONE;
-+ }
-+
-+ /* fill the multiboot info structure */
-+ mbi.cmdline = (int) arg;
-+ mbi.mods_count = 0;
-+ mbi.mods_addr = 0;
-+ mbi.boot_device = (current_drive << 24) | current_partition;
-+ mbi.flags &= ~(MB_INFO_MODS | MB_INFO_AOUT_SYMS | MB_INFO_ELF_SHDR);
-+ mbi.syms.a.tabsize = 0;
-+ mbi.syms.a.strsize = 0;
-+ mbi.syms.a.addr = 0;
-+ mbi.syms.a.pad = 0;
-+
-+ printf (" [%s-%s", str2, str);
-+
-+ str = "";
-+
-+ if (exec_type) /* can be loaded like a.out */
-+ {
-+ if (flags & MULTIBOOT_AOUT_KLUDGE)
-+ str = "-and-data";
-+
-+ printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
-+
-+ /* read text, then read data */
-+ if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
-+ {
-+ cur_addr += text_len;
-+
-+ if (!(flags & MULTIBOOT_AOUT_KLUDGE))
-+ {
-+ /* we have to align to a 4K boundary */
-+ if (align_4k)
-+ cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
-+ else
-+ printf (", C");
-+
-+ printf (", data=0x%x", data_len);
-+
-+ if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
-+ != data_len)
-+ && !errnum)
-+ errnum = ERR_EXEC_FORMAT;
-+ cur_addr += data_len;
-+ }
-+
-+ if (!errnum)
-+ {
-+ memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
-+ cur_addr += bss_len;
-+
-+ printf (", bss=0x%x", bss_len);
-+ }
-+ }
-+ else if (!errnum)
-+ errnum = ERR_EXEC_FORMAT;
-+
-+ if (!errnum && pu.aout->a_syms
-+ && pu.aout->a_syms < (filemax - filepos))
-+ {
-+ int symtab_err, orig_addr = cur_addr;
-+
-+ /* we should align to a 4K boundary here for good measure */
-+ if (align_4k)
-+ cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
-+
-+ mbi.syms.a.addr = cur_addr;
-+
-+ *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
-+ cur_addr += sizeof (int);
-+
-+ printf (", symtab=0x%x", pu.aout->a_syms);
-+
-+ if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
-+ == pu.aout->a_syms)
-+ {
-+ cur_addr += pu.aout->a_syms;
-+ mbi.syms.a.tabsize = pu.aout->a_syms;
-+
-+ if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
-+ {
-+ *((int *) RAW_ADDR (cur_addr)) = i;
-+ cur_addr += sizeof (int);
-+
-+ mbi.syms.a.strsize = i;
-+
-+ i -= sizeof (int);
-+
-+ printf (", strtab=0x%x", i);
-+
-+ symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
-+ != i);
-+ cur_addr += i;
-+ }
-+ else
-+ symtab_err = 1;
-+ }
-+ else
-+ symtab_err = 1;
-+
-+ if (symtab_err)
-+ {
-+ printf ("(bad)");
-+ cur_addr = orig_addr;
-+ mbi.syms.a.tabsize = 0;
-+ mbi.syms.a.strsize = 0;
-+ mbi.syms.a.addr = 0;
-+ }
-+ else
-+ mbi.flags |= MB_INFO_AOUT_SYMS;
-+ }
-+ }
-+ else
-+ /* ELF executable */
-+ {
-+ unsigned loaded = 0, memaddr, memsiz, filesiz;
-+ Elf32_Phdr *phdr;
-+
-+ /* reset this to zero for now */
-+ cur_addr = 0;
-+
-+ /* scan for program segments */
-+ for (i = 0; i < pu.elf->e_phnum; i++)
-+ {
-+ phdr = (Elf32_Phdr *)
-+ (pu.elf->e_phoff + ((int) buffer)
-+ + (pu.elf->e_phentsize * i));
-+ if (phdr->p_type == PT_LOAD)
-+ {
-+ /* offset into file */
-+ grub_seek (phdr->p_offset);
-+ filesiz = phdr->p_filesz;
-+
-+ if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
-+ memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
-+ else
-+ memaddr = RAW_ADDR (phdr->p_paddr);
-+
-+ memsiz = phdr->p_memsz;
-+ if (memaddr < RAW_ADDR (0x100000))
-+ errnum = ERR_BELOW_1MB;
-+
-+ /* If the memory range contains the entry address, get the
-+ physical address here. */
-+ if (type == KERNEL_TYPE_MULTIBOOT
-+ && (unsigned) entry_addr >= phdr->p_vaddr
-+ && (unsigned) entry_addr < phdr->p_vaddr + memsiz)
-+ real_entry_addr = (entry_func) ((unsigned) entry_addr
-+ + memaddr - phdr->p_vaddr);
-+
-+ /* make sure we only load what we're supposed to! */
-+ if (filesiz > memsiz)
-+ filesiz = memsiz;
-+ /* mark memory as used */
-+ if (cur_addr < memaddr + memsiz)
-+ cur_addr = memaddr + memsiz;
-+ printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
-+ memsiz - filesiz);
-+ /* increment number of segments */
-+ loaded++;
-+
-+ /* load the segment */
-+ if (memcheck (memaddr, memsiz)
-+ && grub_read ((char *) memaddr, filesiz) == filesiz)
-+ {
-+ if (memsiz > filesiz)
-+ memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
-+ }
-+ else
-+ break;
-+ }
-+ }
-+
-+ if (! errnum)
-+ {
-+ if (! loaded)
-+ errnum = ERR_EXEC_FORMAT;
-+ else
-+ {
-+ /* Load ELF symbols. */
-+ Elf32_Shdr *shdr = NULL;
-+ int tab_size, sec_size;
-+ int symtab_err = 0;
-+
-+ mbi.syms.e.num = pu.elf->e_shnum;
-+ mbi.syms.e.size = pu.elf->e_shentsize;
-+ mbi.syms.e.shndx = pu.elf->e_shstrndx;
-+
-+ /* We should align to a 4K boundary here for good measure. */
-+ if (align_4k)
-+ cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
-+
-+ tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
-+
-+ grub_seek (pu.elf->e_shoff);
-+ if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size)
-+ == tab_size)
-+ {
-+ mbi.syms.e.addr = cur_addr;
-+ shdr = (Elf32_Shdr *) mbi.syms.e.addr;
-+ cur_addr += tab_size;
-+
-+ printf (", shtab=0x%x", cur_addr);
-+
-+ for (i = 0; i < mbi.syms.e.num; i++)
-+ {
-+ /* This section is a loaded section,
-+ so we don't care. */
-+ if (shdr[i].sh_addr != 0)
-+ continue;
-+
-+ /* This section is empty, so we don't care. */
-+ if (shdr[i].sh_size == 0)
-+ continue;
-+
-+ /* Align the section to a sh_addralign bits boundary. */
-+ cur_addr = ((cur_addr + shdr[i].sh_addralign) &
-+ - (int) shdr[i].sh_addralign);
-+
-+ grub_seek (shdr[i].sh_offset);
-+
-+ sec_size = shdr[i].sh_size;
-+
-+ if (! (memcheck (cur_addr, sec_size)
-+ && (grub_read ((char *) RAW_ADDR (cur_addr),
-+ sec_size)
-+ == sec_size)))
-+ {
-+ symtab_err = 1;
-+ break;
-+ }
-+
-+ shdr[i].sh_addr = cur_addr;
-+ cur_addr += sec_size;
-+ }
-+ }
-+ else
-+ symtab_err = 1;
-+
-+ if (mbi.syms.e.addr < RAW_ADDR(0x10000))
-+ symtab_err = 1;
-+
-+ if (symtab_err)
-+ {
-+ printf ("(bad)");
-+ mbi.syms.e.num = 0;
-+ mbi.syms.e.size = 0;
-+ mbi.syms.e.addr = 0;
-+ mbi.syms.e.shndx = 0;
-+ cur_addr = 0;
-+ }
-+ else
-+ mbi.flags |= MB_INFO_ELF_SHDR;
-+ }
-+ }
-+ }
-+
-+ if (! errnum)
-+ {
-+ grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
-+
-+ /* If the entry address is physically different from that of the ELF
-+ header, correct it here. */
-+ if (real_entry_addr)
-+ entry_addr = real_entry_addr;
-+ }
-+ else
-+ {
-+ putchar ('\n');
-+ type = KERNEL_TYPE_NONE;
-+ }
-+
-+ grub_close ();
-+
-+ /* Sanity check. */
-+ if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
-+ {
-+ errnum = ERR_EXEC_FORMAT;
-+ return KERNEL_TYPE_NONE;
-+ }
-+
-+ return type;
-+}
-+
-+int
-+load_module (char *module, char *arg)
-+{
-+ int len;
-+
-+ /* if we are supposed to load on 4K boundaries */
-+ cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
-+
-+ if (!grub_open (module))
-+ return 0;
-+
-+ len = grub_read ((char *) cur_addr, -1);
-+ if (! len)
-+ {
-+ grub_close ();
-+ return 0;
-+ }
-+
-+ printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
-+
-+ /* these two simply need to be set if any modules are loaded at all */
-+ mbi.flags |= MB_INFO_MODS;
-+ mbi.mods_addr = (int) mll;
-+
-+ mll[mbi.mods_count].cmdline = (int) arg;
-+ mll[mbi.mods_count].mod_start = cur_addr;
-+ cur_addr += len;
-+ mll[mbi.mods_count].mod_end = cur_addr;
-+ mll[mbi.mods_count].pad = 0;
-+
-+ /* increment number of modules included */
-+ mbi.mods_count++;
-+
-+ grub_close ();
-+ return 1;
-+}
-+
-+int
-+load_initrd (char *initrd)
-+{
-+ int len;
-+ unsigned long moveto;
-+ unsigned long max_addr;
-+ struct linux_kernel_header *lh
-+ = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
-+
-+#ifndef NO_DECOMPRESSION
-+ no_decompression = 1;
-+#endif
-+
-+ if (! grub_open (initrd))
-+ goto fail;
-+
-+ len = grub_read ((char *) cur_addr, -1);
-+ if (! len)
-+ {
-+ grub_close ();
-+ goto fail;
-+ }
-+
-+ if (linux_mem_size)
-+ moveto = linux_mem_size;
-+ else
-+ moveto = (mbi.mem_upper + 0x400) << 10;
-+
-+ moveto = (moveto - len) & 0xfffff000;
-+ max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
-+ ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
-+ if (moveto + len >= max_addr)
-+ moveto = (max_addr - len) & 0xfffff000;
-+
-+ /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
-+ the last page.
-+ XXX: Linux 2.2.xx has a bug in the memory range check, which is
-+ worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */
-+ moveto -= 0x10000;
-+ memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
-+
-+ printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
-+
-+ /* FIXME: Should check if the kernel supports INITRD. */
-+ lh->ramdisk_image = RAW_ADDR (moveto);
-+ lh->ramdisk_size = len;
-+
-+ grub_close ();
-+
-+ fail:
-+
-+#ifndef NO_DECOMPRESSION
-+ no_decompression = 0;
-+#endif
-+
-+ return ! errnum;
-+}
-+
-+
-+#ifdef GRUB_UTIL
-+/* Dummy function to fake the *BSD boot. */
-+static void
-+bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
-+ int mem_upper, int mem_lower)
-+{
-+ stop ();
-+}
-+#endif
-+
-+
-+/*
-+ * All "*_boot" commands depend on the images being loaded into memory
-+ * correctly, the variables in this file being set up correctly, and
-+ * the root partition being set in the 'saved_drive' and 'saved_partition'
-+ * variables.
-+ */
-+
-+
-+void
-+bsd_boot (kernel_t type, int bootdev, char *arg)
-+{
-+ char *str;
-+ int clval = 0, i;
-+ struct bootinfo bi;
-+
-+#ifdef GRUB_UTIL
-+ entry_addr = (entry_func) bsd_boot_entry;
-+#else
-+ stop_floppy ();
-+#endif
-+
-+ while (*(++arg) && *arg != ' ');
-+ str = arg;
-+ while (*str)
-+ {
-+ if (*str == '-')
-+ {
-+ while (*str && *str != ' ')
-+ {
-+ if (*str == 'C')
-+ clval |= RB_CDROM;
-+ if (*str == 'a')
-+ clval |= RB_ASKNAME;
-+ if (*str == 'b')
-+ clval |= RB_HALT;
-+ if (*str == 'c')
-+ clval |= RB_CONFIG;
-+ if (*str == 'd')
-+ clval |= RB_KDB;
-+ if (*str == 'D')
-+ clval |= RB_MULTIPLE;
-+ if (*str == 'g')
-+ clval |= RB_GDB;
-+ if (*str == 'h')
-+ clval |= RB_SERIAL;
-+ if (*str == 'm')
-+ clval |= RB_MUTE;
-+ if (*str == 'r')
-+ clval |= RB_DFLTROOT;
-+ if (*str == 's')
-+ clval |= RB_SINGLE;
-+ if (*str == 'v')
-+ clval |= RB_VERBOSE;
-+ str++;
-+ }
-+ continue;
-+ }
-+ str++;
-+ }
-+
-+ if (type == KERNEL_TYPE_FREEBSD)
-+ {
-+ clval |= RB_BOOTINFO;
-+
-+ bi.bi_version = BOOTINFO_VERSION;
-+
-+ *arg = 0;
-+ while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
-+ if (*arg == '/')
-+ bi.bi_kernelname = arg + 1;
-+ else
-+ bi.bi_kernelname = 0;
-+
-+ bi.bi_nfs_diskless = 0;
-+ bi.bi_n_bios_used = 0; /* this field is apparently unused */
-+
-+ for (i = 0; i < N_BIOS_GEOM; i++)
-+ {
-+ struct geometry geom;
-+
-+ /* XXX Should check the return value. */
-+ get_diskinfo (i + 0x80, &geom);
-+ /* FIXME: If HEADS or SECTORS is greater than 255, then this will
-+ break the geometry information. That is a drawback of BSD
-+ but not of GRUB. */
-+ bi.bi_bios_geom[i] = (((geom.cylinders - 1) << 16)
-+ + (((geom.heads - 1) & 0xff) << 8)
-+ + (geom.sectors & 0xff));
-+ }
-+
-+ bi.bi_size = sizeof (struct bootinfo);
-+ bi.bi_memsizes_valid = 1;
-+ bi.bi_bios_dev = saved_drive;
-+ bi.bi_basemem = mbi.mem_lower;
-+ bi.bi_extmem = extended_memory;
-+
-+ if (mbi.flags & MB_INFO_AOUT_SYMS)
-+ {
-+ bi.bi_symtab = mbi.syms.a.addr;
-+ bi.bi_esymtab = mbi.syms.a.addr + 4
-+ + mbi.syms.a.tabsize + mbi.syms.a.strsize;
-+ }
-+#if 0
-+ else if (mbi.flags & MB_INFO_ELF_SHDR)
-+ {
-+ /* FIXME: Should check if a symbol table exists and, if exists,
-+ pass the table to BI. */
-+ }
-+#endif
-+ else
-+ {
-+ bi.bi_symtab = 0;
-+ bi.bi_esymtab = 0;
-+ }
-+
-+ /* call entry point */
-+ (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi)));
-+ }
-+ else
-+ {
-+ /*
-+ * We now pass the various bootstrap parameters to the loaded
-+ * image via the argument list.
-+ *
-+ * This is the official list:
-+ *
-+ * arg0 = 8 (magic)
-+ * arg1 = boot flags
-+ * arg2 = boot device
-+ * arg3 = start of symbol table (0 if not loaded)
-+ * arg4 = end of symbol table (0 if not loaded)
-+ * arg5 = transfer address from image
-+ * arg6 = transfer address for next image pointer
-+ * arg7 = conventional memory size (640)
-+ * arg8 = extended memory size (8196)
-+ *
-+ * ...in actuality, we just pass the parameters used by the kernel.
-+ */
-+
-+ /* call entry point */
-+ unsigned long end_mark;
-+
-+ if (mbi.flags & MB_INFO_AOUT_SYMS)
-+ end_mark = (mbi.syms.a.addr + 4
-+ + mbi.syms.a.tabsize + mbi.syms.a.strsize);
-+ else
-+ /* FIXME: it should be mbi.syms.e.size. */
-+ end_mark = 0;
-+
-+ (*entry_addr) (clval, bootdev, 0, end_mark,
-+ extended_memory, mbi.mem_lower);
-+ }
-+}
-diff -Nur grub-0.97/stage2/builtins.c grub-0.97-patched/stage2/builtins.c
---- grub-0.97/stage2/builtins.c 2005-02-15 22:58:23.000000000 +0100
-+++ grub-0.97-patched/stage2/builtins.c 2012-11-11 17:07:12.729729661 +0100
-@@ -131,63 +131,98 @@
- }
-
- \f
-+/* blocklist_read_helper nee disk_read_blocklist_func was a nested
-+ * function, to which pointers were taken and exposed globally. Even
-+ * in the GNU-C nested functions extension, they have local linkage,
-+ * and aren't guaranteed to be accessable *at all* outside of their
-+ * containing scope.
-+ *
-+ * Above and beyond all of that, the variables within blocklist_func_context
-+ * are originally local variables, with local (not even static) linkage,
-+ * from within blocklist_func. These were each referenced by
-+ * disk_read_blocklist_func, which is only called from other functions
-+ * through a globally scoped pointer.
-+ *
-+ * The documentation in GCC actually uses the words "all hell will break
-+ * loose" to describe this scenario.
-+ *
-+ * Also, "start_sector" was also used uninitialized, but gcc doesn't warn
-+ * about it (possibly because of the scoping madness?)
-+ */
-+
-+static struct {
-+ int start_sector;
-+ int num_sectors;
-+ int num_entries;
-+ int last_length;
-+} blocklist_func_context = {
-+ .start_sector = 0,
-+ .num_sectors = 0,
-+ .num_entries = 0,
-+ .last_length = 0
-+};
-+
-+/* Collect contiguous blocks into one entry as many as possible,
-+ and print the blocklist notation on the screen. */
-+static void
-+blocklist_read_helper (int sector, int offset, int length)
-+{
-+ int *start_sector = &blocklist_func_context.start_sector;
-+ int *num_sectors = &blocklist_func_context.num_sectors;
-+ int *num_entries = &blocklist_func_context.num_entries;
-+ int *last_length = &blocklist_func_context.last_length;
-+
-+ if (*num_sectors > 0)
-+ {
-+ if (*start_sector + *num_sectors == sector
-+ && offset == 0 && *last_length == SECTOR_SIZE)
-+ {
-+ *num_sectors++;
-+ *last_length = length;
-+ return;
-+ }
-+ else
-+ {
-+ if (*last_length == SECTOR_SIZE)
-+ grub_printf ("%s%d+%d", *num_entries ? "," : "",
-+ *start_sector - part_start, *num_sectors);
-+ else if (*num_sectors > 1)
-+ grub_printf ("%s%d+%d,%d[0-%d]", *num_entries ? "," : "",
-+ *start_sector - part_start, *num_sectors-1,
-+ *start_sector + *num_sectors-1 - part_start,
-+ *last_length);
-+ else
-+ grub_printf ("%s%d[0-%d]", *num_entries ? "," : "",
-+ *start_sector - part_start, *last_length);
-+ *num_entries++;
-+ *num_sectors = 0;
-+ }
-+ }
-+
-+ if (offset > 0)
-+ {
-+ grub_printf("%s%d[%d-%d]", *num_entries ? "," : "",
-+ sector-part_start, offset, offset+length);
-+ *num_entries++;
-+ }
-+ else
-+ {
-+ *start_sector = sector;
-+ *num_sectors = 1;
-+ *last_length = length;
-+ }
-+}
-+
- /* blocklist */
- static int
- blocklist_func (char *arg, int flags)
- {
- char *dummy = (char *) RAW_ADDR (0x100000);
-- int start_sector;
-- int num_sectors = 0;
-- int num_entries = 0;
-- int last_length = 0;
-
-- auto void disk_read_blocklist_func (int sector, int offset, int length);
-+ int *start_sector = &blocklist_func_context.start_sector;
-+ int *num_sectors = &blocklist_func_context.num_sectors;
-+ int *num_entries = &blocklist_func_context.num_entries;
-
-- /* Collect contiguous blocks into one entry as many as possible,
-- and print the blocklist notation on the screen. */
-- auto void disk_read_blocklist_func (int sector, int offset, int length)
-- {
-- if (num_sectors > 0)
-- {
-- if (start_sector + num_sectors == sector
-- && offset == 0 && last_length == SECTOR_SIZE)
-- {
-- num_sectors++;
-- last_length = length;
-- return;
-- }
-- else
-- {
-- if (last_length == SECTOR_SIZE)
-- grub_printf ("%s%d+%d", num_entries ? "," : "",
-- start_sector - part_start, num_sectors);
-- else if (num_sectors > 1)
-- grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "",
-- start_sector - part_start, num_sectors-1,
-- start_sector + num_sectors-1 - part_start,
-- last_length);
-- else
-- grub_printf ("%s%d[0-%d]", num_entries ? "," : "",
-- start_sector - part_start, last_length);
-- num_entries++;
-- num_sectors = 0;
-- }
-- }
--
-- if (offset > 0)
-- {
-- grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
-- sector-part_start, offset, offset+length);
-- num_entries++;
-- }
-- else
-- {
-- start_sector = sector;
-- num_sectors = 1;
-- last_length = length;
-- }
-- }
--
- /* Open the file. */
- if (! grub_open (arg))
- return 1;
-@@ -206,15 +241,15 @@
- grub_printf (")");
-
- /* Read in the whole file to DUMMY. */
-- disk_read_hook = disk_read_blocklist_func;
-+ disk_read_hook = blocklist_read_helper;
- if (! grub_read (dummy, -1))
- goto fail;
-
- /* The last entry may not be printed yet. Don't check if it is a
- * full sector, since it doesn't matter if we read too much. */
-- if (num_sectors > 0)
-- grub_printf ("%s%d+%d", num_entries ? "," : "",
-- start_sector - part_start, num_sectors);
-+ if (*num_sectors > 0)
-+ grub_printf ("%s%d+%d", *num_entries ? "," : "",
-+ *start_sector - part_start, *num_sectors);
-
- grub_printf ("\n");
-
-@@ -852,6 +887,138 @@
- };
- #endif /* SUPPORT_NETBOOT */
-
-+static int terminal_func (char *arg, int flags);
-+
-+#ifdef SUPPORT_GRAPHICS
-+\f
-+static int splashimage_func(char *arg, int flags) {
-+ char splashimage[64];
-+ int i;
-+
-+ /* filename can only be 64 characters due to our buffer size */
-+ if (strlen(arg) > 63)
-+ return 1;
-+ if (flags == BUILTIN_CMDLINE) {
-+ if (!grub_open(arg))
-+ return 1;
-+ grub_close();
-+ }
-+
-+ strcpy(splashimage, arg);
-+
-+ /* get rid of TERM_NEED_INIT from the graphics terminal. */
-+ for (i = 0; term_table[i].name; i++) {
-+ if (grub_strcmp (term_table[i].name, "graphics") == 0) {
-+ term_table[i].flags &= ~TERM_NEED_INIT;
-+ break;
-+ }
-+ }
-+
-+ graphics_set_splash(splashimage);
-+
-+ if (flags == BUILTIN_CMDLINE && graphics_inited) {
-+ graphics_end();
-+ graphics_init();
-+ graphics_cls();
-+ }
-+
-+ /* FIXME: should we be explicitly switching the terminal as a
-+ * side effect here? */
-+ terminal_func("graphics", flags);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_splashimage =
-+{
-+ "splashimage",
-+ splashimage_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "splashimage FILE",
-+ "Load FILE as the background image when in graphics mode."
-+};
-+
-+\f
-+/* foreground */
-+static int
-+foreground_func(char *arg, int flags)
-+{
-+ if (grub_strlen(arg) == 6) {
-+ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
-+ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
-+ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
-+
-+ foreground = (r << 16) | (g << 8) | b;
-+ if (graphics_inited)
-+ graphics_set_palette(15, r, g, b);
-+
-+ return (0);
-+ }
-+
-+ return (1);
-+}
-+
-+static struct builtin builtin_foreground =
-+{
-+ "foreground",
-+ foreground_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "foreground RRGGBB",
-+ "Sets the foreground color when in graphics mode."
-+ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
-+};
-+
-+\f
-+/* background */
-+static int
-+background_func(char *arg, int flags)
-+{
-+ if (grub_strlen(arg) == 6) {
-+ int r = ((hex(arg[0]) << 4) | hex(arg[1])) >> 2;
-+ int g = ((hex(arg[2]) << 4) | hex(arg[3])) >> 2;
-+ int b = ((hex(arg[4]) << 4) | hex(arg[5])) >> 2;
-+
-+ background = (r << 16) | (g << 8) | b;
-+ if (graphics_inited)
-+ graphics_set_palette(0, r, g, b);
-+ return (0);
-+ }
-+
-+ return (1);
-+}
-+
-+static struct builtin builtin_background =
-+{
-+ "background",
-+ background_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "background RRGGBB",
-+ "Sets the background color when in graphics mode."
-+ "RR is red, GG is green, and BB blue. Numbers must be in hexadecimal."
-+};
-+
-+#endif /* SUPPORT_GRAPHICS */
-+
-+\f
-+/* clear */
-+static int
-+clear_func()
-+{
-+ if (current_term->cls)
-+ current_term->cls();
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_clear =
-+{
-+ "clear",
-+ clear_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "clear",
-+ "Clear the screen"
-+};
-+
- \f
- /* displayapm */
- static int
-@@ -1233,14 +1400,15 @@
- for (drive = 0x80; drive < 0x88; drive++)
- {
- unsigned long part = 0xFFFFFF;
-- unsigned long start, len, offset, ext_offset;
-- int type, entry;
-+ unsigned long start, len, offset, ext_offset, gpt_offset;
-+ int type, entry, gpt_count, gpt_size;
- char buf[SECTOR_SIZE];
-
- current_drive = drive;
- while (next_partition (drive, 0xFFFFFF, &part, &type,
- &start, &len, &offset, &entry,
-- &ext_offset, buf))
-+ &ext_offset, &gpt_offset,
-+ &gpt_count, &gpt_size, buf))
- {
- if (type != PC_SLICE_TYPE_NONE
- && ! IS_PC_SLICE_TYPE_BSD (type)
-@@ -1740,6 +1908,77 @@
-
- \f
- /* install */
-+static struct {
-+ int saved_sector;
-+ int installaddr;
-+ int installlist;
-+ char *stage2_first_buffer;
-+} install_func_context = {
-+ .saved_sector = 0,
-+ .installaddr = 0,
-+ .installlist = 0,
-+ .stage2_first_buffer = NULL,
-+};
-+
-+/* Save the first sector of Stage2 in STAGE2_SECT. */
-+/* Formerly disk_read_savesect_func with local scope inside install_func */
-+static void
-+install_savesect_helper(int sector, int offset, int length)
-+{
-+ if (debug)
-+ printf ("[%d]", sector);
-+
-+ /* ReiserFS has files which sometimes contain data not aligned
-+ on sector boundaries. Returning an error is better than
-+ silently failing. */
-+ if (offset != 0 || length != SECTOR_SIZE)
-+ errnum = ERR_UNALIGNED;
-+
-+ install_func_context.saved_sector = sector;
-+}
-+
-+/* Write SECTOR to INSTALLLIST, and update INSTALLADDR and INSTALLSECT. */
-+/* Formerly disk_read_blocklist_func with local scope inside install_func */
-+static void
-+install_blocklist_helper (int sector, int offset, int length)
-+{
-+ int *installaddr = &install_func_context.installaddr;
-+ int *installlist = &install_func_context.installlist;
-+ char **stage2_first_buffer = &install_func_context.stage2_first_buffer;
-+ /* Was the last sector full? */
-+ static int last_length = SECTOR_SIZE;
-+
-+ if (debug)
-+ printf("[%d]", sector);
-+
-+ if (offset != 0 || last_length != SECTOR_SIZE)
-+ {
-+ /* We found a non-sector-aligned data block. */
-+ errnum = ERR_UNALIGNED;
-+ return;
-+ }
-+
-+ last_length = length;
-+
-+ if (*((unsigned long *) (*installlist - 4))
-+ + *((unsigned short *) *installlist) != sector
-+ || *installlist == (int) *stage2_first_buffer + SECTOR_SIZE + 4)
-+ {
-+ *installlist -= 8;
-+
-+ if (*((unsigned long *) (*installlist - 8)))
-+ errnum = ERR_WONT_FIT;
-+ else
-+ {
-+ *((unsigned short *) (*installlist + 2)) = (*installaddr >> 4);
-+ *((unsigned long *) (*installlist - 4)) = sector;
-+ }
-+ }
-+
-+ *((unsigned short *) *installlist) += 1;
-+ *installaddr += 512;
-+}
-+
- static int
- install_func (char *arg, int flags)
- {
-@@ -1747,8 +1986,12 @@
- char *stage1_buffer = (char *) RAW_ADDR (0x100000);
- char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
- char *old_sect = stage2_buffer + SECTOR_SIZE;
-- char *stage2_first_buffer = old_sect + SECTOR_SIZE;
-- char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
-+ /* stage2_first_buffer used to be defined as:
-+ * char *stage2_first_buffer = old_sect + SECTOR_SIZE; */
-+ char **stage2_first_buffer = &install_func_context.stage2_first_buffer;
-+ /* and stage2_second_buffer was:
-+ * char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; */
-+ char *stage2_second_buffer = old_sect + SECTOR_SIZE + SECTOR_SIZE;
- /* XXX: Probably SECTOR_SIZE is reasonable. */
- char *config_filename = stage2_second_buffer + SECTOR_SIZE;
- char *dummy = config_filename + SECTOR_SIZE;
-@@ -1757,10 +2000,11 @@
- int src_drive, src_partition, src_part_start;
- int i;
- struct geometry dest_geom, src_geom;
-- int saved_sector;
-+ int *saved_sector = &install_func_context.saved_sector;
- int stage2_first_sector, stage2_second_sector;
- char *ptr;
-- int installaddr, installlist;
-+ int *installaddr = &install_func_context.installaddr;
-+ int *installlist = &install_func_context.installlist;
- /* Point to the location of the name of a configuration file in Stage 2. */
- char *config_file_location;
- /* If FILE is a Stage 1.5? */
-@@ -1769,67 +2013,13 @@
- int is_open = 0;
- /* If LBA is forced? */
- int is_force_lba = 0;
-- /* Was the last sector full? */
-- int last_length = SECTOR_SIZE;
--
-+
-+ *stage2_first_buffer = old_sect + SECTOR_SIZE;
- #ifdef GRUB_UTIL
- /* If the Stage 2 is in a partition mounted by an OS, this will store
- the filename under the OS. */
- char *stage2_os_file = 0;
- #endif /* GRUB_UTIL */
--
-- auto void disk_read_savesect_func (int sector, int offset, int length);
-- auto void disk_read_blocklist_func (int sector, int offset, int length);
--
-- /* Save the first sector of Stage2 in STAGE2_SECT. */
-- auto void disk_read_savesect_func (int sector, int offset, int length)
-- {
-- if (debug)
-- printf ("[%d]", sector);
--
-- /* ReiserFS has files which sometimes contain data not aligned
-- on sector boundaries. Returning an error is better than
-- silently failing. */
-- if (offset != 0 || length != SECTOR_SIZE)
-- errnum = ERR_UNALIGNED;
--
-- saved_sector = sector;
-- }
--
-- /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
-- INSTALLSECT. */
-- auto void disk_read_blocklist_func (int sector, int offset, int length)
-- {
-- if (debug)
-- printf("[%d]", sector);
--
-- if (offset != 0 || last_length != SECTOR_SIZE)
-- {
-- /* We found a non-sector-aligned data block. */
-- errnum = ERR_UNALIGNED;
-- return;
-- }
--
-- last_length = length;
--
-- if (*((unsigned long *) (installlist - 4))
-- + *((unsigned short *) installlist) != sector
-- || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
-- {
-- installlist -= 8;
--
-- if (*((unsigned long *) (installlist - 8)))
-- errnum = ERR_WONT_FIT;
-- else
-- {
-- *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
-- *((unsigned long *) (installlist - 4)) = sector;
-- }
-- }
--
-- *((unsigned short *) installlist) += 1;
-- installaddr += 512;
-- }
-
- /* First, check the GNU-style long option. */
- while (1)
-@@ -1862,10 +2052,10 @@
- addr = skip_to (0, file);
-
- /* Get the installation address. */
-- if (! safe_parse_maxint (&addr, &installaddr))
-+ if (! safe_parse_maxint (&addr, installaddr))
- {
- /* ADDR is not specified. */
-- installaddr = 0;
-+ *installaddr = 0;
- ptr = addr;
- errnum = 0;
- }
-@@ -1961,17 +2151,17 @@
- = 0x9090;
-
- /* Read the first sector of Stage 2. */
-- disk_read_hook = disk_read_savesect_func;
-- if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
-+ disk_read_hook = install_savesect_helper;
-+ if (grub_read (*stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
- goto fail;
-
-- stage2_first_sector = saved_sector;
-+ stage2_first_sector = *saved_sector;
-
- /* Read the second sector of Stage 2. */
- if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
- goto fail;
-
-- stage2_second_sector = saved_sector;
-+ stage2_second_sector = *saved_sector;
-
- /* Check for the version of Stage 2. */
- if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
-@@ -1987,27 +2177,27 @@
-
- /* If INSTALLADDR is not specified explicitly in the command-line,
- determine it by the Stage 2 id. */
-- if (! installaddr)
-+ if (! *installaddr)
- {
- if (! is_stage1_5)
- /* Stage 2. */
-- installaddr = 0x8000;
-+ *installaddr = 0x8000;
- else
- /* Stage 1.5. */
-- installaddr = 0x2000;
-+ *installaddr = 0x2000;
- }
-
- *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
- = stage2_first_sector;
- *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
-- = installaddr;
-+ = *installaddr;
- *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
-- = installaddr >> 4;
-+ = *installaddr >> 4;
-
-- i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
-+ i = (int) *stage2_first_buffer + SECTOR_SIZE - 4;
- while (*((unsigned long *) i))
- {
-- if (i < (int) stage2_first_buffer
-+ if (i < (int) *stage2_first_buffer
- || (*((int *) (i - 4)) & 0x80000000)
- || *((unsigned short *) i) >= 0xA00
- || *((short *) (i + 2)) == 0)
-@@ -2021,13 +2211,13 @@
- i -= 8;
- }
-
-- installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;
-- installaddr += SECTOR_SIZE;
-+ *installlist = (int) *stage2_first_buffer + SECTOR_SIZE + 4;
-+ *installaddr += SECTOR_SIZE;
-
- /* Read the whole of Stage2 except for the first sector. */
- grub_seek (SECTOR_SIZE);
-
-- disk_read_hook = disk_read_blocklist_func;
-+ disk_read_hook = install_blocklist_helper;
- if (! grub_read (dummy, -1))
- goto fail;
-
-@@ -2110,7 +2300,7 @@
- /* Skip the first sector. */
- grub_seek (SECTOR_SIZE);
-
-- disk_read_hook = disk_read_savesect_func;
-+ disk_read_hook = install_savesect_helper;
- if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
- goto fail;
-
-@@ -2180,7 +2370,7 @@
- else
- #endif /* GRUB_UTIL */
- {
-- if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
-+ if (! devwrite (*saved_sector - part_start, 1, stage2_buffer))
- goto fail;
- }
- }
-@@ -2202,7 +2392,7 @@
- goto fail;
- }
-
-- if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
-+ if (fwrite (*stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
- {
- fclose (fp);
- errnum = ERR_WRITE;
-@@ -2229,7 +2419,7 @@
- goto fail;
-
- if (! devwrite (stage2_first_sector - src_part_start, 1,
-- stage2_first_buffer))
-+ *stage2_first_buffer))
- goto fail;
-
- if (! devwrite (stage2_second_sector - src_part_start, 1,
-@@ -2815,8 +3005,8 @@
- {
- int new_type;
- unsigned long part = 0xFFFFFF;
-- unsigned long start, len, offset, ext_offset;
-- int entry, type;
-+ unsigned long start, len, offset, ext_offset, gpt_offset;
-+ int entry, type, gpt_count, gpt_size;
- char mbr[512];
-
- /* Get the drive and the partition. */
-@@ -2853,8 +3043,15 @@
- /* Look for the partition. */
- while (next_partition (current_drive, 0xFFFFFF, &part, &type,
- &start, &len, &offset, &entry,
-- &ext_offset, mbr))
-+ &ext_offset, &gpt_offset, &gpt_count, &gpt_size, mbr))
- {
-+ /* The partition may not be a GPT partition. */
-+ if (gpt_offset != 0)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
- if (part == current_partition)
- {
- /* Found. */
-@@ -3830,15 +4027,15 @@
- {
- char tmp[16];
- grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
-- grub_strncat (device, tmp, 256);
-+ grub_strncat (device, tmp, sizeof (device));
- }
- if ((partition & 0x00FF00) != 0x00FF00)
- {
- char tmp[16];
- grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
-- grub_strncat (device, tmp, 256);
-+ grub_strncat (device, tmp, sizeof (device));
- }
-- grub_strncat (device, ")", 256);
-+ grub_strncat (device, ")", sizeof (device));
- }
-
- int embed_stage1_5 (char *stage1_5, int drive, int partition)
-@@ -4085,7 +4282,7 @@
- };
-
- \f
--#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
-+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
- /* terminal */
- static int
- terminal_func (char *arg, int flags)
-@@ -4244,17 +4441,21 @@
- end:
- current_term = term_table + default_term;
- current_term->flags = term_flags;
--
-+
- if (lines)
- max_lines = lines;
- else
-- /* 24 would be a good default value. */
-- max_lines = 24;
--
-+ max_lines = current_term->max_lines;
-+
- /* If the interface is currently the command-line,
- restart it to repaint the screen. */
-- if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
-+ if ((current_term != prev_term) && (flags & BUILTIN_CMDLINE)){
-+ if (prev_term->shutdown)
-+ prev_term->shutdown();
-+ if (current_term->startup)
-+ current_term->startup();
- grub_longjmp (restart_cmdline_env, 0);
-+ }
-
- return 0;
- }
-@@ -4264,7 +4465,7 @@
- "terminal",
- terminal_func,
- BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-- "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]",
-+ "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules] [graphics]",
- "Select a terminal. When multiple terminals are specified, wait until"
- " you push any key to continue. If both console and serial are specified,"
- " the terminal to which you input a key first will be selected. If no"
-@@ -4276,7 +4477,7 @@
- " seconds. The option --lines specifies the maximum number of lines."
- " The option --silent is used to suppress messages."
- };
--#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
-+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
-
- \f
- #ifdef SUPPORT_SERIAL
-@@ -4795,6 +4996,9 @@
- /* The table of builtin commands. Sorted in dictionary order. */
- struct builtin *builtin_table[] =
- {
-+#ifdef SUPPORT_GRAPHICS
-+ &builtin_background,
-+#endif
- &builtin_blocklist,
- &builtin_boot,
- #ifdef SUPPORT_NETBOOT
-@@ -4802,6 +5006,7 @@
- #endif /* SUPPORT_NETBOOT */
- &builtin_cat,
- &builtin_chainloader,
-+ &builtin_clear,
- &builtin_cmp,
- &builtin_color,
- &builtin_configfile,
-@@ -4821,6 +5026,9 @@
- &builtin_embed,
- &builtin_fallback,
- &builtin_find,
-+#ifdef SUPPORT_GRAPHICS
-+ &builtin_foreground,
-+#endif
- &builtin_fstest,
- &builtin_geometry,
- &builtin_halt,
-@@ -4864,9 +5072,12 @@
- #endif /* SUPPORT_SERIAL */
- &builtin_setkey,
- &builtin_setup,
--#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
-+#ifdef SUPPORT_GRAPHICS
-+ &builtin_splashimage,
-+#endif /* SUPPORT_GRAPHICS */
-+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
- &builtin_terminal,
--#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
-+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES || SUPPORT_GRAPHICS */
- #ifdef SUPPORT_SERIAL
- &builtin_terminfo,
- #endif /* SUPPORT_SERIAL */
-diff -Nur grub-0.97/stage2/builtins.c.orig grub-0.97-patched/stage2/builtins.c.orig
---- grub-0.97/stage2/builtins.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/builtins.c.orig 2005-02-15 22:58:23.000000000 +0100
-@@ -0,0 +1,4884 @@
-+/* builtins.c - the GRUB builtin commands */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+/* Include stdio.h before shared.h, because we can't define
-+ WITHOUT_LIBC_STUBS here. */
-+#ifdef GRUB_UTIL
-+# include <stdio.h>
-+#endif
-+
-+#include <shared.h>
-+#include <filesys.h>
-+#include <term.h>
-+
-+#ifdef SUPPORT_NETBOOT
-+# define GRUB 1
-+# include <etherboot.h>
-+#endif
-+
-+#ifdef SUPPORT_SERIAL
-+# include <serial.h>
-+# include <terminfo.h>
-+#endif
-+
-+#ifdef GRUB_UTIL
-+# include <device.h>
-+#else /* ! GRUB_UTIL */
-+# include <apic.h>
-+# include <smp-imps.h>
-+#endif /* ! GRUB_UTIL */
-+
-+#ifdef USE_MD5_PASSWORDS
-+# include <md5.h>
-+#endif
-+
-+/* The type of kernel loaded. */
-+kernel_t kernel_type;
-+/* The boot device. */
-+static int bootdev;
-+/* True when the debug mode is turned on, and false
-+ when it is turned off. */
-+int debug = 0;
-+/* The default entry. */
-+int default_entry = 0;
-+/* The fallback entry. */
-+int fallback_entryno;
-+int fallback_entries[MAX_FALLBACK_ENTRIES];
-+/* The number of current entry. */
-+int current_entryno;
-+/* The address for Multiboot command-line buffer. */
-+static char *mb_cmdline;
-+/* The password. */
-+char *password;
-+/* The password type. */
-+password_t password_type;
-+/* The flag for indicating that the user is authoritative. */
-+int auth = 0;
-+/* The timeout. */
-+int grub_timeout = -1;
-+/* Whether to show the menu or not. */
-+int show_menu = 1;
-+/* The BIOS drive map. */
-+static unsigned short bios_drive_map[DRIVE_MAP_SIZE + 1];
-+
-+/* Prototypes for allowing straightfoward calling of builtins functions
-+ inside other functions. */
-+static int configfile_func (char *arg, int flags);
-+
-+/* Initialize the data for builtins. */
-+void
-+init_builtins (void)
-+{
-+ kernel_type = KERNEL_TYPE_NONE;
-+ /* BSD and chainloading evil hacks! */
-+ bootdev = set_bootdev (0);
-+ mb_cmdline = (char *) MB_CMDLINE_BUF;
-+}
-+
-+/* Initialize the data for the configuration file. */
-+void
-+init_config (void)
-+{
-+ default_entry = 0;
-+ password = 0;
-+ fallback_entryno = -1;
-+ fallback_entries[0] = -1;
-+ grub_timeout = -1;
-+}
-+
-+/* Check a password for correctness. Returns 0 if password was
-+ correct, and a value != 0 for error, similarly to strcmp. */
-+int
-+check_password (char *entered, char* expected, password_t type)
-+{
-+ switch (type)
-+ {
-+ case PASSWORD_PLAIN:
-+ return strcmp (entered, expected);
-+
-+#ifdef USE_MD5_PASSWORDS
-+ case PASSWORD_MD5:
-+ return check_md5_password (entered, expected);
-+#endif
-+ default:
-+ /* unsupported password type: be secure */
-+ return 1;
-+ }
-+}
-+
-+/* Print which sector is read when loading a file. */
-+static void
-+disk_read_print_func (int sector, int offset, int length)
-+{
-+ grub_printf ("[%d,%d,%d]", sector, offset, length);
-+}
-+
-+\f
-+/* blocklist */
-+static int
-+blocklist_func (char *arg, int flags)
-+{
-+ char *dummy = (char *) RAW_ADDR (0x100000);
-+ int start_sector;
-+ int num_sectors = 0;
-+ int num_entries = 0;
-+ int last_length = 0;
-+
-+ auto void disk_read_blocklist_func (int sector, int offset, int length);
-+
-+ /* Collect contiguous blocks into one entry as many as possible,
-+ and print the blocklist notation on the screen. */
-+ auto void disk_read_blocklist_func (int sector, int offset, int length)
-+ {
-+ if (num_sectors > 0)
-+ {
-+ if (start_sector + num_sectors == sector
-+ && offset == 0 && last_length == SECTOR_SIZE)
-+ {
-+ num_sectors++;
-+ last_length = length;
-+ return;
-+ }
-+ else
-+ {
-+ if (last_length == SECTOR_SIZE)
-+ grub_printf ("%s%d+%d", num_entries ? "," : "",
-+ start_sector - part_start, num_sectors);
-+ else if (num_sectors > 1)
-+ grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "",
-+ start_sector - part_start, num_sectors-1,
-+ start_sector + num_sectors-1 - part_start,
-+ last_length);
-+ else
-+ grub_printf ("%s%d[0-%d]", num_entries ? "," : "",
-+ start_sector - part_start, last_length);
-+ num_entries++;
-+ num_sectors = 0;
-+ }
-+ }
-+
-+ if (offset > 0)
-+ {
-+ grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
-+ sector-part_start, offset, offset+length);
-+ num_entries++;
-+ }
-+ else
-+ {
-+ start_sector = sector;
-+ num_sectors = 1;
-+ last_length = length;
-+ }
-+ }
-+
-+ /* Open the file. */
-+ if (! grub_open (arg))
-+ return 1;
-+
-+ /* Print the device name. */
-+ grub_printf ("(%cd%d",
-+ (current_drive & 0x80) ? 'h' : 'f',
-+ current_drive & ~0x80);
-+
-+ if ((current_partition & 0xFF0000) != 0xFF0000)
-+ grub_printf (",%d", (current_partition >> 16) & 0xFF);
-+
-+ if ((current_partition & 0x00FF00) != 0x00FF00)
-+ grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF));
-+
-+ grub_printf (")");
-+
-+ /* Read in the whole file to DUMMY. */
-+ disk_read_hook = disk_read_blocklist_func;
-+ if (! grub_read (dummy, -1))
-+ goto fail;
-+
-+ /* The last entry may not be printed yet. Don't check if it is a
-+ * full sector, since it doesn't matter if we read too much. */
-+ if (num_sectors > 0)
-+ grub_printf ("%s%d+%d", num_entries ? "," : "",
-+ start_sector - part_start, num_sectors);
-+
-+ grub_printf ("\n");
-+
-+ fail:
-+ disk_read_hook = 0;
-+ grub_close ();
-+ return errnum;
-+}
-+
-+static struct builtin builtin_blocklist =
-+{
-+ "blocklist",
-+ blocklist_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "blocklist FILE",
-+ "Print the blocklist notation of the file FILE."
-+};
-+
-+/* boot */
-+static int
-+boot_func (char *arg, int flags)
-+{
-+ /* Clear the int15 handler if we can boot the kernel successfully.
-+ This assumes that the boot code never fails only if KERNEL_TYPE is
-+ not KERNEL_TYPE_NONE. Is this assumption is bad? */
-+ if (kernel_type != KERNEL_TYPE_NONE)
-+ unset_int15_handler ();
-+
-+#ifdef SUPPORT_NETBOOT
-+ /* Shut down the networking. */
-+ cleanup_net ();
-+#endif
-+
-+ switch (kernel_type)
-+ {
-+ case KERNEL_TYPE_FREEBSD:
-+ case KERNEL_TYPE_NETBSD:
-+ /* *BSD */
-+ bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);
-+ break;
-+
-+ case KERNEL_TYPE_LINUX:
-+ /* Linux */
-+ linux_boot ();
-+ break;
-+
-+ case KERNEL_TYPE_BIG_LINUX:
-+ /* Big Linux */
-+ big_linux_boot ();
-+ break;
-+
-+ case KERNEL_TYPE_CHAINLOADER:
-+ /* Chainloader */
-+
-+ /* Check if we should set the int13 handler. */
-+ if (bios_drive_map[0] != 0)
-+ {
-+ int i;
-+
-+ /* Search for SAVED_DRIVE. */
-+ for (i = 0; i < DRIVE_MAP_SIZE; i++)
-+ {
-+ if (! bios_drive_map[i])
-+ break;
-+ else if ((bios_drive_map[i] & 0xFF) == saved_drive)
-+ {
-+ /* Exchage SAVED_DRIVE with the mapped drive. */
-+ saved_drive = (bios_drive_map[i] >> 8) & 0xFF;
-+ break;
-+ }
-+ }
-+
-+ /* Set the handler. This is somewhat dangerous. */
-+ set_int13_handler (bios_drive_map);
-+ }
-+
-+ gateA20 (0);
-+ boot_drive = saved_drive;
-+ chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr);
-+ break;
-+
-+ case KERNEL_TYPE_MULTIBOOT:
-+ /* Multiboot */
-+ multi_boot ((int) entry_addr, (int) &mbi);
-+ break;
-+
-+ default:
-+ errnum = ERR_BOOT_COMMAND;
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_boot =
-+{
-+ "boot",
-+ boot_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "boot",
-+ "Boot the OS/chain-loader which has been loaded."
-+};
-+
-+\f
-+#ifdef SUPPORT_NETBOOT
-+/* bootp */
-+static int
-+bootp_func (char *arg, int flags)
-+{
-+ int with_configfile = 0;
-+
-+ if (grub_memcmp (arg, "--with-configfile", sizeof ("--with-configfile") - 1)
-+ == 0)
-+ {
-+ with_configfile = 1;
-+ arg = skip_to (0, arg);
-+ }
-+
-+ if (! bootp ())
-+ {
-+ if (errnum == ERR_NONE)
-+ errnum = ERR_DEV_VALUES;
-+
-+ return 1;
-+ }
-+
-+ /* Notify the configuration. */
-+ print_network_configuration ();
-+
-+ /* XXX: this can cause an endless loop, but there is no easy way to
-+ detect such a loop unfortunately. */
-+ if (with_configfile)
-+ configfile_func (config_file, flags);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_bootp =
-+{
-+ "bootp",
-+ bootp_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "bootp [--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."
-+};
-+#endif /* SUPPORT_NETBOOT */
-+
-+\f
-+/* cat */
-+static int
-+cat_func (char *arg, int flags)
-+{
-+ char c;
-+
-+ if (! grub_open (arg))
-+ return 1;
-+
-+ while (grub_read (&c, 1))
-+ {
-+ /* Because running "cat" with a binary file can confuse the terminal,
-+ print only some characters as they are. */
-+ if (grub_isspace (c) || (c >= ' ' && c <= '~'))
-+ grub_putchar (c);
-+ else
-+ grub_putchar ('?');
-+ }
-+
-+ grub_close ();
-+ return 0;
-+}
-+
-+static struct builtin builtin_cat =
-+{
-+ "cat",
-+ cat_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "cat FILE",
-+ "Print the contents of the file FILE."
-+};
-+
-+\f
-+/* chainloader */
-+static int
-+chainloader_func (char *arg, int flags)
-+{
-+ int force = 0;
-+ char *file = arg;
-+
-+ /* If the option `--force' is specified? */
-+ if (substring ("--force", arg) <= 0)
-+ {
-+ force = 1;
-+ file = skip_to (0, arg);
-+ }
-+
-+ /* Open the file. */
-+ if (! grub_open (file))
-+ {
-+ kernel_type = KERNEL_TYPE_NONE;
-+ return 1;
-+ }
-+
-+ /* Read the first block. */
-+ if (grub_read ((char *) BOOTSEC_LOCATION, SECTOR_SIZE) != SECTOR_SIZE)
-+ {
-+ grub_close ();
-+ kernel_type = KERNEL_TYPE_NONE;
-+
-+ /* This below happens, if a file whose size is less than 512 bytes
-+ is loaded. */
-+ if (errnum == ERR_NONE)
-+ errnum = ERR_EXEC_FORMAT;
-+
-+ return 1;
-+ }
-+
-+ /* If not loading it forcibly, check for the signature. */
-+ if (! force
-+ && (*((unsigned short *) (BOOTSEC_LOCATION + BOOTSEC_SIG_OFFSET))
-+ != BOOTSEC_SIGNATURE))
-+ {
-+ grub_close ();
-+ errnum = ERR_EXEC_FORMAT;
-+ kernel_type = KERNEL_TYPE_NONE;
-+ return 1;
-+ }
-+
-+ grub_close ();
-+ kernel_type = KERNEL_TYPE_CHAINLOADER;
-+
-+ /* XXX: Windows evil hack. For now, only the first five letters are
-+ checked. */
-+ if (IS_PC_SLICE_TYPE_FAT (current_slice)
-+ && ! grub_memcmp ((char *) BOOTSEC_LOCATION + BOOTSEC_BPB_SYSTEM_ID,
-+ "MSWIN", 5))
-+ *((unsigned long *) (BOOTSEC_LOCATION + BOOTSEC_BPB_HIDDEN_SECTORS))
-+ = part_start;
-+
-+ errnum = ERR_NONE;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_chainloader =
-+{
-+ "chainloader",
-+ chainloader_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "chainloader [--force] FILE",
-+ "Load the chain-loader FILE. If --force is specified, then load it"
-+ " forcibly, whether the boot loader signature is present or not."
-+};
-+
-+\f
-+/* This function could be used to debug new filesystem code. Put a file
-+ in the new filesystem and the same file in a well-tested filesystem.
-+ Then, run "cmp" with the files. If no output is obtained, probably
-+ the code is good, otherwise investigate what's wrong... */
-+/* cmp FILE1 FILE2 */
-+static int
-+cmp_func (char *arg, int flags)
-+{
-+ /* The filenames. */
-+ char *file1, *file2;
-+ /* The addresses. */
-+ char *addr1, *addr2;
-+ int i;
-+ /* The size of the file. */
-+ int size;
-+
-+ /* Get the filenames from ARG. */
-+ file1 = arg;
-+ file2 = skip_to (0, arg);
-+ if (! *file1 || ! *file2)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ /* Terminate the filenames for convenience. */
-+ nul_terminate (file1);
-+ nul_terminate (file2);
-+
-+ /* Read the whole data from FILE1. */
-+ addr1 = (char *) RAW_ADDR (0x100000);
-+ if (! grub_open (file1))
-+ return 1;
-+
-+ /* Get the size. */
-+ size = filemax;
-+ if (grub_read (addr1, -1) != size)
-+ {
-+ grub_close ();
-+ return 1;
-+ }
-+
-+ grub_close ();
-+
-+ /* Read the whole data from FILE2. */
-+ addr2 = addr1 + size;
-+ if (! grub_open (file2))
-+ return 1;
-+
-+ /* Check if the size of FILE2 is equal to the one of FILE2. */
-+ if (size != filemax)
-+ {
-+ grub_printf ("Differ in size: 0x%x [%s], 0x%x [%s]\n",
-+ size, file1, filemax, file2);
-+ grub_close ();
-+ return 0;
-+ }
-+
-+ if (! grub_read (addr2, -1))
-+ {
-+ grub_close ();
-+ return 1;
-+ }
-+
-+ grub_close ();
-+
-+ /* Now compare ADDR1 with ADDR2. */
-+ for (i = 0; i < size; i++)
-+ {
-+ if (addr1[i] != addr2[i])
-+ grub_printf ("Differ at the offset %d: 0x%x [%s], 0x%x [%s]\n",
-+ i, (unsigned) addr1[i], file1,
-+ (unsigned) addr2[i], file2);
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_cmp =
-+{
-+ "cmp",
-+ cmp_func,
-+ BUILTIN_CMDLINE,
-+ "cmp FILE1 FILE2",
-+ "Compare the file FILE1 with the FILE2 and inform the different values"
-+ " if any."
-+};
-+
-+\f
-+/* color */
-+/* Set new colors used for the menu interface. Support two methods to
-+ specify a color name: a direct integer representation and a symbolic
-+ color name. An example of the latter is "blink-light-gray/blue". */
-+static int
-+color_func (char *arg, int flags)
-+{
-+ char *normal;
-+ char *highlight;
-+ int new_normal_color;
-+ int new_highlight_color;
-+ static char *color_list[16] =
-+ {
-+ "black",
-+ "blue",
-+ "green",
-+ "cyan",
-+ "red",
-+ "magenta",
-+ "brown",
-+ "light-gray",
-+ "dark-gray",
-+ "light-blue",
-+ "light-green",
-+ "light-cyan",
-+ "light-red",
-+ "light-magenta",
-+ "yellow",
-+ "white"
-+ };
-+
-+ auto int color_number (char *str);
-+
-+ /* Convert the color name STR into the magical number. */
-+ auto int color_number (char *str)
-+ {
-+ char *ptr;
-+ int i;
-+ int color = 0;
-+
-+ /* Find the separator. */
-+ for (ptr = str; *ptr && *ptr != '/'; ptr++)
-+ ;
-+
-+ /* If not found, return -1. */
-+ if (! *ptr)
-+ return -1;
-+
-+ /* Terminate the string STR. */
-+ *ptr++ = 0;
-+
-+ /* If STR contains the prefix "blink-", then set the `blink' bit
-+ in COLOR. */
-+ if (substring ("blink-", str) <= 0)
-+ {
-+ color = 0x80;
-+ str += 6;
-+ }
-+
-+ /* Search for the color name. */
-+ for (i = 0; i < 16; i++)
-+ if (grub_strcmp (color_list[i], str) == 0)
-+ {
-+ color |= i;
-+ break;
-+ }
-+
-+ if (i == 16)
-+ return -1;
-+
-+ str = ptr;
-+ nul_terminate (str);
-+
-+ /* Search for the color name. */
-+ for (i = 0; i < 8; i++)
-+ if (grub_strcmp (color_list[i], str) == 0)
-+ {
-+ color |= i << 4;
-+ break;
-+ }
-+
-+ if (i == 8)
-+ return -1;
-+
-+ return color;
-+ }
-+
-+ normal = arg;
-+ highlight = skip_to (0, arg);
-+
-+ new_normal_color = color_number (normal);
-+ if (new_normal_color < 0 && ! safe_parse_maxint (&normal, &new_normal_color))
-+ return 1;
-+
-+ /* The second argument is optional, so set highlight_color
-+ to inverted NORMAL_COLOR. */
-+ if (! *highlight)
-+ new_highlight_color = ((new_normal_color >> 4)
-+ | ((new_normal_color & 0xf) << 4));
-+ else
-+ {
-+ new_highlight_color = color_number (highlight);
-+ if (new_highlight_color < 0
-+ && ! safe_parse_maxint (&highlight, &new_highlight_color))
-+ return 1;
-+ }
-+
-+ if (current_term->setcolor)
-+ current_term->setcolor (new_normal_color, new_highlight_color);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_color =
-+{
-+ "color",
-+ color_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "color NORMAL [HIGHLIGHT]",
-+ "Change the menu colors. The color NORMAL is used for most"
-+ " lines in the menu, and the color HIGHLIGHT is used to highlight the"
-+ " line where the cursor points. If you omit HIGHLIGHT, then the"
-+ " inverted color of NORMAL is used for the highlighted line."
-+ " The format of a color is \"FG/BG\". FG and BG are symbolic color names."
-+ " A symbolic color name must be one of these: black, blue, green,"
-+ " cyan, red, magenta, brown, light-gray, dark-gray, light-blue,"
-+ " light-green, light-cyan, light-red, light-magenta, yellow and white."
-+ " But only the first eight names can be used for BG. You can prefix"
-+ " \"blink-\" to FG if you want a blinking foreground color."
-+};
-+
-+\f
-+/* configfile */
-+static int
-+configfile_func (char *arg, int flags)
-+{
-+ char *new_config = config_file;
-+
-+ /* Check if the file ARG is present. */
-+ if (! grub_open (arg))
-+ return 1;
-+
-+ grub_close ();
-+
-+ /* Copy ARG to CONFIG_FILE. */
-+ while ((*new_config++ = *arg++) != 0)
-+ ;
-+
-+#ifdef GRUB_UTIL
-+ /* Force to load the configuration file. */
-+ use_config_file = 1;
-+#endif
-+
-+ /* Make sure that the user will not be authoritative. */
-+ auth = 0;
-+
-+ /* Restart cmain. */
-+ grub_longjmp (restart_env, 0);
-+
-+ /* Never reach here. */
-+ return 0;
-+}
-+
-+static struct builtin builtin_configfile =
-+{
-+ "configfile",
-+ configfile_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "configfile FILE",
-+ "Load FILE as the configuration file."
-+};
-+
-+\f
-+/* debug */
-+static int
-+debug_func (char *arg, int flags)
-+{
-+ if (debug)
-+ {
-+ debug = 0;
-+ grub_printf (" Debug mode is turned off\n");
-+ }
-+ else
-+ {
-+ debug = 1;
-+ grub_printf (" Debug mode is turned on\n");
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_debug =
-+{
-+ "debug",
-+ debug_func,
-+ BUILTIN_CMDLINE,
-+ "debug",
-+ "Turn on/off the debug mode."
-+};
-+
-+\f
-+/* default */
-+static int
-+default_func (char *arg, int flags)
-+{
-+#ifndef SUPPORT_DISKLESS
-+ if (grub_strcmp (arg, "saved") == 0)
-+ {
-+ default_entry = saved_entryno;
-+ return 0;
-+ }
-+#endif /* SUPPORT_DISKLESS */
-+
-+ if (! safe_parse_maxint (&arg, &default_entry))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_default =
-+{
-+ "default",
-+ default_func,
-+ BUILTIN_MENU,
-+#if 0
-+ "default [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."
-+#endif
-+};
-+
-+\f
-+#ifdef GRUB_UTIL
-+/* device */
-+static int
-+device_func (char *arg, int flags)
-+{
-+ char *drive = arg;
-+ char *device;
-+
-+ /* Get the drive number from DRIVE. */
-+ if (! set_device (drive))
-+ return 1;
-+
-+ /* Get the device argument. */
-+ device = skip_to (0, drive);
-+
-+ /* Terminate DEVICE. */
-+ nul_terminate (device);
-+
-+ if (! *device || ! check_device (device))
-+ {
-+ errnum = ERR_FILE_NOT_FOUND;
-+ return 1;
-+ }
-+
-+ assign_device_name (current_drive, device);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_device =
-+{
-+ "device",
-+ device_func,
-+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "device DRIVE DEVICE",
-+ "Specify DEVICE as the actual drive for a BIOS drive DRIVE. This command"
-+ " can be used only in the grub shell."
-+};
-+#endif /* GRUB_UTIL */
-+
-+\f
-+#ifdef SUPPORT_NETBOOT
-+/* dhcp */
-+static int
-+dhcp_func (char *arg, int flags)
-+{
-+ /* For now, this is an alias for bootp. */
-+ return bootp_func (arg, flags);
-+}
-+
-+static struct builtin builtin_dhcp =
-+{
-+ "dhcp",
-+ dhcp_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "dhcp",
-+ "Initialize a network device via DHCP."
-+};
-+#endif /* SUPPORT_NETBOOT */
-+
-+\f
-+/* displayapm */
-+static int
-+displayapm_func (char *arg, int flags)
-+{
-+ if (mbi.flags & MB_INFO_APM_TABLE)
-+ {
-+ grub_printf ("APM BIOS information:\n"
-+ " Version: 0x%x\n"
-+ " 32-bit CS: 0x%x\n"
-+ " Offset: 0x%x\n"
-+ " 16-bit CS: 0x%x\n"
-+ " 16-bit DS: 0x%x\n"
-+ " 32-bit CS length: 0x%x\n"
-+ " 16-bit CS length: 0x%x\n"
-+ " 16-bit DS length: 0x%x\n",
-+ (unsigned) apm_bios_info.version,
-+ (unsigned) apm_bios_info.cseg,
-+ apm_bios_info.offset,
-+ (unsigned) apm_bios_info.cseg_16,
-+ (unsigned) apm_bios_info.dseg_16,
-+ (unsigned) apm_bios_info.cseg_len,
-+ (unsigned) apm_bios_info.cseg_16_len,
-+ (unsigned) apm_bios_info.dseg_16_len);
-+ }
-+ else
-+ {
-+ grub_printf ("No APM BIOS found or probe failed\n");
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_displayapm =
-+{
-+ "displayapm",
-+ displayapm_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "displayapm",
-+ "Display APM BIOS information."
-+};
-+
-+\f
-+/* displaymem */
-+static int
-+displaymem_func (char *arg, int flags)
-+{
-+ if (get_eisamemsize () != -1)
-+ grub_printf (" EISA Memory BIOS Interface is present\n");
-+ if (get_mmap_entry ((void *) SCRATCHADDR, 0) != 0
-+ || *((int *) SCRATCHADDR) != 0)
-+ grub_printf (" Address Map BIOS Interface is present\n");
-+
-+ grub_printf (" Lower memory: %uK, "
-+ "Upper memory (to first chipset hole): %uK\n",
-+ mbi.mem_lower, mbi.mem_upper);
-+
-+ if (mbi.flags & MB_INFO_MEM_MAP)
-+ {
-+ struct AddrRangeDesc *map = (struct AddrRangeDesc *) mbi.mmap_addr;
-+ int end_addr = mbi.mmap_addr + mbi.mmap_length;
-+
-+ grub_printf (" [Address Range Descriptor entries "
-+ "immediately follow (values are 64-bit)]\n");
-+ while (end_addr > (int) map)
-+ {
-+ char *str;
-+
-+ if (map->Type == MB_ARD_MEMORY)
-+ str = "Usable RAM";
-+ else
-+ str = "Reserved";
-+ grub_printf (" %s: Base Address: 0x%x X 4GB + 0x%x,\n"
-+ " Length: 0x%x X 4GB + 0x%x bytes\n",
-+ str,
-+ (unsigned long) (map->BaseAddr >> 32),
-+ (unsigned long) (map->BaseAddr & 0xFFFFFFFF),
-+ (unsigned long) (map->Length >> 32),
-+ (unsigned long) (map->Length & 0xFFFFFFFF));
-+
-+ map = ((struct AddrRangeDesc *) (((int) map) + 4 + map->size));
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_displaymem =
-+{
-+ "displaymem",
-+ displaymem_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "displaymem",
-+ "Display what GRUB thinks the system address space map of the"
-+ " machine is, including all regions of physical RAM installed."
-+};
-+
-+\f
-+/* dump FROM TO */
-+#ifdef GRUB_UTIL
-+static int
-+dump_func (char *arg, int flags)
-+{
-+ char *from, *to;
-+ FILE *fp;
-+ char c;
-+
-+ from = arg;
-+ to = skip_to (0, arg);
-+ if (! *from || ! *to)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ nul_terminate (from);
-+ nul_terminate (to);
-+
-+ if (! grub_open (from))
-+ return 1;
-+
-+ fp = fopen (to, "w");
-+ if (! fp)
-+ {
-+ errnum = ERR_WRITE;
-+ return 1;
-+ }
-+
-+ while (grub_read (&c, 1))
-+ if (fputc (c, fp) == EOF)
-+ {
-+ errnum = ERR_WRITE;
-+ fclose (fp);
-+ return 1;
-+ }
-+
-+ if (fclose (fp) == EOF)
-+ {
-+ errnum = ERR_WRITE;
-+ return 1;
-+ }
-+
-+ grub_close ();
-+ return 0;
-+}
-+
-+static struct builtin builtin_dump =
-+ {
-+ "dump",
-+ dump_func,
-+ BUILTIN_CMDLINE,
-+ "dump FROM TO",
-+ "Dump the contents of the file FROM to the file TO. FROM must be"
-+ " a GRUB file and TO must be an OS file."
-+ };
-+#endif /* GRUB_UTIL */
-+
-+\f
-+static char embed_info[32];
-+/* embed */
-+/* Embed a Stage 1.5 in the first cylinder after MBR or in the
-+ bootloader block in a FFS. */
-+static int
-+embed_func (char *arg, int flags)
-+{
-+ char *stage1_5;
-+ char *device;
-+ char *stage1_5_buffer = (char *) RAW_ADDR (0x100000);
-+ int len, size;
-+ int sector;
-+
-+ stage1_5 = arg;
-+ device = skip_to (0, stage1_5);
-+
-+ /* Open a Stage 1.5. */
-+ if (! grub_open (stage1_5))
-+ return 1;
-+
-+ /* Read the whole of the Stage 1.5. */
-+ len = grub_read (stage1_5_buffer, -1);
-+ grub_close ();
-+
-+ if (errnum)
-+ return 1;
-+
-+ size = (len + SECTOR_SIZE - 1) / SECTOR_SIZE;
-+
-+ /* Get the device where the Stage 1.5 will be embedded. */
-+ set_device (device);
-+ if (errnum)
-+ return 1;
-+
-+ if (current_partition == 0xFFFFFF)
-+ {
-+ /* Embed it after the MBR. */
-+
-+ char mbr[SECTOR_SIZE];
-+ char ezbios_check[2*SECTOR_SIZE];
-+ int i;
-+
-+ /* Open the partition. */
-+ if (! open_partition ())
-+ return 1;
-+
-+ /* No floppy has MBR. */
-+ if (! (current_drive & 0x80))
-+ {
-+ errnum = ERR_DEV_VALUES;
-+ return 1;
-+ }
-+
-+ /* Read the MBR of CURRENT_DRIVE. */
-+ if (! rawread (current_drive, PC_MBR_SECTOR, 0, SECTOR_SIZE, mbr))
-+ return 1;
-+
-+ /* Sanity check. */
-+ if (! PC_MBR_CHECK_SIG (mbr))
-+ {
-+ errnum = ERR_BAD_PART_TABLE;
-+ return 1;
-+ }
-+
-+ /* Check if the disk can store the Stage 1.5. */
-+ for (i = 0; i < 4; i++)
-+ if (PC_SLICE_TYPE (mbr, i) && PC_SLICE_START (mbr, i) - 1 < size)
-+ {
-+ errnum = ERR_NO_DISK_SPACE;
-+ return 1;
-+ }
-+
-+ /* Check for EZ-BIOS signature. It should be in the third
-+ * sector, but due to remapping it can appear in the second, so
-+ * load and check both.
-+ */
-+ if (! rawread (current_drive, 1, 0, 2 * SECTOR_SIZE, ezbios_check))
-+ return 1;
-+
-+ if (! memcmp (ezbios_check + 3, "AERMH", 5)
-+ || ! memcmp (ezbios_check + 512 + 3, "AERMH", 5))
-+ {
-+ /* The space after the MBR is used by EZ-BIOS which we must
-+ * not overwrite.
-+ */
-+ errnum = ERR_NO_DISK_SPACE;
-+ return 1;
-+ }
-+
-+ sector = 1;
-+ }
-+ else
-+ {
-+ /* Embed it in the bootloader block in the filesystem. */
-+ int start_sector;
-+
-+ /* Open the partition. */
-+ if (! open_device ())
-+ return 1;
-+
-+ /* Check if the current slice supports embedding. */
-+ if (fsys_table[fsys_type].embed_func == 0
-+ || ! fsys_table[fsys_type].embed_func (&start_sector, size))
-+ {
-+ errnum = ERR_DEV_VALUES;
-+ return 1;
-+ }
-+
-+ sector = part_start + start_sector;
-+ }
-+
-+ /* Clear the cache. */
-+ buf_track = -1;
-+
-+ /* Now perform the embedding. */
-+ if (! devwrite (sector - part_start, size, stage1_5_buffer))
-+ return 1;
-+
-+ grub_printf (" %d sectors are embedded.\n", size);
-+ grub_sprintf (embed_info, "%d+%d", sector - part_start, size);
-+ return 0;
-+}
-+
-+static struct builtin builtin_embed =
-+{
-+ "embed",
-+ embed_func,
-+ BUILTIN_CMDLINE,
-+ "embed STAGE1_5 DEVICE",
-+ "Embed the Stage 1.5 STAGE1_5 in the sectors after MBR if DEVICE"
-+ " is a drive, or in the \"bootloader\" area if DEVICE is a FFS partition."
-+ " Print the number of sectors which STAGE1_5 occupies if successful."
-+};
-+
-+\f
-+/* fallback */
-+static int
-+fallback_func (char *arg, int flags)
-+{
-+ int i = 0;
-+
-+ while (*arg)
-+ {
-+ int entry;
-+ int j;
-+
-+ if (! safe_parse_maxint (&arg, &entry))
-+ return 1;
-+
-+ /* Remove duplications to prevent infinite looping. */
-+ for (j = 0; j < i; j++)
-+ if (entry == fallback_entries[j])
-+ break;
-+ if (j != i)
-+ continue;
-+
-+ fallback_entries[i++] = entry;
-+ if (i == MAX_FALLBACK_ENTRIES)
-+ break;
-+
-+ arg = skip_to (0, arg);
-+ }
-+
-+ if (i < MAX_FALLBACK_ENTRIES)
-+ fallback_entries[i] = -1;
-+
-+ fallback_entryno = (i == 0) ? -1 : 0;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_fallback =
-+{
-+ "fallback",
-+ fallback_func,
-+ BUILTIN_MENU,
-+#if 0
-+ "fallback NUM...",
-+ "Go into unattended boot mode: if the default boot entry has any"
-+ " errors, instead of waiting for the user to do anything, it"
-+ " immediately starts over using the NUM entry (same numbering as the"
-+ " `default' command). This obviously won't help if the machine"
-+ " was rebooted by a kernel that GRUB loaded."
-+#endif
-+};
-+
-+\f
-+/* find */
-+/* Search for the filename ARG in all of partitions. */
-+static int
-+find_func (char *arg, int flags)
-+{
-+ char *filename = arg;
-+ unsigned long drive;
-+ unsigned long tmp_drive = saved_drive;
-+ unsigned long tmp_partition = saved_partition;
-+ int got_file = 0;
-+
-+ /* Floppies. */
-+ for (drive = 0; drive < 8; drive++)
-+ {
-+ current_drive = drive;
-+ current_partition = 0xFFFFFF;
-+
-+ if (open_device ())
-+ {
-+ saved_drive = current_drive;
-+ saved_partition = current_partition;
-+ if (grub_open (filename))
-+ {
-+ grub_close ();
-+ grub_printf (" (fd%d)\n", drive);
-+ got_file = 1;
-+ }
-+ }
-+
-+ errnum = ERR_NONE;
-+ }
-+
-+ /* Hard disks. */
-+ for (drive = 0x80; drive < 0x88; drive++)
-+ {
-+ unsigned long part = 0xFFFFFF;
-+ unsigned long start, len, offset, ext_offset;
-+ int type, entry;
-+ char buf[SECTOR_SIZE];
-+
-+ current_drive = drive;
-+ while (next_partition (drive, 0xFFFFFF, &part, &type,
-+ &start, &len, &offset, &entry,
-+ &ext_offset, buf))
-+ {
-+ if (type != PC_SLICE_TYPE_NONE
-+ && ! IS_PC_SLICE_TYPE_BSD (type)
-+ && ! IS_PC_SLICE_TYPE_EXTENDED (type))
-+ {
-+ current_partition = part;
-+ if (open_device ())
-+ {
-+ saved_drive = current_drive;
-+ saved_partition = current_partition;
-+ if (grub_open (filename))
-+ {
-+ int bsd_part = (part >> 8) & 0xFF;
-+ int pc_slice = part >> 16;
-+
-+ grub_close ();
-+
-+ if (bsd_part == 0xFF)
-+ grub_printf (" (hd%d,%d)\n",
-+ drive - 0x80, pc_slice);
-+ else
-+ grub_printf (" (hd%d,%d,%c)\n",
-+ drive - 0x80, pc_slice, bsd_part + 'a');
-+
-+ got_file = 1;
-+ }
-+ }
-+ }
-+
-+ /* We want to ignore any error here. */
-+ errnum = ERR_NONE;
-+ }
-+
-+ /* next_partition always sets ERRNUM in the last call, so clear
-+ it. */
-+ errnum = ERR_NONE;
-+ }
-+
-+ saved_drive = tmp_drive;
-+ saved_partition = tmp_partition;
-+
-+ if (got_file)
-+ {
-+ errnum = ERR_NONE;
-+ return 0;
-+ }
-+
-+ errnum = ERR_FILE_NOT_FOUND;
-+ return 1;
-+}
-+
-+static struct builtin builtin_find =
-+{
-+ "find",
-+ find_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "find FILENAME",
-+ "Search for the filename FILENAME in all of partitions and print the list of"
-+ " the devices which contain the file."
-+};
-+
-+\f
-+/* fstest */
-+static int
-+fstest_func (char *arg, int flags)
-+{
-+ if (disk_read_hook)
-+ {
-+ disk_read_hook = NULL;
-+ printf (" Filesystem tracing is now off\n");
-+ }
-+ else
-+ {
-+ disk_read_hook = disk_read_print_func;
-+ printf (" Filesystem tracing is now on\n");
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_fstest =
-+{
-+ "fstest",
-+ fstest_func,
-+ BUILTIN_CMDLINE,
-+ "fstest",
-+ "Toggle filesystem test mode."
-+};
-+
-+\f
-+/* geometry */
-+static int
-+geometry_func (char *arg, int flags)
-+{
-+ struct geometry geom;
-+ char *msg;
-+ char *device = arg;
-+#ifdef GRUB_UTIL
-+ char *ptr;
-+#endif
-+
-+ /* Get the device number. */
-+ set_device (device);
-+ if (errnum)
-+ return 1;
-+
-+ /* Check for the geometry. */
-+ if (get_diskinfo (current_drive, &geom))
-+ {
-+ errnum = ERR_NO_DISK;
-+ return 1;
-+ }
-+
-+ /* Attempt to read the first sector, because some BIOSes turns out not
-+ to support LBA even though they set the bit 0 in the support
-+ bitmap, only after reading something actually. */
-+ if (biosdisk (BIOSDISK_READ, current_drive, &geom, 0, 1, SCRATCHSEG))
-+ {
-+ errnum = ERR_READ;
-+ return 1;
-+ }
-+
-+#ifdef GRUB_UTIL
-+ ptr = skip_to (0, device);
-+ if (*ptr)
-+ {
-+ char *cylinder, *head, *sector, *total_sector;
-+ int num_cylinder, num_head, num_sector, num_total_sector;
-+
-+ cylinder = ptr;
-+ head = skip_to (0, cylinder);
-+ sector = skip_to (0, head);
-+ total_sector = skip_to (0, sector);
-+ if (! safe_parse_maxint (&cylinder, &num_cylinder)
-+ || ! safe_parse_maxint (&head, &num_head)
-+ || ! safe_parse_maxint (§or, &num_sector))
-+ return 1;
-+
-+ disks[current_drive].cylinders = num_cylinder;
-+ disks[current_drive].heads = num_head;
-+ disks[current_drive].sectors = num_sector;
-+
-+ if (safe_parse_maxint (&total_sector, &num_total_sector))
-+ disks[current_drive].total_sectors = num_total_sector;
-+ else
-+ disks[current_drive].total_sectors
-+ = num_cylinder * num_head * num_sector;
-+ errnum = 0;
-+
-+ geom = disks[current_drive];
-+ buf_drive = -1;
-+ }
-+#endif /* GRUB_UTIL */
-+
-+#ifdef GRUB_UTIL
-+ msg = device_map[current_drive];
-+#else
-+ if (geom.flags & BIOSDISK_FLAG_LBA_EXTENSION)
-+ msg = "LBA";
-+ else
-+ msg = "CHS";
-+#endif
-+
-+ grub_printf ("drive 0x%x: C/H/S = %d/%d/%d, "
-+ "The number of sectors = %d, %s\n",
-+ current_drive,
-+ geom.cylinders, geom.heads, geom.sectors,
-+ geom.total_sectors, msg);
-+ real_open_partition (1);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_geometry =
-+{
-+ "geometry",
-+ geometry_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "geometry DRIVE [CYLINDER HEAD SECTOR [TOTAL_SECTOR]]",
-+ "Print the information for a drive DRIVE. In the grub shell, you can"
-+ " set the geometry of the drive arbitrarily. The number of the cylinders,"
-+ " the one of the heads, the one of the sectors and the one of the total"
-+ " sectors are set to CYLINDER, HEAD, SECTOR and TOTAL_SECTOR,"
-+ " respectively. If you omit TOTAL_SECTOR, then it will be calculated based"
-+ " on the C/H/S values automatically."
-+};
-+
-+\f
-+/* halt */
-+static int
-+halt_func (char *arg, int flags)
-+{
-+ int no_apm;
-+
-+ no_apm = (grub_memcmp (arg, "--no-apm", 8) == 0);
-+ grub_halt (no_apm);
-+
-+ /* Never reach here. */
-+ return 1;
-+}
-+
-+static struct builtin builtin_halt =
-+{
-+ "halt",
-+ halt_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "halt [--no-apm]",
-+ "Halt your system. If APM is avaiable on it, turn off the power using"
-+ " the APM BIOS, unless you specify the option `--no-apm'."
-+};
-+
-+\f
-+/* help */
-+#define MAX_SHORT_DOC_LEN 39
-+#define MAX_LONG_DOC_LEN 66
-+
-+static int
-+help_func (char *arg, int flags)
-+{
-+ int all = 0;
-+
-+ if (grub_memcmp (arg, "--all", sizeof ("--all") - 1) == 0)
-+ {
-+ all = 1;
-+ arg = skip_to (0, arg);
-+ }
-+
-+ if (! *arg)
-+ {
-+ /* Invoked with no argument. Print the list of the short docs. */
-+ struct builtin **builtin;
-+ int left = 1;
-+
-+ for (builtin = builtin_table; *builtin != 0; builtin++)
-+ {
-+ int len;
-+ int i;
-+
-+ /* If this cannot be used in the command-line interface,
-+ skip this. */
-+ if (! ((*builtin)->flags & BUILTIN_CMDLINE))
-+ continue;
-+
-+ /* If this doesn't need to be listed automatically and "--all"
-+ is not specified, skip this. */
-+ if (! all && ! ((*builtin)->flags & BUILTIN_HELP_LIST))
-+ continue;
-+
-+ len = grub_strlen ((*builtin)->short_doc);
-+ /* If the length of SHORT_DOC is too long, truncate it. */
-+ if (len > MAX_SHORT_DOC_LEN - 1)
-+ len = MAX_SHORT_DOC_LEN - 1;
-+
-+ for (i = 0; i < len; i++)
-+ grub_putchar ((*builtin)->short_doc[i]);
-+
-+ for (; i < MAX_SHORT_DOC_LEN; i++)
-+ grub_putchar (' ');
-+
-+ if (! left)
-+ grub_putchar ('\n');
-+
-+ left = ! left;
-+ }
-+
-+ /* If the last entry was at the left column, no newline was printed
-+ at the end. */
-+ if (! left)
-+ grub_putchar ('\n');
-+ }
-+ else
-+ {
-+ /* Invoked with one or more patterns. */
-+ do
-+ {
-+ struct builtin **builtin;
-+ char *next_arg;
-+
-+ /* Get the next argument. */
-+ next_arg = skip_to (0, arg);
-+
-+ /* Terminate ARG. */
-+ nul_terminate (arg);
-+
-+ for (builtin = builtin_table; *builtin; builtin++)
-+ {
-+ /* Skip this if this is only for the configuration file. */
-+ if (! ((*builtin)->flags & BUILTIN_CMDLINE))
-+ continue;
-+
-+ if (substring (arg, (*builtin)->name) < 1)
-+ {
-+ char *doc = (*builtin)->long_doc;
-+
-+ /* At first, print the name and the short doc. */
-+ grub_printf ("%s: %s\n",
-+ (*builtin)->name, (*builtin)->short_doc);
-+
-+ /* Print the long doc. */
-+ while (*doc)
-+ {
-+ int len = grub_strlen (doc);
-+ int i;
-+
-+ /* If LEN is too long, fold DOC. */
-+ if (len > MAX_LONG_DOC_LEN)
-+ {
-+ /* Fold this line at the position of a space. */
-+ for (len = MAX_LONG_DOC_LEN; len > 0; len--)
-+ if (doc[len - 1] == ' ')
-+ break;
-+ }
-+
-+ grub_printf (" ");
-+ for (i = 0; i < len; i++)
-+ grub_putchar (*doc++);
-+ grub_putchar ('\n');
-+ }
-+ }
-+ }
-+
-+ arg = next_arg;
-+ }
-+ while (*arg);
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_help =
-+{
-+ "help",
-+ help_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "help [--all] [PATTERN ...]",
-+ "Display helpful information about builtin commands. Not all commands"
-+ " aren't shown without the option `--all'."
-+};
-+
-+\f
-+/* hiddenmenu */
-+static int
-+hiddenmenu_func (char *arg, int flags)
-+{
-+ show_menu = 0;
-+ return 0;
-+}
-+
-+static struct builtin builtin_hiddenmenu =
-+{
-+ "hiddenmenu",
-+ hiddenmenu_func,
-+ BUILTIN_MENU,
-+#if 0
-+ "hiddenmenu",
-+ "Hide the menu."
-+#endif
-+};
-+
-+\f
-+/* hide */
-+static int
-+hide_func (char *arg, int flags)
-+{
-+ if (! set_device (arg))
-+ return 1;
-+
-+ if (! set_partition_hidden_flag (1))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_hide =
-+{
-+ "hide",
-+ hide_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "hide PARTITION",
-+ "Hide PARTITION by setting the \"hidden\" bit in"
-+ " its partition type code."
-+};
-+
-+\f
-+#ifdef SUPPORT_NETBOOT
-+/* ifconfig */
-+static int
-+ifconfig_func (char *arg, int flags)
-+{
-+ char *svr = 0, *ip = 0, *gw = 0, *sm = 0;
-+
-+ if (! eth_probe ())
-+ {
-+ grub_printf ("No ethernet card found.\n");
-+ errnum = ERR_DEV_VALUES;
-+ return 1;
-+ }
-+
-+ while (*arg)
-+ {
-+ if (! grub_memcmp ("--server=", arg, sizeof ("--server=") - 1))
-+ svr = arg + sizeof("--server=") - 1;
-+ else if (! grub_memcmp ("--address=", arg, sizeof ("--address=") - 1))
-+ ip = arg + sizeof ("--address=") - 1;
-+ else if (! grub_memcmp ("--gateway=", arg, sizeof ("--gateway=") - 1))
-+ gw = arg + sizeof ("--gateway=") - 1;
-+ else if (! grub_memcmp ("--mask=", arg, sizeof("--mask=") - 1))
-+ sm = arg + sizeof ("--mask=") - 1;
-+ else
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ arg = skip_to (0, arg);
-+ }
-+
-+ if (! ifconfig (ip, sm, gw, svr))
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ print_network_configuration ();
-+ return 0;
-+}
-+
-+static struct builtin builtin_ifconfig =
-+{
-+ "ifconfig",
-+ ifconfig_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "ifconfig [--address=IP] [--gateway=IP] [--mask=MASK] [--server=IP]",
-+ "Configure the IP address, the netmask, the gateway and the server"
-+ " address or print current network configuration."
-+};
-+#endif /* SUPPORT_NETBOOT */
-+
-+\f
-+/* impsprobe */
-+static int
-+impsprobe_func (char *arg, int flags)
-+{
-+#ifdef GRUB_UTIL
-+ /* In the grub shell, we cannot probe IMPS. */
-+ errnum = ERR_UNRECOGNIZED;
-+ return 1;
-+#else /* ! GRUB_UTIL */
-+ if (!imps_probe ())
-+ printf (" No MPS information found or probe failed\n");
-+
-+ return 0;
-+#endif /* ! GRUB_UTIL */
-+}
-+
-+static struct builtin builtin_impsprobe =
-+{
-+ "impsprobe",
-+ impsprobe_func,
-+ BUILTIN_CMDLINE,
-+ "impsprobe",
-+ "Probe the Intel Multiprocessor Specification 1.1 or 1.4"
-+ " configuration table and boot the various CPUs which are found into"
-+ " a tight loop."
-+};
-+
-+\f
-+/* initrd */
-+static int
-+initrd_func (char *arg, int flags)
-+{
-+ switch (kernel_type)
-+ {
-+ case KERNEL_TYPE_LINUX:
-+ case KERNEL_TYPE_BIG_LINUX:
-+ if (! load_initrd (arg))
-+ return 1;
-+ break;
-+
-+ default:
-+ errnum = ERR_NEED_LX_KERNEL;
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_initrd =
-+{
-+ "initrd",
-+ initrd_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "initrd FILE [ARG ...]",
-+ "Load an initial ramdisk FILE for a Linux format boot image and set the"
-+ " appropriate parameters in the Linux setup area in memory."
-+};
-+
-+\f
-+/* install */
-+static int
-+install_func (char *arg, int flags)
-+{
-+ char *stage1_file, *dest_dev, *file, *addr;
-+ char *stage1_buffer = (char *) RAW_ADDR (0x100000);
-+ char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
-+ char *old_sect = stage2_buffer + SECTOR_SIZE;
-+ char *stage2_first_buffer = old_sect + SECTOR_SIZE;
-+ char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE;
-+ /* XXX: Probably SECTOR_SIZE is reasonable. */
-+ char *config_filename = stage2_second_buffer + SECTOR_SIZE;
-+ char *dummy = config_filename + SECTOR_SIZE;
-+ int new_drive = GRUB_INVALID_DRIVE;
-+ int dest_drive, dest_partition, dest_sector;
-+ int src_drive, src_partition, src_part_start;
-+ int i;
-+ struct geometry dest_geom, src_geom;
-+ int saved_sector;
-+ int stage2_first_sector, stage2_second_sector;
-+ char *ptr;
-+ int installaddr, installlist;
-+ /* Point to the location of the name of a configuration file in Stage 2. */
-+ char *config_file_location;
-+ /* If FILE is a Stage 1.5? */
-+ int is_stage1_5 = 0;
-+ /* Must call grub_close? */
-+ int is_open = 0;
-+ /* If LBA is forced? */
-+ int is_force_lba = 0;
-+ /* Was the last sector full? */
-+ int last_length = SECTOR_SIZE;
-+
-+#ifdef GRUB_UTIL
-+ /* If the Stage 2 is in a partition mounted by an OS, this will store
-+ the filename under the OS. */
-+ char *stage2_os_file = 0;
-+#endif /* GRUB_UTIL */
-+
-+ auto void disk_read_savesect_func (int sector, int offset, int length);
-+ auto void disk_read_blocklist_func (int sector, int offset, int length);
-+
-+ /* Save the first sector of Stage2 in STAGE2_SECT. */
-+ auto void disk_read_savesect_func (int sector, int offset, int length)
-+ {
-+ if (debug)
-+ printf ("[%d]", sector);
-+
-+ /* ReiserFS has files which sometimes contain data not aligned
-+ on sector boundaries. Returning an error is better than
-+ silently failing. */
-+ if (offset != 0 || length != SECTOR_SIZE)
-+ errnum = ERR_UNALIGNED;
-+
-+ saved_sector = sector;
-+ }
-+
-+ /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and
-+ INSTALLSECT. */
-+ auto void disk_read_blocklist_func (int sector, int offset, int length)
-+ {
-+ if (debug)
-+ printf("[%d]", sector);
-+
-+ if (offset != 0 || last_length != SECTOR_SIZE)
-+ {
-+ /* We found a non-sector-aligned data block. */
-+ errnum = ERR_UNALIGNED;
-+ return;
-+ }
-+
-+ last_length = length;
-+
-+ if (*((unsigned long *) (installlist - 4))
-+ + *((unsigned short *) installlist) != sector
-+ || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4)
-+ {
-+ installlist -= 8;
-+
-+ if (*((unsigned long *) (installlist - 8)))
-+ errnum = ERR_WONT_FIT;
-+ else
-+ {
-+ *((unsigned short *) (installlist + 2)) = (installaddr >> 4);
-+ *((unsigned long *) (installlist - 4)) = sector;
-+ }
-+ }
-+
-+ *((unsigned short *) installlist) += 1;
-+ installaddr += 512;
-+ }
-+
-+ /* First, check the GNU-style long option. */
-+ while (1)
-+ {
-+ if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
-+ {
-+ is_force_lba = 1;
-+ arg = skip_to (0, arg);
-+ }
-+#ifdef GRUB_UTIL
-+ else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
-+ {
-+ stage2_os_file = arg + sizeof ("--stage2=") - 1;
-+ arg = skip_to (0, arg);
-+ nul_terminate (stage2_os_file);
-+ }
-+#endif /* GRUB_UTIL */
-+ else
-+ break;
-+ }
-+
-+ stage1_file = arg;
-+ dest_dev = skip_to (0, stage1_file);
-+ if (*dest_dev == 'd')
-+ {
-+ new_drive = 0;
-+ dest_dev = skip_to (0, dest_dev);
-+ }
-+ file = skip_to (0, dest_dev);
-+ addr = skip_to (0, file);
-+
-+ /* Get the installation address. */
-+ if (! safe_parse_maxint (&addr, &installaddr))
-+ {
-+ /* ADDR is not specified. */
-+ installaddr = 0;
-+ ptr = addr;
-+ errnum = 0;
-+ }
-+ else
-+ ptr = skip_to (0, addr);
-+
-+#ifndef NO_DECOMPRESSION
-+ /* Do not decompress Stage 1 or Stage 2. */
-+ no_decompression = 1;
-+#endif
-+
-+ /* Read Stage 1. */
-+ is_open = grub_open (stage1_file);
-+ if (! is_open
-+ || ! grub_read (stage1_buffer, SECTOR_SIZE) == SECTOR_SIZE)
-+ goto fail;
-+
-+ /* Read the old sector from DEST_DEV. */
-+ if (! set_device (dest_dev)
-+ || ! open_partition ()
-+ || ! devread (0, 0, SECTOR_SIZE, old_sect))
-+ goto fail;
-+
-+ /* Store the information for the destination device. */
-+ dest_drive = current_drive;
-+ dest_partition = current_partition;
-+ dest_geom = buf_geom;
-+ dest_sector = part_start;
-+
-+ /* Copy the possible DOS BPB, 59 bytes at byte offset 3. */
-+ grub_memmove (stage1_buffer + BOOTSEC_BPB_OFFSET,
-+ old_sect + BOOTSEC_BPB_OFFSET,
-+ BOOTSEC_BPB_LENGTH);
-+
-+ /* If for a hard disk, copy the possible MBR/extended part table. */
-+ if (dest_drive & 0x80)
-+ grub_memmove (stage1_buffer + STAGE1_WINDOWS_NT_MAGIC,
-+ old_sect + STAGE1_WINDOWS_NT_MAGIC,
-+ STAGE1_PARTEND - STAGE1_WINDOWS_NT_MAGIC);
-+
-+ /* Check for the version and the signature of Stage 1. */
-+ if (*((short *)(stage1_buffer + STAGE1_VER_MAJ_OFFS)) != COMPAT_VERSION
-+ || (*((unsigned short *) (stage1_buffer + BOOTSEC_SIG_OFFSET))
-+ != BOOTSEC_SIGNATURE))
-+ {
-+ errnum = ERR_BAD_VERSION;
-+ goto fail;
-+ }
-+
-+ /* This below is not true any longer. But should we leave this alone? */
-+
-+ /* If DEST_DRIVE is a floppy, Stage 2 must have the iteration probe
-+ routine. */
-+ if (! (dest_drive & 0x80)
-+ && (*((unsigned char *) (stage1_buffer + BOOTSEC_PART_OFFSET)) == 0x80
-+ || stage1_buffer[BOOTSEC_PART_OFFSET] == 0))
-+ {
-+ errnum = ERR_BAD_VERSION;
-+ goto fail;
-+ }
-+
-+ grub_close ();
-+
-+ /* Open Stage 2. */
-+ is_open = grub_open (file);
-+ if (! is_open)
-+ goto fail;
-+
-+ src_drive = current_drive;
-+ src_partition = current_partition;
-+ src_part_start = part_start;
-+ src_geom = buf_geom;
-+
-+ if (! new_drive)
-+ new_drive = src_drive;
-+ else if (src_drive != dest_drive)
-+ grub_printf ("Warning: the option `d' was not used, but the Stage 1 will"
-+ " be installed on a\ndifferent drive than the drive where"
-+ " the Stage 2 resides.\n");
-+
-+ /* Set the boot drive. */
-+ *((unsigned char *) (stage1_buffer + STAGE1_BOOT_DRIVE)) = new_drive;
-+
-+ /* Set the "force LBA" flag. */
-+ *((unsigned char *) (stage1_buffer + STAGE1_FORCE_LBA)) = is_force_lba;
-+
-+ /* If DEST_DRIVE is a hard disk, enable the workaround, which is
-+ for buggy BIOSes which don't pass boot drive correctly. Instead,
-+ they pass 0x00 or 0x01 even when booted from 0x80. */
-+ if (dest_drive & BIOS_FLAG_FIXED_DISK)
-+ /* Replace the jmp (2 bytes) with double nop's. */
-+ *((unsigned short *) (stage1_buffer + STAGE1_BOOT_DRIVE_CHECK))
-+ = 0x9090;
-+
-+ /* Read the first sector of Stage 2. */
-+ disk_read_hook = disk_read_savesect_func;
-+ if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE)
-+ goto fail;
-+
-+ stage2_first_sector = saved_sector;
-+
-+ /* Read the second sector of Stage 2. */
-+ if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE)
-+ goto fail;
-+
-+ stage2_second_sector = saved_sector;
-+
-+ /* Check for the version of Stage 2. */
-+ if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
-+ != COMPAT_VERSION)
-+ {
-+ errnum = ERR_BAD_VERSION;
-+ goto fail;
-+ }
-+
-+ /* Check for the Stage 2 id. */
-+ if (stage2_second_buffer[STAGE2_STAGE2_ID] != STAGE2_ID_STAGE2)
-+ is_stage1_5 = 1;
-+
-+ /* If INSTALLADDR is not specified explicitly in the command-line,
-+ determine it by the Stage 2 id. */
-+ if (! installaddr)
-+ {
-+ if (! is_stage1_5)
-+ /* Stage 2. */
-+ installaddr = 0x8000;
-+ else
-+ /* Stage 1.5. */
-+ installaddr = 0x2000;
-+ }
-+
-+ *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR))
-+ = stage2_first_sector;
-+ *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS))
-+ = installaddr;
-+ *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT))
-+ = installaddr >> 4;
-+
-+ i = (int) stage2_first_buffer + SECTOR_SIZE - 4;
-+ while (*((unsigned long *) i))
-+ {
-+ if (i < (int) stage2_first_buffer
-+ || (*((int *) (i - 4)) & 0x80000000)
-+ || *((unsigned short *) i) >= 0xA00
-+ || *((short *) (i + 2)) == 0)
-+ {
-+ errnum = ERR_BAD_VERSION;
-+ goto fail;
-+ }
-+
-+ *((int *) i) = 0;
-+ *((int *) (i - 4)) = 0;
-+ i -= 8;
-+ }
-+
-+ installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4;
-+ installaddr += SECTOR_SIZE;
-+
-+ /* Read the whole of Stage2 except for the first sector. */
-+ grub_seek (SECTOR_SIZE);
-+
-+ disk_read_hook = disk_read_blocklist_func;
-+ if (! grub_read (dummy, -1))
-+ goto fail;
-+
-+ disk_read_hook = 0;
-+
-+ /* Find a string for the configuration filename. */
-+ config_file_location = stage2_second_buffer + STAGE2_VER_STR_OFFS;
-+ while (*(config_file_location++))
-+ ;
-+
-+ /* Set the "force LBA" flag for Stage2. */
-+ *((unsigned char *) (stage2_second_buffer + STAGE2_FORCE_LBA))
-+ = is_force_lba;
-+
-+ if (*ptr == 'p')
-+ {
-+ *((long *) (stage2_second_buffer + STAGE2_INSTALLPART))
-+ = src_partition;
-+ if (is_stage1_5)
-+ {
-+ /* Reset the device information in FILE if it is a Stage 1.5. */
-+ unsigned long device = 0xFFFFFFFF;
-+
-+ grub_memmove (config_file_location, (char *) &device,
-+ sizeof (device));
-+ }
-+
-+ ptr = skip_to (0, ptr);
-+ }
-+
-+ if (*ptr)
-+ {
-+ grub_strcpy (config_filename, ptr);
-+ nul_terminate (config_filename);
-+
-+ if (! is_stage1_5)
-+ /* If it is a Stage 2, just copy PTR to CONFIG_FILE_LOCATION. */
-+ grub_strcpy (config_file_location, ptr);
-+ else
-+ {
-+ char *real_config;
-+ unsigned long device;
-+
-+ /* Translate the external device syntax to the internal device
-+ syntax. */
-+ if (! (real_config = set_device (ptr)))
-+ {
-+ /* The Stage 2 PTR does not contain the device name, so
-+ use the root device instead. */
-+ errnum = ERR_NONE;
-+ current_drive = saved_drive;
-+ current_partition = saved_partition;
-+ real_config = ptr;
-+ }
-+
-+ if (current_drive == src_drive)
-+ {
-+ /* If the drive where the Stage 2 resides is the same as
-+ the one where the Stage 1.5 resides, do not embed the
-+ drive number. */
-+ current_drive = GRUB_INVALID_DRIVE;
-+ }
-+
-+ device = (current_drive << 24) | current_partition;
-+ grub_memmove (config_file_location, (char *) &device,
-+ sizeof (device));
-+ grub_strcpy (config_file_location + sizeof (device),
-+ real_config);
-+ }
-+
-+ /* If a Stage 1.5 is used, then we need to modify the Stage2. */
-+ if (is_stage1_5)
-+ {
-+ char *real_config_filename = skip_to (0, ptr);
-+
-+ is_open = grub_open (config_filename);
-+ if (! is_open)
-+ goto fail;
-+
-+ /* Skip the first sector. */
-+ grub_seek (SECTOR_SIZE);
-+
-+ disk_read_hook = disk_read_savesect_func;
-+ if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
-+ goto fail;
-+
-+ disk_read_hook = 0;
-+ grub_close ();
-+ is_open = 0;
-+
-+ /* Sanity check. */
-+ if (*(stage2_buffer + STAGE2_STAGE2_ID) != STAGE2_ID_STAGE2)
-+ {
-+ errnum = ERR_BAD_VERSION;
-+ goto fail;
-+ }
-+
-+ /* Set the "force LBA" flag for Stage2. */
-+ *(stage2_buffer + STAGE2_FORCE_LBA) = is_force_lba;
-+
-+ /* If REAL_CONFIG_FILENAME is specified, copy it to the Stage2. */
-+ if (*real_config_filename)
-+ {
-+ /* Specified */
-+ char *location;
-+
-+ /* Find a string for the configuration filename. */
-+ location = stage2_buffer + STAGE2_VER_STR_OFFS;
-+ while (*(location++))
-+ ;
-+
-+ /* Copy the name. */
-+ grub_strcpy (location, real_config_filename);
-+ }
-+
-+ /* Write it to the disk. */
-+ buf_track = -1;
-+
-+#ifdef GRUB_UTIL
-+ /* In the grub shell, access the Stage 2 via the OS filesystem
-+ service, if possible. */
-+ if (stage2_os_file)
-+ {
-+ FILE *fp;
-+
-+ fp = fopen (stage2_os_file, "r+");
-+ if (! fp)
-+ {
-+ errnum = ERR_FILE_NOT_FOUND;
-+ goto fail;
-+ }
-+
-+ if (fseek (fp, SECTOR_SIZE, SEEK_SET) != 0)
-+ {
-+ fclose (fp);
-+ errnum = ERR_BAD_VERSION;
-+ goto fail;
-+ }
-+
-+ if (fwrite (stage2_buffer, 1, SECTOR_SIZE, fp)
-+ != SECTOR_SIZE)
-+ {
-+ fclose (fp);
-+ errnum = ERR_WRITE;
-+ goto fail;
-+ }
-+
-+ fclose (fp);
-+ }
-+ else
-+#endif /* GRUB_UTIL */
-+ {
-+ if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
-+ goto fail;
-+ }
-+ }
-+ }
-+
-+ /* Clear the cache. */
-+ buf_track = -1;
-+
-+ /* Write the modified sectors of Stage2 to the disk. */
-+#ifdef GRUB_UTIL
-+ if (! is_stage1_5 && stage2_os_file)
-+ {
-+ FILE *fp;
-+
-+ fp = fopen (stage2_os_file, "r+");
-+ if (! fp)
-+ {
-+ errnum = ERR_FILE_NOT_FOUND;
-+ goto fail;
-+ }
-+
-+ if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
-+ {
-+ fclose (fp);
-+ errnum = ERR_WRITE;
-+ goto fail;
-+ }
-+
-+ if (fwrite (stage2_second_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE)
-+ {
-+ fclose (fp);
-+ errnum = ERR_WRITE;
-+ goto fail;
-+ }
-+
-+ fclose (fp);
-+ }
-+ else
-+#endif /* GRUB_UTIL */
-+ {
-+ /* The first. */
-+ current_drive = src_drive;
-+ current_partition = src_partition;
-+
-+ if (! open_partition ())
-+ goto fail;
-+
-+ if (! devwrite (stage2_first_sector - src_part_start, 1,
-+ stage2_first_buffer))
-+ goto fail;
-+
-+ if (! devwrite (stage2_second_sector - src_part_start, 1,
-+ stage2_second_buffer))
-+ goto fail;
-+ }
-+
-+ /* Write the modified sector of Stage 1 to the disk. */
-+ current_drive = dest_drive;
-+ current_partition = dest_partition;
-+ if (! open_partition ())
-+ goto fail;
-+
-+ devwrite (0, 1, stage1_buffer);
-+
-+ fail:
-+ if (is_open)
-+ grub_close ();
-+
-+ disk_read_hook = 0;
-+
-+#ifndef NO_DECOMPRESSION
-+ no_decompression = 0;
-+#endif
-+
-+ return errnum;
-+}
-+
-+static struct builtin builtin_install =
-+{
-+ "install",
-+ install_func,
-+ BUILTIN_CMDLINE,
-+ "install [--stage2=STAGE2_FILE] [--force-lba] STAGE1 [d] DEVICE STAGE2 [ADDR] [p] [CONFIG_FILE] [REAL_CONFIG_FILE]",
-+ "Install STAGE1 on DEVICE, and install a blocklist for loading STAGE2"
-+ " as a Stage 2. If the option `d' is present, the Stage 1 will always"
-+ " look for the disk where STAGE2 was installed, rather than using"
-+ " the booting drive. The Stage 2 will be loaded at address ADDR, which"
-+ " will be determined automatically if you don't specify it. If"
-+ " the option `p' or CONFIG_FILE is present, then the first block"
-+ " of Stage 2 is patched with new values of the partition and name"
-+ " of the configuration file used by the true Stage 2 (for a Stage 1.5,"
-+ " this is the name of the true Stage 2) at boot time. If STAGE2 is a Stage"
-+ " 1.5 and REAL_CONFIG_FILE is present, then the Stage 2 CONFIG_FILE is"
-+ " patched with the configuration filename REAL_CONFIG_FILE."
-+ " If the option `--force-lba' is specified, disable some sanity checks"
-+ " for LBA mode. If the option `--stage2' is specified, rewrite the Stage"
-+ " 2 via your OS's filesystem instead of the raw device."
-+};
-+
-+\f
-+/* ioprobe */
-+static int
-+ioprobe_func (char *arg, int flags)
-+{
-+#ifdef GRUB_UTIL
-+
-+ errnum = ERR_UNRECOGNIZED;
-+ return 1;
-+
-+#else /* ! GRUB_UTIL */
-+
-+ unsigned short *port;
-+
-+ /* Get the drive number. */
-+ set_device (arg);
-+ if (errnum)
-+ return 1;
-+
-+ /* Clean out IO_MAP. */
-+ grub_memset ((char *) io_map, 0, IO_MAP_SIZE * sizeof (unsigned short));
-+
-+ /* Track the int13 handler. */
-+ track_int13 (current_drive);
-+
-+ /* Print out the result. */
-+ for (port = io_map; *port != 0; port++)
-+ grub_printf (" 0x%x", (unsigned int) *port);
-+
-+ return 0;
-+
-+#endif /* ! GRUB_UTIL */
-+}
-+
-+static struct builtin builtin_ioprobe =
-+{
-+ "ioprobe",
-+ ioprobe_func,
-+ BUILTIN_CMDLINE,
-+ "ioprobe DRIVE",
-+ "Probe I/O ports used for the drive DRIVE."
-+};
-+
-+\f
-+/* kernel */
-+static int
-+kernel_func (char *arg, int flags)
-+{
-+ int len;
-+ kernel_t suggested_type = KERNEL_TYPE_NONE;
-+ unsigned long load_flags = 0;
-+
-+#ifndef AUTO_LINUX_MEM_OPT
-+ load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
-+#endif
-+
-+ /* Deal with GNU-style long options. */
-+ while (1)
-+ {
-+ /* If the option `--type=TYPE' is specified, convert the string to
-+ a kernel type. */
-+ if (grub_memcmp (arg, "--type=", 7) == 0)
-+ {
-+ arg += 7;
-+
-+ if (grub_memcmp (arg, "netbsd", 6) == 0)
-+ suggested_type = KERNEL_TYPE_NETBSD;
-+ else if (grub_memcmp (arg, "freebsd", 7) == 0)
-+ suggested_type = KERNEL_TYPE_FREEBSD;
-+ else if (grub_memcmp (arg, "openbsd", 7) == 0)
-+ /* XXX: For now, OpenBSD is identical to NetBSD, from GRUB's
-+ point of view. */
-+ suggested_type = KERNEL_TYPE_NETBSD;
-+ else if (grub_memcmp (arg, "linux", 5) == 0)
-+ suggested_type = KERNEL_TYPE_LINUX;
-+ else if (grub_memcmp (arg, "biglinux", 8) == 0)
-+ suggested_type = KERNEL_TYPE_BIG_LINUX;
-+ else if (grub_memcmp (arg, "multiboot", 9) == 0)
-+ suggested_type = KERNEL_TYPE_MULTIBOOT;
-+ else
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+ }
-+ /* If the `--no-mem-option' is specified, don't pass a Linux's mem
-+ option automatically. If the kernel is another type, this flag
-+ has no effect. */
-+ else if (grub_memcmp (arg, "--no-mem-option", 15) == 0)
-+ load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
-+ else
-+ break;
-+
-+ /* Try the next. */
-+ arg = skip_to (0, arg);
-+ }
-+
-+ len = grub_strlen (arg);
-+
-+ /* Reset MB_CMDLINE. */
-+ mb_cmdline = (char *) MB_CMDLINE_BUF;
-+ if (len + 1 > MB_CMDLINE_BUFLEN)
-+ {
-+ errnum = ERR_WONT_FIT;
-+ return 1;
-+ }
-+
-+ /* Copy the command-line to MB_CMDLINE. */
-+ grub_memmove (mb_cmdline, arg, len + 1);
-+ kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags);
-+ if (kernel_type == KERNEL_TYPE_NONE)
-+ return 1;
-+
-+ mb_cmdline += len + 1;
-+ return 0;
-+}
-+
-+static struct builtin builtin_kernel =
-+{
-+ "kernel",
-+ kernel_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]",
-+ "Attempt to load the primary boot image from FILE. The rest of the"
-+ " line is passed verbatim as the \"kernel command line\". Any modules"
-+ " must be reloaded after using this command. The option --type is used"
-+ " to suggest what type of kernel to be loaded. TYPE must be either of"
-+ " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and"
-+ " \"multiboot\". The option --no-mem-option tells GRUB not to pass a"
-+ " Linux's mem option automatically."
-+};
-+
-+\f
-+/* lock */
-+static int
-+lock_func (char *arg, int flags)
-+{
-+ if (! auth && password)
-+ {
-+ errnum = ERR_PRIVILEGED;
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_lock =
-+{
-+ "lock",
-+ lock_func,
-+ BUILTIN_CMDLINE,
-+ "lock",
-+ "Break a command execution unless the user is authenticated."
-+};
-+
-+\f
-+/* makeactive */
-+static int
-+makeactive_func (char *arg, int flags)
-+{
-+ if (! make_saved_active ())
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_makeactive =
-+{
-+ "makeactive",
-+ makeactive_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "makeactive",
-+ "Set the active partition on the root disk to GRUB's root device."
-+ " This command is limited to _primary_ PC partitions on a hard disk."
-+};
-+
-+\f
-+/* map */
-+/* Map FROM_DRIVE to TO_DRIVE. */
-+static int
-+map_func (char *arg, int flags)
-+{
-+ char *to_drive;
-+ char *from_drive;
-+ unsigned long to, from;
-+ int i;
-+
-+ to_drive = arg;
-+ from_drive = skip_to (0, arg);
-+
-+ /* Get the drive number for TO_DRIVE. */
-+ set_device (to_drive);
-+ if (errnum)
-+ return 1;
-+ to = current_drive;
-+
-+ /* Get the drive number for FROM_DRIVE. */
-+ set_device (from_drive);
-+ if (errnum)
-+ return 1;
-+ from = current_drive;
-+
-+ /* Search for an empty slot in BIOS_DRIVE_MAP. */
-+ for (i = 0; i < DRIVE_MAP_SIZE; i++)
-+ {
-+ /* Perhaps the user wants to override the map. */
-+ if ((bios_drive_map[i] & 0xff) == from)
-+ break;
-+
-+ if (! bios_drive_map[i])
-+ break;
-+ }
-+
-+ if (i == DRIVE_MAP_SIZE)
-+ {
-+ errnum = ERR_WONT_FIT;
-+ return 1;
-+ }
-+
-+ if (to == from)
-+ /* If TO is equal to FROM, delete the entry. */
-+ grub_memmove ((char *) &bios_drive_map[i], (char *) &bios_drive_map[i + 1],
-+ sizeof (unsigned short) * (DRIVE_MAP_SIZE - i));
-+ else
-+ bios_drive_map[i] = from | (to << 8);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_map =
-+{
-+ "map",
-+ map_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "map TO_DRIVE FROM_DRIVE",
-+ "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary"
-+ " when you chain-load some operating systems, such as DOS, if such an"
-+ " OS resides at a non-first drive."
-+};
-+
-+\f
-+#ifdef USE_MD5_PASSWORDS
-+/* md5crypt */
-+static int
-+md5crypt_func (char *arg, int flags)
-+{
-+ char crypted[36];
-+ char key[32];
-+ unsigned int seed;
-+ int i;
-+ const char *const seedchars =
-+ "./0123456789ABCDEFGHIJKLMNOPQRST"
-+ "UVWXYZabcdefghijklmnopqrstuvwxyz";
-+
-+ /* First create a salt. */
-+
-+ /* The magical prefix. */
-+ grub_memset (crypted, 0, sizeof (crypted));
-+ grub_memmove (crypted, "$1$", 3);
-+
-+ /* Create the length of a salt. */
-+ seed = currticks ();
-+
-+ /* Generate a salt. */
-+ for (i = 0; i < 8 && seed; i++)
-+ {
-+ /* FIXME: This should be more random. */
-+ crypted[3 + i] = seedchars[seed & 0x3f];
-+ seed >>= 6;
-+ }
-+
-+ /* A salt must be terminated with `$', if it is less than 8 chars. */
-+ crypted[3 + i] = '$';
-+
-+#ifdef DEBUG_MD5CRYPT
-+ grub_printf ("salt = %s\n", crypted);
-+#endif
-+
-+ /* Get a password. */
-+ grub_memset (key, 0, sizeof (key));
-+ get_cmdline ("Password: ", key, sizeof (key) - 1, '*', 0);
-+
-+ /* Crypt the key. */
-+ make_md5_password (key, crypted);
-+
-+ grub_printf ("Encrypted: %s\n", crypted);
-+ return 0;
-+}
-+
-+static struct builtin builtin_md5crypt =
-+{
-+ "md5crypt",
-+ md5crypt_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "md5crypt",
-+ "Generate a password in MD5 format."
-+};
-+#endif /* USE_MD5_PASSWORDS */
-+
-+\f
-+/* module */
-+static int
-+module_func (char *arg, int flags)
-+{
-+ int len = grub_strlen (arg);
-+
-+ switch (kernel_type)
-+ {
-+ case KERNEL_TYPE_MULTIBOOT:
-+ if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN)
-+ {
-+ errnum = ERR_WONT_FIT;
-+ return 1;
-+ }
-+ grub_memmove (mb_cmdline, arg, len + 1);
-+ if (! load_module (arg, mb_cmdline))
-+ return 1;
-+ mb_cmdline += len + 1;
-+ break;
-+
-+ case KERNEL_TYPE_LINUX:
-+ case KERNEL_TYPE_BIG_LINUX:
-+ if (! load_initrd (arg))
-+ return 1;
-+ break;
-+
-+ default:
-+ errnum = ERR_NEED_MB_KERNEL;
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_module =
-+{
-+ "module",
-+ module_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "module FILE [ARG ...]",
-+ "Load a boot module FILE for a Multiboot format boot image (no"
-+ " interpretation of the file contents is made, so users of this"
-+ " command must know what the kernel in question expects). The"
-+ " rest of the line is passed as the \"module command line\", like"
-+ " the `kernel' command."
-+};
-+
-+\f
-+/* modulenounzip */
-+static int
-+modulenounzip_func (char *arg, int flags)
-+{
-+ int ret;
-+
-+#ifndef NO_DECOMPRESSION
-+ no_decompression = 1;
-+#endif
-+
-+ ret = module_func (arg, flags);
-+
-+#ifndef NO_DECOMPRESSION
-+ no_decompression = 0;
-+#endif
-+
-+ return ret;
-+}
-+
-+static struct builtin builtin_modulenounzip =
-+{
-+ "modulenounzip",
-+ modulenounzip_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "modulenounzip FILE [ARG ...]",
-+ "The same as `module', except that automatic decompression is"
-+ " disabled."
-+};
-+
-+\f
-+/* pager [on|off] */
-+static int
-+pager_func (char *arg, int flags)
-+{
-+ /* If ARG is empty, toggle the flag. */
-+ if (! *arg)
-+ use_pager = ! use_pager;
-+ else if (grub_memcmp (arg, "on", 2) == 0)
-+ use_pager = 1;
-+ else if (grub_memcmp (arg, "off", 3) == 0)
-+ use_pager = 0;
-+ else
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ grub_printf (" Internal pager is now %s\n", use_pager ? "on" : "off");
-+ return 0;
-+}
-+
-+static struct builtin builtin_pager =
-+{
-+ "pager",
-+ pager_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "pager [FLAG]",
-+ "Toggle pager mode with no argument. If FLAG is given and its value"
-+ " is `on', turn on the mode. If FLAG is `off', turn off the mode."
-+};
-+
-+\f
-+/* partnew PART TYPE START LEN */
-+static int
-+partnew_func (char *arg, int flags)
-+{
-+ int new_type, new_start, new_len;
-+ int start_cl, start_ch, start_dh;
-+ int end_cl, end_ch, end_dh;
-+ int entry;
-+ char mbr[512];
-+
-+ /* Convert a LBA address to a CHS address in the INT 13 format. */
-+ auto void lba_to_chs (int lba, int *cl, int *ch, int *dh);
-+ void lba_to_chs (int lba, int *cl, int *ch, int *dh)
-+ {
-+ int cylinder, head, sector;
-+
-+ sector = lba % buf_geom.sectors + 1;
-+ head = (lba / buf_geom.sectors) % buf_geom.heads;
-+ cylinder = lba / (buf_geom.sectors * buf_geom.heads);
-+
-+ if (cylinder >= buf_geom.cylinders)
-+ cylinder = buf_geom.cylinders - 1;
-+
-+ *cl = sector | ((cylinder & 0x300) >> 2);
-+ *ch = cylinder & 0xFF;
-+ *dh = head;
-+ }
-+
-+ /* Get the drive and the partition. */
-+ if (! set_device (arg))
-+ return 1;
-+
-+ /* The drive must be a hard disk. */
-+ if (! (current_drive & 0x80))
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ /* The partition must a primary partition. */
-+ if ((current_partition >> 16) > 3
-+ || (current_partition & 0xFFFF) != 0xFFFF)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ entry = current_partition >> 16;
-+
-+ /* Get the new partition type. */
-+ arg = skip_to (0, arg);
-+ if (! safe_parse_maxint (&arg, &new_type))
-+ return 1;
-+
-+ /* The partition type is unsigned char. */
-+ if (new_type > 0xFF)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ /* Get the new partition start. */
-+ arg = skip_to (0, arg);
-+ if (! safe_parse_maxint (&arg, &new_start))
-+ return 1;
-+
-+ /* Get the new partition length. */
-+ arg = skip_to (0, arg);
-+ if (! safe_parse_maxint (&arg, &new_len))
-+ return 1;
-+
-+ /* Read the MBR. */
-+ if (! rawread (current_drive, 0, 0, SECTOR_SIZE, mbr))
-+ return 1;
-+
-+ /* Check if the new partition will fit in the disk. */
-+ if (new_start + new_len > buf_geom.total_sectors)
-+ {
-+ errnum = ERR_GEOM;
-+ return 1;
-+ }
-+
-+ /* Store the partition information in the MBR. */
-+ lba_to_chs (new_start, &start_cl, &start_ch, &start_dh);
-+ lba_to_chs (new_start + new_len - 1, &end_cl, &end_ch, &end_dh);
-+
-+ PC_SLICE_FLAG (mbr, entry) = 0;
-+ PC_SLICE_HEAD (mbr, entry) = start_dh;
-+ PC_SLICE_SEC (mbr, entry) = start_cl;
-+ PC_SLICE_CYL (mbr, entry) = start_ch;
-+ PC_SLICE_TYPE (mbr, entry) = new_type;
-+ PC_SLICE_EHEAD (mbr, entry) = end_dh;
-+ PC_SLICE_ESEC (mbr, entry) = end_cl;
-+ PC_SLICE_ECYL (mbr, entry) = end_ch;
-+ PC_SLICE_START (mbr, entry) = new_start;
-+ PC_SLICE_LENGTH (mbr, entry) = new_len;
-+
-+ /* Make sure that the MBR has a valid signature. */
-+ PC_MBR_SIG (mbr) = PC_MBR_SIGNATURE;
-+
-+ /* Write back the MBR to the disk. */
-+ buf_track = -1;
-+ if (! rawwrite (current_drive, 0, mbr))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_partnew =
-+{
-+ "partnew",
-+ partnew_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "partnew PART TYPE START LEN",
-+ "Create a primary partition at the starting address START with the"
-+ " length LEN, with the type TYPE. START and LEN are in sector units."
-+};
-+
-+\f
-+/* parttype PART TYPE */
-+static int
-+parttype_func (char *arg, int flags)
-+{
-+ int new_type;
-+ unsigned long part = 0xFFFFFF;
-+ unsigned long start, len, offset, ext_offset;
-+ int entry, type;
-+ char mbr[512];
-+
-+ /* Get the drive and the partition. */
-+ if (! set_device (arg))
-+ return 1;
-+
-+ /* The drive must be a hard disk. */
-+ if (! (current_drive & 0x80))
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ /* The partition must be a PC slice. */
-+ if ((current_partition >> 16) == 0xFF
-+ || (current_partition & 0xFFFF) != 0xFFFF)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ /* Get the new partition type. */
-+ arg = skip_to (0, arg);
-+ if (! safe_parse_maxint (&arg, &new_type))
-+ return 1;
-+
-+ /* The partition type is unsigned char. */
-+ if (new_type > 0xFF)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ /* Look for the partition. */
-+ while (next_partition (current_drive, 0xFFFFFF, &part, &type,
-+ &start, &len, &offset, &entry,
-+ &ext_offset, mbr))
-+ {
-+ if (part == current_partition)
-+ {
-+ /* Found. */
-+
-+ /* Set the type to NEW_TYPE. */
-+ PC_SLICE_TYPE (mbr, entry) = new_type;
-+
-+ /* Write back the MBR to the disk. */
-+ buf_track = -1;
-+ if (! rawwrite (current_drive, offset, mbr))
-+ return 1;
-+
-+ /* Succeed. */
-+ return 0;
-+ }
-+ }
-+
-+ /* The partition was not found. ERRNUM was set by next_partition. */
-+ return 1;
-+}
-+
-+static struct builtin builtin_parttype =
-+{
-+ "parttype",
-+ parttype_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "parttype PART TYPE",
-+ "Change the type of the partition PART to TYPE."
-+};
-+
-+\f
-+/* password */
-+static int
-+password_func (char *arg, int flags)
-+{
-+ int len;
-+ password_t type = PASSWORD_PLAIN;
-+
-+#ifdef USE_MD5_PASSWORDS
-+ if (grub_memcmp (arg, "--md5", 5) == 0)
-+ {
-+ type = PASSWORD_MD5;
-+ arg = skip_to (0, arg);
-+ }
-+#endif
-+ if (grub_memcmp (arg, "--", 2) == 0)
-+ {
-+ type = PASSWORD_UNSUPPORTED;
-+ arg = skip_to (0, arg);
-+ }
-+
-+ if ((flags & (BUILTIN_CMDLINE | BUILTIN_SCRIPT)) != 0)
-+ {
-+ /* Do password check! */
-+ char entered[32];
-+
-+ /* Wipe out any previously entered password */
-+ entered[0] = 0;
-+ get_cmdline ("Password: ", entered, 31, '*', 0);
-+
-+ nul_terminate (arg);
-+ if (check_password (entered, arg, type) != 0)
-+ {
-+ errnum = ERR_PRIVILEGED;
-+ return 1;
-+ }
-+ }
-+ else
-+ {
-+ len = grub_strlen (arg);
-+
-+ /* PASSWORD NUL NUL ... */
-+ if (len + 2 > PASSWORD_BUFLEN)
-+ {
-+ errnum = ERR_WONT_FIT;
-+ return 1;
-+ }
-+
-+ /* Copy the password and clear the rest of the buffer. */
-+ password = (char *) PASSWORD_BUF;
-+ grub_memmove (password, arg, len);
-+ grub_memset (password + len, 0, PASSWORD_BUFLEN - len);
-+ password_type = type;
-+ }
-+ return 0;
-+}
-+
-+static struct builtin builtin_password =
-+{
-+ "password",
-+ password_func,
-+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
-+ "password [--md5] PASSWD [FILE]",
-+ "If used in the first section of a menu file, disable all"
-+ " interactive editing control (menu entry editor and"
-+ " command line). If the password PASSWD is entered, it loads the"
-+ " FILE as a new config file and restarts the GRUB Stage 2. If you"
-+ " omit the argument FILE, then GRUB just unlocks privileged"
-+ " instructions. You can also use it in the script section, in"
-+ " which case it will ask for the password, before continueing."
-+ " The option --md5 tells GRUB that PASSWD is encrypted with"
-+ " md5crypt."
-+};
-+
-+\f
-+/* pause */
-+static int
-+pause_func (char *arg, int flags)
-+{
-+ printf("%s\n", arg);
-+
-+ /* If ESC is returned, then abort this entry. */
-+ if (ASCII_CHAR (getkey ()) == 27)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_pause =
-+{
-+ "pause",
-+ pause_func,
-+ BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
-+ "pause [MESSAGE ...]",
-+ "Print MESSAGE, then wait until a key is pressed."
-+};
-+
-+\f
-+#ifdef GRUB_UTIL
-+/* quit */
-+static int
-+quit_func (char *arg, int flags)
-+{
-+ stop ();
-+
-+ /* Never reach here. */
-+ return 0;
-+}
-+
-+static struct builtin builtin_quit =
-+{
-+ "quit",
-+ quit_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "quit",
-+ "Exit from the GRUB shell."
-+};
-+#endif /* GRUB_UTIL */
-+
-+\f
-+#ifdef SUPPORT_NETBOOT
-+/* rarp */
-+static int
-+rarp_func (char *arg, int flags)
-+{
-+ if (! rarp ())
-+ {
-+ if (errnum == ERR_NONE)
-+ errnum = ERR_DEV_VALUES;
-+
-+ return 1;
-+ }
-+
-+ /* Notify the configuration. */
-+ print_network_configuration ();
-+ return 0;
-+}
-+
-+static struct builtin builtin_rarp =
-+{
-+ "rarp",
-+ rarp_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "rarp",
-+ "Initialize a network device via RARP."
-+};
-+#endif /* SUPPORT_NETBOOT */
-+
-+\f
-+static int
-+read_func (char *arg, int flags)
-+{
-+ int addr;
-+
-+ if (! safe_parse_maxint (&arg, &addr))
-+ return 1;
-+
-+ grub_printf ("Address 0x%x: Value 0x%x\n",
-+ addr, *((unsigned *) RAW_ADDR (addr)));
-+ return 0;
-+}
-+
-+static struct builtin builtin_read =
-+{
-+ "read",
-+ read_func,
-+ BUILTIN_CMDLINE,
-+ "read ADDR",
-+ "Read a 32-bit value from memory at address ADDR and"
-+ " display it in hex format."
-+};
-+
-+\f
-+/* reboot */
-+static int
-+reboot_func (char *arg, int flags)
-+{
-+ grub_reboot ();
-+
-+ /* Never reach here. */
-+ return 1;
-+}
-+
-+static struct builtin builtin_reboot =
-+{
-+ "reboot",
-+ reboot_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "reboot",
-+ "Reboot your system."
-+};
-+
-+\f
-+/* Print the root device information. */
-+static void
-+print_root_device (void)
-+{
-+ if (saved_drive == NETWORK_DRIVE)
-+ {
-+ /* Network drive. */
-+ grub_printf (" (nd):");
-+ }
-+ else if (saved_drive & 0x80)
-+ {
-+ /* Hard disk drive. */
-+ grub_printf (" (hd%d", saved_drive - 0x80);
-+
-+ if ((saved_partition & 0xFF0000) != 0xFF0000)
-+ grub_printf (",%d", saved_partition >> 16);
-+
-+ if ((saved_partition & 0x00FF00) != 0x00FF00)
-+ grub_printf (",%c", ((saved_partition >> 8) & 0xFF) + 'a');
-+
-+ grub_printf ("):");
-+ }
-+ else
-+ {
-+ /* Floppy disk drive. */
-+ grub_printf (" (fd%d):", saved_drive);
-+ }
-+
-+ /* Print the filesystem information. */
-+ current_partition = saved_partition;
-+ current_drive = saved_drive;
-+ print_fsys_type ();
-+}
-+
-+static int
-+real_root_func (char *arg, int attempt_mount)
-+{
-+ int hdbias = 0;
-+ char *biasptr;
-+ char *next;
-+
-+ /* If ARG is empty, just print the current root device. */
-+ if (! *arg)
-+ {
-+ print_root_device ();
-+ return 0;
-+ }
-+
-+ /* Call set_device to get the drive and the partition in ARG. */
-+ next = set_device (arg);
-+ if (! next)
-+ return 1;
-+
-+ /* Ignore ERR_FSYS_MOUNT. */
-+ if (attempt_mount)
-+ {
-+ if (! open_device () && errnum != ERR_FSYS_MOUNT)
-+ return 1;
-+ }
-+ else
-+ {
-+ /* This is necessary, because the location of a partition table
-+ must be set appropriately. */
-+ if (open_partition ())
-+ {
-+ set_bootdev (0);
-+ if (errnum)
-+ return 1;
-+ }
-+ }
-+
-+ /* Clear ERRNUM. */
-+ errnum = 0;
-+ saved_partition = current_partition;
-+ saved_drive = current_drive;
-+
-+ if (attempt_mount)
-+ {
-+ /* BSD and chainloading evil hacks !! */
-+ biasptr = skip_to (0, next);
-+ safe_parse_maxint (&biasptr, &hdbias);
-+ errnum = 0;
-+ bootdev = set_bootdev (hdbias);
-+ if (errnum)
-+ return 1;
-+
-+ /* Print the type of the filesystem. */
-+ print_fsys_type ();
-+ }
-+
-+ return 0;
-+}
-+
-+static int
-+root_func (char *arg, int flags)
-+{
-+ return real_root_func (arg, 1);
-+}
-+
-+static struct builtin builtin_root =
-+{
-+ "root",
-+ root_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "root [DEVICE [HDBIAS]]",
-+ "Set the current \"root device\" to the device DEVICE, then"
-+ " attempt to mount it to get the partition size (for passing the"
-+ " partition descriptor in `ES:ESI', used by some chain-loaded"
-+ " bootloaders), the BSD drive-type (for booting BSD kernels using"
-+ " their native boot format), and correctly determine "
-+ " the PC partition where a BSD sub-partition is located. The"
-+ " optional HDBIAS parameter is a number to tell a BSD kernel"
-+ " how many BIOS drive numbers are on controllers before the current"
-+ " one. For example, if there is an IDE disk and a SCSI disk, and your"
-+ " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."
-+};
-+
-+\f
-+/* rootnoverify */
-+static int
-+rootnoverify_func (char *arg, int flags)
-+{
-+ return real_root_func (arg, 0);
-+}
-+
-+static struct builtin builtin_rootnoverify =
-+{
-+ "rootnoverify",
-+ rootnoverify_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "rootnoverify [DEVICE [HDBIAS]]",
-+ "Similar to `root', but don't attempt to mount the partition. This"
-+ " is useful for when an OS is outside of the area of the disk that"
-+ " GRUB can read, but setting the correct root device is still"
-+ " desired. Note that the items mentioned in `root' which"
-+ " derived from attempting the mount will NOT work correctly."
-+};
-+
-+\f
-+/* savedefault */
-+static int
-+savedefault_func (char *arg, int flags)
-+{
-+#if !defined(SUPPORT_DISKLESS) && !defined(GRUB_UTIL)
-+ unsigned long tmp_drive = saved_drive;
-+ unsigned long tmp_partition = saved_partition;
-+ char *default_file = (char *) DEFAULT_FILE_BUF;
-+ char buf[10];
-+ char sect[SECTOR_SIZE];
-+ int entryno;
-+ int sector_count = 0;
-+ int saved_sectors[2];
-+ int saved_offsets[2];
-+ int saved_lengths[2];
-+
-+ /* Save sector information about at most two sectors. */
-+ auto void disk_read_savesect_func (int sector, int offset, int length);
-+ void disk_read_savesect_func (int sector, int offset, int length)
-+ {
-+ if (sector_count < 2)
-+ {
-+ saved_sectors[sector_count] = sector;
-+ saved_offsets[sector_count] = offset;
-+ saved_lengths[sector_count] = length;
-+ }
-+ sector_count++;
-+ }
-+
-+ /* This command is only useful when you boot an entry from the menu
-+ interface. */
-+ if (! (flags & BUILTIN_SCRIPT))
-+ {
-+ errnum = ERR_UNRECOGNIZED;
-+ return 1;
-+ }
-+
-+ /* Determine a saved entry number. */
-+ if (*arg)
-+ {
-+ if (grub_memcmp (arg, "fallback", sizeof ("fallback") - 1) == 0)
-+ {
-+ int i;
-+ int index = 0;
-+
-+ for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
-+ {
-+ if (fallback_entries[i] < 0)
-+ break;
-+ if (fallback_entries[i] == current_entryno)
-+ {
-+ index = i + 1;
-+ break;
-+ }
-+ }
-+
-+ if (index >= MAX_FALLBACK_ENTRIES || fallback_entries[index] < 0)
-+ {
-+ /* This is the last. */
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ entryno = fallback_entries[index];
-+ }
-+ else if (! safe_parse_maxint (&arg, &entryno))
-+ return 1;
-+ }
-+ else
-+ entryno = current_entryno;
-+
-+ /* Open the default file. */
-+ saved_drive = boot_drive;
-+ saved_partition = install_partition;
-+ if (grub_open (default_file))
-+ {
-+ int len;
-+
-+ disk_read_hook = disk_read_savesect_func;
-+ len = grub_read (buf, sizeof (buf));
-+ disk_read_hook = 0;
-+ grub_close ();
-+
-+ if (len != sizeof (buf))
-+ {
-+ /* This is too small. Do not modify the file manually, please! */
-+ errnum = ERR_READ;
-+ goto fail;
-+ }
-+
-+ if (sector_count > 2)
-+ {
-+ /* Is this possible?! Too fragmented! */
-+ errnum = ERR_FSYS_CORRUPT;
-+ goto fail;
-+ }
-+
-+ /* Set up a string to be written. */
-+ grub_memset (buf, '\n', sizeof (buf));
-+ grub_sprintf (buf, "%d", entryno);
-+
-+ if (saved_lengths[0] < sizeof (buf))
-+ {
-+ /* The file is anchored to another file and the first few bytes
-+ are spanned in two sectors. Uggh... */
-+ if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
-+ sect))
-+ goto fail;
-+ grub_memmove (sect + saved_offsets[0], buf, saved_lengths[0]);
-+ if (! rawwrite (current_drive, saved_sectors[0], sect))
-+ goto fail;
-+
-+ if (! rawread (current_drive, saved_sectors[1], 0, SECTOR_SIZE,
-+ sect))
-+ goto fail;
-+ grub_memmove (sect + saved_offsets[1],
-+ buf + saved_lengths[0],
-+ sizeof (buf) - saved_lengths[0]);
-+ if (! rawwrite (current_drive, saved_sectors[1], sect))
-+ goto fail;
-+ }
-+ else
-+ {
-+ /* This is a simple case. It fits into a single sector. */
-+ if (! rawread (current_drive, saved_sectors[0], 0, SECTOR_SIZE,
-+ sect))
-+ goto fail;
-+ grub_memmove (sect + saved_offsets[0], buf, sizeof (buf));
-+ if (! rawwrite (current_drive, saved_sectors[0], sect))
-+ goto fail;
-+ }
-+
-+ /* Clear the cache. */
-+ buf_track = -1;
-+ }
-+
-+ fail:
-+ saved_drive = tmp_drive;
-+ saved_partition = tmp_partition;
-+ return errnum;
-+#else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
-+ errnum = ERR_UNRECOGNIZED;
-+ return 1;
-+#endif /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
-+}
-+
-+static struct builtin builtin_savedefault =
-+{
-+ "savedefault",
-+ savedefault_func,
-+ BUILTIN_CMDLINE,
-+ "savedefault [NUM | `fallback']",
-+ "Save the current entry as the default boot entry if no argument is"
-+ " specified. If a number is specified, this number is saved. If"
-+ " `fallback' is used, next fallback entry is saved."
-+};
-+
-+\f
-+#ifdef SUPPORT_SERIAL
-+/* serial */
-+static int
-+serial_func (char *arg, int flags)
-+{
-+ unsigned short port = serial_hw_get_port (0);
-+ unsigned int speed = 9600;
-+ int word_len = UART_8BITS_WORD;
-+ int parity = UART_NO_PARITY;
-+ int stop_bit_len = UART_1_STOP_BIT;
-+
-+ /* Process GNU-style long options.
-+ FIXME: We should implement a getopt-like function, to avoid
-+ duplications. */
-+ while (1)
-+ {
-+ if (grub_memcmp (arg, "--unit=", sizeof ("--unit=") - 1) == 0)
-+ {
-+ char *p = arg + sizeof ("--unit=") - 1;
-+ int unit;
-+
-+ if (! safe_parse_maxint (&p, &unit))
-+ return 1;
-+
-+ if (unit < 0 || unit > 3)
-+ {
-+ errnum = ERR_DEV_VALUES;
-+ return 1;
-+ }
-+
-+ port = serial_hw_get_port (unit);
-+ }
-+ else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0)
-+ {
-+ char *p = arg + sizeof ("--speed=") - 1;
-+ int num;
-+
-+ if (! safe_parse_maxint (&p, &num))
-+ return 1;
-+
-+ speed = (unsigned int) num;
-+ }
-+ else if (grub_memcmp (arg, "--port=", sizeof ("--port=") - 1) == 0)
-+ {
-+ char *p = arg + sizeof ("--port=") - 1;
-+ int num;
-+
-+ if (! safe_parse_maxint (&p, &num))
-+ return 1;
-+
-+ port = (unsigned short) num;
-+ }
-+ else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0)
-+ {
-+ char *p = arg + sizeof ("--word=") - 1;
-+ int len;
-+
-+ if (! safe_parse_maxint (&p, &len))
-+ return 1;
-+
-+ switch (len)
-+ {
-+ case 5: word_len = UART_5BITS_WORD; break;
-+ case 6: word_len = UART_6BITS_WORD; break;
-+ case 7: word_len = UART_7BITS_WORD; break;
-+ case 8: word_len = UART_8BITS_WORD; break;
-+ default:
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+ }
-+ else if (grub_memcmp (arg, "--stop=", sizeof ("--stop=") - 1) == 0)
-+ {
-+ char *p = arg + sizeof ("--stop=") - 1;
-+ int len;
-+
-+ if (! safe_parse_maxint (&p, &len))
-+ return 1;
-+
-+ switch (len)
-+ {
-+ case 1: stop_bit_len = UART_1_STOP_BIT; break;
-+ case 2: stop_bit_len = UART_2_STOP_BITS; break;
-+ default:
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+ }
-+ else if (grub_memcmp (arg, "--parity=", sizeof ("--parity=") - 1) == 0)
-+ {
-+ char *p = arg + sizeof ("--parity=") - 1;
-+
-+ if (grub_memcmp (p, "no", sizeof ("no") - 1) == 0)
-+ parity = UART_NO_PARITY;
-+ else if (grub_memcmp (p, "odd", sizeof ("odd") - 1) == 0)
-+ parity = UART_ODD_PARITY;
-+ else if (grub_memcmp (p, "even", sizeof ("even") - 1) == 0)
-+ parity = UART_EVEN_PARITY;
-+ else
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+ }
-+# ifdef GRUB_UTIL
-+ /* In the grub shell, don't use any port number but open a tty
-+ device instead. */
-+ else if (grub_memcmp (arg, "--device=", sizeof ("--device=") - 1) == 0)
-+ {
-+ char *p = arg + sizeof ("--device=") - 1;
-+ char dev[256]; /* XXX */
-+ char *q = dev;
-+
-+ while (*p && ! grub_isspace (*p))
-+ *q++ = *p++;
-+
-+ *q = 0;
-+ serial_set_device (dev);
-+ }
-+# endif /* GRUB_UTIL */
-+ else
-+ break;
-+
-+ arg = skip_to (0, arg);
-+ }
-+
-+ /* Initialize the serial unit. */
-+ if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len))
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_serial =
-+{
-+ "serial",
-+ serial_func,
-+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]",
-+ "Initialize a serial device. UNIT is a digit that specifies which serial"
-+ " device is used (e.g. 0 == COM1). If you need to specify the port number,"
-+ " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length,"
-+ " PARITY is the type of parity, which is one of `no', `odd' and `even'."
-+ " STOP is the length of stop bit(s). The option --device can be used only"
-+ " in the grub shell, which specifies the file name of a tty device. The"
-+ " default values are COM1, 9600, 8N1."
-+};
-+#endif /* SUPPORT_SERIAL */
-+
-+\f
-+/* setkey */
-+struct keysym
-+{
-+ char *unshifted_name; /* the name in unshifted state */
-+ 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 */
-+};
-+
-+/* The table for key symbols. If the "shifted" member of an entry is
-+ NULL, the entry does not have shifted state. */
-+static struct keysym keysym_table[] =
-+{
-+ {"escape", 0, 0x1b, 0, 0x01},
-+ {"1", "exclam", '1', '!', 0x02},
-+ {"2", "at", '2', '@', 0x03},
-+ {"3", "numbersign", '3', '#', 0x04},
-+ {"4", "dollar", '4', '$', 0x05},
-+ {"5", "percent", '5', '%', 0x06},
-+ {"6", "caret", '6', '^', 0x07},
-+ {"7", "ampersand", '7', '&', 0x08},
-+ {"8", "asterisk", '8', '*', 0x09},
-+ {"9", "parenleft", '9', '(', 0x0a},
-+ {"0", "parenright", '0', ')', 0x0b},
-+ {"minus", "underscore", '-', '_', 0x0c},
-+ {"equal", "plus", '=', '+', 0x0d},
-+ {"backspace", 0, '\b', 0, 0x0e},
-+ {"tab", 0, '\t', 0, 0x0f},
-+ {"q", "Q", 'q', 'Q', 0x10},
-+ {"w", "W", 'w', 'W', 0x11},
-+ {"e", "E", 'e', 'E', 0x12},
-+ {"r", "R", 'r', 'R', 0x13},
-+ {"t", "T", 't', 'T', 0x14},
-+ {"y", "Y", 'y', 'Y', 0x15},
-+ {"u", "U", 'u', 'U', 0x16},
-+ {"i", "I", 'i', 'I', 0x17},
-+ {"o", "O", 'o', 'O', 0x18},
-+ {"p", "P", 'p', 'P', 0x19},
-+ {"bracketleft", "braceleft", '[', '{', 0x1a},
-+ {"bracketright", "braceright", ']', '}', 0x1b},
-+ {"enter", 0, '\n', 0, 0x1c},
-+ {"control", 0, 0, 0, 0x1d},
-+ {"a", "A", 'a', 'A', 0x1e},
-+ {"s", "S", 's', 'S', 0x1f},
-+ {"d", "D", 'd', 'D', 0x20},
-+ {"f", "F", 'f', 'F', 0x21},
-+ {"g", "G", 'g', 'G', 0x22},
-+ {"h", "H", 'h', 'H', 0x23},
-+ {"j", "J", 'j', 'J', 0x24},
-+ {"k", "K", 'k', 'K', 0x25},
-+ {"l", "L", 'l', 'L', 0x26},
-+ {"semicolon", "colon", ';', ':', 0x27},
-+ {"quote", "doublequote", '\'', '"', 0x28},
-+ {"backquote", "tilde", '`', '~', 0x29},
-+ {"shift", 0, 0, 0, 0x2a},
-+ {"backslash", "bar", '\\', '|', 0x2b},
-+ {"z", "Z", 'z', 'Z', 0x2c},
-+ {"x", "X", 'x', 'X', 0x2d},
-+ {"c", "C", 'c', 'C', 0x2e},
-+ {"v", "V", 'v', 'V', 0x2f},
-+ {"b", "B", 'b', 'B', 0x30},
-+ {"n", "N", 'n', 'N', 0x31},
-+ {"m", "M", 'm', 'M', 0x32},
-+ {"comma", "less", ',', '<', 0x33},
-+ {"period", "greater", '.', '>', 0x34},
-+ {"slash", "question", '/', '?', 0x35},
-+ {"alt", 0, 0, 0, 0x38},
-+ {"space", 0, ' ', 0, 0x39},
-+ {"capslock", 0, 0, 0, 0x3a},
-+ {"F1", 0, 0, 0, 0x3b},
-+ {"F2", 0, 0, 0, 0x3c},
-+ {"F3", 0, 0, 0, 0x3d},
-+ {"F4", 0, 0, 0, 0x3e},
-+ {"F5", 0, 0, 0, 0x3f},
-+ {"F6", 0, 0, 0, 0x40},
-+ {"F7", 0, 0, 0, 0x41},
-+ {"F8", 0, 0, 0, 0x42},
-+ {"F9", 0, 0, 0, 0x43},
-+ {"F10", 0, 0, 0, 0x44},
-+ /* Caution: do not add NumLock here! we cannot deal with it properly. */
-+ {"delete", 0, 0x7f, 0, 0x53}
-+};
-+
-+static int
-+setkey_func (char *arg, int flags)
-+{
-+ char *to_key, *from_key;
-+ int to_code, from_code;
-+ int map_in_interrupt = 0;
-+
-+ auto int find_key_code (char *key);
-+ auto int find_ascii_code (char *key);
-+
-+ auto int find_key_code (char *key)
-+ {
-+ int i;
-+
-+ for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
-+ {
-+ if (keysym_table[i].unshifted_name &&
-+ grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
-+ return keysym_table[i].keycode;
-+ else if (keysym_table[i].shifted_name &&
-+ grub_strcmp (key, keysym_table[i].shifted_name) == 0)
-+ return keysym_table[i].keycode;
-+ }
-+
-+ return 0;
-+ }
-+
-+ auto int find_ascii_code (char *key)
-+ {
-+ int i;
-+
-+ for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++)
-+ {
-+ if (keysym_table[i].unshifted_name &&
-+ grub_strcmp (key, keysym_table[i].unshifted_name) == 0)
-+ return keysym_table[i].unshifted_ascii;
-+ else if (keysym_table[i].shifted_name &&
-+ grub_strcmp (key, keysym_table[i].shifted_name) == 0)
-+ return keysym_table[i].shifted_ascii;
-+ }
-+
-+ return 0;
-+ }
-+
-+ to_key = arg;
-+ from_key = skip_to (0, to_key);
-+
-+ if (! *to_key)
-+ {
-+ /* If the user specifies no argument, reset the key mappings. */
-+ grub_memset (bios_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short));
-+ grub_memset (ascii_key_map, 0, KEY_MAP_SIZE * sizeof (unsigned short));
-+
-+ return 0;
-+ }
-+ else if (! *from_key)
-+ {
-+ /* The user must specify two arguments or zero argument. */
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ nul_terminate (to_key);
-+ nul_terminate (from_key);
-+
-+ to_code = find_ascii_code (to_key);
-+ from_code = find_ascii_code (from_key);
-+ if (! to_code || ! from_code)
-+ {
-+ map_in_interrupt = 1;
-+ to_code = find_key_code (to_key);
-+ from_code = find_key_code (from_key);
-+ if (! to_code || ! from_code)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+ }
-+
-+ if (map_in_interrupt)
-+ {
-+ int i;
-+
-+ /* Find an empty slot. */
-+ for (i = 0; i < KEY_MAP_SIZE; i++)
-+ {
-+ if ((bios_key_map[i] & 0xff) == from_code)
-+ /* Perhaps the user wants to overwrite the map. */
-+ break;
-+
-+ if (! bios_key_map[i])
-+ break;
-+ }
-+
-+ if (i == KEY_MAP_SIZE)
-+ {
-+ errnum = ERR_WONT_FIT;
-+ return 1;
-+ }
-+
-+ if (to_code == from_code)
-+ /* If TO is equal to FROM, delete the entry. */
-+ grub_memmove ((char *) &bios_key_map[i],
-+ (char *) &bios_key_map[i + 1],
-+ sizeof (unsigned short) * (KEY_MAP_SIZE - i));
-+ else
-+ bios_key_map[i] = (to_code << 8) | from_code;
-+
-+ /* Ugly but should work. */
-+ unset_int15_handler ();
-+ set_int15_handler ();
-+ }
-+ else
-+ {
-+ int i;
-+
-+ /* Find an empty slot. */
-+ for (i = 0; i < KEY_MAP_SIZE; i++)
-+ {
-+ if ((ascii_key_map[i] & 0xff) == from_code)
-+ /* Perhaps the user wants to overwrite the map. */
-+ break;
-+
-+ if (! ascii_key_map[i])
-+ break;
-+ }
-+
-+ if (i == KEY_MAP_SIZE)
-+ {
-+ errnum = ERR_WONT_FIT;
-+ return 1;
-+ }
-+
-+ if (to_code == from_code)
-+ /* If TO is equal to FROM, delete the entry. */
-+ grub_memmove ((char *) &ascii_key_map[i],
-+ (char *) &ascii_key_map[i + 1],
-+ sizeof (unsigned short) * (KEY_MAP_SIZE - i));
-+ else
-+ ascii_key_map[i] = (to_code << 8) | from_code;
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_setkey =
-+{
-+ "setkey",
-+ setkey_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "setkey [TO_KEY FROM_KEY]",
-+ "Change the keyboard map. The key FROM_KEY is mapped to the key TO_KEY."
-+ " A key must be an alphabet, a digit, or one of these: escape, exclam,"
-+ " at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft,"
-+ " parenright, minus, underscore, equal, plus, backspace, tab, bracketleft,"
-+ " braceleft, bracketright, braceright, enter, control, semicolon, colon,"
-+ " quote, doublequote, backquote, tilde, shift, backslash, bar, comma,"
-+ " less, period, greater, slash, question, alt, space, capslock, FX (X"
-+ " is a digit), and delete. If no argument is specified, reset key"
-+ " mappings."
-+};
-+
-+\f
-+/* setup */
-+static int
-+setup_func (char *arg, int flags)
-+{
-+ /* Point to the string of the installed drive/partition. */
-+ char *install_ptr;
-+ /* Point to the string of the drive/parition where the GRUB images
-+ reside. */
-+ char *image_ptr;
-+ unsigned long installed_drive, installed_partition;
-+ unsigned long image_drive, image_partition;
-+ unsigned long tmp_drive, tmp_partition;
-+ char stage1[64];
-+ char stage2[64];
-+ char config_filename[64];
-+ char real_config_filename[64];
-+ char cmd_arg[256];
-+ char device[16];
-+ char *buffer = (char *) RAW_ADDR (0x100000);
-+ int is_force_lba = 0;
-+ char *stage2_arg = 0;
-+ char *prefix = 0;
-+
-+ auto int check_file (char *file);
-+ auto void sprint_device (int drive, int partition);
-+ auto int embed_stage1_5 (char * stage1_5, int drive, int partition);
-+
-+ /* Check if the file FILE exists like Autoconf. */
-+ int check_file (char *file)
-+ {
-+ int ret;
-+
-+ grub_printf (" Checking if \"%s\" exists... ", file);
-+ ret = grub_open (file);
-+ if (ret)
-+ {
-+ grub_close ();
-+ grub_printf ("yes\n");
-+ }
-+ else
-+ grub_printf ("no\n");
-+
-+ return ret;
-+ }
-+
-+ /* Construct a device name in DEVICE. */
-+ void sprint_device (int drive, int partition)
-+ {
-+ grub_sprintf (device, "(%cd%d",
-+ (drive & 0x80) ? 'h' : 'f',
-+ drive & ~0x80);
-+ if ((partition & 0xFF0000) != 0xFF0000)
-+ {
-+ char tmp[16];
-+ grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
-+ grub_strncat (device, tmp, 256);
-+ }
-+ if ((partition & 0x00FF00) != 0x00FF00)
-+ {
-+ char tmp[16];
-+ grub_sprintf (tmp, ",%c", 'a' + ((partition >> 8) & 0xFF));
-+ grub_strncat (device, tmp, 256);
-+ }
-+ grub_strncat (device, ")", 256);
-+ }
-+
-+ int embed_stage1_5 (char *stage1_5, int drive, int partition)
-+ {
-+ /* We install GRUB into the MBR, so try to embed the
-+ Stage 1.5 in the sectors right after the MBR. */
-+ sprint_device (drive, partition);
-+ grub_sprintf (cmd_arg, "%s %s", stage1_5, device);
-+
-+ /* Notify what will be run. */
-+ grub_printf (" Running \"embed %s\"... ", cmd_arg);
-+
-+ embed_func (cmd_arg, flags);
-+ if (! errnum)
-+ {
-+ /* Construct the blocklist representation. */
-+ grub_sprintf (buffer, "%s%s", device, embed_info);
-+ grub_printf ("succeeded\n");
-+ return 1;
-+ }
-+ else
-+ {
-+ grub_printf ("failed (this is not fatal)\n");
-+ return 0;
-+ }
-+ }
-+
-+ struct stage1_5_map {
-+ char *fsys;
-+ char *name;
-+ };
-+ struct stage1_5_map stage1_5_map[] =
-+ {
-+ {"ext2fs", "/e2fs_stage1_5"},
-+ {"fat", "/fat_stage1_5"},
-+ {"ufs2", "/ufs2_stage1_5"},
-+ {"ffs", "/ffs_stage1_5"},
-+ {"iso9660", "/iso9660_stage1_5"},
-+ {"jfs", "/jfs_stage1_5"},
-+ {"minix", "/minix_stage1_5"},
-+ {"reiserfs", "/reiserfs_stage1_5"},
-+ {"vstafs", "/vstafs_stage1_5"},
-+ {"xfs", "/xfs_stage1_5"}
-+ };
-+
-+ tmp_drive = saved_drive;
-+ tmp_partition = saved_partition;
-+
-+ /* Check if the user specifies --force-lba. */
-+ while (1)
-+ {
-+ if (grub_memcmp ("--force-lba", arg, sizeof ("--force-lba") - 1) == 0)
-+ {
-+ is_force_lba = 1;
-+ arg = skip_to (0, arg);
-+ }
-+ else if (grub_memcmp ("--prefix=", arg, sizeof ("--prefix=") - 1) == 0)
-+ {
-+ prefix = arg + sizeof ("--prefix=") - 1;
-+ arg = skip_to (0, arg);
-+ nul_terminate (prefix);
-+ }
-+#ifdef GRUB_UTIL
-+ else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0)
-+ {
-+ stage2_arg = arg;
-+ arg = skip_to (0, arg);
-+ nul_terminate (stage2_arg);
-+ }
-+#endif /* GRUB_UTIL */
-+ else
-+ break;
-+ }
-+
-+ install_ptr = arg;
-+ image_ptr = skip_to (0, install_ptr);
-+
-+ /* Make sure that INSTALL_PTR is valid. */
-+ set_device (install_ptr);
-+ if (errnum)
-+ return 1;
-+
-+ installed_drive = current_drive;
-+ installed_partition = current_partition;
-+
-+ /* Mount the drive pointed by IMAGE_PTR. */
-+ if (*image_ptr)
-+ {
-+ /* If the drive/partition where the images reside is specified,
-+ get the drive and the partition. */
-+ set_device (image_ptr);
-+ if (errnum)
-+ return 1;
-+ }
-+ else
-+ {
-+ /* If omitted, use SAVED_PARTITION and SAVED_DRIVE. */
-+ current_drive = saved_drive;
-+ current_partition = saved_partition;
-+ }
-+
-+ image_drive = saved_drive = current_drive;
-+ image_partition = saved_partition = current_partition;
-+
-+ /* Open it. */
-+ if (! open_device ())
-+ goto fail;
-+
-+ /* Check if stage1 exists. If the user doesn't specify the option
-+ `--prefix', attempt /boot/grub and /grub. */
-+ /* NOTE: It is dangerous to run this command without `--prefix' in the
-+ grub shell, since that affects `--stage2'. */
-+ if (! prefix)
-+ {
-+ prefix = "/boot/grub";
-+ grub_sprintf (stage1, "%s%s", prefix, "/stage1");
-+ if (! check_file (stage1))
-+ {
-+ errnum = ERR_NONE;
-+ prefix = "/grub";
-+ grub_sprintf (stage1, "%s%s", prefix, "/stage1");
-+ if (! check_file (stage1))
-+ goto fail;
-+ }
-+ }
-+ else
-+ {
-+ grub_sprintf (stage1, "%s%s", prefix, "/stage1");
-+ if (! check_file (stage1))
-+ goto fail;
-+ }
-+
-+ /* The prefix was determined. */
-+ grub_sprintf (stage2, "%s%s", prefix, "/stage2");
-+ grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst");
-+ *real_config_filename = 0;
-+
-+ /* Check if stage2 exists. */
-+ if (! check_file (stage2))
-+ goto fail;
-+
-+ {
-+ char *fsys = fsys_table[fsys_type].name;
-+ int i;
-+ int size = sizeof (stage1_5_map) / sizeof (stage1_5_map[0]);
-+
-+ /* Iterate finding the same filesystem name as FSYS. */
-+ for (i = 0; i < size; i++)
-+ if (grub_strcmp (fsys, stage1_5_map[i].fsys) == 0)
-+ {
-+ /* OK, check if the Stage 1.5 exists. */
-+ char stage1_5[64];
-+
-+ grub_sprintf (stage1_5, "%s%s", prefix, stage1_5_map[i].name);
-+ if (check_file (stage1_5))
-+ {
-+ if (embed_stage1_5 (stage1_5,
-+ installed_drive, installed_partition)
-+ || embed_stage1_5 (stage1_5,
-+ image_drive, image_partition))
-+ {
-+ grub_strcpy (real_config_filename, config_filename);
-+ sprint_device (image_drive, image_partition);
-+ grub_sprintf (config_filename, "%s%s", device, stage2);
-+ grub_strcpy (stage2, buffer);
-+ }
-+ }
-+ errnum = 0;
-+ break;
-+ }
-+ }
-+
-+ /* Construct a string that is used by the command "install" as its
-+ arguments. */
-+ sprint_device (installed_drive, installed_partition);
-+
-+#if 1
-+ /* Don't embed a drive number unnecessarily. */
-+ grub_sprintf (cmd_arg, "%s%s%s%s %s%s %s p %s %s",
-+ is_force_lba? "--force-lba " : "",
-+ stage2_arg? stage2_arg : "",
-+ stage2_arg? " " : "",
-+ stage1,
-+ (installed_drive != image_drive) ? "d " : "",
-+ device,
-+ stage2,
-+ config_filename,
-+ real_config_filename);
-+#else /* NOT USED */
-+ /* This code was used, because we belived some BIOSes had a problem
-+ that they didn't pass a booting drive correctly. It turned out,
-+ however, stage1 could trash a booting drive when checking LBA support,
-+ because some BIOSes modified the register %dx in INT 13H, AH=48H.
-+ So it becamed unclear whether GRUB should use a pre-defined booting
-+ drive or not. If the problem still exists, it would be necessary to
-+ switch back to this code. */
-+ grub_sprintf (cmd_arg, "%s%s%s%s d %s %s p %s %s",
-+ is_force_lba? "--force-lba " : "",
-+ stage2_arg? stage2_arg : "",
-+ stage2_arg? " " : "",
-+ stage1,
-+ device,
-+ stage2,
-+ config_filename,
-+ real_config_filename);
-+#endif /* NOT USED */
-+
-+ /* Notify what will be run. */
-+ grub_printf (" Running \"install %s\"... ", cmd_arg);
-+
-+ /* Make sure that SAVED_DRIVE and SAVED_PARTITION are identical
-+ with IMAGE_DRIVE and IMAGE_PARTITION, respectively. */
-+ saved_drive = image_drive;
-+ saved_partition = image_partition;
-+
-+ /* Run the command. */
-+ if (! install_func (cmd_arg, flags))
-+ grub_printf ("succeeded\nDone.\n");
-+ else
-+ grub_printf ("failed\n");
-+
-+ fail:
-+ saved_drive = tmp_drive;
-+ saved_partition = tmp_partition;
-+ return errnum;
-+}
-+
-+static struct builtin builtin_setup =
-+{
-+ "setup",
-+ setup_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "setup [--prefix=DIR] [--stage2=STAGE2_FILE] [--force-lba] INSTALL_DEVICE [IMAGE_DEVICE]",
-+ "Set up the installation of GRUB automatically. This command uses"
-+ " the more flexible command \"install\" in the backend and installs"
-+ " GRUB into the device INSTALL_DEVICE. If IMAGE_DEVICE is specified,"
-+ " then find the GRUB images in the device IMAGE_DEVICE, otherwise"
-+ " use the current \"root device\", which can be set by the command"
-+ " \"root\". If you know that your BIOS should support LBA but GRUB"
-+ " doesn't work in LBA mode, specify the option `--force-lba'."
-+ " If you install GRUB under the grub shell and you cannot unmount the"
-+ " partition where GRUB images reside, specify the option `--stage2'"
-+ " to tell GRUB the file name under your OS."
-+};
-+
-+\f
-+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
-+/* terminal */
-+static int
-+terminal_func (char *arg, int flags)
-+{
-+ /* The index of the default terminal in TERM_TABLE. */
-+ int default_term = -1;
-+ struct term_entry *prev_term = current_term;
-+ int to = -1;
-+ int lines = 0;
-+ int no_message = 0;
-+ unsigned long term_flags = 0;
-+ /* XXX: Assume less than 32 terminals. */
-+ unsigned long term_bitmap = 0;
-+
-+ /* Get GNU-style long options. */
-+ while (1)
-+ {
-+ if (grub_memcmp (arg, "--dumb", sizeof ("--dumb") - 1) == 0)
-+ term_flags |= TERM_DUMB;
-+ else if (grub_memcmp (arg, "--no-echo", sizeof ("--no-echo") - 1) == 0)
-+ /* ``--no-echo'' implies ``--no-edit''. */
-+ term_flags |= (TERM_NO_ECHO | TERM_NO_EDIT);
-+ else if (grub_memcmp (arg, "--no-edit", sizeof ("--no-edit") - 1) == 0)
-+ term_flags |= TERM_NO_EDIT;
-+ else if (grub_memcmp (arg, "--timeout=", sizeof ("--timeout=") - 1) == 0)
-+ {
-+ char *val = arg + sizeof ("--timeout=") - 1;
-+
-+ if (! safe_parse_maxint (&val, &to))
-+ return 1;
-+ }
-+ else if (grub_memcmp (arg, "--lines=", sizeof ("--lines=") - 1) == 0)
-+ {
-+ char *val = arg + sizeof ("--lines=") - 1;
-+
-+ if (! safe_parse_maxint (&val, &lines))
-+ return 1;
-+
-+ /* Probably less than four is meaningless.... */
-+ if (lines < 4)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+ }
-+ else if (grub_memcmp (arg, "--silent", sizeof ("--silent") - 1) == 0)
-+ no_message = 1;
-+ else
-+ break;
-+
-+ arg = skip_to (0, arg);
-+ }
-+
-+ /* If no argument is specified, show current setting. */
-+ if (! *arg)
-+ {
-+ grub_printf ("%s%s%s%s\n",
-+ current_term->name,
-+ current_term->flags & TERM_DUMB ? " (dumb)" : "",
-+ current_term->flags & TERM_NO_EDIT ? " (no edit)" : "",
-+ current_term->flags & TERM_NO_ECHO ? " (no echo)" : "");
-+ return 0;
-+ }
-+
-+ while (*arg)
-+ {
-+ int i;
-+ char *next = skip_to (0, arg);
-+
-+ nul_terminate (arg);
-+
-+ for (i = 0; term_table[i].name; i++)
-+ {
-+ if (grub_strcmp (arg, term_table[i].name) == 0)
-+ {
-+ if (term_table[i].flags & TERM_NEED_INIT)
-+ {
-+ errnum = ERR_DEV_NEED_INIT;
-+ return 1;
-+ }
-+
-+ if (default_term < 0)
-+ default_term = i;
-+
-+ term_bitmap |= (1 << i);
-+ break;
-+ }
-+ }
-+
-+ if (! term_table[i].name)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ arg = next;
-+ }
-+
-+ /* If multiple terminals are specified, wait until the user pushes any
-+ key on one of the terminals. */
-+ if (term_bitmap & ~(1 << default_term))
-+ {
-+ int time1, time2 = -1;
-+
-+ /* XXX: Disable the pager. */
-+ count_lines = -1;
-+
-+ /* Get current time. */
-+ while ((time1 = getrtsecs ()) == 0xFF)
-+ ;
-+
-+ /* Wait for a key input. */
-+ while (to)
-+ {
-+ int i;
-+
-+ for (i = 0; term_table[i].name; i++)
-+ {
-+ if (term_bitmap & (1 << i))
-+ {
-+ if (term_table[i].checkkey () >= 0)
-+ {
-+ (void) term_table[i].getkey ();
-+ default_term = i;
-+
-+ goto end;
-+ }
-+ }
-+ }
-+
-+ /* Prompt the user, once per sec. */
-+ if ((time1 = getrtsecs ()) != time2 && time1 != 0xFF)
-+ {
-+ if (! no_message)
-+ {
-+ /* Need to set CURRENT_TERM to each of selected
-+ terminals. */
-+ for (i = 0; term_table[i].name; i++)
-+ if (term_bitmap & (1 << i))
-+ {
-+ current_term = term_table + i;
-+ grub_printf ("\rPress any key to continue.\n");
-+ }
-+
-+ /* Restore CURRENT_TERM. */
-+ current_term = prev_term;
-+ }
-+
-+ time2 = time1;
-+ if (to > 0)
-+ to--;
-+ }
-+ }
-+ }
-+
-+ end:
-+ current_term = term_table + default_term;
-+ current_term->flags = term_flags;
-+
-+ if (lines)
-+ max_lines = lines;
-+ else
-+ /* 24 would be a good default value. */
-+ max_lines = 24;
-+
-+ /* If the interface is currently the command-line,
-+ restart it to repaint the screen. */
-+ if (current_term != prev_term && (flags & BUILTIN_CMDLINE))
-+ grub_longjmp (restart_cmdline_env, 0);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_terminal =
-+{
-+ "terminal",
-+ terminal_func,
-+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "terminal [--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] [--silent] [console] [serial] [hercules]",
-+ "Select a terminal. When multiple terminals are specified, wait until"
-+ " you push any key to continue. If both console and serial are specified,"
-+ " the terminal to which you input a key first will be selected. If no"
-+ " argument is specified, print current setting. The option --dumb"
-+ " specifies that your terminal is dumb, otherwise, vt100-compatibility"
-+ " is assumed. If you specify --no-echo, input characters won't be echoed."
-+ " If you specify --no-edit, the BASH-like editing feature will be disabled."
-+ " If --timeout is present, this command will wait at most for SECS"
-+ " seconds. The option --lines specifies the maximum number of lines."
-+ " The option --silent is used to suppress messages."
-+};
-+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
-+
-+\f
-+#ifdef SUPPORT_SERIAL
-+static int
-+terminfo_func (char *arg, int flags)
-+{
-+ struct terminfo term;
-+
-+ if (*arg)
-+ {
-+ struct
-+ {
-+ const char *name;
-+ char *var;
-+ }
-+ options[] =
-+ {
-+ {"--name=", term.name},
-+ {"--cursor-address=", term.cursor_address},
-+ {"--clear-screen=", term.clear_screen},
-+ {"--enter-standout-mode=", term.enter_standout_mode},
-+ {"--exit-standout-mode=", term.exit_standout_mode}
-+ };
-+
-+ grub_memset (&term, 0, sizeof (term));
-+
-+ while (*arg)
-+ {
-+ int i;
-+ char *next = skip_to (0, arg);
-+
-+ nul_terminate (arg);
-+
-+ for (i = 0; i < sizeof (options) / sizeof (options[0]); i++)
-+ {
-+ const char *name = options[i].name;
-+ int len = grub_strlen (name);
-+
-+ if (! grub_memcmp (arg, name, len))
-+ {
-+ grub_strcpy (options[i].var, ti_unescape_string (arg + len));
-+ break;
-+ }
-+ }
-+
-+ if (i == sizeof (options) / sizeof (options[0]))
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return errnum;
-+ }
-+
-+ arg = next;
-+ }
-+
-+ if (term.name[0] == 0 || term.cursor_address[0] == 0)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return errnum;
-+ }
-+
-+ ti_set_term (&term);
-+ }
-+ else
-+ {
-+ /* No option specifies printing out current settings. */
-+ ti_get_term (&term);
-+
-+ grub_printf ("name=%s\n",
-+ ti_escape_string (term.name));
-+ grub_printf ("cursor_address=%s\n",
-+ ti_escape_string (term.cursor_address));
-+ grub_printf ("clear_screen=%s\n",
-+ ti_escape_string (term.clear_screen));
-+ grub_printf ("enter_standout_mode=%s\n",
-+ ti_escape_string (term.enter_standout_mode));
-+ grub_printf ("exit_standout_mode=%s\n",
-+ ti_escape_string (term.exit_standout_mode));
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_terminfo =
-+{
-+ "terminfo",
-+ terminfo_func,
-+ BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "terminfo [--name=NAME --cursor-address=SEQ [--clear-screen=SEQ]"
-+ " [--enter-standout-mode=SEQ] [--exit-standout-mode=SEQ]]",
-+
-+ "Define the capabilities of your terminal. Use this command to"
-+ " define escape sequences, if it is not vt100-compatible."
-+ " You may use \\e for ESC and ^X for a control character."
-+ " If no option is specified, the current settings are printed."
-+};
-+#endif /* SUPPORT_SERIAL */
-+
-+\f
-+/* testload */
-+static int
-+testload_func (char *arg, int flags)
-+{
-+ int i;
-+
-+ kernel_type = KERNEL_TYPE_NONE;
-+
-+ if (! grub_open (arg))
-+ return 1;
-+
-+ disk_read_hook = disk_read_print_func;
-+
-+ /* Perform filesystem test on the specified file. */
-+ /* Read whole file first. */
-+ grub_printf ("Whole file: ");
-+
-+ grub_read ((char *) RAW_ADDR (0x100000), -1);
-+
-+ /* Now compare two sections of the file read differently. */
-+
-+ for (i = 0; i < 0x10ac0; i++)
-+ {
-+ *((unsigned char *) RAW_ADDR (0x200000 + i)) = 0;
-+ *((unsigned char *) RAW_ADDR (0x300000 + i)) = 1;
-+ }
-+
-+ /* First partial read. */
-+ grub_printf ("\nPartial read 1: ");
-+
-+ grub_seek (0);
-+ grub_read ((char *) RAW_ADDR (0x200000), 0x7);
-+ grub_read ((char *) RAW_ADDR (0x200007), 0x100);
-+ grub_read ((char *) RAW_ADDR (0x200107), 0x10);
-+ grub_read ((char *) RAW_ADDR (0x200117), 0x999);
-+ grub_read ((char *) RAW_ADDR (0x200ab0), 0x10);
-+ grub_read ((char *) RAW_ADDR (0x200ac0), 0x10000);
-+
-+ /* Second partial read. */
-+ grub_printf ("\nPartial read 2: ");
-+
-+ grub_seek (0);
-+ grub_read ((char *) RAW_ADDR (0x300000), 0x10000);
-+ grub_read ((char *) RAW_ADDR (0x310000), 0x10);
-+ grub_read ((char *) RAW_ADDR (0x310010), 0x7);
-+ grub_read ((char *) RAW_ADDR (0x310017), 0x10);
-+ grub_read ((char *) RAW_ADDR (0x310027), 0x999);
-+ grub_read ((char *) RAW_ADDR (0x3109c0), 0x100);
-+
-+ grub_printf ("\nHeader1 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n",
-+ *((int *) RAW_ADDR (0x200000)),
-+ *((int *) RAW_ADDR (0x200004)),
-+ *((int *) RAW_ADDR (0x200008)),
-+ *((int *) RAW_ADDR (0x20000c)));
-+
-+ grub_printf ("Header2 = 0x%x, next = 0x%x, next = 0x%x, next = 0x%x\n",
-+ *((int *) RAW_ADDR (0x300000)),
-+ *((int *) RAW_ADDR (0x300004)),
-+ *((int *) RAW_ADDR (0x300008)),
-+ *((int *) RAW_ADDR (0x30000c)));
-+
-+ for (i = 0; i < 0x10ac0; i++)
-+ if (*((unsigned char *) RAW_ADDR (0x200000 + i))
-+ != *((unsigned char *) RAW_ADDR (0x300000 + i)))
-+ break;
-+
-+ grub_printf ("Max is 0x10ac0: i=0x%x, filepos=0x%x\n", i, filepos);
-+ disk_read_hook = 0;
-+ grub_close ();
-+ return 0;
-+}
-+
-+static struct builtin builtin_testload =
-+{
-+ "testload",
-+ testload_func,
-+ BUILTIN_CMDLINE,
-+ "testload FILE",
-+ "Read the entire contents of FILE in several different ways and"
-+ " compares them, to test the filesystem code. The output is somewhat"
-+ " cryptic, but if no errors are reported and the final `i=X,"
-+ " filepos=Y' reading has X and Y equal, then it is definitely"
-+ " consistent, and very likely works correctly subject to a"
-+ " consistent offset error. If this test succeeds, then a good next"
-+ " step is to try loading a kernel."
-+};
-+
-+\f
-+/* testvbe MODE */
-+static int
-+testvbe_func (char *arg, int flags)
-+{
-+ int mode_number;
-+ struct vbe_controller controller;
-+ struct vbe_mode mode;
-+
-+ if (! *arg)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ if (! safe_parse_maxint (&arg, &mode_number))
-+ return 1;
-+
-+ /* Preset `VBE2'. */
-+ grub_memmove (controller.signature, "VBE2", 4);
-+
-+ /* Detect VBE BIOS. */
-+ if (get_vbe_controller_info (&controller) != 0x004F)
-+ {
-+ grub_printf (" VBE BIOS is not present.\n");
-+ return 0;
-+ }
-+
-+ if (controller.version < 0x0200)
-+ {
-+ grub_printf (" VBE version %d.%d is not supported.\n",
-+ (int) (controller.version >> 8),
-+ (int) (controller.version & 0xFF));
-+ return 0;
-+ }
-+
-+ if (get_vbe_mode_info (mode_number, &mode) != 0x004F
-+ || (mode.mode_attributes & 0x0091) != 0x0091)
-+ {
-+ grub_printf (" Mode 0x%x is not supported.\n", mode_number);
-+ return 0;
-+ }
-+
-+ /* Now trip to the graphics mode. */
-+ if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F)
-+ {
-+ grub_printf (" Switching to Mode 0x%x failed.\n", mode_number);
-+ return 0;
-+ }
-+
-+ /* Draw something on the screen... */
-+ {
-+ unsigned char *base_buf = (unsigned char *) mode.phys_base;
-+ int scanline = controller.version >= 0x0300
-+ ? mode.linear_bytes_per_scanline : mode.bytes_per_scanline;
-+ /* FIXME: this assumes that any depth is a modulo of 8. */
-+ int bpp = mode.bits_per_pixel / 8;
-+ int width = mode.x_resolution;
-+ int height = mode.y_resolution;
-+ int x, y;
-+ unsigned color = 0;
-+
-+ /* Iterate drawing on the screen, until the user hits any key. */
-+ while (checkkey () == -1)
-+ {
-+ for (y = 0; y < height; y++)
-+ {
-+ unsigned char *line_buf = base_buf + scanline * y;
-+
-+ for (x = 0; x < width; x++)
-+ {
-+ unsigned char *buf = line_buf + bpp * x;
-+ int i;
-+
-+ for (i = 0; i < bpp; i++, buf++)
-+ *buf = (color >> (i * 8)) & 0xff;
-+ }
-+
-+ color++;
-+ }
-+ }
-+
-+ /* Discard the input. */
-+ getkey ();
-+ }
-+
-+ /* Back to the default text mode. */
-+ if (set_vbe_mode (0x03) != 0x004F)
-+ {
-+ /* Why?! */
-+ grub_reboot ();
-+ }
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_testvbe =
-+{
-+ "testvbe",
-+ testvbe_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "testvbe MODE",
-+ "Test the VBE mode MODE. Hit any key to return."
-+};
-+
-+\f
-+#ifdef SUPPORT_NETBOOT
-+/* tftpserver */
-+static int
-+tftpserver_func (char *arg, int flags)
-+{
-+ if (! *arg || ! ifconfig (0, 0, 0, arg))
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
-+ print_network_configuration ();
-+ return 0;
-+}
-+
-+static struct builtin builtin_tftpserver =
-+{
-+ "tftpserver",
-+ tftpserver_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "tftpserver IPADDR",
-+ "Override the TFTP server address."
-+};
-+#endif /* SUPPORT_NETBOOT */
-+
-+\f
-+/* timeout */
-+static int
-+timeout_func (char *arg, int flags)
-+{
-+ if (! safe_parse_maxint (&arg, &grub_timeout))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_timeout =
-+{
-+ "timeout",
-+ timeout_func,
-+ BUILTIN_MENU,
-+#if 0
-+ "timeout SEC",
-+ "Set a timeout, in SEC seconds, before automatically booting the"
-+ " default entry (normally the first entry defined)."
-+#endif
-+};
-+
-+\f
-+/* title */
-+static int
-+title_func (char *arg, int flags)
-+{
-+ /* This function is not actually used at least currently. */
-+ return 0;
-+}
-+
-+static struct builtin builtin_title =
-+{
-+ "title",
-+ title_func,
-+ BUILTIN_TITLE,
-+#if 0
-+ "title [NAME ...]",
-+ "Start a new boot entry, and set its name to the contents of the"
-+ " rest of the line, starting with the first non-space character."
-+#endif
-+};
-+
-+\f
-+/* unhide */
-+static int
-+unhide_func (char *arg, int flags)
-+{
-+ if (! set_device (arg))
-+ return 1;
-+
-+ if (! set_partition_hidden_flag (0))
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_unhide =
-+{
-+ "unhide",
-+ unhide_func,
-+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
-+ "unhide PARTITION",
-+ "Unhide PARTITION by clearing the \"hidden\" bit in its"
-+ " partition type code."
-+};
-+
-+\f
-+/* uppermem */
-+static int
-+uppermem_func (char *arg, int flags)
-+{
-+ if (! safe_parse_maxint (&arg, (int *) &mbi.mem_upper))
-+ return 1;
-+
-+ mbi.flags &= ~MB_INFO_MEM_MAP;
-+ return 0;
-+}
-+
-+static struct builtin builtin_uppermem =
-+{
-+ "uppermem",
-+ uppermem_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "uppermem KBYTES",
-+ "Force GRUB to assume that only KBYTES kilobytes of upper memory are"
-+ " installed. Any system address range maps are discarded."
-+};
-+
-+\f
-+/* vbeprobe */
-+static int
-+vbeprobe_func (char *arg, int flags)
-+{
-+ struct vbe_controller controller;
-+ unsigned short *mode_list;
-+ int mode_number = -1;
-+
-+ auto unsigned long vbe_far_ptr_to_linear (unsigned long);
-+
-+ unsigned long vbe_far_ptr_to_linear (unsigned long ptr)
-+ {
-+ unsigned short seg = (ptr >> 16);
-+ unsigned short off = (ptr & 0xFFFF);
-+
-+ return (seg << 4) + off;
-+ }
-+
-+ if (*arg)
-+ {
-+ if (! safe_parse_maxint (&arg, &mode_number))
-+ return 1;
-+ }
-+
-+ /* Set the signature to `VBE2', to obtain VBE 3.0 information. */
-+ grub_memmove (controller.signature, "VBE2", 4);
-+
-+ if (get_vbe_controller_info (&controller) != 0x004F)
-+ {
-+ grub_printf (" VBE BIOS is not present.\n");
-+ return 0;
-+ }
-+
-+ /* Check the version. */
-+ if (controller.version < 0x0200)
-+ {
-+ grub_printf (" VBE version %d.%d is not supported.\n",
-+ (int) (controller.version >> 8),
-+ (int) (controller.version & 0xFF));
-+ return 0;
-+ }
-+
-+ /* Print some information. */
-+ grub_printf (" VBE version %d.%d\n",
-+ (int) (controller.version >> 8),
-+ (int) (controller.version & 0xFF));
-+
-+ /* Iterate probing modes. */
-+ for (mode_list
-+ = (unsigned short *) vbe_far_ptr_to_linear (controller.video_mode);
-+ *mode_list != 0xFFFF;
-+ mode_list++)
-+ {
-+ struct vbe_mode mode;
-+
-+ if (get_vbe_mode_info (*mode_list, &mode) != 0x004F)
-+ continue;
-+
-+ /* Skip this, if this is not supported or linear frame buffer
-+ mode is not support. */
-+ if ((mode.mode_attributes & 0x0081) != 0x0081)
-+ continue;
-+
-+ if (mode_number == -1 || mode_number == *mode_list)
-+ {
-+ char *model;
-+ switch (mode.memory_model)
-+ {
-+ case 0x00: model = "Text"; break;
-+ case 0x01: model = "CGA graphics"; break;
-+ case 0x02: model = "Hercules graphics"; break;
-+ case 0x03: model = "Planar"; break;
-+ case 0x04: model = "Packed pixel"; break;
-+ case 0x05: model = "Non-chain 4, 256 color"; break;
-+ case 0x06: model = "Direct Color"; break;
-+ case 0x07: model = "YUV"; break;
-+ default: model = "Unknown"; break;
-+ }
-+
-+ grub_printf (" 0x%x: %s, %ux%ux%u\n",
-+ (unsigned) *mode_list,
-+ model,
-+ (unsigned) mode.x_resolution,
-+ (unsigned) mode.y_resolution,
-+ (unsigned) mode.bits_per_pixel);
-+
-+ if (mode_number != -1)
-+ break;
-+ }
-+ }
-+
-+ if (mode_number != -1 && mode_number != *mode_list)
-+ grub_printf (" Mode 0x%x is not found or supported.\n", mode_number);
-+
-+ return 0;
-+}
-+
-+static struct builtin builtin_vbeprobe =
-+{
-+ "vbeprobe",
-+ vbeprobe_func,
-+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-+ "vbeprobe [MODE]",
-+ "Probe VBE information. If the mode number MODE is specified, show only"
-+ " the information about only the mode."
-+};
-+
-+\f
-+/* The table of builtin commands. Sorted in dictionary order. */
-+struct builtin *builtin_table[] =
-+{
-+ &builtin_blocklist,
-+ &builtin_boot,
-+#ifdef SUPPORT_NETBOOT
-+ &builtin_bootp,
-+#endif /* SUPPORT_NETBOOT */
-+ &builtin_cat,
-+ &builtin_chainloader,
-+ &builtin_cmp,
-+ &builtin_color,
-+ &builtin_configfile,
-+ &builtin_debug,
-+ &builtin_default,
-+#ifdef GRUB_UTIL
-+ &builtin_device,
-+#endif /* GRUB_UTIL */
-+#ifdef SUPPORT_NETBOOT
-+ &builtin_dhcp,
-+#endif /* SUPPORT_NETBOOT */
-+ &builtin_displayapm,
-+ &builtin_displaymem,
-+#ifdef GRUB_UTIL
-+ &builtin_dump,
-+#endif /* GRUB_UTIL */
-+ &builtin_embed,
-+ &builtin_fallback,
-+ &builtin_find,
-+ &builtin_fstest,
-+ &builtin_geometry,
-+ &builtin_halt,
-+ &builtin_help,
-+ &builtin_hiddenmenu,
-+ &builtin_hide,
-+#ifdef SUPPORT_NETBOOT
-+ &builtin_ifconfig,
-+#endif /* SUPPORT_NETBOOT */
-+ &builtin_impsprobe,
-+ &builtin_initrd,
-+ &builtin_install,
-+ &builtin_ioprobe,
-+ &builtin_kernel,
-+ &builtin_lock,
-+ &builtin_makeactive,
-+ &builtin_map,
-+#ifdef USE_MD5_PASSWORDS
-+ &builtin_md5crypt,
-+#endif /* USE_MD5_PASSWORDS */
-+ &builtin_module,
-+ &builtin_modulenounzip,
-+ &builtin_pager,
-+ &builtin_partnew,
-+ &builtin_parttype,
-+ &builtin_password,
-+ &builtin_pause,
-+#ifdef GRUB_UTIL
-+ &builtin_quit,
-+#endif /* GRUB_UTIL */
-+#ifdef SUPPORT_NETBOOT
-+ &builtin_rarp,
-+#endif /* SUPPORT_NETBOOT */
-+ &builtin_read,
-+ &builtin_reboot,
-+ &builtin_root,
-+ &builtin_rootnoverify,
-+ &builtin_savedefault,
-+#ifdef SUPPORT_SERIAL
-+ &builtin_serial,
-+#endif /* SUPPORT_SERIAL */
-+ &builtin_setkey,
-+ &builtin_setup,
-+#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
-+ &builtin_terminal,
-+#endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
-+#ifdef SUPPORT_SERIAL
-+ &builtin_terminfo,
-+#endif /* SUPPORT_SERIAL */
-+ &builtin_testload,
-+ &builtin_testvbe,
-+#ifdef SUPPORT_NETBOOT
-+ &builtin_tftpserver,
-+#endif /* SUPPORT_NETBOOT */
-+ &builtin_timeout,
-+ &builtin_title,
-+ &builtin_unhide,
-+ &builtin_uppermem,
-+ &builtin_vbeprobe,
-+ 0
-+};
-diff -Nur grub-0.97/stage2/char_io.c grub-0.97-patched/stage2/char_io.c
---- grub-0.97/stage2/char_io.c 2005-02-01 21:51:23.000000000 +0100
-+++ grub-0.97-patched/stage2/char_io.c 2012-11-11 17:06:52.556085241 +0100
-@@ -35,6 +35,7 @@
- {
- "console",
- 0,
-+ 24,
- console_putchar,
- console_checkkey,
- console_getkey,
-@@ -43,13 +44,16 @@
- console_cls,
- console_setcolorstate,
- console_setcolor,
-- console_setcursor
-+ console_setcursor,
-+ 0,
-+ 0
- },
- #ifdef SUPPORT_SERIAL
- {
- "serial",
- /* A serial device must be initialized. */
- TERM_NEED_INIT,
-+ 24,
- serial_putchar,
- serial_checkkey,
- serial_getkey,
-@@ -58,6 +62,8 @@
- serial_cls,
- serial_setcolorstate,
- 0,
-+ 0,
-+ 0,
- 0
- },
- #endif /* SUPPORT_SERIAL */
-@@ -65,6 +71,7 @@
- {
- "hercules",
- 0,
-+ 24,
- hercules_putchar,
- console_checkkey,
- console_getkey,
-@@ -73,9 +80,28 @@
- hercules_cls,
- hercules_setcolorstate,
- hercules_setcolor,
-- hercules_setcursor
-+ hercules_setcursor,
-+ 0,
-+ 0
- },
- #endif /* SUPPORT_HERCULES */
-+#ifdef SUPPORT_GRAPHICS
-+ { "graphics",
-+ TERM_NEED_INIT, /* flags */
-+ 30, /* number of lines */
-+ graphics_putchar, /* putchar */
-+ console_checkkey, /* checkkey */
-+ console_getkey, /* getkey */
-+ graphics_getxy, /* getxy */
-+ graphics_gotoxy, /* gotoxy */
-+ graphics_cls, /* cls */
-+ graphics_setcolorstate, /* setcolorstate */
-+ graphics_setcolor, /* setcolor */
-+ graphics_setcursor, /* nocursor */
-+ graphics_init, /* initialize */
-+ graphics_end /* shutdown */
-+ },
-+#endif /* SUPPORT_GRAPHICS */
- /* This must be the last entry. */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
- };
-@@ -1046,13 +1072,15 @@
- the following grub_printf call will print newlines. */
- count_lines = -1;
-
-+ grub_printf("\n");
- if (current_term->setcolorstate)
- current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
-
-- grub_printf ("\n[Hit return to continue]");
-+ grub_printf ("[Hit return to continue]");
-
- if (current_term->setcolorstate)
- current_term->setcolorstate (COLOR_STATE_NORMAL);
-+
-
- do
- {
-@@ -1090,7 +1118,7 @@
- cls (void)
- {
- /* If the terminal is dumb, there is no way to clean the terminal. */
-- if (current_term->flags & TERM_DUMB)
-+ if (current_term->flags & TERM_DUMB)
- grub_putchar ('\n');
- else
- current_term->cls ();
-@@ -1174,37 +1202,62 @@
- }
- #endif /* ! STAGE1_5 */
-
-+#ifdef GRUB_UTIL
-+# ifdef __PIC__
-+# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL)
-+ extern char start[];
-+ extern char end[];
-+# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL)
-+ extern char _start[];
-+ extern char _end[];
-+# endif
-+# endif
-+#endif
- int
--memcheck (int addr, int len)
-+memcheck (unsigned long addr, unsigned long len)
- {
- #ifdef GRUB_UTIL
-- auto int start_addr (void);
-- auto int end_addr (void);
-+# ifdef __PIC__
-+# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL)
-+ if (start <= addr && end > addr + len)
-+ return ! errnum;
-+# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL)
-+ if (_start <= addr && _end > addr + len)
-+ return ! errnum;
-+# endif
-+# else /* __PIC__ */
-+ auto unsigned long start_addr (void);
-+ auto unsigned long end_addr (void);
-
-- auto int start_addr (void)
-+ auto unsigned long start_addr (void)
- {
-- int ret;
--# if defined(HAVE_START_SYMBOL)
-+ unsigned long ret;
-+# if defined(HAVE_START_SYMBOL)
- asm volatile ("movl $start, %0" : "=a" (ret));
--# elif defined(HAVE_USCORE_START_SYMBOL)
-+# elif defined(HAVE_USCORE_START_SYMBOL)
- asm volatile ("movl $_start, %0" : "=a" (ret));
--# endif
-+# else
-+ erk! /* function would return undefined data in this case - barf */
-+# endif
- return ret;
- }
-
-- auto int end_addr (void)
-+ auto unsigned long end_addr (void)
- {
-- int ret;
--# if defined(HAVE_END_SYMBOL)
-+ unsigned long ret;
-+# if defined(HAVE_END_SYMBOL)
- asm volatile ("movl $end, %0" : "=a" (ret));
--# elif defined(HAVE_USCORE_END_SYMBOL)
-+# elif defined(HAVE_USCORE_END_SYMBOL)
- asm volatile ("movl $_end, %0" : "=a" (ret));
--# endif
-+# else
-+ erk! /* function would return undefined data in this case - barf */
-+# endif
- return ret;
- }
-
- if (start_addr () <= addr && end_addr () > addr + len)
- return ! errnum;
-+# endif /* __PIC__ */
- #endif /* GRUB_UTIL */
-
- if ((addr < RAW_ADDR (0x1000))
-@@ -1217,10 +1270,20 @@
- return ! errnum;
- }
-
-+void
-+grub_memcpy(void *dest, const void *src, int len)
-+{
-+ int i;
-+ register char *d = (char*)dest, *s = (char*)src;
-+
-+ for (i = 0; i < len; i++)
-+ d[i] = s[i];
-+}
-+
- void *
- grub_memmove (void *to, const void *from, int len)
- {
-- if (memcheck ((int) to, len))
-+ if (memcheck ((unsigned long) to, len))
- {
- /* This assembly code is stolen from
- linux-2.2.2/include/asm-i386/string.h. This is not very fast
-@@ -1258,7 +1321,7 @@
- {
- char *p = start;
-
-- if (memcheck ((int) start, len))
-+ if (memcheck ((unsigned long) start, len))
- {
- while (len -- > 0)
- *p ++ = c;
-diff -Nur grub-0.97/stage2/char_io.c.orig grub-0.97-patched/stage2/char_io.c.orig
---- grub-0.97/stage2/char_io.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/char_io.c.orig 2005-02-01 21:51:23.000000000 +0100
-@@ -0,0 +1,1283 @@
-+/* char_io.c - basic console input and output */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#include <shared.h>
-+#include <term.h>
-+
-+#ifdef SUPPORT_HERCULES
-+# include <hercules.h>
-+#endif
-+
-+#ifdef SUPPORT_SERIAL
-+# include <serial.h>
-+#endif
-+
-+#ifndef STAGE1_5
-+struct term_entry term_table[] =
-+ {
-+ {
-+ "console",
-+ 0,
-+ console_putchar,
-+ console_checkkey,
-+ console_getkey,
-+ console_getxy,
-+ console_gotoxy,
-+ console_cls,
-+ console_setcolorstate,
-+ console_setcolor,
-+ console_setcursor
-+ },
-+#ifdef SUPPORT_SERIAL
-+ {
-+ "serial",
-+ /* A serial device must be initialized. */
-+ TERM_NEED_INIT,
-+ serial_putchar,
-+ serial_checkkey,
-+ serial_getkey,
-+ serial_getxy,
-+ serial_gotoxy,
-+ serial_cls,
-+ serial_setcolorstate,
-+ 0,
-+ 0
-+ },
-+#endif /* SUPPORT_SERIAL */
-+#ifdef SUPPORT_HERCULES
-+ {
-+ "hercules",
-+ 0,
-+ hercules_putchar,
-+ console_checkkey,
-+ console_getkey,
-+ hercules_getxy,
-+ hercules_gotoxy,
-+ hercules_cls,
-+ hercules_setcolorstate,
-+ hercules_setcolor,
-+ hercules_setcursor
-+ },
-+#endif /* SUPPORT_HERCULES */
-+ /* This must be the last entry. */
-+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-+ };
-+
-+/* This must be console. */
-+struct term_entry *current_term = term_table;
-+
-+int max_lines = 24;
-+int count_lines = -1;
-+int use_pager = 1;
-+#endif
-+
-+void
-+print_error (void)
-+{
-+ if (errnum > ERR_NONE && errnum < MAX_ERR_NUM)
-+#ifndef STAGE1_5
-+ /* printf("\7\n %s\n", err_list[errnum]); */
-+ printf ("\nError %u: %s\n", errnum, err_list[errnum]);
-+#else /* STAGE1_5 */
-+ printf ("Error %u\n", errnum);
-+#endif /* STAGE1_5 */
-+}
-+
-+char *
-+convert_to_ascii (char *buf, int c,...)
-+{
-+ unsigned long num = *((&c) + 1), mult = 10;
-+ char *ptr = buf;
-+
-+#ifndef STAGE1_5
-+ if (c == 'x' || c == 'X')
-+ mult = 16;
-+
-+ if ((num & 0x80000000uL) && c == 'd')
-+ {
-+ num = (~num) + 1;
-+ *(ptr++) = '-';
-+ buf++;
-+ }
-+#endif
-+
-+ do
-+ {
-+ int dig = num % mult;
-+ *(ptr++) = ((dig > 9) ? dig + 'a' - 10 : '0' + dig);
-+ }
-+ while (num /= mult);
-+
-+ /* reorder to correct direction!! */
-+ {
-+ char *ptr1 = ptr - 1;
-+ char *ptr2 = buf;
-+ while (ptr1 > ptr2)
-+ {
-+ int tmp = *ptr1;
-+ *ptr1 = *ptr2;
-+ *ptr2 = tmp;
-+ ptr1--;
-+ ptr2++;
-+ }
-+ }
-+
-+ return ptr;
-+}
-+
-+void
-+grub_putstr (const char *str)
-+{
-+ while (*str)
-+ grub_putchar (*str++);
-+}
-+
-+void
-+grub_printf (const char *format,...)
-+{
-+ int *dataptr = (int *) &format;
-+ char c, str[16];
-+
-+ dataptr++;
-+
-+ while ((c = *(format++)) != 0)
-+ {
-+ if (c != '%')
-+ grub_putchar (c);
-+ else
-+ switch (c = *(format++))
-+ {
-+#ifndef STAGE1_5
-+ case 'd':
-+ case 'x':
-+ case 'X':
-+#endif
-+ case 'u':
-+ *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
-+ grub_putstr (str);
-+ break;
-+
-+#ifndef STAGE1_5
-+ case 'c':
-+ grub_putchar ((*(dataptr++)) & 0xff);
-+ break;
-+
-+ case 's':
-+ grub_putstr ((char *) *(dataptr++));
-+ break;
-+#endif
-+ }
-+ }
-+}
-+
-+#ifndef STAGE1_5
-+int
-+grub_sprintf (char *buffer, const char *format, ...)
-+{
-+ /* XXX hohmuth
-+ ugly hack -- should unify with printf() */
-+ int *dataptr = (int *) &format;
-+ char c, *ptr, str[16];
-+ char *bp = buffer;
-+
-+ dataptr++;
-+
-+ while ((c = *format++) != 0)
-+ {
-+ if (c != '%')
-+ *bp++ = c; /* putchar(c); */
-+ else
-+ switch (c = *(format++))
-+ {
-+ case 'd': case 'u': case 'x':
-+ *convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
-+
-+ ptr = str;
-+
-+ while (*ptr)
-+ *bp++ = *(ptr++); /* putchar(*(ptr++)); */
-+ break;
-+
-+ case 'c': *bp++ = (*(dataptr++))&0xff;
-+ /* putchar((*(dataptr++))&0xff); */
-+ break;
-+
-+ case 's':
-+ ptr = (char *) (*(dataptr++));
-+
-+ while ((c = *ptr++) != 0)
-+ *bp++ = c; /* putchar(c); */
-+ break;
-+ }
-+ }
-+
-+ *bp = 0;
-+ return bp - buffer;
-+}
-+
-+
-+void
-+init_page (void)
-+{
-+ cls ();
-+
-+ grub_printf ("\n GNU GRUB version %s (%dK lower / %dK upper memory)\n\n",
-+ version_string, mbi.mem_lower, mbi.mem_upper);
-+}
-+
-+/* The number of the history entries. */
-+static int num_history = 0;
-+
-+/* Get the NOth history. If NO is less than zero or greater than or
-+ equal to NUM_HISTORY, return NULL. Otherwise return a valid string. */
-+static char *
-+get_history (int no)
-+{
-+ if (no < 0 || no >= num_history)
-+ return 0;
-+
-+ return (char *) HISTORY_BUF + MAX_CMDLINE * no;
-+}
-+
-+/* Add CMDLINE to the history buffer. */
-+static void
-+add_history (const char *cmdline, int no)
-+{
-+ grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1),
-+ (char *) HISTORY_BUF + MAX_CMDLINE * no,
-+ MAX_CMDLINE * (num_history - no));
-+ grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline);
-+ if (num_history < HISTORY_SIZE)
-+ num_history++;
-+}
-+
-+static int
-+real_get_cmdline (char *prompt, char *cmdline, int maxlen,
-+ int echo_char, int readline)
-+{
-+ /* This is a rather complicated function. So explain the concept.
-+
-+ A command-line consists of ``section''s. A section is a part of the
-+ line which may be displayed on the screen, but a section is never
-+ displayed with another section simultaneously.
-+
-+ Each section is basically 77 or less characters, but the exception
-+ is the first section, which is 78 or less characters, because the
-+ starting point is special. See below.
-+
-+ The first section contains a prompt and a command-line (or the
-+ first part of a command-line when it is too long to be fit in the
-+ screen). So, in the first section, the number of command-line
-+ characters displayed is 78 minus the length of the prompt (or
-+ less). If the command-line has more characters, `>' is put at the
-+ position 78 (zero-origin), to inform the user of the hidden
-+ characters.
-+
-+ Other sections always have `<' at the first position, since there
-+ is absolutely a section before each section. If there is a section
-+ after another section, this section consists of 77 characters and
-+ `>' at the last position. The last section has 77 or less
-+ characters and doesn't have `>'.
-+
-+ Each section other than the last shares some characters with the
-+ previous section. This region is called ``margin''. If the cursor
-+ is put at the magin which is shared by the first section and the
-+ second, the first section is displayed. Otherwise, a displayed
-+ section is switched to another section, only if the cursor is put
-+ outside that section. */
-+
-+ /* XXX: These should be defined in shared.h, but I leave these here,
-+ until this code is freezed. */
-+#define CMDLINE_WIDTH 78
-+#define CMDLINE_MARGIN 10
-+
-+ int xpos, lpos, c, section;
-+ /* The length of PROMPT. */
-+ int plen;
-+ /* The length of the command-line. */
-+ int llen;
-+ /* The index for the history. */
-+ int history = -1;
-+ /* The working buffer for the command-line. */
-+ char *buf = (char *) CMDLINE_BUF;
-+ /* The kill buffer. */
-+ char *kill_buf = (char *) KILL_BUF;
-+
-+ /* Nested function definitions for code simplicity. */
-+
-+ /* The forward declarations of nested functions are prefixed
-+ with `auto'. */
-+ auto void cl_refresh (int full, int len);
-+ auto void cl_backward (int count);
-+ auto void cl_forward (int count);
-+ auto void cl_insert (const char *str);
-+ auto void cl_delete (int count);
-+ auto void cl_init (void);
-+
-+ /* Move the cursor backward. */
-+ void cl_backward (int count)
-+ {
-+ lpos -= count;
-+
-+ /* If the cursor is in the first section, display the first section
-+ instead of the second. */
-+ if (section == 1 && plen + lpos < CMDLINE_WIDTH)
-+ cl_refresh (1, 0);
-+ else if (xpos - count < 1)
-+ cl_refresh (1, 0);
-+ else
-+ {
-+ xpos -= count;
-+
-+ if (current_term->flags & TERM_DUMB)
-+ {
-+ int i;
-+
-+ for (i = 0; i < count; i++)
-+ grub_putchar ('\b');
-+ }
-+ else
-+ gotoxy (xpos, getxy () & 0xFF);
-+ }
-+ }
-+
-+ /* Move the cursor forward. */
-+ void cl_forward (int count)
-+ {
-+ lpos += count;
-+
-+ /* If the cursor goes outside, scroll the screen to the right. */
-+ if (xpos + count >= CMDLINE_WIDTH)
-+ cl_refresh (1, 0);
-+ else
-+ {
-+ xpos += count;
-+
-+ if (current_term->flags & TERM_DUMB)
-+ {
-+ int i;
-+
-+ for (i = lpos - count; i < lpos; i++)
-+ {
-+ if (! echo_char)
-+ grub_putchar (buf[i]);
-+ else
-+ grub_putchar (echo_char);
-+ }
-+ }
-+ else
-+ gotoxy (xpos, getxy () & 0xFF);
-+ }
-+ }
-+
-+ /* Refresh the screen. If FULL is true, redraw the full line, otherwise,
-+ only LEN characters from LPOS. */
-+ void cl_refresh (int full, int len)
-+ {
-+ int i;
-+ int start;
-+ int pos = xpos;
-+
-+ if (full)
-+ {
-+ /* Recompute the section number. */
-+ if (lpos + plen < CMDLINE_WIDTH)
-+ section = 0;
-+ else
-+ section = ((lpos + plen - CMDLINE_WIDTH)
-+ / (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
-+
-+ /* From the start to the end. */
-+ len = CMDLINE_WIDTH;
-+ pos = 0;
-+ grub_putchar ('\r');
-+
-+ /* If SECTION is the first section, print the prompt, otherwise,
-+ print `<'. */
-+ if (section == 0)
-+ {
-+ grub_printf ("%s", prompt);
-+ len -= plen;
-+ pos += plen;
-+ }
-+ else
-+ {
-+ grub_putchar ('<');
-+ len--;
-+ pos++;
-+ }
-+ }
-+
-+ /* Compute the index to start writing BUF and the resulting position
-+ on the screen. */
-+ if (section == 0)
-+ {
-+ int offset = 0;
-+
-+ if (! full)
-+ offset = xpos - plen;
-+
-+ start = 0;
-+ xpos = lpos + plen;
-+ start += offset;
-+ }
-+ else
-+ {
-+ int offset = 0;
-+
-+ if (! full)
-+ offset = xpos - 1;
-+
-+ start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
-+ + CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
-+ xpos = lpos + 1 - start;
-+ start += offset;
-+ }
-+
-+ /* Print BUF. If ECHO_CHAR is not zero, put it instead. */
-+ for (i = start; i < start + len && i < llen; i++)
-+ {
-+ if (! echo_char)
-+ grub_putchar (buf[i]);
-+ else
-+ grub_putchar (echo_char);
-+
-+ pos++;
-+ }
-+
-+ /* Fill up the rest of the line with spaces. */
-+ for (; i < start + len; i++)
-+ {
-+ grub_putchar (' ');
-+ pos++;
-+ }
-+
-+ /* If the cursor is at the last position, put `>' or a space,
-+ depending on if there are more characters in BUF. */
-+ if (pos == CMDLINE_WIDTH)
-+ {
-+ if (start + len < llen)
-+ grub_putchar ('>');
-+ else
-+ grub_putchar (' ');
-+
-+ pos++;
-+ }
-+
-+ /* Back to XPOS. */
-+ if (current_term->flags & TERM_DUMB)
-+ {
-+ for (i = 0; i < pos - xpos; i++)
-+ grub_putchar ('\b');
-+ }
-+ else
-+ gotoxy (xpos, getxy () & 0xFF);
-+ }
-+
-+ /* Initialize the command-line. */
-+ void cl_init (void)
-+ {
-+ /* Distinguish us from other lines and error messages! */
-+ grub_putchar ('\n');
-+
-+ /* Print full line and set position here. */
-+ cl_refresh (1, 0);
-+ }
-+
-+ /* Insert STR to BUF. */
-+ void cl_insert (const char *str)
-+ {
-+ int l = grub_strlen (str);
-+
-+ if (llen + l < maxlen)
-+ {
-+ if (lpos == llen)
-+ grub_memmove (buf + lpos, str, l + 1);
-+ else
-+ {
-+ grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);
-+ grub_memmove (buf + lpos, str, l);
-+ }
-+
-+ llen += l;
-+ lpos += l;
-+ if (xpos + l >= CMDLINE_WIDTH)
-+ cl_refresh (1, 0);
-+ else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
-+ cl_refresh (0, CMDLINE_WIDTH - xpos);
-+ else
-+ cl_refresh (0, l + llen - lpos);
-+ }
-+ }
-+
-+ /* Delete COUNT characters in BUF. */
-+ void cl_delete (int count)
-+ {
-+ grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
-+ llen -= count;
-+
-+ if (xpos + llen + count - lpos > CMDLINE_WIDTH)
-+ cl_refresh (0, CMDLINE_WIDTH - xpos);
-+ else
-+ cl_refresh (0, llen + count - lpos);
-+ }
-+
-+ plen = grub_strlen (prompt);
-+ llen = grub_strlen (cmdline);
-+
-+ if (maxlen > MAX_CMDLINE)
-+ {
-+ maxlen = MAX_CMDLINE;
-+ if (llen >= MAX_CMDLINE)
-+ {
-+ llen = MAX_CMDLINE - 1;
-+ cmdline[MAX_CMDLINE] = 0;
-+ }
-+ }
-+ lpos = llen;
-+ grub_strcpy (buf, cmdline);
-+
-+ cl_init ();
-+
-+ while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
-+ {
-+ /* If READLINE is non-zero, handle readline-like key bindings. */
-+ if (readline)
-+ {
-+ switch (c)
-+ {
-+ case 9: /* TAB lists completions */
-+ {
-+ int i;
-+ /* POS points to the first space after a command. */
-+ int pos = 0;
-+ int ret;
-+ char *completion_buffer = (char *) COMPLETION_BUF;
-+ int equal_pos = -1;
-+ int is_filename;
-+
-+ /* Find the first word. */
-+ while (buf[pos] == ' ')
-+ pos++;
-+ while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')
-+ pos++;
-+
-+ is_filename = (lpos > pos);
-+
-+ /* Find the position of the equal character after a
-+ command, and replace it with a space. */
-+ for (i = pos; buf[i] && buf[i] != ' '; i++)
-+ if (buf[i] == '=')
-+ {
-+ equal_pos = i;
-+ buf[i] = ' ';
-+ break;
-+ }
-+
-+ /* Find the position of the first character in this
-+ word. */
-+ for (i = lpos; i > 0 && buf[i - 1] != ' '; i--)
-+ ;
-+
-+ /* Invalidate the cache, because the user may exchange
-+ removable disks. */
-+ buf_drive = -1;
-+
-+ /* Copy this word to COMPLETION_BUFFER and do the
-+ completion. */
-+ grub_memmove (completion_buffer, buf + i, lpos - i);
-+ completion_buffer[lpos - i] = 0;
-+ ret = print_completions (is_filename, 1);
-+ errnum = ERR_NONE;
-+
-+ if (ret >= 0)
-+ {
-+ /* Found, so insert COMPLETION_BUFFER. */
-+ cl_insert (completion_buffer + lpos - i);
-+
-+ if (ret > 0)
-+ {
-+ /* There are more than one candidates, so print
-+ the list. */
-+ grub_putchar ('\n');
-+ print_completions (is_filename, 0);
-+ errnum = ERR_NONE;
-+ }
-+ }
-+
-+ /* Restore the command-line. */
-+ if (equal_pos >= 0)
-+ buf[equal_pos] = '=';
-+
-+ if (ret)
-+ cl_init ();
-+ }
-+ break;
-+ case 1: /* C-a go to beginning of line */
-+ cl_backward (lpos);
-+ break;
-+ case 5: /* C-e go to end of line */
-+ cl_forward (llen - lpos);
-+ break;
-+ case 6: /* C-f forward one character */
-+ if (lpos < llen)
-+ cl_forward (1);
-+ break;
-+ case 2: /* C-b backward one character */
-+ if (lpos > 0)
-+ cl_backward (1);
-+ break;
-+ case 21: /* C-u kill to beginning of line */
-+ if (lpos == 0)
-+ break;
-+ /* Copy the string being deleted to KILL_BUF. */
-+ grub_memmove (kill_buf, buf, lpos);
-+ kill_buf[lpos] = 0;
-+ {
-+ /* XXX: Not very clever. */
-+
-+ int count = lpos;
-+
-+ cl_backward (lpos);
-+ cl_delete (count);
-+ }
-+ break;
-+ case 11: /* C-k kill to end of line */
-+ if (lpos == llen)
-+ break;
-+ /* Copy the string being deleted to KILL_BUF. */
-+ grub_memmove (kill_buf, buf + lpos, llen - lpos + 1);
-+ cl_delete (llen - lpos);
-+ break;
-+ case 25: /* C-y yank the kill buffer */
-+ cl_insert (kill_buf);
-+ break;
-+ case 16: /* C-p fetch the previous command */
-+ {
-+ char *p;
-+
-+ if (history < 0)
-+ /* Save the working buffer. */
-+ grub_strcpy (cmdline, buf);
-+ else if (grub_strcmp (get_history (history), buf) != 0)
-+ /* If BUF is modified, add it into the history list. */
-+ add_history (buf, history);
-+
-+ history++;
-+ p = get_history (history);
-+ if (! p)
-+ {
-+ history--;
-+ break;
-+ }
-+
-+ grub_strcpy (buf, p);
-+ llen = grub_strlen (buf);
-+ lpos = llen;
-+ cl_refresh (1, 0);
-+ }
-+ break;
-+ case 14: /* C-n fetch the next command */
-+ {
-+ char *p;
-+
-+ if (history < 0)
-+ {
-+ break;
-+ }
-+ else if (grub_strcmp (get_history (history), buf) != 0)
-+ /* If BUF is modified, add it into the history list. */
-+ add_history (buf, history);
-+
-+ history--;
-+ p = get_history (history);
-+ if (! p)
-+ p = cmdline;
-+
-+ grub_strcpy (buf, p);
-+ llen = grub_strlen (buf);
-+ lpos = llen;
-+ cl_refresh (1, 0);
-+ }
-+ break;
-+ }
-+ }
-+
-+ /* ESC, C-d and C-h are always handled. Actually C-d is not
-+ functional if READLINE is zero, as the cursor cannot go
-+ backward, but that's ok. */
-+ switch (c)
-+ {
-+ case 27: /* ESC immediately return 1 */
-+ return 1;
-+ case 4: /* C-d delete character under cursor */
-+ if (lpos == llen)
-+ break;
-+ cl_delete (1);
-+ break;
-+ case 8: /* C-h backspace */
-+# ifdef GRUB_UTIL
-+ case 127: /* also backspace */
-+# endif
-+ if (lpos > 0)
-+ {
-+ cl_backward (1);
-+ cl_delete (1);
-+ }
-+ break;
-+ default: /* insert printable character into line */
-+ if (c >= ' ' && c <= '~')
-+ {
-+ char str[2];
-+
-+ str[0] = c;
-+ str[1] = 0;
-+ cl_insert (str);
-+ }
-+ }
-+ }
-+
-+ grub_putchar ('\n');
-+
-+ /* If ECHO_CHAR is NUL, remove the leading spaces. */
-+ lpos = 0;
-+ if (! echo_char)
-+ while (buf[lpos] == ' ')
-+ lpos++;
-+
-+ /* Copy the working buffer to CMDLINE. */
-+ grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
-+
-+ /* If the readline-like feature is turned on and CMDLINE is not
-+ empty, add it into the history list. */
-+ if (readline && lpos < llen)
-+ add_history (cmdline, 0);
-+
-+ return 0;
-+}
-+
-+/* Don't use this with a MAXLEN greater than 1600 or so! The problem
-+ is that GET_CMDLINE depends on the everything fitting on the screen
-+ at once. So, the whole screen is about 2000 characters, minus the
-+ PROMPT, and space for error and status lines, etc. MAXLEN must be
-+ at least 1, and PROMPT and CMDLINE must be valid strings (not NULL
-+ or zero-length).
-+
-+ If ECHO_CHAR is nonzero, echo it instead of the typed character. */
-+int
-+get_cmdline (char *prompt, char *cmdline, int maxlen,
-+ int echo_char, int readline)
-+{
-+ int old_cursor;
-+ int ret;
-+
-+ old_cursor = setcursor (1);
-+
-+ /* Because it is hard to deal with different conditions simultaneously,
-+ less functional cases are handled here. Assume that TERM_NO_ECHO
-+ implies TERM_NO_EDIT. */
-+ if (current_term->flags & (TERM_NO_ECHO | TERM_NO_EDIT))
-+ {
-+ char *p = cmdline;
-+ int c;
-+
-+ /* Make sure that MAXLEN is not too large. */
-+ if (maxlen > MAX_CMDLINE)
-+ maxlen = MAX_CMDLINE;
-+
-+ /* Print only the prompt. The contents of CMDLINE is simply discarded,
-+ even if it is not empty. */
-+ grub_printf ("%s", prompt);
-+
-+ /* Gather characters until a newline is gotten. */
-+ while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
-+ {
-+ /* Return immediately if ESC is pressed. */
-+ if (c == 27)
-+ {
-+ setcursor (old_cursor);
-+ return 1;
-+ }
-+
-+ /* Printable characters are added into CMDLINE. */
-+ if (c >= ' ' && c <= '~')
-+ {
-+ if (! (current_term->flags & TERM_NO_ECHO))
-+ grub_putchar (c);
-+
-+ /* Preceding space characters must be ignored. */
-+ if (c != ' ' || p != cmdline)
-+ *p++ = c;
-+ }
-+ }
-+
-+ *p = 0;
-+
-+ if (! (current_term->flags & TERM_NO_ECHO))
-+ grub_putchar ('\n');
-+
-+ setcursor (old_cursor);
-+ return 0;
-+ }
-+
-+ /* Complicated features are left to real_get_cmdline. */
-+ ret = real_get_cmdline (prompt, cmdline, maxlen, echo_char, readline);
-+ setcursor (old_cursor);
-+ return ret;
-+}
-+
-+int
-+safe_parse_maxint (char **str_ptr, int *myint_ptr)
-+{
-+ char *ptr = *str_ptr;
-+ int myint = 0;
-+ int mult = 10, found = 0;
-+
-+ /*
-+ * Is this a hex number?
-+ */
-+ if (*ptr == '0' && tolower (*(ptr + 1)) == 'x')
-+ {
-+ ptr += 2;
-+ mult = 16;
-+ }
-+
-+ while (1)
-+ {
-+ /* A bit tricky. This below makes use of the equivalence:
-+ (A >= B && A <= C) <=> ((A - B) <= (C - B))
-+ when C > B and A is unsigned. */
-+ unsigned int digit;
-+
-+ digit = tolower (*ptr) - '0';
-+ if (digit > 9)
-+ {
-+ digit -= 'a' - '0';
-+ if (mult == 10 || digit > 5)
-+ break;
-+ digit += 10;
-+ }
-+
-+ found = 1;
-+ if (myint > ((MAXINT - digit) / mult))
-+ {
-+ errnum = ERR_NUMBER_OVERFLOW;
-+ return 0;
-+ }
-+ myint = (myint * mult) + digit;
-+ ptr++;
-+ }
-+
-+ if (!found)
-+ {
-+ errnum = ERR_NUMBER_PARSING;
-+ return 0;
-+ }
-+
-+ *str_ptr = ptr;
-+ *myint_ptr = myint;
-+
-+ return 1;
-+}
-+#endif /* STAGE1_5 */
-+
-+#if !defined(STAGE1_5) || defined(FSYS_FAT)
-+int
-+grub_tolower (int c)
-+{
-+ if (c >= 'A' && c <= 'Z')
-+ return (c + ('a' - 'A'));
-+
-+ return c;
-+}
-+#endif /* ! STAGE1_5 || FSYS_FAT */
-+
-+int
-+grub_isspace (int c)
-+{
-+ switch (c)
-+ {
-+ case ' ':
-+ case '\t':
-+ case '\r':
-+ case '\n':
-+ return 1;
-+ default:
-+ break;
-+ }
-+
-+ return 0;
-+}
-+
-+#if !defined(STAGE1_5) || defined(FSYS_ISO9660)
-+int
-+grub_memcmp (const char *s1, const char *s2, int n)
-+{
-+ while (n)
-+ {
-+ if (*s1 < *s2)
-+ return -1;
-+ else if (*s1 > *s2)
-+ return 1;
-+ s1++;
-+ s2++;
-+ n--;
-+ }
-+
-+ return 0;
-+}
-+#endif /* ! STAGE1_5 || FSYS_ISO9660 */
-+
-+#ifndef STAGE1_5
-+int
-+grub_strncat (char *s1, const char *s2, int n)
-+{
-+ int i = -1;
-+
-+ while (++i < n && s1[i] != 0);
-+
-+ while (i < n && (s1[i++] = *(s2++)) != 0);
-+
-+ s1[n - 1] = 0;
-+
-+ if (i >= n)
-+ return 0;
-+
-+ s1[i] = 0;
-+
-+ return 1;
-+}
-+#endif /* ! STAGE1_5 */
-+
-+/* XXX: This below is an evil hack. Certainly, we should change the
-+ strategy to determine what should be defined and what shouldn't be
-+ defined for each image. For example, it would be better to create
-+ a static library supporting minimal standard C functions and link
-+ each image with the library. Complicated things should be left to
-+ computer, definitely. -okuji */
-+#if !defined(STAGE1_5) || defined(FSYS_VSTAFS)
-+int
-+grub_strcmp (const char *s1, const char *s2)
-+{
-+ while (*s1 || *s2)
-+ {
-+ if (*s1 < *s2)
-+ return -1;
-+ else if (*s1 > *s2)
-+ return 1;
-+ s1 ++;
-+ s2 ++;
-+ }
-+
-+ return 0;
-+}
-+#endif /* ! STAGE1_5 || FSYS_VSTAFS */
-+
-+#ifndef STAGE1_5
-+/* Wait for a keypress and return its code. */
-+int
-+getkey (void)
-+{
-+ return current_term->getkey ();
-+}
-+
-+/* Check if a key code is available. */
-+int
-+checkkey (void)
-+{
-+ return current_term->checkkey ();
-+}
-+#endif /* ! STAGE1_5 */
-+
-+/* Display an ASCII character. */
-+void
-+grub_putchar (int c)
-+{
-+ if (c == '\n')
-+ grub_putchar ('\r');
-+#ifndef STAGE1_5
-+ else if (c == '\t' && current_term->getxy)
-+ {
-+ int n;
-+
-+ n = 8 - ((current_term->getxy () >> 8) & 3);
-+ while (n--)
-+ grub_putchar (' ');
-+
-+ return;
-+ }
-+#endif /* ! STAGE1_5 */
-+
-+#ifdef STAGE1_5
-+
-+ /* In Stage 1.5, only the normal console is supported. */
-+ console_putchar (c);
-+
-+#else /* ! STAGE1_5 */
-+
-+ if (c == '\n')
-+ {
-+ /* Internal `more'-like feature. */
-+ if (count_lines >= 0)
-+ {
-+ count_lines++;
-+ if (count_lines >= max_lines - 2)
-+ {
-+ int tmp;
-+
-+ /* It's important to disable the feature temporarily, because
-+ the following grub_printf call will print newlines. */
-+ count_lines = -1;
-+
-+ if (current_term->setcolorstate)
-+ current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
-+
-+ grub_printf ("\n[Hit return to continue]");
-+
-+ if (current_term->setcolorstate)
-+ current_term->setcolorstate (COLOR_STATE_NORMAL);
-+
-+ do
-+ {
-+ tmp = ASCII_CHAR (getkey ());
-+ }
-+ while (tmp != '\n' && tmp != '\r');
-+ grub_printf ("\r \r");
-+
-+ /* Restart to count lines. */
-+ count_lines = 0;
-+ return;
-+ }
-+ }
-+ }
-+
-+ current_term->putchar (c);
-+
-+#endif /* ! STAGE1_5 */
-+}
-+
-+#ifndef STAGE1_5
-+void
-+gotoxy (int x, int y)
-+{
-+ current_term->gotoxy (x, y);
-+}
-+
-+int
-+getxy (void)
-+{
-+ return current_term->getxy ();
-+}
-+
-+void
-+cls (void)
-+{
-+ /* If the terminal is dumb, there is no way to clean the terminal. */
-+ if (current_term->flags & TERM_DUMB)
-+ grub_putchar ('\n');
-+ else
-+ current_term->cls ();
-+}
-+
-+int
-+setcursor (int on)
-+{
-+ if (current_term->setcursor)
-+ return current_term->setcursor (on);
-+
-+ return 1;
-+}
-+#endif /* ! STAGE1_5 */
-+
-+int
-+substring (const char *s1, const char *s2)
-+{
-+ while (*s1 == *s2)
-+ {
-+ /* The strings match exactly. */
-+ if (! *(s1++))
-+ return 0;
-+ s2 ++;
-+ }
-+
-+ /* S1 is a substring of S2. */
-+ if (*s1 == 0)
-+ return -1;
-+
-+ /* S1 isn't a substring. */
-+ return 1;
-+}
-+
-+#ifndef STAGE1_5
-+/* Terminate the string STR with NUL. */
-+int
-+nul_terminate (char *str)
-+{
-+ int ch;
-+
-+ while (*str && ! grub_isspace (*str))
-+ str++;
-+
-+ ch = *str;
-+ *str = 0;
-+ return ch;
-+}
-+
-+char *
-+grub_strstr (const char *s1, const char *s2)
-+{
-+ while (*s1)
-+ {
-+ const char *ptr, *tmp;
-+
-+ ptr = s1;
-+ tmp = s2;
-+
-+ while (*tmp && *ptr == *tmp)
-+ ptr++, tmp++;
-+
-+ if (tmp > s2 && ! *tmp)
-+ return (char *) s1;
-+
-+ s1++;
-+ }
-+
-+ return 0;
-+}
-+
-+int
-+grub_strlen (const char *str)
-+{
-+ int len = 0;
-+
-+ while (*str++)
-+ len++;
-+
-+ return len;
-+}
-+#endif /* ! STAGE1_5 */
-+
-+int
-+memcheck (int addr, int len)
-+{
-+#ifdef GRUB_UTIL
-+ auto int start_addr (void);
-+ auto int end_addr (void);
-+
-+ auto int start_addr (void)
-+ {
-+ int ret;
-+# if defined(HAVE_START_SYMBOL)
-+ asm volatile ("movl $start, %0" : "=a" (ret));
-+# elif defined(HAVE_USCORE_START_SYMBOL)
-+ asm volatile ("movl $_start, %0" : "=a" (ret));
-+# endif
-+ return ret;
-+ }
-+
-+ auto int end_addr (void)
-+ {
-+ int ret;
-+# if defined(HAVE_END_SYMBOL)
-+ asm volatile ("movl $end, %0" : "=a" (ret));
-+# elif defined(HAVE_USCORE_END_SYMBOL)
-+ asm volatile ("movl $_end, %0" : "=a" (ret));
-+# endif
-+ return ret;
-+ }
-+
-+ if (start_addr () <= addr && end_addr () > addr + len)
-+ return ! errnum;
-+#endif /* GRUB_UTIL */
-+
-+ if ((addr < RAW_ADDR (0x1000))
-+ || (addr < RAW_ADDR (0x100000)
-+ && RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
-+ || (addr >= RAW_ADDR (0x100000)
-+ && RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
-+ errnum = ERR_WONT_FIT;
-+
-+ return ! errnum;
-+}
-+
-+void *
-+grub_memmove (void *to, const void *from, int len)
-+{
-+ if (memcheck ((int) to, len))
-+ {
-+ /* This assembly code is stolen from
-+ linux-2.2.2/include/asm-i386/string.h. This is not very fast
-+ but compact. */
-+ int d0, d1, d2;
-+
-+ if (to < from)
-+ {
-+ asm volatile ("cld\n\t"
-+ "rep\n\t"
-+ "movsb"
-+ : "=&c" (d0), "=&S" (d1), "=&D" (d2)
-+ : "0" (len),"1" (from),"2" (to)
-+ : "memory");
-+ }
-+ else
-+ {
-+ asm volatile ("std\n\t"
-+ "rep\n\t"
-+ "movsb\n\t"
-+ "cld"
-+ : "=&c" (d0), "=&S" (d1), "=&D" (d2)
-+ : "0" (len),
-+ "1" (len - 1 + (const char *) from),
-+ "2" (len - 1 + (char *) to)
-+ : "memory");
-+ }
-+ }
-+
-+ return errnum ? NULL : to;
-+}
-+
-+void *
-+grub_memset (void *start, int c, int len)
-+{
-+ char *p = start;
-+
-+ if (memcheck ((int) start, len))
-+ {
-+ while (len -- > 0)
-+ *p ++ = c;
-+ }
-+
-+ return errnum ? NULL : start;
-+}
-+
-+#ifndef STAGE1_5
-+char *
-+grub_strcpy (char *dest, const char *src)
-+{
-+ grub_memmove (dest, src, grub_strlen (src) + 1);
-+ return dest;
-+}
-+#endif /* ! STAGE1_5 */
-+
-+#ifndef GRUB_UTIL
-+# undef memcpy
-+/* GCC emits references to memcpy() for struct copies etc. */
-+void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
-+#endif
-diff -Nur grub-0.97/stage2/common.c grub-0.97-patched/stage2/common.c
---- grub-0.97/stage2/common.c 2004-03-27 17:25:44.000000000 +0100
-+++ grub-0.97-patched/stage2/common.c 2012-11-11 17:06:52.558085305 +0100
-@@ -142,7 +142,8 @@
- init_bios_info (void)
- {
- #ifndef STAGE1_5
-- unsigned long cont, memtmp, addr;
-+ unsigned long memtmp, addr;
-+ volatile unsigned long cont;
- int drive;
- #endif
-
-diff -Nur grub-0.97/stage2/disk_io.c grub-0.97-patched/stage2/disk_io.c
---- grub-0.97/stage2/disk_io.c 2004-05-23 18:35:24.000000000 +0200
-+++ grub-0.97-patched/stage2/disk_io.c 2012-11-11 17:07:12.740730013 +0100
-@@ -21,6 +21,7 @@
-
- #include <shared.h>
- #include <filesys.h>
-+#include <gpt.h>
-
- #ifdef SUPPORT_NETBOOT
- # define GRUB 1
-@@ -137,7 +138,7 @@
- }
-
- int
--rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
-+rawread (int drive, unsigned int sector, int byte_offset, int byte_len, char *buf)
- {
- int slen, sectors_per_vtrack;
- int sector_size_bits = log2 (buf_geom.sector_size);
-@@ -261,7 +262,7 @@
- */
- if (disk_read_func)
- {
-- int sector_num = sector;
-+ unsigned int sector_num = sector;
- int length = buf_geom.sector_size - byte_offset;
- if (length > size)
- length = size;
-@@ -291,7 +292,7 @@
-
-
- int
--devread (int sector, int byte_offset, int byte_len, char *buf)
-+devread (unsigned int sector, int byte_offset, int byte_len, char *buf)
- {
- /*
- * Check partition boundaries
-@@ -330,7 +331,7 @@
-
- #ifndef STAGE1_5
- int
--rawwrite (int drive, int sector, char *buf)
-+rawwrite (int drive, unsigned int sector, char *buf)
- {
- if (sector == 0)
- {
-@@ -363,7 +364,7 @@
- }
-
- int
--devwrite (int sector, int sector_count, char *buf)
-+devwrite (unsigned int sector, int sector_count, char *buf)
- {
- #if defined(GRUB_UTIL) && defined(__linux__)
- if (current_partition != 0xFFFFFF
-@@ -502,8 +503,8 @@
- set_partition_hidden_flag (int hidden)
- {
- unsigned long part = 0xFFFFFF;
-- unsigned long start, len, offset, ext_offset;
-- int entry, type;
-+ unsigned long start, len, offset, ext_offset, gpt_offset;
-+ int entry, type, gpt_count, gpt_size;
- char mbr[512];
-
- /* The drive must be a hard disk. */
-@@ -524,8 +525,15 @@
- /* Look for the partition. */
- while (next_partition (current_drive, 0xFFFFFF, &part, &type,
- &start, &len, &offset, &entry,
-- &ext_offset, mbr))
-+ &ext_offset, &gpt_offset, &gpt_count, &gpt_size, mbr))
- {
-+ /* The partition may not be a GPT partition. */
-+ if (gpt_offset != 0)
-+ {
-+ errnum = ERR_BAD_ARGUMENT;
-+ return 1;
-+ }
-+
- if (part == current_partition)
- {
- /* Found. */
-@@ -577,11 +585,14 @@
- unsigned long *partition, int *type,
- unsigned long *start, unsigned long *len,
- unsigned long *offset, int *entry,
-- unsigned long *ext_offset, char *buf)
-+ unsigned long *ext_offset,
-+ unsigned long *gpt_offset, int *gpt_count,
-+ int *gpt_size, char *buf)
- {
- /* Forward declarations. */
- auto int next_bsd_partition (void);
- auto int next_pc_slice (void);
-+ auto int next_gpt_slice(void);
-
- /* Get next BSD partition in current PC slice. */
- int next_bsd_partition (void)
-@@ -666,6 +677,40 @@
- return 0;
- }
-
-+ /* If this is a GPT partition table, read it as such. */
-+ if (*entry == -1 && *offset == 0 && PC_SLICE_TYPE (buf, 0) == PC_SLICE_TYPE_GPT)
-+ {
-+ struct grub_gpt_header *hdr = (struct grub_gpt_header *) buf;
-+
-+ /* Read in the GPT Partition table header. */
-+ if (! rawread (drive, 1, 0, SECTOR_SIZE, buf))
-+ return 0;
-+
-+ if (hdr->magic == GPT_HEADER_MAGIC && hdr->version == 0x10000)
-+ {
-+ /* Let gpt_offset point to the first entry in the GPT
-+ partition table. This can also be used by callers of
-+ next_partition to determine if a entry comes from a
-+ GPT partition table or not. */
-+ *gpt_offset = hdr->partitions;
-+ *gpt_count = hdr->maxpart;
-+ *gpt_size = hdr->partentry_size;
-+
-+ return next_gpt_slice();
-+ }
-+ else
-+ {
-+ /* This is not a valid header for a GPT partition table.
-+ Re-read the MBR or the boot sector of the extended
-+ partition. */
-+ if (! rawread (drive, *offset, 0, SECTOR_SIZE, buf))
-+ return 0;
-+ }
-+ }
-+
-+ /* Not a GPT partition. */
-+ *gpt_offset = 0;
-+
- /* Increase the entry number. */
- (*entry)++;
-
-@@ -710,6 +755,43 @@
- return 1;
- }
-
-+ /* Get the next GPT slice. */
-+ int next_gpt_slice (void)
-+ {
-+ struct grub_gpt_partentry *gptentry = (struct grub_gpt_partentry *) buf;
-+ /* Make GPT partitions show up as PC slices. */
-+ int pc_slice_no = (*partition & 0xFF0000) >> 16;
-+
-+ /* If this is the first time... */
-+ if (pc_slice_no == 0xFF)
-+ {
-+ pc_slice_no = -1;
-+ *entry = -1;
-+ }
-+
-+ do {
-+ (*entry)++;
-+
-+ if (*entry >= *gpt_count)
-+ {
-+ errnum = ERR_NO_PART;
-+ return 0;
-+ }
-+ /* Read in the GPT Partition table entry. */
-+ if (! rawread (drive, (*gpt_offset) + GPT_ENTRY_SECTOR (*gpt_size, *entry), GPT_ENTRY_INDEX (*gpt_size, *entry), *gpt_size, buf))
-+ return 0;
-+ } while (! (gptentry->type1 && gptentry->type2));
-+
-+ pc_slice_no++;
-+ *start = gptentry->start;
-+ *len = gptentry->end - gptentry->start + 1;
-+ *type = PC_SLICE_TYPE_EXT2FS;
-+ *entry = pc_slice_no;
-+ *partition = (*entry << 16) | 0xFFFF;
-+
-+ return 1;
-+ }
-+
- /* Start the body of this function. */
-
- #ifndef STAGE1_5
-@@ -717,6 +799,9 @@
- return 0;
- #endif
-
-+ if (*partition != 0xFFFFFF && *gpt_offset != 0)
-+ return next_gpt_slice ();
-+
- /* If previous partition is a BSD partition or a PC slice which
- contains BSD partitions... */
- if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff))
-@@ -746,6 +831,8 @@
- #ifndef STAGE1_5
- static unsigned long cur_part_offset;
- static unsigned long cur_part_addr;
-+static unsigned long cur_part_start;
-+static int cur_part_entry;
- #endif
-
- /* Open a partition. */
-@@ -755,6 +842,9 @@
- unsigned long dest_partition = current_partition;
- unsigned long part_offset;
- unsigned long ext_offset;
-+ unsigned long gpt_offset;
-+ int gpt_count;
-+ int gpt_size;
- int entry;
- char buf[SECTOR_SIZE];
- int bsd_part, pc_slice;
-@@ -766,7 +856,8 @@
- int ret = next_partition (current_drive, dest_partition,
- ¤t_partition, ¤t_slice,
- &part_start, &part_length,
-- &part_offset, &entry, &ext_offset, buf);
-+ &part_offset, &entry, &ext_offset,
-+ &gpt_offset, &gpt_count, &gpt_size, buf);
- bsd_part = (current_partition >> 8) & 0xFF;
- pc_slice = current_partition >> 16;
- return ret;
-@@ -800,7 +891,12 @@
-
- /* If this is the whole disk, return here. */
- if (! flags && current_partition == 0xFFFFFF)
-- return 1;
-+ {
-+#ifndef STAGE1_5
-+ cur_part_offset = 0;
-+#endif /* ! STAGE1_5 */
-+ return 1;
-+ }
-
- if (flags)
- dest_partition = 0xFFFFFF;
-@@ -815,6 +911,8 @@
-
- cur_part_offset = part_offset;
- cur_part_addr = BOOT_PART_TABLE + (entry << 4);
-+ cur_part_start = part_start;
-+ cur_part_entry = entry;
- #endif /* ! STAGE1_5 */
-
- /* If this is a valid partition... */
-@@ -1142,6 +1240,7 @@
- src = (char *) SCRATCHADDR + BOOTSEC_PART_OFFSET;
- while (dst < (char *) BOOT_PART_TABLE + BOOTSEC_PART_LENGTH)
- *dst++ = *src++;
-+ PC_SLICE_START (BOOT_PART_TABLE - PC_SLICE_OFFSET, cur_part_entry) = cur_part_start;
-
- /* Set the active flag of the booted partition. */
- for (i = 0; i < 4; i++)
-diff -Nur grub-0.97/stage2/fsys_ext2fs.c grub-0.97-patched/stage2/fsys_ext2fs.c
---- grub-0.97/stage2/fsys_ext2fs.c 2004-08-08 20:19:18.000000000 +0200
-+++ grub-0.97-patched/stage2/fsys_ext2fs.c 2012-11-11 17:07:12.750730331 +0100
-@@ -41,6 +41,7 @@
- typedef unsigned short __u16;
- typedef __signed__ int __s32;
- typedef unsigned int __u32;
-+typedef unsigned long long __u64;
-
- /*
- * Constants relative to the data blocks, from ext2_fs.h
-@@ -61,9 +62,9 @@
- __u32 s_free_inodes_count; /* Free inodes count */
- __u32 s_first_data_block; /* First Data Block */
- __u32 s_log_block_size; /* Block size */
-- __s32 s_log_frag_size; /* Fragment size */
-+ __s32 s_obso_log_frag_size; /* Obsoleted Fragment size */
- __u32 s_blocks_per_group; /* # Blocks per group */
-- __u32 s_frags_per_group; /* # Fragments per group */
-+ __u32 s_obso_frags_per_group; /* Obsoleted Fragments per group */
- __u32 s_inodes_per_group; /* # Inodes per group */
- __u32 s_mtime; /* Mount time */
- __u32 s_wtime; /* Write time */
-@@ -72,17 +73,62 @@
- __u16 s_magic; /* Magic signature */
- __u16 s_state; /* File system state */
- __u16 s_errors; /* Behaviour when detecting errors */
-- __u16 s_pad;
-+ __u16 s_minor_rev_level; /* minor revision level */
- __u32 s_lastcheck; /* time of last check */
- __u32 s_checkinterval; /* max. time between checks */
- __u32 s_creator_os; /* OS */
- __u32 s_rev_level; /* Revision level */
- __u16 s_def_resuid; /* Default uid for reserved blocks */
- __u16 s_def_resgid; /* Default gid for reserved blocks */
-- __u32 s_reserved[235]; /* Padding to the end of the block */
-+ /*
-+ * These fields are for EXT2_DYNAMIC_REV superblocks only.
-+ *
-+ * Note: the difference between the compatible feature set and
-+ * the incompatible feature set is that if there is a bit set
-+ * in the incompatible feature set that the kernel doesn't
-+ * know about, it should refuse to mount the filesystem.
-+ *
-+ * e2fsck's requirements are more strict; if it doesn't know
-+ * about a feature in either the compatible or incompatible
-+ * feature set, it must abort and not try to meddle with
-+ * things it doesn't understand...
-+ */
-+ __u32 s_first_ino; /* First non-reserved inode */
-+ __u16 s_inode_size; /* size of inode structure */
-+ __u16 s_block_group_nr; /* block group # of this superblock */
-+ __u32 s_feature_compat; /* compatible feature set */
-+ __u32 s_feature_incompat; /* incompatible feature set */
-+ __u32 s_feature_ro_compat; /* readonly-compatible feature set */
-+ __u8 s_uuid[16]; /* 128-bit uuid for volume */
-+ char s_volume_name[16]; /* volume name */
-+ char s_last_mounted[64]; /* directory where last mounted */
-+ __u32 s_algorithm_usage_bitmap; /* For compression */
-+ /*
-+ * Performance hints. Directory preallocation should only
-+ * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
-+ */
-+ __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/
-+ __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */
-+ __u16 s_reserved_gdt_blocks;/* Per group table for online growth */
-+ /*
-+ * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
-+ */
-+ __u8 s_journal_uuid[16]; /* uuid of journal superblock */
-+ __u32 s_journal_inum; /* inode number of journal file */
-+ __u32 s_journal_dev; /* device number of journal file */
-+ __u32 s_last_orphan; /* start of list of inodes to delete */
-+ __u32 s_hash_seed[4]; /* HTREE hash seed */
-+ __u8 s_def_hash_version; /* Default hash version to use */
-+ __u8 s_jnl_backup_type; /* Default type of journal backup */
-+ __u16 s_desc_size; /* size of group descriptor */
-+ __u32 s_default_mount_opts;
-+ __u32 s_first_meta_bg; /* First metablock group */
-+ __u32 s_mkfs_time; /* When the filesystem was created */
-+ __u32 s_jnl_blocks[17]; /* Backup of the journal inode */
-+ __u32 s_reserved[172]; /* Padding to the end of the block */
- };
-
--struct ext2_group_desc
-+struct ext4_group_desc
- {
- __u32 bg_block_bitmap; /* Blocks bitmap block */
- __u32 bg_inode_bitmap; /* Inodes bitmap block */
-@@ -90,8 +136,18 @@
- __u16 bg_free_blocks_count; /* Free blocks count */
- __u16 bg_free_inodes_count; /* Free inodes count */
- __u16 bg_used_dirs_count; /* Directories count */
-- __u16 bg_pad;
-- __u32 bg_reserved[3];
-+ __u16 bg_flags; /* EXT4_BG_flags (INODE_UNINIT, etc) */
-+ __u32 bg_reserved[2]; /* Likely block/inode bitmap checksum */
-+ __u16 bg_itable_unused; /* Unused inodes count */
-+ __u16 bg_checksum; /* crc16(sb_uuid+group+desc) */
-+ __u32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
-+ __u32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
-+ __u32 bg_inode_table_hi; /* Inodes table block MSB */
-+ __u16 bg_free_blocks_count_hi;/* Free blocks count MSB */
-+ __u16 bg_free_inodes_count_hi;/* Free inodes count MSB */
-+ __u16 bg_used_dirs_count_hi; /* Directories count MSB */
-+ __u16 bg_itable_unused_hi; /* Unused inodes count MSB */
-+ __u32 bg_reserved2[3];
- };
-
- struct ext2_inode
-@@ -129,22 +185,22 @@
- __u32 i_block[EXT2_N_BLOCKS]; /* 40: Pointers to blocks */
- __u32 i_version; /* File version (for NFS) */
- __u32 i_file_acl; /* File ACL */
-- __u32 i_dir_acl; /* Directory ACL */
-- __u32 i_faddr; /* Fragment address */
-+ __u32 i_size_high;
-+ __u32 i_obso_faddr; /* Obsoleted fragment address */
- union
- {
- struct
- {
-- __u8 l_i_frag; /* Fragment number */
-- __u8 l_i_fsize; /* Fragment size */
-- __u16 i_pad1;
-- __u32 l_i_reserved2[2];
-+ __u16 l_i_blocks_high; /* were l_i_reserved1 */
-+ __u16 l_i_file_acl_high;
-+ __u16 l_i_uid_high; /* these 2 fields */
-+ __u16 l_i_gid_high; /* were reserved2[0] */
-+ __u32 l_i_reserved2;
- }
- linux2;
- struct
- {
-- __u8 h_i_frag; /* Fragment number */
-- __u8 h_i_fsize; /* Fragment size */
-+ __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
- __u16 h_i_mode_high;
- __u16 h_i_uid_high;
- __u16 h_i_gid_high;
-@@ -153,16 +209,36 @@
- hurd2;
- struct
- {
-- __u8 m_i_frag; /* Fragment number */
-- __u8 m_i_fsize; /* Fragment size */
-- __u16 m_pad1;
-+ __u16 h_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */
-+ __u16 m_i_file_acl_high;
- __u32 m_i_reserved2[2];
- }
- masix2;
- }
- osd2; /* OS dependent 2 */
-+ __u16 i_extra_isize;
-+ __u16 i_pad1;
-+ __u32 i_ctime_extra; /* extra Change time (nsec << 2 | epoch) */
-+ __u32 i_mtime_extra; /* extra Modification time(nsec << 2 | epoch) */
-+ __u32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */
-+ __u32 i_crtime; /* File Creation time */
-+ __u32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */
-+ __u32 i_version_hi; /* high 32 bits for 64-bit version */
- };
-
-+#define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
-+#define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 /* grub not supported*/
-+#define EXT4_FEATURE_INCOMPAT_MMP 0x0100
-+#define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200
-+
-+#define EXT4_HAS_INCOMPAT_FEATURE(sb,mask) \
-+ ( sb->s_feature_incompat & mask )
-+
-+#define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */
-+#define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
-+
-+#define EXT4_MIN_DESC_SIZE 32
-+
- /* linux/limits.h */
- #define NAME_MAX 255 /* # chars in a file name */
-
-@@ -180,6 +256,57 @@
- char name[EXT2_NAME_LEN]; /* File name */
- };
-
-+/* linux/ext4_fs_extents.h */
-+/* This is the extent on-disk structure.
-+ * It's used at the bottom of the tree.
-+ */
-+struct ext4_extent
-+ {
-+ __u32 ee_block; /* first logical block extent covers */
-+ __u16 ee_len; /* number of blocks covered by extent */
-+ __u16 ee_start_hi; /* high 16 bits of physical block */
-+ __u32 ee_start_lo; /* low 32 bits of physical block */
-+ };
-+
-+/*
-+ * This is index on-disk structure.
-+ * It's used at all the levels except the bottom.
-+ */
-+struct ext4_extent_idx
-+ {
-+ __u32 ei_block; /* index covers logical blocks from 'block' */
-+ __u32 ei_leaf_lo; /* pointer to the physical block of the next *
-+ * level. leaf or next index could be there */
-+ __u16 ei_leaf_hi; /* high 16 bits of physical block */
-+ __u16 ei_unused;
-+ };
-+
-+/*
-+ * Each block (leaves and indexes), even inode-stored has header.
-+ */
-+struct ext4_extent_header
-+ {
-+ __u16 eh_magic; /* probably will support different formats */
-+ __u16 eh_entries; /* number of valid entries */
-+ __u16 eh_max; /* capacity of store in entries */
-+ __u16 eh_depth; /* has tree real underlying blocks? */
-+ __u32 eh_generation; /* generation of the tree */
-+ };
-+
-+#define EXT4_EXT_MAGIC (0xf30a)
-+#define EXT_FIRST_EXTENT(__hdr__) \
-+ ((struct ext4_extent *) (((char *) (__hdr__)) + \
-+ sizeof(struct ext4_extent_header)))
-+#define EXT_FIRST_INDEX(__hdr__) \
-+ ((struct ext4_extent_idx *) (((char *) (__hdr__)) + \
-+ sizeof(struct ext4_extent_header)))
-+#define EXT_LAST_EXTENT(__hdr__) \
-+ (EXT_FIRST_EXTENT((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
-+#define EXT_LAST_INDEX(__hdr__) \
-+ (EXT_FIRST_INDEX((__hdr__)) + (__u16)((__hdr__)->eh_entries) - 1)
-+
-+
-+
- /* linux/ext2fs.h */
- /*
- * EXT2_DIR_PAD defines the directory entries boundaries
-@@ -218,13 +345,30 @@
- #define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
- #define EXT2_ADDR_PER_BLOCK_BITS(s) (log2(EXT2_ADDR_PER_BLOCK(s)))
-
-+#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
-+#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
-+#define EXT2_GOOD_OLD_INODE_SIZE 128
-+#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \
-+ EXT2_GOOD_OLD_INODE_SIZE : \
-+ (s)->s_inode_size)
-+#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s))
-+
- /* linux/ext2_fs.h */
- #define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10)
- /* kind of from ext2/super.c */
- #define EXT2_BLOCK_SIZE(s) (1 << EXT2_BLOCK_SIZE_BITS(s))
- /* linux/ext2fs.h */
-+/* sizeof(struct ext2_group_desc) is changed in ext4
-+ * in kernel code, ext2/3 uses sizeof(struct ext2_group_desc) to calculate
-+ * number of desc per block, while ext4 uses superblock->s_desc_size in stead
-+ * superblock->s_desc_size is not available in ext2/3
-+ * */
-+#define EXT2_DESC_SIZE(s) \
-+ (EXT4_HAS_INCOMPAT_FEATURE(s,EXT4_FEATURE_INCOMPAT_64BIT)? \
-+ s->s_desc_size : EXT4_MIN_DESC_SIZE)
- #define EXT2_DESC_PER_BLOCK(s) \
-- (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
-+ (EXT2_BLOCK_SIZE(s) / EXT2_DESC_SIZE(s))
-+
- /* linux/stat.h */
- #define S_IFMT 00170000
- #define S_IFLNK 0120000
-@@ -386,6 +530,122 @@
- [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
- }
-
-+/* extent binary search index
-+ * find closest index in the current level extent tree
-+ * kind of from ext4_ext_binsearch_idx in ext4/extents.c
-+ */
-+static struct ext4_extent_idx*
-+ext4_ext_binsearch_idx(struct ext4_extent_header* eh, int logical_block)
-+{
-+ struct ext4_extent_idx *r, *l, *m;
-+ l = EXT_FIRST_INDEX(eh) + 1;
-+ r = EXT_LAST_INDEX(eh);
-+ while (l <= r)
-+ {
-+ m = l + (r - l) / 2;
-+ if (logical_block < m->ei_block)
-+ r = m - 1;
-+ else
-+ l = m + 1;
-+ }
-+ return (struct ext4_extent_idx*)(l - 1);
-+}
-+
-+/* extent binary search
-+ * find closest extent in the leaf level
-+ * kind of from ext4_ext_binsearch in ext4/extents.c
-+ */
-+static struct ext4_extent*
-+ext4_ext_binsearch(struct ext4_extent_header* eh, int logical_block)
-+{
-+ struct ext4_extent *r, *l, *m;
-+ l = EXT_FIRST_EXTENT(eh) + 1;
-+ r = EXT_LAST_EXTENT(eh);
-+ while (l <= r)
-+ {
-+ m = l + (r - l) / 2;
-+ if (logical_block < m->ee_block)
-+ r = m - 1;
-+ else
-+ l = m + 1;
-+ }
-+ return (struct ext4_extent*)(l - 1);
-+}
-+
-+/* Maps extents enabled logical block into physical block via an inode.
-+ * EXT4_HUGE_FILE_FL should be checked before calling this.
-+ */
-+static int
-+ext4fs_block_map (int logical_block)
-+{
-+ struct ext4_extent_header *eh;
-+ struct ext4_extent *ex, *extent;
-+ struct ext4_extent_idx *ei, *index;
-+ int depth;
-+ int i;
-+
-+#ifdef E2DEBUG
-+ unsigned char *i;
-+ for (i = (unsigned char *) INODE;
-+ i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
-+ i++)
-+ {
-+ printf ("%c", "0123456789abcdef"[*i >> 4]);
-+ printf ("%c", "0123456789abcdef"[*i % 16]);
-+ if (!((i + 1 - (unsigned char *) INODE) % 16))
-+ {
-+ printf ("\n");
-+ }
-+ else
-+ {
-+ printf (" ");
-+ }
-+ }
-+ printf ("logical block %d\n", logical_block);
-+#endif /* E2DEBUG */
-+ eh = (struct ext4_extent_header*)INODE->i_block;
-+ if (eh->eh_magic != EXT4_EXT_MAGIC)
-+ {
-+ errnum = ERR_FSYS_CORRUPT;
-+ return -1;
-+ }
-+ while((depth = eh->eh_depth) != 0)
-+ { /* extent index */
-+ if (eh->eh_magic != EXT4_EXT_MAGIC)
-+ {
-+ errnum = ERR_FSYS_CORRUPT;
-+ return -1;
-+ }
-+ ei = ext4_ext_binsearch_idx(eh, logical_block);
-+ if (ei->ei_leaf_hi)
-+ {/* 64bit physical block number not supported */
-+ errnum = ERR_FILELENGTH;
-+ return -1;
-+ }
-+ if (!ext2_rdfsb(ei->ei_leaf_lo, DATABLOCK1))
-+ {
-+ errnum = ERR_FSYS_CORRUPT;
-+ return -1;
-+ }
-+ eh = (struct ext4_extent_header*)DATABLOCK1;
-+ }
-+
-+ /* depth==0, we come to the leaf */
-+ ex = ext4_ext_binsearch(eh, logical_block);
-+ if (ex->ee_start_hi)
-+ {/* 64bit physical block number not supported */
-+ errnum = ERR_FILELENGTH;
-+ return -1;
-+ }
-+ if ((ex->ee_block + ex->ee_len) < logical_block)
-+ {
-+ errnum = ERR_FSYS_CORRUPT;
-+ return -1;
-+ }
-+ return ex->ee_start_lo + logical_block - ex->ee_block;
-+
-+}
-+
- /* preconditions: all preconds of ext2fs_block_map */
- int
- ext2fs_read (char *buf, int len)
-@@ -420,6 +680,11 @@
- /* find the (logical) block component of our location */
- logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
- offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
-+ /* map extents enabled logical block number to physical fs on-dick block number */
-+ if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
-+ && INODE->i_flags & EXT4_EXTENTS_FL)
-+ map = ext4fs_block_map (logical_block);
-+ else
- map = ext2fs_block_map (logical_block);
- #ifdef E2DEBUG
- printf ("map=%d\n", map);
-@@ -504,7 +769,7 @@
- int desc; /* index within that group */
- int ino_blk; /* fs pointer of the inode's information */
- int str_chk = 0; /* used to hold the results of a string compare */
-- struct ext2_group_desc *gdp;
-+ struct ext4_group_desc *ext4_gdp;
- struct ext2_inode *raw_inode; /* inode info corresponding to current_ino */
-
- char linkbuf[PATH_MAX]; /* buffer for following symbolic links */
-@@ -550,10 +815,17 @@
- {
- return 0;
- }
-- gdp = GROUP_DESC;
-- ino_blk = gdp[desc].bg_inode_table +
-+ ext4_gdp = (struct ext4_group_desc *)( (__u8*)GROUP_DESC +
-+ desc * EXT2_DESC_SIZE(SUPERBLOCK));
-+ if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK, EXT4_FEATURE_INCOMPAT_64BIT)
-+ && (! ext4_gdp->bg_inode_table_hi))
-+ {/* 64bit itable not supported */
-+ errnum = ERR_FILELENGTH;
-+ return -1;
-+ }
-+ ino_blk = ext4_gdp->bg_inode_table +
- (((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
-- >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
-+ >> log2 (EXT2_INODES_PER_BLOCK (SUPERBLOCK)));
- #ifdef E2DEBUG
- printf ("inode table fsblock=%d\n", ino_blk);
- #endif /* E2DEBUG */
-@@ -565,13 +837,12 @@
- /* reset indirect blocks! */
- mapblock2 = mapblock1 = -1;
-
-- raw_inode = INODE +
-- ((current_ino - 1)
-- & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
-+ raw_inode = (struct ext2_inode *)((char *)INODE +
-+ ((current_ino - 1) & (EXT2_INODES_PER_BLOCK (SUPERBLOCK) - 1)) *
-+ EXT2_INODE_SIZE (SUPERBLOCK));
- #ifdef E2DEBUG
- printf ("ipb=%d, sizeof(inode)=%d\n",
-- (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
-- sizeof (struct ext2_inode));
-+ EXT2_INODES_PER_BLOCK (SUPERBLOCK), EXT2_INODE_SIZE (SUPERBLOCK));
- printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
- printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
- for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
-@@ -629,7 +900,10 @@
- }
- linkbuf[filemax + len] = '\0';
-
-- /* Read the symlink data. */
-+ /* Read the symlink data.
-+ * Slow symlink is extents enabled
-+ * But since grub_read invokes ext2fs_read, nothing to change here
-+ * */
- if (! ext2_is_fast_symlink ())
- {
- /* Read the necessary blocks, and reset the file pointer. */
-@@ -640,7 +914,9 @@
- }
- else
- {
-- /* Copy the data directly from the inode. */
-+ /* Copy the data directly from the inode.
-+ * Fast symlink is not extents enabled
-+ * */
- len = filemax;
- memmove (linkbuf, (char *) INODE->i_block, len);
- }
-@@ -674,6 +950,13 @@
- errnum = ERR_BAD_FILETYPE;
- return 0;
- }
-+ /* if file is too large, just stop and report an error*/
-+ if ( (INODE->i_flags & EXT4_HUGE_FILE_FL) && !(INODE->i_size_high))
-+ {
-+ /* file too large, stop reading */
-+ errnum = ERR_FILELENGTH;
-+ return 0;
-+ }
-
- filemax = (INODE->i_size);
- return 1;
-@@ -728,17 +1011,28 @@
- }
-
- /* else, find the (logical) block component of our location */
-+ /* ext4 logical block number the same as ext2/3 */
- blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
-
- /* we know which logical block of the directory entry we are looking
- for, now we have to translate that to the physical (fs) block on
- the disk */
-+ /* map extents enabled logical block number to physical fs on-dick block number */
-+ if (EXT4_HAS_INCOMPAT_FEATURE(SUPERBLOCK,EXT4_FEATURE_INCOMPAT_EXTENTS)
-+ && INODE->i_flags & EXT4_EXTENTS_FL)
-+ map = ext4fs_block_map (blk);
-+ else
- map = ext2fs_block_map (blk);
- #ifdef E2DEBUG
- printf ("fs block=%d\n", map);
- #endif /* E2DEBUG */
- mapblock2 = -1;
-- if ((map < 0) || !ext2_rdfsb (map, DATABLOCK2))
-+ if (map < 0)
-+ {
-+ *rest = ch;
-+ return 0;
-+ }
-+ if (!ext2_rdfsb (map, DATABLOCK2))
- {
- errnum = ERR_FSYS_CORRUPT;
- *rest = ch;
-diff -Nur grub-0.97/stage2/gpt.h grub-0.97-patched/stage2/gpt.h
---- grub-0.97/stage2/gpt.h 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/gpt.h 2012-11-11 17:07:12.697728638 +0100
-@@ -0,0 +1,68 @@
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 2002,2005,2006 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#ifndef _GPT_H
-+#define _GPT_H
-+
-+typedef signed char grub_int8_t;
-+typedef signed short grub_int16_t;
-+typedef signed int grub_int32_t;
-+typedef signed long long int grub_int64_t;
-+typedef unsigned char grub_uint8_t;
-+typedef unsigned short grub_uint16_t;
-+typedef unsigned int grub_uint32_t;
-+typedef unsigned long long int grub_uint64_t;
-+
-+struct grub_gpt_header
-+{
-+ grub_uint64_t magic;
-+ grub_uint32_t version;
-+ grub_uint32_t headersize;
-+ grub_uint32_t crc32;
-+ grub_uint32_t unused1;
-+ grub_uint64_t primary;
-+ grub_uint64_t backup;
-+ grub_uint64_t start;
-+ grub_uint64_t end;
-+ grub_uint8_t guid[16];
-+ grub_uint64_t partitions;
-+ grub_uint32_t maxpart;
-+ grub_uint32_t partentry_size;
-+ grub_uint32_t partentry_crc32;
-+} __attribute__ ((packed));
-+
-+struct grub_gpt_partentry
-+{
-+ grub_uint64_t type1;
-+ grub_uint64_t type2;
-+ grub_uint8_t guid[16];
-+ grub_uint64_t start;
-+ grub_uint64_t end;
-+ grub_uint8_t attrib;
-+ char name[72];
-+} __attribute__ ((packed));
-+
-+#define GPT_HEADER_MAGIC 0x5452415020494645UL
-+
-+#define GPT_ENTRY_SECTOR(size,entry) \
-+ ((((entry) * (size) + 1) & ~(SECTOR_SIZE - 1)) >> SECTOR_BITS)
-+#define GPT_ENTRY_INDEX(size,entry) \
-+ ((((entry) * (size) + 1) & (SECTOR_SIZE - 1)) - 1)
-+
-+#endif /* _GPT_H */
-diff -Nur grub-0.97/stage2/graphics.c grub-0.97-patched/stage2/graphics.c
---- grub-0.97/stage2/graphics.c 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/graphics.c 2012-11-11 17:06:33.320470847 +0100
-@@ -0,0 +1,563 @@
-+/* graphics.c - graphics mode support for GRUB */
-+/* Implemented as a terminal type by Jeremy Katz <katzj@redhat.com> based
-+ * on a patch by Paulo César Pereira de Andrade <pcpa@conectiva.com.br>
-+ */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 2001,2002 Red Hat, Inc.
-+ * Portions copyright (C) 2000 Conectiva, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+
-+
-+#ifdef SUPPORT_GRAPHICS
-+
-+#include <term.h>
-+#include <shared.h>
-+#include <graphics.h>
-+
-+int saved_videomode;
-+unsigned char *font8x16;
-+
-+int graphics_inited = 0;
-+static char splashimage[64];
-+
-+#define VSHADOW VSHADOW1
-+unsigned char VSHADOW1[38400];
-+unsigned char VSHADOW2[38400];
-+unsigned char VSHADOW4[38400];
-+unsigned char VSHADOW8[38400];
-+
-+/* constants to define the viewable area */
-+const int x0 = 0;
-+const int x1 = 80;
-+const int y0 = 0;
-+const int y1 = 30;
-+
-+/* text buffer has to be kept around so that we can write things as we
-+ * scroll and the like */
-+unsigned short text[80 * 30];
-+
-+/* why do these have to be kept here? */
-+int foreground = (63 << 16) | (63 << 8) | (63), background = 0, border = 0;
-+
-+/* current position */
-+static int fontx = 0;
-+static int fonty = 0;
-+
-+/* global state so that we don't try to recursively scroll or cursor */
-+static int no_scroll = 0;
-+
-+/* color state */
-+static int graphics_standard_color = A_NORMAL;
-+static int graphics_normal_color = A_NORMAL;
-+static int graphics_highlight_color = A_REVERSE;
-+static int graphics_current_color = A_NORMAL;
-+static color_state graphics_color_state = COLOR_STATE_STANDARD;
-+
-+
-+/* graphics local functions */
-+static void graphics_setxy(int col, int row);
-+static void graphics_scroll();
-+
-+/* FIXME: where do these really belong? */
-+static inline void outb(unsigned short port, unsigned char val)
-+{
-+ __asm __volatile ("outb %0,%1"::"a" (val), "d" (port));
-+}
-+
-+static void MapMask(int value) {
-+ outb(0x3c4, 2);
-+ outb(0x3c5, value);
-+}
-+
-+/* bit mask register */
-+static void BitMask(int value) {
-+ outb(0x3ce, 8);
-+ outb(0x3cf, value);
-+}
-+
-+
-+
-+/* Set the splash image */
-+void graphics_set_splash(char *splashfile) {
-+ grub_strcpy(splashimage, splashfile);
-+}
-+
-+/* Get the current splash image */
-+char *graphics_get_splash(void) {
-+ return splashimage;
-+}
-+
-+/* Initialize a vga16 graphics display with the palette based off of
-+ * the image in splashimage. If the image doesn't exist, leave graphics
-+ * mode. */
-+int graphics_init()
-+{
-+ if(!grub_file_exists(splashimage)) {
-+ return 0;
-+ }
-+
-+ if (!graphics_inited) {
-+ saved_videomode = set_videomode(0x12);
-+ }
-+
-+ if (!read_image(splashimage)) {
-+ set_videomode(saved_videomode);
-+ grub_printf("failed to read image\n");
-+ return 0;
-+ }
-+
-+ font8x16 = (unsigned char*)graphics_get_font();
-+
-+ graphics_inited = 1;
-+
-+ /* make sure that the highlight color is set correctly */
-+ graphics_highlight_color = ((graphics_normal_color >> 4) |
-+ ((graphics_normal_color & 0xf) << 4));
-+
-+ return 1;
-+}
-+
-+/* Leave graphics mode */
-+void graphics_end(void)
-+{
-+ if (graphics_inited) {
-+ set_videomode(saved_videomode);
-+ graphics_inited = 0;
-+ }
-+}
-+
-+/* Print ch on the screen. Handle any needed scrolling or the like */
-+void graphics_putchar(int ch) {
-+ ch &= 0xff;
-+
-+ graphics_cursor(0);
-+
-+ if (ch == '\n') {
-+ if (fonty + 1 < y1)
-+ graphics_setxy(fontx, fonty + 1);
-+ else
-+ graphics_scroll();
-+ graphics_cursor(1);
-+ return;
-+ } else if (ch == '\r') {
-+ graphics_setxy(x0, fonty);
-+ graphics_cursor(1);
-+ return;
-+ }
-+
-+ graphics_cursor(0);
-+
-+ text[fonty * 80 + fontx] = ch;
-+ text[fonty * 80 + fontx] &= 0x00ff;
-+ if (graphics_current_color & 0xf0)
-+ text[fonty * 80 + fontx] |= 0x100;
-+
-+ graphics_cursor(0);
-+
-+ if ((fontx + 1) >= x1) {
-+ graphics_setxy(x0, fonty);
-+ if (fonty + 1 < y1)
-+ graphics_setxy(x0, fonty + 1);
-+ else
-+ graphics_scroll();
-+ } else {
-+ graphics_setxy(fontx + 1, fonty);
-+ }
-+
-+ graphics_cursor(1);
-+}
-+
-+/* get the current location of the cursor */
-+int graphics_getxy(void) {
-+ return (fontx << 8) | fonty;
-+}
-+
-+void graphics_gotoxy(int x, int y) {
-+ graphics_cursor(0);
-+
-+ graphics_setxy(x, y);
-+
-+ graphics_cursor(1);
-+}
-+
-+void graphics_cls(void) {
-+ int i;
-+ unsigned char *mem, *s1, *s2, *s4, *s8;
-+
-+ graphics_cursor(0);
-+ graphics_gotoxy(x0, y0);
-+
-+ mem = (unsigned char*)VIDEOMEM;
-+ s1 = (unsigned char*)VSHADOW1;
-+ s2 = (unsigned char*)VSHADOW2;
-+ s4 = (unsigned char*)VSHADOW4;
-+ s8 = (unsigned char*)VSHADOW8;
-+
-+ for (i = 0; i < 80 * 30; i++)
-+ text[i] = ' ';
-+ graphics_cursor(1);
-+
-+ BitMask(0xff);
-+
-+ /* plano 1 */
-+ MapMask(1);
-+ grub_memcpy(mem, s1, 38400);
-+
-+ /* plano 2 */
-+ MapMask(2);
-+ grub_memcpy(mem, s2, 38400);
-+
-+ /* plano 3 */
-+ MapMask(4);
-+ grub_memcpy(mem, s4, 38400);
-+
-+ /* plano 4 */
-+ MapMask(8);
-+ grub_memcpy(mem, s8, 38400);
-+
-+ MapMask(15);
-+
-+}
-+
-+void graphics_setcolorstate (color_state state) {
-+ switch (state) {
-+ case COLOR_STATE_STANDARD:
-+ graphics_current_color = graphics_standard_color;
-+ break;
-+ case COLOR_STATE_NORMAL:
-+ graphics_current_color = graphics_normal_color;
-+ break;
-+ case COLOR_STATE_HIGHLIGHT:
-+ graphics_current_color = graphics_highlight_color;
-+ break;
-+ default:
-+ graphics_current_color = graphics_standard_color;
-+ break;
-+ }
-+
-+ graphics_color_state = state;
-+}
-+
-+void graphics_setcolor (int normal_color, int highlight_color) {
-+ graphics_normal_color = normal_color;
-+ graphics_highlight_color = highlight_color;
-+
-+ graphics_setcolorstate (graphics_color_state);
-+}
-+
-+void graphics_setcursor (int on) {
-+ /* FIXME: we don't have a cursor in graphics */
-+ return;
-+}
-+
-+/* Read in the splashscreen image and set the palette up appropriately.
-+ * Format of splashscreen is an xpm (can be gzipped) with 16 colors and
-+ * 640x480. */
-+int read_image(char *s)
-+{
-+ char buf[32], pal[16];
-+ unsigned char c, base, mask, *s1, *s2, *s4, *s8;
-+ unsigned i, len, idx, colors, x, y, width, height;
-+
-+ if (!grub_open(s))
-+ return 0;
-+
-+ /* read header */
-+ if (!grub_read((char*)&buf, 10) || grub_memcmp(buf, "/* XPM */\n", 10)) {
-+ grub_close();
-+ return 0;
-+ }
-+
-+ /* parse info */
-+ while (grub_read(&c, 1)) {
-+ if (c == '"')
-+ break;
-+ }
-+
-+ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
-+ ;
-+
-+ i = 0;
-+ width = c - '0';
-+ while (grub_read(&c, 1)) {
-+ if (c >= '0' && c <= '9')
-+ width = width * 10 + c - '0';
-+ else
-+ break;
-+ }
-+ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
-+ ;
-+
-+ height = c - '0';
-+ while (grub_read(&c, 1)) {
-+ if (c >= '0' && c <= '9')
-+ height = height * 10 + c - '0';
-+ else
-+ break;
-+ }
-+ while (grub_read(&c, 1) && (c == ' ' || c == '\t'))
-+ ;
-+
-+ colors = c - '0';
-+ while (grub_read(&c, 1)) {
-+ if (c >= '0' && c <= '9')
-+ colors = colors * 10 + c - '0';
-+ else
-+ break;
-+ }
-+
-+ base = 0;
-+ while (grub_read(&c, 1) && c != '"')
-+ ;
-+
-+ /* palette */
-+ for (i = 0, idx = 1; i < colors; i++) {
-+ len = 0;
-+
-+ while (grub_read(&c, 1) && c != '"')
-+ ;
-+ grub_read(&c, 1); /* char */
-+ base = c;
-+ grub_read(buf, 4); /* \t c # */
-+
-+ while (grub_read(&c, 1) && c != '"') {
-+ if (len < sizeof(buf))
-+ buf[len++] = c;
-+ }
-+
-+ if (len == 6 && idx < 15) {
-+ int r = ((hex(buf[0]) << 4) | hex(buf[1])) >> 2;
-+ int g = ((hex(buf[2]) << 4) | hex(buf[3])) >> 2;
-+ int b = ((hex(buf[4]) << 4) | hex(buf[5])) >> 2;
-+
-+ pal[idx] = base;
-+ graphics_set_palette(idx, r, g, b);
-+ ++idx;
-+ }
-+ }
-+
-+ x = y = len = 0;
-+
-+ s1 = (unsigned char*)VSHADOW1;
-+ s2 = (unsigned char*)VSHADOW2;
-+ s4 = (unsigned char*)VSHADOW4;
-+ s8 = (unsigned char*)VSHADOW8;
-+
-+ for (i = 0; i < 38400; i++)
-+ s1[i] = s2[i] = s4[i] = s8[i] = 0;
-+
-+ /* parse xpm data */
-+ while (y < height) {
-+ while (1) {
-+ if (!grub_read(&c, 1)) {
-+ grub_close();
-+ return 0;
-+ }
-+ if (c == '"')
-+ break;
-+ }
-+
-+ while (grub_read(&c, 1) && c != '"') {
-+ for (i = 1; i < 15; i++)
-+ if (pal[i] == c) {
-+ c = i;
-+ break;
-+ }
-+
-+ mask = 0x80 >> (x & 7);
-+ if (c & 1)
-+ s1[len + (x >> 3)] |= mask;
-+ if (c & 2)
-+ s2[len + (x >> 3)] |= mask;
-+ if (c & 4)
-+ s4[len + (x >> 3)] |= mask;
-+ if (c & 8)
-+ s8[len + (x >> 3)] |= mask;
-+
-+ if (++x >= 640) {
-+ x = 0;
-+
-+ if (y < 480)
-+ len += 80;
-+ ++y;
-+ }
-+ }
-+ }
-+
-+ grub_close();
-+
-+ graphics_set_palette(0, (background >> 16), (background >> 8) & 63,
-+ background & 63);
-+ graphics_set_palette(15, (foreground >> 16), (foreground >> 8) & 63,
-+ foreground & 63);
-+ graphics_set_palette(0x11, (border >> 16), (border >> 8) & 63,
-+ border & 63);
-+
-+ return 1;
-+}
-+
-+
-+/* Convert a character which is a hex digit to the appropriate integer */
-+int hex(int v)
-+{
-+ if (v >= 'A' && v <= 'F')
-+ return (v - 'A' + 10);
-+ if (v >= 'a' && v <= 'f')
-+ return (v - 'a' + 10);
-+ return (v - '0');
-+}
-+
-+
-+/* move the graphics cursor location to col, row */
-+static void graphics_setxy(int col, int row) {
-+ if (col >= x0 && col < x1) {
-+ fontx = col;
-+ cursorX = col << 3;
-+ }
-+ if (row >= y0 && row < y1) {
-+ fonty = row;
-+ cursorY = row << 4;
-+ }
-+}
-+
-+/* scroll the screen */
-+static void graphics_scroll() {
-+ int i, j;
-+
-+ /* we don't want to scroll recursively... that would be bad */
-+ if (no_scroll)
-+ return;
-+ no_scroll = 1;
-+
-+ /* move everything up a line */
-+ for (j = y0 + 1; j < y1; j++) {
-+ graphics_gotoxy(x0, j - 1);
-+ for (i = x0; i < x1; i++) {
-+ graphics_putchar(text[j * 80 + i]);
-+ }
-+ }
-+
-+ /* last line should be blank */
-+ graphics_gotoxy(x0, y1 - 1);
-+ for (i = x0; i < x1; i++)
-+ graphics_putchar(' ');
-+ graphics_setxy(x0, y1 - 1);
-+
-+ no_scroll = 0;
-+}
-+
-+
-+void graphics_cursor(int set) {
-+ unsigned char *pat, *mem, *ptr, chr[16 << 2];
-+ int i, ch, invert, offset;
-+
-+ if (set && no_scroll)
-+ return;
-+
-+ offset = cursorY * 80 + fontx;
-+ ch = text[fonty * 80 + fontx] & 0xff;
-+ invert = (text[fonty * 80 + fontx] & 0xff00) != 0;
-+ pat = font8x16 + (ch << 4);
-+
-+ mem = (unsigned char*)VIDEOMEM + offset;
-+
-+ if (!set) {
-+ for (i = 0; i < 16; i++) {
-+ unsigned char mask = pat[i];
-+
-+ if (!invert) {
-+ chr[i ] = ((unsigned char*)VSHADOW1)[offset];
-+ chr[16 + i] = ((unsigned char*)VSHADOW2)[offset];
-+ chr[32 + i] = ((unsigned char*)VSHADOW4)[offset];
-+ chr[48 + i] = ((unsigned char*)VSHADOW8)[offset];
-+
-+ /* FIXME: if (shade) */
-+ if (1) {
-+ if (ch == DISP_VERT || ch == DISP_LL ||
-+ ch == DISP_UR || ch == DISP_LR) {
-+ unsigned char pmask = ~(pat[i] >> 1);
-+
-+ chr[i ] &= pmask;
-+ chr[16 + i] &= pmask;
-+ chr[32 + i] &= pmask;
-+ chr[48 + i] &= pmask;
-+ }
-+ if (i > 0 && ch != DISP_VERT) {
-+ unsigned char pmask = ~(pat[i - 1] >> 1);
-+
-+ chr[i ] &= pmask;
-+ chr[16 + i] &= pmask;
-+ chr[32 + i] &= pmask;
-+ chr[48 + i] &= pmask;
-+ if (ch == DISP_HORIZ || ch == DISP_UR || ch == DISP_LR) {
-+ pmask = ~pat[i - 1];
-+
-+ chr[i ] &= pmask;
-+ chr[16 + i] &= pmask;
-+ chr[32 + i] &= pmask;
-+ chr[48 + i] &= pmask;
-+ }
-+ }
-+ }
-+ chr[i ] |= mask;
-+ chr[16 + i] |= mask;
-+ chr[32 + i] |= mask;
-+ chr[48 + i] |= mask;
-+
-+ offset += 80;
-+ }
-+ else {
-+ chr[i ] = mask;
-+ chr[16 + i] = mask;
-+ chr[32 + i] = mask;
-+ chr[48 + i] = mask;
-+ }
-+ }
-+ }
-+ else {
-+ MapMask(15);
-+ ptr = mem;
-+ for (i = 0; i < 16; i++, ptr += 80) {
-+ cursorBuf[i] = pat[i];
-+ *ptr = ~pat[i];
-+ }
-+ return;
-+ }
-+
-+ offset = 0;
-+ for (i = 1; i < 16; i <<= 1, offset += 16) {
-+ int j;
-+
-+ MapMask(i);
-+ ptr = mem;
-+ for (j = 0; j < 16; j++, ptr += 80)
-+ *ptr = chr[j + offset];
-+ }
-+
-+ MapMask(15);
-+}
-+
-+int grub_file_exists(char *s) {
-+ if (!grub_open(s))
-+ return 0;
-+ grub_close();
-+ return 1;
-+}
-+
-+#endif /* SUPPORT_GRAPHICS */
-diff -Nur grub-0.97/stage2/graphics.h grub-0.97-patched/stage2/graphics.h
---- grub-0.97/stage2/graphics.h 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/graphics.h 2012-11-11 17:06:33.321470879 +0100
-@@ -0,0 +1,45 @@
-+/* graphics.h - graphics console interface */
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 2002 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#ifndef GRAPHICS_H
-+#define GRAPHICS_H
-+
-+/* magic constant */
-+#define VIDEOMEM 0xA0000
-+
-+/* function prototypes */
-+char *graphics_get_splash(void);
-+
-+int read_image(char *s);
-+void graphics_cursor(int set);
-+
-+/* function prototypes for asm functions */
-+void * graphics_get_font();
-+void graphics_set_palette(int idx, int red, int green, int blue);
-+void set_int1c_handler();
-+void unset_int1c_handler();
-+
-+/* Only to check for safe opening before we start */
-+int grub_file_exists(char *s);
-+
-+extern short cursorX, cursorY;
-+extern char cursorBuf[16];
-+
-+#endif /* GRAPHICS_H */
-diff -Nur grub-0.97/stage2/iso9660.h grub-0.97-patched/stage2/iso9660.h
---- grub-0.97/stage2/iso9660.h 2004-03-27 17:02:38.000000000 +0100
-+++ grub-0.97-patched/stage2/iso9660.h 2012-11-11 17:07:12.740730013 +0100
-@@ -73,11 +73,11 @@
-
- typedef struct __iso_16bit {
- u_int16_t l, b;
--} iso_16bit_t __attribute__ ((packed));
-+} iso_16bit_t;
-
- typedef struct __iso_32bit {
- u_int32_t l, b;
--} iso_32bit_t __attribute__ ((packed));
-+} iso_32bit_t;
-
- typedef u_int8_t iso_date_t[7];
-
-diff -Nur grub-0.97/stage2/Makefile.am grub-0.97-patched/stage2/Makefile.am
---- grub-0.97/stage2/Makefile.am 2005-02-02 21:37:35.000000000 +0100
-+++ grub-0.97-patched/stage2/Makefile.am 2012-11-11 17:07:12.747730236 +0100
-@@ -7,7 +7,7 @@
- fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
- imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
- nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
-- terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h
-+ terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h
- EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
-
- # For <stage1.h>.
-@@ -19,20 +19,20 @@
- disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
- fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
- fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
-- terminfo.c tparm.c
--libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
-+ terminfo.c tparm.c graphics.c
-+libgrub_a_CFLAGS = $(GRUB_CFLAGS) -fno-stack-protector -I$(top_srcdir)/lib \
- -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
- -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
- -DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
- -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
-
- # Stage 2 and Stage 1.5's.
--pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-+stagedir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-
- EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
-
- if DISKLESS_SUPPORT
--pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
-+stage_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
- ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
- reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
- nbgrub pxegrub
-@@ -43,7 +43,7 @@
- reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
- xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
- else
--pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
-+stage_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
- ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
- reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
- noinst_DATA = pre_stage2 start start_eltorito
-@@ -79,8 +79,14 @@
- HERCULES_FLAGS =
- endif
-
--STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-- $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
-+if GRAPHICS_SUPPORT
-+GRAPHICS_FLAGS = -DSUPPORT_GRAPHICS=1
-+else
-+GRAPHICS_FLAGS =
-+endif
-+
-+STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-reorder-functions -fno-builtin -nostdinc \
-+ $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
-
- STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
- STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
-@@ -90,7 +96,8 @@
- cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
- fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
- fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
-- hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
-+ hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
-+ graphics.c
- pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
- pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
- pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
-@@ -105,7 +112,7 @@
- BUILT_SOURCES = stage2_size.h
- endif
-
--CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
-+CLEANFILES = $(stage_DATA) $(noinst_DATA) $(BUILT_SOURCES)
-
- stage2_size.h: pre_stage2
- -rm -f stage2_size.h
-diff -Nur grub-0.97/stage2/Makefile.am.orig grub-0.97-patched/stage2/Makefile.am.orig
---- grub-0.97/stage2/Makefile.am.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/Makefile.am.orig 2005-02-02 21:37:35.000000000 +0100
-@@ -0,0 +1,272 @@
-+# For test target.
-+TESTS = size_test
-+noinst_SCRIPTS = $(TESTS)
-+
-+# For dist target.
-+noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \
-+ fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
-+ imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
-+ nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
-+ terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h
-+EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
-+
-+# For <stage1.h>.
-+INCLUDES = -I$(top_srcdir)/stage1
-+
-+# The library for /sbin/grub.
-+noinst_LIBRARIES = libgrub.a
-+libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \
-+ disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
-+ fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
-+ fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
-+ terminfo.c tparm.c
-+libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
-+ -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
-+ -DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
-+ -DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
-+ -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
-+
-+# Stage 2 and Stage 1.5's.
-+pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor)
-+
-+EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec
-+
-+if DISKLESS_SUPPORT
-+pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
-+ ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
-+ reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
-+ nbgrub pxegrub
-+noinst_DATA = pre_stage2 start start_eltorito nbloader pxeloader diskless
-+noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
-+ e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
-+ iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
-+ reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
-+ xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
-+else
-+pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
-+ ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
-+ reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
-+noinst_DATA = pre_stage2 start start_eltorito
-+noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
-+ e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
-+ iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
-+ reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
-+ xfs_stage1_5.exec
-+endif
-+MOSTLYCLEANFILES = $(noinst_PROGRAMS)
-+
-+PRE_STAGE2_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8200
-+START_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,8000
-+NBLOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,0
-+PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
-+START_ELTORITO_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
-+
-+if NETBOOT_SUPPORT
-+NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1
-+else
-+NETBOOT_FLAGS =
-+endif
-+
-+if SERIAL_SUPPORT
-+SERIAL_FLAGS = -DSUPPORT_SERIAL=1
-+else
-+SERIAL_FLAGS =
-+endif
-+
-+if HERCULES_SUPPORT
-+HERCULES_FLAGS = -DSUPPORT_HERCULES=1
-+else
-+HERCULES_FLAGS =
-+endif
-+
-+STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-+ $(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
-+
-+STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
-+STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
-+
-+# For stage2 target.
-+pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \
-+ cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
-+ fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
-+ fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
-+ hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
-+pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
-+pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
-+pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
-+
-+if NETBOOT_SUPPORT
-+pre_stage2_exec_LDADD = ../netboot/libdrivers.a
-+endif
-+
-+if DISKLESS_SUPPORT
-+BUILT_SOURCES = stage2_size.h diskless_size.h
-+else
-+BUILT_SOURCES = stage2_size.h
-+endif
-+
-+CLEANFILES = $(pkglib_DATA) $(noinst_DATA) $(BUILT_SOURCES)
-+
-+stage2_size.h: pre_stage2
-+ -rm -f stage2_size.h
-+ set dummy `ls -l pre_stage2`; \
-+ echo "#define STAGE2_SIZE $$6" > stage2_size.h
-+
-+start_exec_SOURCES = start.S
-+start_exec_CCASFLAGS = $(STAGE2_COMPILE)
-+start_exec_LDFLAGS = $(START_LINK)
-+
-+# XXX: automake doesn't provide a way to specify dependencies for object
-+# files explicitly, so we must write this by a general Makefile scheme.
-+# If automake change the naming scheme for per-executable objects, this
-+# will be broken.
-+start_exec-start.$(OBJEXT): stage2_size.h
-+
-+stage2: pre_stage2 start
-+ -rm -f stage2
-+ cat start pre_stage2 > stage2
-+
-+start_eltorito_exec_SOURCES = start_eltorito.S
-+start_eltorito_exec_CCASFLAGS = $(STAGE2_COMPILE)
-+start_eltorito_exec_LDFLAGS = $(START_ELTORITO_LINK)
-+
-+start_eltorito_exec-start.$(OBJEXT): stage2_size.h
-+
-+stage2_eltorito: pre_stage2 start_eltorito
-+ -rm -f stage2_eltorito
-+ cat start_eltorito pre_stage2 > stage2_eltorito
-+
-+# For e2fs_stage1_5 target.
-+e2fs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-+ stage1_5.c fsys_ext2fs.c bios.c
-+e2fs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \
-+ -DNO_BLOCK_FILES=1
-+e2fs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \
-+ -DNO_BLOCK_FILES=1
-+e2fs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For fat_stage1_5 target.
-+fat_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-+ stage1_5.c fsys_fat.c bios.c
-+fat_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \
-+ -DNO_BLOCK_FILES=1
-+fat_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \
-+ -DNO_BLOCK_FILES=1
-+fat_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For ffs_stage1_5 target.
-+ffs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-+ stage1_5.c fsys_ffs.c bios.c
-+ffs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
-+ -DNO_BLOCK_FILES=1
-+ffs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
-+ -DNO_BLOCK_FILES=1
-+ffs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For ufs2_stage1_5 target.
-+ufs2_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-+ stage1_5.c fsys_ufs2.c bios.c
-+ufs2_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_UFS2=1 \
-+ -DNO_BLOCK_FILES=1
-+ufs2_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_UFS2=1 \
-+ -DNO_BLOCK_FILES=1
-+ufs2_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For minix_stage1_5 target.
-+minix_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-+ stage1_5.c fsys_minix.c bios.c
-+minix_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
-+ -DNO_BLOCK_FILES=1
-+minix_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
-+ -DNO_BLOCK_FILES=1
-+minix_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For reiserfs_stage1_5 target.
-+reiserfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-+ disk_io.c stage1_5.c fsys_reiserfs.c bios.c
-+reiserfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \
-+ -DNO_BLOCK_FILES=1
-+reiserfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \
-+ -DNO_BLOCK_FILES=1
-+reiserfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For vstafs_stage1_5 target.
-+vstafs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-+ disk_io.c stage1_5.c fsys_vstafs.c bios.c
-+vstafs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \
-+ -DNO_BLOCK_FILES=1
-+vstafs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \
-+ -DNO_BLOCK_FILES=1
-+vstafs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For jfs_stage1_5 target.
-+jfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-+ disk_io.c stage1_5.c fsys_jfs.c bios.c
-+jfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \
-+ -DNO_BLOCK_FILES=1
-+jfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \
-+ -DNO_BLOCK_FILES=1
-+jfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For xfs_stage1_5 target.
-+xfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-+ disk_io.c stage1_5.c fsys_xfs.c bios.c
-+xfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
-+ -DNO_BLOCK_FILES=1
-+xfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
-+ -DNO_BLOCK_FILES=1
-+xfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For iso9660_stage1_5 target.
-+iso9660_stage1_5_exec_SOURCES = start_eltorito.S asm.S common.c char_io.c \
-+ disk_io.c stage1_5.c fsys_iso9660.c bios.c
-+iso9660_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ISO9660=1 \
-+ -DNO_BLOCK_FILES=1
-+iso9660_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ISO9660=1 \
-+ -DNO_BLOCK_FILES=1
-+iso9660_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+
-+# For diskless target.
-+diskless_exec_SOURCES = $(pre_stage2_exec_SOURCES)
-+diskless_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
-+ -DSUPPORT_DISKLESS=1
-+diskless_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
-+ -DSUPPORT_DISKLESS=1
-+diskless_exec_LDFLAGS = $(PRE_STAGE2_LINK)
-+diskless_exec_LDADD = ../netboot/libdrivers.a
-+
-+diskless_size.h: diskless
-+ -rm -f $@
-+ set dummy `ls -l $^`; \
-+ echo "#define DISKLESS_SIZE $$6" > $@
-+
-+# For nbloader target.
-+nbloader_exec_SOURCES = nbloader.S
-+nbloader_exec_CCASFLAGS = $(STAGE2_COMPILE)
-+nbloader_exec_LDFLAGS = $(NBLOADER_LINK)
-+
-+# XXX: See the comment for start_exec-start.o.
-+nbloader_exec-nbloader.$(OBJEXT): diskless_size.h
-+
-+# For nbgrub target.
-+nbgrub: nbloader diskless
-+ -rm -f $@
-+ cat $^ > $@
-+
-+# For pxeloader target.
-+pxeloader_exec_SOURCES = pxeloader.S
-+pxeloader_exec_CCASFLAGS = $(STAGE2_COMPILE)
-+pxeloader_exec_LDFLAGS = $(PXELOADER_LINK)
-+
-+# XXX: See the comment for start_exec-start.o.
-+pxeloader_exec-pxeloader.$(OBJEXT): diskless_size.h
-+
-+# For pxegrub target.
-+pxegrub: pxeloader diskless
-+ -rm -f $@
-+ cat $^ > $@
-+
-+# General rule for making a raw binary.
-+SUFFIXES = .exec
-+.exec:
-+ $(OBJCOPY) -O binary $< $@
-diff -Nur grub-0.97/stage2/pc_slice.h grub-0.97-patched/stage2/pc_slice.h
---- grub-0.97/stage2/pc_slice.h 2003-07-09 13:45:53.000000000 +0200
-+++ grub-0.97-patched/stage2/pc_slice.h 2012-11-11 17:07:12.698728671 +0100
-@@ -115,6 +115,7 @@
- #define PC_SLICE_TYPE_LINUX_EXTENDED 0x85
- #define PC_SLICE_TYPE_VSTAFS 0x9e
- #define PC_SLICE_TYPE_DELL_UTIL 0xde
-+#define PC_SLICE_TYPE_GPT 0xee
- #define PC_SLICE_TYPE_LINUX_RAID 0xfd
-
-
-diff -Nur grub-0.97/stage2/shared.h grub-0.97-patched/stage2/shared.h
---- grub-0.97/stage2/shared.h 2004-06-19 18:40:09.000000000 +0200
-+++ grub-0.97-patched/stage2/shared.h 2012-11-11 17:07:12.741730044 +0100
-@@ -36,8 +36,8 @@
-
- /* Maybe redirect memory requests through grub_scratch_mem. */
- #ifdef GRUB_UTIL
--extern char *grub_scratch_mem;
--# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem)
-+extern void *grub_scratch_mem;
-+# define RAW_ADDR(x) ((x) + (unsigned long) grub_scratch_mem)
- # define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4)
- #else
- # define RAW_ADDR(x) (x)
-@@ -161,7 +161,9 @@
-
- #define LINUX_CL_OFFSET 0x9000
- #define LINUX_CL_END_OFFSET 0x90FF
--#define LINUX_SETUP_MOVE_SIZE 0x9100
-+#define LINUX_CL_0202_PRM_OFFSET 0x9500
-+#define LINUX_CL_0202_PRM_END_OFFSET 0x9FFF
-+#define LINUX_SETUP_MOVE_SIZE 0xA000
- #define LINUX_CL_MAGIC 0xA33F
-
- /*
-@@ -499,7 +501,11 @@
- unsigned char linear_reserved_field_position;
- unsigned long max_pixel_clock;
-
-- unsigned char reserved3[189];
-+ /* Reserved field to make structure to be 256 bytes long, VESA BIOS
-+ Extension 3.0 Specification says to reserve 189 bytes here but
-+ that doesn't make structure to be 256 bytes. So additional one is
-+ added here. */
-+ unsigned char reserved3[189 + 1];
- } __attribute__ ((packed));
-
-
-@@ -807,7 +813,7 @@
- /* Low-level disk I/O */
- int get_diskinfo (int drive, struct geometry *geometry);
- int biosdisk (int subfunc, int drive, struct geometry *geometry,
-- int sector, int nsec, int segment);
-+ unsigned int sector, int nsec, int segment);
- void stop_floppy (void);
-
- /* Command-line interface functions. */
-@@ -871,6 +877,7 @@
- int grub_tolower (int c);
- int grub_isspace (int c);
- int grub_strncat (char *s1, const char *s2, int n);
-+void grub_memcpy(void *dest, const void *src, int len);
- void *grub_memmove (void *to, const void *from, int len);
- void *grub_memset (void *start, int c, int len);
- int grub_strncat (char *s1, const char *s2, int n);
-@@ -911,7 +918,7 @@
- int nul_terminate (char *str);
- int get_based_digit (int c, int base);
- int safe_parse_maxint (char **str_ptr, int *myint_ptr);
--int memcheck (int start, int len);
-+int memcheck (unsigned long start, unsigned long len);
- void grub_putstr (const char *str);
-
- #ifndef NO_DECOMPRESSION
-@@ -920,10 +927,10 @@
- int gunzip_read (char *buf, int len);
- #endif /* NO_DECOMPRESSION */
-
--int rawread (int drive, int sector, int byte_offset, int byte_len, char *buf);
--int devread (int sector, int byte_offset, int byte_len, char *buf);
--int rawwrite (int drive, int sector, char *buf);
--int devwrite (int sector, int sector_len, char *buf);
-+int rawread (int drive, unsigned int sector, int byte_offset, int byte_len, char *buf);
-+int devread (unsigned int sector, int byte_offset, int byte_len, char *buf);
-+int rawwrite (int drive, unsigned int sector, char *buf);
-+int devwrite (unsigned int sector, int sector_len, char *buf);
-
- /* Parse a device string and initialize the global parameters. */
- char *set_device (char *device);
-@@ -934,7 +941,9 @@
- unsigned long *partition, int *type,
- unsigned long *start, unsigned long *len,
- unsigned long *offset, int *entry,
-- unsigned long *ext_offset, char *buf);
-+ unsigned long *ext_offset,
-+ unsigned long *gpt_offset, int *gpt_count,
-+ int *gpt_size, char *buf);
-
- /* Sets device to the one represented by the SAVED_* parameters. */
- int make_saved_active (void);
-diff -Nur grub-0.97/stage2/size_test grub-0.97-patched/stage2/size_test
---- grub-0.97/stage2/size_test 2004-05-14 21:30:52.000000000 +0200
-+++ grub-0.97-patched/stage2/size_test 2012-11-11 17:06:52.554085177 +0100
-@@ -36,9 +36,9 @@
- }
-
- # The bootloader area of a FFS partition is 14 sectors.
--check ffs_stage1_5 7168
--
--check ufs2_stage1_5 7168
-+#check ffs_stage1_5 7168
-+#
-+#check ufs2_stage1_5 7168
-
- # Stage 1.5 can be installed in the sectors immediately after MBR in the
- # first cylinder, so the size is (63 - 1) sectors.
-diff -Nur grub-0.97/stage2/stage2.c grub-0.97-patched/stage2/stage2.c
---- grub-0.97/stage2/stage2.c 2005-03-19 18:51:57.000000000 +0100
-+++ grub-0.97-patched/stage2/stage2.c 2012-11-11 17:07:12.742730076 +0100
-@@ -233,6 +233,7 @@
- {
- int c, time1, time2 = -1, first_entry = 0;
- char *cur_entry = 0;
-+ struct term_entry *prev_term = NULL;
-
- /*
- * Main loop for menu UI.
-@@ -651,7 +652,10 @@
- *(new_heap++) = 0;
-
- if (config_entries)
-- run_menu (heap, NULL, new_num_entries, new_heap, 0);
-+ {
-+ current_entryno = first_entry + entryno;
-+ run_menu (heap, NULL, new_num_entries, new_heap, 0);
-+ }
- else
- {
- cls ();
-@@ -714,6 +718,15 @@
-
- cls ();
- setcursor (1);
-+ /* if our terminal needed initialization, we should shut it down
-+ * before booting the kernel, but we want to save what it was so
-+ * we can come back if needed */
-+ prev_term = current_term;
-+ if (current_term->shutdown)
-+ {
-+ (*current_term->shutdown)();
-+ current_term = term_table; /* assumption: console is first */
-+ }
-
- while (1)
- {
-@@ -727,7 +740,8 @@
- cur_entry = get_entry (config_entries, first_entry + entryno, 1);
-
- /* Set CURRENT_ENTRYNO for the command "savedefault". */
-- current_entryno = first_entry + entryno;
-+ if (config_entries)
-+ current_entryno = first_entry + entryno;
-
- if (run_script (cur_entry, heap))
- {
-@@ -748,6 +762,13 @@
- break;
- }
-
-+ /* if we get back here, we should go back to what our term was before */
-+ current_term = prev_term;
-+ if (current_term->startup)
-+ /* if our terminal fails to initialize, fall back to console since
-+ * it should always work */
-+ if ((*current_term->startup)() == 0)
-+ current_term = term_table; /* we know that console is first */
- show_menu = 1;
- goto restart;
- }
-@@ -1050,6 +1071,10 @@
- while (is_preset);
- }
-
-+ /* go ahead and make sure the terminal is setup */
-+ if (current_term->startup)
-+ (*current_term->startup)();
-+
- if (! num_entries)
- {
- /* If no acceptable config file, goto command-line, starting
-diff -Nur grub-0.97/stage2/stage2.c.orig grub-0.97-patched/stage2/stage2.c.orig
---- grub-0.97/stage2/stage2.c.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/stage2/stage2.c.orig 2005-03-19 18:51:57.000000000 +0100
-@@ -0,0 +1,1067 @@
-+/*
-+ * GRUB -- GRand Unified Bootloader
-+ * Copyright (C) 2000,2001,2002,2004,2005 Free Software Foundation, Inc.
-+ *
-+ * This program 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.
-+ *
-+ * 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 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 Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ */
-+
-+#include <shared.h>
-+#include <term.h>
-+
-+grub_jmp_buf restart_env;
-+
-+#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
-+
-+# if defined(PRESET_MENU_STRING)
-+static const char *preset_menu = PRESET_MENU_STRING;
-+# elif defined(SUPPORT_DISKLESS)
-+/* Execute the command "bootp" automatically. */
-+static const char *preset_menu = "bootp\n";
-+# endif /* SUPPORT_DISKLESS */
-+
-+static int preset_menu_offset;
-+
-+static int
-+open_preset_menu (void)
-+{
-+#ifdef GRUB_UTIL
-+ /* Unless the user explicitly requests to use the preset menu,
-+ always opening the preset menu fails in the grub shell. */
-+ if (! use_preset_menu)
-+ return 0;
-+#endif /* GRUB_UTIL */
-+
-+ preset_menu_offset = 0;
-+ return preset_menu != 0;
-+}
-+
-+static int
-+read_from_preset_menu (char *buf, int maxlen)
-+{
-+ int len = grub_strlen (preset_menu + preset_menu_offset);
-+
-+ if (len > maxlen)
-+ len = maxlen;
-+
-+ grub_memmove (buf, preset_menu + preset_menu_offset, len);
-+ preset_menu_offset += len;
-+
-+ return len;
-+}
-+
-+static void
-+close_preset_menu (void)
-+{
-+ /* Disable the preset menu. */
-+ preset_menu = 0;
-+}
-+
-+#else /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
-+
-+#define open_preset_menu() 0
-+#define read_from_preset_menu(buf, maxlen) 0
-+#define close_preset_menu()
-+
-+#endif /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
-+
-+static char *
-+get_entry (char *list, int num, int nested)
-+{
-+ int i;
-+
-+ for (i = 0; i < num; i++)
-+ {
-+ do
-+ {
-+ while (*(list++));
-+ }
-+ while (nested && *(list++));
-+ }
-+
-+ return list;
-+}
-+
-+/* Print an entry in a line of the menu box. */
-+static void
-+print_entry (int y, int highlight, char *entry)
-+{
-+ int x;
-+
-+ if (current_term->setcolorstate)
-+ current_term->setcolorstate (COLOR_STATE_NORMAL);
-+
-+ if (highlight && current_term->setcolorstate)
-+ current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
-+
-+ gotoxy (2, y);
-+ grub_putchar (' ');
-+ for (x = 3; x < 75; x++)
-+ {
-+ if (*entry && x <= 72)
-+ {
-+ if (x == 72)
-+ grub_putchar (DISP_RIGHT);
-+ else
-+ grub_putchar (*entry++);
-+ }
-+ else
-+ grub_putchar (' ');
-+ }
-+ gotoxy (74, y);
-+
-+ if (current_term->setcolorstate)
-+ current_term->setcolorstate (COLOR_STATE_STANDARD);
-+}
-+
-+/* Print entries in the menu box. */
-+static void
-+print_entries (int y, int size, int first, int entryno, char *menu_entries)
-+{
-+ int i;
-+
-+ gotoxy (77, y + 1);
-+
-+ if (first)
-+ grub_putchar (DISP_UP);
-+ else
-+ grub_putchar (' ');
-+
-+ menu_entries = get_entry (menu_entries, first, 0);
-+
-+ for (i = 0; i < size; i++)
-+ {
-+ print_entry (y + i + 1, entryno == i, menu_entries);
-+
-+ while (*menu_entries)
-+ menu_entries++;
-+
-+ if (*(menu_entries - 1))
-+ menu_entries++;
-+ }
-+
-+ gotoxy (77, y + size);
-+
-+ if (*menu_entries)
-+ grub_putchar (DISP_DOWN);
-+ else
-+ grub_putchar (' ');
-+
-+ gotoxy (74, y + entryno + 1);
-+}
-+
-+static void
-+print_entries_raw (int size, int first, char *menu_entries)
-+{
-+ int i;
-+
-+#define LINE_LENGTH 67
-+
-+ for (i = 0; i < LINE_LENGTH; i++)
-+ grub_putchar ('-');
-+ grub_putchar ('\n');
-+
-+ for (i = first; i < size; i++)
-+ {
-+ /* grub's printf can't %02d so ... */
-+ if (i < 10)
-+ grub_putchar (' ');
-+ grub_printf ("%d: %s\n", i, get_entry (menu_entries, i, 0));
-+ }
-+
-+ for (i = 0; i < LINE_LENGTH; i++)
-+ grub_putchar ('-');
-+ grub_putchar ('\n');
-+
-+#undef LINE_LENGTH
-+}
-+
-+
-+static void
-+print_border (int y, int size)
-+{
-+ int i;
-+
-+ if (current_term->setcolorstate)
-+ current_term->setcolorstate (COLOR_STATE_NORMAL);
-+
-+ gotoxy (1, y);
-+
-+ grub_putchar (DISP_UL);
-+ for (i = 0; i < 73; i++)
-+ grub_putchar (DISP_HORIZ);
-+ grub_putchar (DISP_UR);
-+
-+ i = 1;
-+ while (1)
-+ {
-+ gotoxy (1, y + i);
-+
-+ if (i > size)
-+ break;
-+
-+ grub_putchar (DISP_VERT);
-+ gotoxy (75, y + i);
-+ grub_putchar (DISP_VERT);
-+
-+ i++;
-+ }
-+
-+ grub_putchar (DISP_LL);
-+ for (i = 0; i < 73; i++)
-+ grub_putchar (DISP_HORIZ);
-+ grub_putchar (DISP_LR);
-+
-+ if (current_term->setcolorstate)
-+ current_term->setcolorstate (COLOR_STATE_STANDARD);
-+}
-+
-+static void
-+run_menu (char *menu_entries, char *config_entries, int num_entries,
-+ char *heap, int entryno)
-+{
-+ int c, time1, time2 = -1, first_entry = 0;
-+ char *cur_entry = 0;
-+
-+ /*
-+ * Main loop for menu UI.
-+ */
-+
-+restart:
-+ /* Dumb terminal always use all entries for display
-+ invariant for TERM_DUMB: first_entry == 0 */
-+ if (! (current_term->flags & TERM_DUMB))
-+ {
-+ while (entryno > 11)
-+ {
-+ first_entry++;
-+ entryno--;
-+ }
-+ }
-+
-+ /* If the timeout was expired or wasn't set, force to show the menu
-+ interface. */
-+ if (grub_timeout < 0)
-+ show_menu = 1;
-+
-+ /* If SHOW_MENU is false, don't display the menu until ESC is pressed. */
-+ if (! show_menu)
-+ {
-+ /* Get current time. */
-+ while ((time1 = getrtsecs ()) == 0xFF)
-+ ;
-+
-+ while (1)
-+ {
-+ /* Check if ESC is pressed. */
-+ if (checkkey () != -1 && ASCII_CHAR (getkey ()) == '\e')
-+ {
-+ grub_timeout = -1;
-+ show_menu = 1;
-+ break;
-+ }
-+
-+ /* If GRUB_TIMEOUT is expired, boot the default entry. */
-+ if (grub_timeout >=0
-+ && (time1 = getrtsecs ()) != time2
-+ && time1 != 0xFF)
-+ {
-+ if (grub_timeout <= 0)
-+ {
-+ grub_timeout = -1;
-+ goto boot_entry;
-+ }
-+
-+ time2 = time1;
-+ grub_timeout--;
-+
-+ /* Print a message. */
-+ grub_printf ("\rPress `ESC' to enter the menu... %d ",
-+ grub_timeout);
-+ }
-+ }
-+ }
-+
-+ /* Only display the menu if the user wants to see it. */
-+ if (show_menu)
-+ {
-+ init_page ();
-+ setcursor (0);
-+
-+ if (current_term->flags & TERM_DUMB)
-+ print_entries_raw (num_entries, first_entry, menu_entries);
-+ else
-+ print_border (3, 12);
-+
-+ grub_printf ("\n\
-+ Use the %c and %c keys to select which entry is highlighted.\n",
-+ DISP_UP, DISP_DOWN);
-+
-+ if (! auth && password)
-+ {
-+ printf ("\
-+ Press enter to boot the selected OS or \'p\' to enter a\n\
-+ password to unlock the next set of features.");
-+ }
-+ else
-+ {
-+ if (config_entries)
-+ printf ("\
-+ Press enter to boot the selected OS, \'e\' to edit the\n\
-+ commands before booting, or \'c\' for a command-line.");
-+ else
-+ printf ("\
-+ Press \'b\' to boot, \'e\' to edit the selected command in the\n\
-+ boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
-+ after (\'O\' for before) the selected line, \'d\' to remove the\n\
-+ selected line, or escape to go back to the main menu.");
-+ }
-+
-+ if (current_term->flags & TERM_DUMB)
-+ grub_printf ("\n\nThe selected entry is %d ", entryno);
-+ else
-+ print_entries (3, 12, first_entry, entryno, menu_entries);
-+ }
-+
-+ /* XX using RT clock now, need to initialize value */
-+ while ((time1 = getrtsecs()) == 0xFF);
-+
-+ while (1)
-+ {
-+ /* Initialize to NULL just in case... */
-+ cur_entry = NULL;
-+
-+ if (grub_timeout >= 0 && (time1 = getrtsecs()) != time2 && time1 != 0xFF)
-+ {
-+ if (grub_timeout <= 0)
-+ {
-+ grub_timeout = -1;
-+ break;
-+ }
-+
-+ /* else not booting yet! */
-+ time2 = time1;
-+
-+ if (current_term->flags & TERM_DUMB)
-+ grub_printf ("\r Entry %d will be booted automatically in %d seconds. ",
-+ entryno, grub_timeout);
-+ else
-+ {
-+ gotoxy (3, 22);
-+ grub_printf ("The highlighted entry will be booted automatically in %d seconds. ",
-+ grub_timeout);
-+ gotoxy (74, 4 + entryno);
-+ }
-+
-+ grub_timeout--;
-+ }
-+
-+ /* Check for a keypress, however if TIMEOUT has been expired
-+ (GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been
-+ pressed.
-+ This avoids polling (relevant in the grub-shell and later on
-+ in grub if interrupt driven I/O is done). */
-+ if (checkkey () >= 0 || grub_timeout < 0)
-+ {
-+ /* Key was pressed, show which entry is selected before GETKEY,
-+ since we're comming in here also on GRUB_TIMEOUT == -1 and
-+ hang in GETKEY */
-+ if (current_term->flags & TERM_DUMB)
-+ grub_printf ("\r Highlighted entry is %d: ", entryno);
-+
-+ c = ASCII_CHAR (getkey ());
-+
-+ if (grub_timeout >= 0)
-+ {
-+ if (current_term->flags & TERM_DUMB)
-+ grub_putchar ('\r');
-+ else
-+ gotoxy (3, 22);
-+ printf (" ");
-+ grub_timeout = -1;
-+ fallback_entryno = -1;
-+ if (! (current_term->flags & TERM_DUMB))
-+ gotoxy (74, 4 + entryno);
-+ }
-+
-+ /* We told them above (at least in SUPPORT_SERIAL) to use
-+ '^' or 'v' so accept these keys. */
-+ if (c == 16 || c == '^')
-+ {
-+ if (current_term->flags & TERM_DUMB)
-+ {
-+ if (entryno > 0)
-+ entryno--;
-+ }
-+ else
-+ {
-+ if (entryno > 0)
-+ {
-+ print_entry (4 + entryno, 0,
-+ get_entry (menu_entries,
-+ first_entry + entryno,
-+ 0));
-+ entryno--;
-+ print_entry (4 + entryno, 1,
-+ get_entry (menu_entries,
-+ first_entry + entryno,
-+ 0));
-+ }
-+ else if (first_entry > 0)
-+ {
-+ first_entry--;
-+ print_entries (3, 12, first_entry, entryno,
-+ menu_entries);
-+ }
-+ }
-+ }
-+ else if ((c == 14 || c == 'v')
-+ && first_entry + entryno + 1 < num_entries)
-+ {
-+ if (current_term->flags & TERM_DUMB)
-+ entryno++;
-+ else
-+ {
-+ if (entryno < 11)
-+ {
-+ print_entry (4 + entryno, 0,
-+ get_entry (menu_entries,
-+ first_entry + entryno,
-+ 0));
-+ entryno++;
-+ print_entry (4 + entryno, 1,
-+ get_entry (menu_entries,
-+ first_entry + entryno,
-+ 0));
-+ }
-+ else if (num_entries > 12 + first_entry)
-+ {
-+ first_entry++;
-+ print_entries (3, 12, first_entry, entryno, menu_entries);
-+ }
-+ }
-+ }
-+ else if (c == 7)
-+ {
-+ /* Page Up */
-+ first_entry -= 12;
-+ if (first_entry < 0)
-+ {
-+ entryno += first_entry;
-+ first_entry = 0;
-+ if (entryno < 0)
-+ entryno = 0;
-+ }
-+ print_entries (3, 12, first_entry, entryno, menu_entries);
-+ }
-+ else if (c == 3)
-+ {
-+ /* Page Down */
-+ first_entry += 12;
-+ if (first_entry + entryno + 1 >= num_entries)
-+ {
-+ first_entry = num_entries - 12;
-+ if (first_entry < 0)
-+ first_entry = 0;
-+ entryno = num_entries - first_entry - 1;
-+ }
-+ print_entries (3, 12, first_entry, entryno, menu_entries);
-+ }
-+
-+ if (config_entries)
-+ {
-+ if ((c == '\n') || (c == '\r') || (c == 6))
-+ break;
-+ }
-+ else
-+ {
-+ if ((c == 'd') || (c == 'o') || (c == 'O'))
-+ {
-+ if (! (current_term->flags & TERM_DUMB))
-+ print_entry (4 + entryno, 0,
-+ get_entry (menu_entries,
-+ first_entry + entryno,
-+ 0));
-+
-+ /* insert after is almost exactly like insert before */
-+ if (c == 'o')
-+ {
-+ /* But `o' differs from `O', since it may causes
-+ the menu screen to scroll up. */
-+ if (entryno < 11 || (current_term->flags & TERM_DUMB))
-+ entryno++;
-+ else
-+ first_entry++;
-+
-+ c = 'O';
-+ }
-+
-+ cur_entry = get_entry (menu_entries,
-+ first_entry + entryno,
-+ 0);
-+
-+ if (c == 'O')
-+ {
-+ grub_memmove (cur_entry + 2, cur_entry,
-+ ((int) heap) - ((int) cur_entry));
-+
-+ cur_entry[0] = ' ';
-+ cur_entry[1] = 0;
-+
-+ heap += 2;
-+
-+ num_entries++;
-+ }
-+ else if (num_entries > 0)
-+ {
-+ char *ptr = get_entry(menu_entries,
-+ first_entry + entryno + 1,
-+ 0);
-+
-+ grub_memmove (cur_entry, ptr,
-+ ((int) heap) - ((int) ptr));
-+ heap -= (((int) ptr) - ((int) cur_entry));
-+
-+ num_entries--;
-+
-+ if (entryno >= num_entries)
-+ entryno--;
-+ if (first_entry && num_entries < 12 + first_entry)
-+ first_entry--;
-+ }
-+
-+ if (current_term->flags & TERM_DUMB)
-+ {
-+ grub_printf ("\n\n");
-+ print_entries_raw (num_entries, first_entry,
-+ menu_entries);
-+ grub_printf ("\n");
-+ }
-+ else
-+ print_entries (3, 12, first_entry, entryno, menu_entries);
-+ }
-+
-+ cur_entry = menu_entries;
-+ if (c == 27)
-+ return;
-+ if (c == 'b')
-+ break;
-+ }
-+
-+ if (! auth && password)
-+ {
-+ if (c == 'p')
-+ {
-+ /* Do password check here! */
-+ char entered[32];
-+ char *pptr = password;
-+
-+ if (current_term->flags & TERM_DUMB)
-+ grub_printf ("\r ");
-+ else
-+ gotoxy (1, 21);
-+
-+ /* Wipe out the previously entered password */
-+ grub_memset (entered, 0, sizeof (entered));
-+ get_cmdline (" Password: ", entered, 31, '*', 0);
-+
-+ while (! isspace (*pptr) && *pptr)
-+ pptr++;
-+
-+ /* Make sure that PASSWORD is NUL-terminated. */
-+ *pptr++ = 0;
-+
-+ if (! check_password (entered, password, password_type))
-+ {
-+ char *new_file = config_file;
-+ while (isspace (*pptr))
-+ pptr++;
-+
-+ /* If *PPTR is NUL, then allow the user to use
-+ privileged instructions, otherwise, load
-+ another configuration file. */
-+ if (*pptr != 0)
-+ {
-+ while ((*(new_file++) = *(pptr++)) != 0)
-+ ;
-+
-+ /* Make sure that the user will not have
-+ authority in the next configuration. */
-+ auth = 0;
-+ return;
-+ }
-+ else
-+ {
-+ /* Now the user is superhuman. */
-+ auth = 1;
-+ goto restart;
-+ }
-+ }
-+ else
-+ {
-+ grub_printf ("Failed!\n Press any key to continue...");
-+ getkey ();
-+ goto restart;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ if (c == 'e')
-+ {
-+ int new_num_entries = 0, i = 0;
-+ char *new_heap;
-+
-+ if (config_entries)
-+ {
-+ new_heap = heap;
-+ cur_entry = get_entry (config_entries,
-+ first_entry + entryno,
-+ 1);
-+ }
-+ else
-+ {
-+ /* safe area! */
-+ new_heap = heap + NEW_HEAPSIZE + 1;
-+ cur_entry = get_entry (menu_entries,
-+ first_entry + entryno,
-+ 0);
-+ }
-+
-+ do
-+ {
-+ while ((*(new_heap++) = cur_entry[i++]) != 0);
-+ new_num_entries++;
-+ }
-+ while (config_entries && cur_entry[i]);
-+
-+ /* this only needs to be done if config_entries is non-NULL,
-+ but it doesn't hurt to do it always */
-+ *(new_heap++) = 0;
-+
-+ if (config_entries)
-+ run_menu (heap, NULL, new_num_entries, new_heap, 0);
-+ else
-+ {
-+ cls ();
-+ print_cmdline_message (0);
-+
-+ new_heap = heap + NEW_HEAPSIZE + 1;
-+
-+ saved_drive = boot_drive;
-+ saved_partition = install_partition;
-+ current_drive = GRUB_INVALID_DRIVE;
-+
-+ if (! get_cmdline (PACKAGE " edit> ", new_heap,
-+ NEW_HEAPSIZE + 1, 0, 1))
-+ {
-+ int j = 0;
-+
-+ /* get length of new command */
-+ while (new_heap[j++])
-+ ;
-+
-+ if (j < 2)
-+ {
-+ j = 2;
-+ new_heap[0] = ' ';
-+ new_heap[1] = 0;
-+ }
-+
-+ /* align rest of commands properly */
-+ grub_memmove (cur_entry + j, cur_entry + i,
-+ (int) heap - ((int) cur_entry + i));
-+
-+ /* copy command to correct area */
-+ grub_memmove (cur_entry, new_heap, j);
-+
-+ heap += (j - i);
-+ }
-+ }
-+
-+ goto restart;
-+ }
-+ if (c == 'c')
-+ {
-+ enter_cmdline (heap, 0);
-+ goto restart;
-+ }
-+#ifdef GRUB_UTIL
-+ if (c == 'q')
-+ {
-+ /* The same as ``quit''. */
-+ stop ();
-+ }
-+#endif
-+ }
-+ }
-+ }
-+
-+ /* Attempt to boot an entry. */
-+
-+ boot_entry:
-+
-+ cls ();
-+ setcursor (1);
-+
-+ while (1)
-+ {
-+ if (config_entries)
-+ printf (" Booting \'%s\'\n\n",
-+ get_entry (menu_entries, first_entry + entryno, 0));
-+ else
-+ printf (" Booting command-list\n\n");
-+
-+ if (! cur_entry)
-+ cur_entry = get_entry (config_entries, first_entry + entryno, 1);
-+
-+ /* Set CURRENT_ENTRYNO for the command "savedefault". */
-+ current_entryno = first_entry + entryno;
-+
-+ if (run_script (cur_entry, heap))
-+ {
-+ if (fallback_entryno >= 0)
-+ {
-+ cur_entry = NULL;
-+ first_entry = 0;
-+ entryno = fallback_entries[fallback_entryno];
-+ fallback_entryno++;
-+ if (fallback_entryno >= MAX_FALLBACK_ENTRIES
-+ || fallback_entries[fallback_entryno] < 0)
-+ fallback_entryno = -1;
-+ }
-+ else
-+ break;
-+ }
-+ else
-+ break;
-+ }
-+
-+ show_menu = 1;
-+ goto restart;
-+}
-+
-+
-+static int
-+get_line_from_config (char *cmdline, int maxlen, int read_from_file)
-+{
-+ int pos = 0, literal = 0, comment = 0;
-+ char c; /* since we're loading it a byte at a time! */
-+
-+ while (1)
-+ {
-+ if (read_from_file)
-+ {
-+ if (! grub_read (&c, 1))
-+ break;
-+ }
-+ else
-+ {
-+ if (! read_from_preset_menu (&c, 1))
-+ break;
-+ }
-+
-+ /* Skip all carriage returns. */
-+ if (c == '\r')
-+ continue;
-+
-+ /* Replace tabs with spaces. */
-+ if (c == '\t')
-+ c = ' ';
-+
-+ /* The previous is a backslash, then... */
-+ if (literal)
-+ {
-+ /* If it is a newline, replace it with a space and continue. */
-+ if (c == '\n')
-+ {
-+ c = ' ';
-+
-+ /* Go back to overwrite a backslash. */
-+ if (pos > 0)
-+ pos--;
-+ }
-+
-+ literal = 0;
-+ }
-+
-+ /* translate characters first! */
-+ if (c == '\\' && ! literal)
-+ literal = 1;
-+
-+ if (comment)
-+ {
-+ if (c == '\n')
-+ comment = 0;
-+ }
-+ else if (! pos)
-+ {
-+ if (c == '#')
-+ comment = 1;
-+ else if ((c != ' ') && (c != '\n'))
-+ cmdline[pos++] = c;
-+ }
-+ else
-+ {
-+ if (c == '\n')
-+ break;
-+
-+ if (pos < maxlen)
-+ cmdline[pos++] = c;
-+ }
-+ }
-+
-+ cmdline[pos] = 0;
-+
-+ return pos;
-+}
-+
-+
-+/* This is the starting function in C. */
-+void
-+cmain (void)
-+{
-+ int config_len, menu_len, num_entries;
-+ char *config_entries, *menu_entries;
-+ char *kill_buf = (char *) KILL_BUF;
-+
-+ auto void reset (void);
-+ void reset (void)
-+ {
-+ count_lines = -1;
-+ config_len = 0;
-+ menu_len = 0;
-+ num_entries = 0;
-+ config_entries = (char *) mbi.drives_addr + mbi.drives_length;
-+ menu_entries = (char *) MENU_BUF;
-+ init_config ();
-+ }
-+
-+ /* Initialize the environment for restarting Stage 2. */
-+ grub_setjmp (restart_env);
-+
-+ /* Initialize the kill buffer. */
-+ *kill_buf = 0;
-+
-+ /* Never return. */
-+ for (;;)
-+ {
-+ int is_opened, is_preset;
-+
-+ reset ();
-+
-+ /* Here load the configuration file. */
-+
-+#ifdef GRUB_UTIL
-+ if (use_config_file)
-+#endif /* GRUB_UTIL */
-+ {
-+ char *default_file = (char *) DEFAULT_FILE_BUF;
-+ int i;
-+
-+ /* Get a saved default entry if possible. */
-+ saved_entryno = 0;
-+ *default_file = 0;
-+ grub_strncat (default_file, config_file, DEFAULT_FILE_BUFLEN);
-+ for (i = grub_strlen(default_file); i >= 0; i--)
-+ if (default_file[i] == '/')
-+ {
-+ i++;
-+ break;
-+ }
-+ default_file[i] = 0;
-+ grub_strncat (default_file + i, "default", DEFAULT_FILE_BUFLEN - i);
-+ if (grub_open (default_file))
-+ {
-+ char buf[10]; /* This is good enough. */
-+ char *p = buf;
-+ int len;
-+
-+ len = grub_read (buf, sizeof (buf));
-+ if (len > 0)
-+ {
-+ buf[sizeof (buf) - 1] = 0;
-+ safe_parse_maxint (&p, &saved_entryno);
-+ }
-+
-+ grub_close ();
-+ }
-+ errnum = ERR_NONE;
-+
-+ do
-+ {
-+ /* STATE 0: Before any title command.
-+ STATE 1: In a title command.
-+ STATE >1: In a entry after a title command. */
-+ int state = 0, prev_config_len = 0, prev_menu_len = 0;
-+ char *cmdline;
-+
-+ /* Try the preset menu first. This will succeed at most once,
-+ because close_preset_menu disables the preset menu. */
-+ is_opened = is_preset = open_preset_menu ();
-+ if (! is_opened)
-+ {
-+ is_opened = grub_open (config_file);
-+ errnum = ERR_NONE;
-+ }
-+
-+ if (! is_opened)
-+ break;
-+
-+ /* This is necessary, because the menu must be overrided. */
-+ reset ();
-+
-+ cmdline = (char *) CMDLINE_BUF;
-+ while (get_line_from_config (cmdline, NEW_HEAPSIZE,
-+ ! is_preset))
-+ {
-+ struct builtin *builtin;
-+
-+ /* Get the pointer to the builtin structure. */
-+ builtin = find_command (cmdline);
-+ errnum = 0;
-+ if (! builtin)
-+ /* Unknown command. Just skip now. */
-+ continue;
-+
-+ if (builtin->flags & BUILTIN_TITLE)
-+ {
-+ char *ptr;
-+
-+ /* the command "title" is specially treated. */
-+ if (state > 1)
-+ {
-+ /* The next title is found. */
-+ num_entries++;
-+ config_entries[config_len++] = 0;
-+ prev_menu_len = menu_len;
-+ prev_config_len = config_len;
-+ }
-+ else
-+ {
-+ /* The first title is found. */
-+ menu_len = prev_menu_len;
-+ config_len = prev_config_len;
-+ }
-+
-+ /* Reset the state. */
-+ state = 1;
-+
-+ /* Copy title into menu area. */
-+ ptr = skip_to (1, cmdline);
-+ while ((menu_entries[menu_len++] = *(ptr++)) != 0)
-+ ;
-+ }
-+ else if (! state)
-+ {
-+ /* Run a command found is possible. */
-+ if (builtin->flags & BUILTIN_MENU)
-+ {
-+ char *arg = skip_to (1, cmdline);
-+ (builtin->func) (arg, BUILTIN_MENU);
-+ errnum = 0;
-+ }
-+ else
-+ /* Ignored. */
-+ continue;
-+ }
-+ else
-+ {
-+ char *ptr = cmdline;
-+
-+ state++;
-+ /* Copy config file data to config area. */
-+ while ((config_entries[config_len++] = *ptr++) != 0)
-+ ;
-+ }
-+ }
-+
-+ if (state > 1)
-+ {
-+ /* Finish the last entry. */
-+ num_entries++;
-+ config_entries[config_len++] = 0;
-+ }
-+ else
-+ {
-+ menu_len = prev_menu_len;
-+ config_len = prev_config_len;
-+ }
-+
-+ menu_entries[menu_len++] = 0;
-+ config_entries[config_len++] = 0;
-+ grub_memmove (config_entries + config_len, menu_entries,
-+ menu_len);
-+ menu_entries = config_entries + config_len;
-+
-+ /* Make sure that all fallback entries are valid. */
-+ if (fallback_entryno >= 0)
-+ {
-+ for (i = 0; i < MAX_FALLBACK_ENTRIES; i++)
-+ {
-+ if (fallback_entries[i] < 0)
-+ break;
-+ if (fallback_entries[i] >= num_entries)
-+ {
-+ grub_memmove (fallback_entries + i,
-+ fallback_entries + i + 1,
-+ ((MAX_FALLBACK_ENTRIES - i - 1)
-+ * sizeof (int)));
-+ i--;
-+ }
-+ }
-+
-+ if (fallback_entries[0] < 0)
-+ fallback_entryno = -1;
-+ }
-+ /* Check if the default entry is present. Otherwise reset
-+ it to fallback if fallback is valid, or to DEFAULT_ENTRY
-+ if not. */
-+ if (default_entry >= num_entries)
-+ {
-+ if (fallback_entryno >= 0)
-+ {
-+ default_entry = fallback_entries[0];
-+ fallback_entryno++;
-+ if (fallback_entryno >= MAX_FALLBACK_ENTRIES
-+ || fallback_entries[fallback_entryno] < 0)
-+ fallback_entryno = -1;
-+ }
-+ else
-+ default_entry = 0;
-+ }
-+
-+ if (is_preset)
-+ close_preset_menu ();
-+ else
-+ grub_close ();
-+ }
-+ while (is_preset);
-+ }
-+
-+ if (! num_entries)
-+ {
-+ /* If no acceptable config file, goto command-line, starting
-+ heap from where the config entries would have been stored
-+ if there were any. */
-+ enter_cmdline (config_entries, 1);
-+ }
-+ else
-+ {
-+ /* Run menu interface. */
-+ run_menu (menu_entries, config_entries, num_entries,
-+ menu_entries + menu_len, default_entry);
-+ }
-+ }
-+}
-diff -Nur grub-0.97/stage2/term.h grub-0.97-patched/stage2/term.h
---- grub-0.97/stage2/term.h 2003-07-09 13:45:53.000000000 +0200
-+++ grub-0.97-patched/stage2/term.h 2012-11-11 17:06:33.311470556 +0100
-@@ -60,6 +60,8 @@
- const char *name;
- /* The feature flags defined above. */
- unsigned long flags;
-+ /* Default for maximum number of lines if not specified */
-+ unsigned short max_lines;
- /* Put a character. */
- void (*putchar) (int c);
- /* Check if any input character is available. */
-@@ -79,6 +81,11 @@
- void (*setcolor) (int normal_color, int highlight_color);
- /* Turn on/off the cursor. */
- int (*setcursor) (int on);
-+
-+ /* function to start a terminal */
-+ int (*startup) (void);
-+ /* function to use to shutdown a terminal */
-+ void (*shutdown) (void);
- };
-
- /* This lists up available terminals. */
-@@ -124,4 +131,23 @@
- int hercules_setcursor (int on);
- #endif
-
-+#ifdef SUPPORT_GRAPHICS
-+extern int foreground, background, border, graphics_inited;
-+
-+void graphics_set_splash(char *splashfile);
-+int set_videomode (int mode);
-+void graphics_putchar (int c);
-+int graphics_getxy(void);
-+void graphics_gotoxy(int x, int y);
-+void graphics_cls(void);
-+void graphics_setcolorstate (color_state state);
-+void graphics_setcolor (int normal_color, int highlight_color);
-+void graphics_setcursor (int on);
-+int graphics_init(void);
-+void graphics_end(void);
-+
-+int hex(int v);
-+void graphics_set_palette(int idx, int red, int green, int blue);
-+#endif /* SUPPORT_GRAPHICS */
-+
- #endif /* ! GRUB_TERM_HEADER */
-diff -Nur grub-0.97/THANKS grub-0.97-patched/THANKS
---- grub-0.97/THANKS 2005-05-08 04:17:43.000000000 +0200
-+++ grub-0.97-patched/THANKS 2012-11-11 17:07:12.709729021 +0100
-@@ -121,3 +121,4 @@
- Yedidyah Bar-David <didi@post.tau.ac.il>
- Yury V. Umanets <umka@namesys.com>
- Yuri Zaporogets <yuriz@ukr.net>
-+Vitaly Fertman <vitaly@namesys.com>
-diff -Nur grub-0.97/util/grub-install.in grub-0.97-patched/util/grub-install.in
---- grub-0.97/util/grub-install.in 2004-07-24 20:57:31.000000000 +0200
-+++ grub-0.97-patched/util/grub-install.in 2012-11-11 17:07:12.748730268 +0100
-@@ -96,24 +96,27 @@
- # Break the device name into the disk part and the partition part.
- case "$host_os" in
- linux*)
-- tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
-+ tmp_disk=`echo "$1" | sed -e 's%\([shv]d[a-z]\)[0-9]*$%\1%' \
- -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
- -e 's%\(fd[0-9]*\)$%\1%' \
- -e 's%/part[0-9]*$%/disc%' \
-- -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
-- tmp_part=`echo "$1" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
-+ -e 's%\(c[0-7]d[0-9]*\).*$%\1%' \
-+ -e 's%\(e[0-9]\.[0-9]*\).*$%\1%'`
-+ tmp_part=`echo "$1" | sed -e 's%.*/[shv]d[a-z]\([0-9]*\)$%\1%' \
- -e 's%.*d[0-9]*p%%' \
- -e 's%.*/fd[0-9]*$%%' \
- -e 's%.*/floppy/[0-9]*$%%' \
- -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
-- -e 's%.*c[0-7]d[0-9]*p%%'`
-+ -e 's%.*c[0-7]d[0-9]*p*%%' \
-+ -e 's%.*e[0-9]\.[0-9]*p%%' \
-+ -e 's%.*e[0-9]\.[0-9]*\$%%'`
- ;;
- gnu*)
- tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
- tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;;
- freebsd* | kfreebsd*-gnu)
-- tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%r\1%' \
-- | sed 's%r\{0,1\}\(da[0-9]*\).*$%r\1%'`
-+ tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%\1%' \
-+ | sed 's%r\{0,1\}\(da[0-9]*\).*$%\1%'`
- tmp_part=`echo "$1" \
- | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
- | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
-@@ -131,7 +134,7 @@
-
- # Get the drive name.
- tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \
-- | sed 's%.*\(([hf]d[0-9][a-g0-9,]*)\).*%\1%'`
-+ | sed 's%.*\(([hf]d[0-9][a-z0-9,]*)\).*%\1%'`
-
- # If not found, print an error message and exit.
- if test "x$tmp_drive" = x; then
-@@ -148,13 +151,13 @@
- gnu*)
- if echo $tmp_part | grep "^s" >/dev/null; then
- tmp_pc_slice=`echo $tmp_part \
-- | sed "s%s\([0-9]*\)[a-g]*$%\1%"`
-+ | sed "s%s\([0-9]*\)[a-z]*$%\1%"`
- tmp_drive=`echo "$tmp_drive" \
- | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
- fi
-- if echo $tmp_part | grep "[a-g]$" >/dev/null; then
-+ if echo $tmp_part | grep "[a-z]$" >/dev/null; then
- tmp_bsd_partition=`echo "$tmp_part" \
-- | sed "s%[^a-g]*\([a-g]\)$%\1%"`
-+ | sed "s%[^a-z]*\([a-z]\)$%\1%"`
- tmp_drive=`echo "$tmp_drive" \
- | sed "s%)%,$tmp_bsd_partition)%"`
- fi
-@@ -336,6 +339,10 @@
- # Create a safe temporary file.
- test -n "$mklog" && log_file=`$mklog`
-
-+ # Before all invocations of the grub shell, call sync to make sure
-+ # the raw device is in sync with any bufferring in filesystems.
-+ sync
-+
- $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
- quit
- EOF
-@@ -450,6 +457,10 @@
- # Create a safe temporary file.
- test -n "$mklog" && log_file=`$mklog`
-
-+# Before all invocations of the grub shell, call sync to make sure
-+# the raw device is in sync with any bufferring in filesystems.
-+sync
-+
- # Now perform the installation.
- $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
- root $root_drive
-diff -Nur grub-0.97/util/grub-install.in.orig grub-0.97-patched/util/grub-install.in.orig
---- grub-0.97/util/grub-install.in.orig 1970-01-01 01:00:00.000000000 +0100
-+++ grub-0.97-patched/util/grub-install.in.orig 2004-07-24 20:57:31.000000000 +0200
-@@ -0,0 +1,477 @@
-+#! /bin/sh
-+
-+# Install GRUB on your drive.
-+# Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
-+#
-+# This file 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.
-+#
-+# 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
-+# 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 Free Software
-+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+
-+# Initialize some variables.
-+prefix=@prefix@
-+exec_prefix=@exec_prefix@
-+sbindir=@sbindir@
-+libdir=@libdir@
-+PACKAGE=@PACKAGE@
-+VERSION=@VERSION@
-+host_cpu=@host_cpu@
-+host_os=@host_os@
-+host_vendor=@host_vendor@
-+pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
-+
-+grub_shell=${sbindir}/grub
-+grub_set_default=${sbindir}/grub-set-default
-+log_file=/tmp/grub-install.log.$$
-+img_file=/tmp/grub-install.img.$$
-+rootdir=
-+grub_prefix=/boot/grub
-+
-+install_device=
-+no_floppy=
-+force_lba=
-+recheck=no
-+debug=no
-+
-+# look for secure tempfile creation wrappers on this platform
-+if test -x /bin/tempfile; then
-+ mklog="/bin/tempfile --prefix=grub"
-+ mkimg="/bin/tempfile --prefix=grub"
-+elif test -x /bin/mktemp; then
-+ mklog="/bin/mktemp /tmp/grub-install.log.XXXXXX"
-+ mkimg="/bin/mktemp /tmp/grub-install.img.XXXXXX"
-+else
-+ mklog=""
-+ mkimg=""
-+fi
-+
-+# Usage: usage
-+# Print the usage.
-+usage () {
-+ cat <<EOF
-+Usage: grub-install [OPTION] install_device
-+Install GRUB on your drive.
-+
-+ -h, --help print this message and exit
-+ -v, --version print the version information and exit
-+ --root-directory=DIR install GRUB images under the directory DIR
-+ instead of the root directory
-+ --grub-shell=FILE use FILE as the grub shell
-+ --no-floppy do not probe any floppy drive
-+ --force-lba force GRUB to use LBA mode even for a buggy
-+ BIOS
-+ --recheck probe a device map even if it already exists
-+
-+INSTALL_DEVICE can be a GRUB device name or a system device filename.
-+
-+grub-install copies GRUB images into the DIR/boot directory specfied by
-+--root-directory, and uses the grub shell to install grub into the boot
-+sector.
-+
-+Report bugs to <bug-grub@gnu.org>.
-+EOF
-+}
-+
-+# Usage: convert os_device
-+# Convert an OS device to the corresponding GRUB drive.
-+# This part is OS-specific.
-+convert () {
-+ # First, check if the device file exists.
-+ if test -e "$1"; then
-+ :
-+ else
-+ echo "$1: Not found or not a block device." 1>&2
-+ exit 1
-+ fi
-+
-+ # Break the device name into the disk part and the partition part.
-+ case "$host_os" in
-+ linux*)
-+ tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
-+ -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
-+ -e 's%\(fd[0-9]*\)$%\1%' \
-+ -e 's%/part[0-9]*$%/disc%' \
-+ -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
-+ tmp_part=`echo "$1" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
-+ -e 's%.*d[0-9]*p%%' \
-+ -e 's%.*/fd[0-9]*$%%' \
-+ -e 's%.*/floppy/[0-9]*$%%' \
-+ -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
-+ -e 's%.*c[0-7]d[0-9]*p%%'`
-+ ;;
-+ gnu*)
-+ tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
-+ tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;;
-+ freebsd* | kfreebsd*-gnu)
-+ tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%r\1%' \
-+ | sed 's%r\{0,1\}\(da[0-9]*\).*$%r\1%'`
-+ tmp_part=`echo "$1" \
-+ | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
-+ | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
-+ ;;
-+ netbsd* | knetbsd*-gnu)
-+ tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([sw]d[0-9]*\).*$%r\1d%' \
-+ | sed 's%r\{0,1\}\(fd[0-9]*\).*$%r\1a%'`
-+ tmp_part=`echo "$1" \
-+ | sed "s%.*/r\{0,1\}[sw]d[0-9]\([abe-p]\)%\1%"`
-+ ;;
-+ *)
-+ echo "grub-install does not support your OS yet." 1>&2
-+ exit 1 ;;
-+ esac
-+
-+ # Get the drive name.
-+ tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \
-+ | sed 's%.*\(([hf]d[0-9][a-g0-9,]*)\).*%\1%'`
-+
-+ # If not found, print an error message and exit.
-+ if test "x$tmp_drive" = x; then
-+ echo "$1 does not have any corresponding BIOS drive." 1>&2
-+ exit 1
-+ fi
-+
-+ if test "x$tmp_part" != x; then
-+ # If a partition is specified, we need to translate it into the
-+ # GRUB's syntax.
-+ case "$host_os" in
-+ linux*)
-+ echo "$tmp_drive" | sed "s%)$%,`expr $tmp_part - 1`)%" ;;
-+ gnu*)
-+ if echo $tmp_part | grep "^s" >/dev/null; then
-+ tmp_pc_slice=`echo $tmp_part \
-+ | sed "s%s\([0-9]*\)[a-g]*$%\1%"`
-+ tmp_drive=`echo "$tmp_drive" \
-+ | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
-+ fi
-+ if echo $tmp_part | grep "[a-g]$" >/dev/null; then
-+ tmp_bsd_partition=`echo "$tmp_part" \
-+ | sed "s%[^a-g]*\([a-g]\)$%\1%"`
-+ tmp_drive=`echo "$tmp_drive" \
-+ | sed "s%)%,$tmp_bsd_partition)%"`
-+ fi
-+ echo "$tmp_drive" ;;
-+ freebsd* | kfreebsd*-gnu)
-+ if echo $tmp_part | grep "^s" >/dev/null; then
-+ tmp_pc_slice=`echo $tmp_part \
-+ | sed "s%s\([0-9]*\)[a-h]*$%\1%"`
-+ tmp_drive=`echo "$tmp_drive" \
-+ | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
-+ fi
-+ if echo $tmp_part | grep "[a-h]$" >/dev/null; then
-+ tmp_bsd_partition=`echo "$tmp_part" \
-+ | sed "s%s\{0,1\}[0-9]*\([a-h]\)$%\1%"`
-+ tmp_drive=`echo "$tmp_drive" \
-+ | sed "s%)%,$tmp_bsd_partition)%"`
-+ fi
-+ echo "$tmp_drive" ;;
-+ netbsd* | knetbsd*-gnu)
-+ if echo $tmp_part | grep "^[abe-p]$" >/dev/null; then
-+ tmp_bsd_partition=`echo "$tmp_part" \
-+ | sed "s%\([a-p]\)$%\1%"`
-+ tmp_drive=`echo "$tmp_drive" \
-+ | sed "s%)%,$tmp_bsd_partition)%"`
-+ fi
-+ echo "$tmp_drive" ;;
-+ esac
-+ else
-+ # If no partition is specified, just print the drive name.
-+ echo "$tmp_drive"
-+ fi
-+}
-+
-+# Usage: resolve_symlink file
-+# Find the real file/device that file points at
-+resolve_symlink () {
-+ tmp_fname=$1
-+ # Resolve symlinks
-+ while test -L $tmp_fname; do
-+ tmp_new_fname=`ls -al $tmp_fname | sed -n 's%.*-> \(.*\)%\1%p'`
-+ if test -z "$tmp_new_fname"; then
-+ echo "Unrecognized ls output" 2>&1
-+ exit 1
-+ fi
-+
-+ # Convert relative symlinks
-+ case $tmp_new_fname in
-+ /*) tmp_fname="$tmp_new_fname"
-+ ;;
-+ *) tmp_fname="`echo $tmp_fname | sed 's%/[^/]*$%%'`/$tmp_new_fname"
-+ ;;
-+ esac
-+ done
-+ echo "$tmp_fname"
-+}
-+
-+# Usage: find_device file
-+# Find block device on which the file resides.
-+find_device () {
-+ # For now, this uses the program `df' to get the device name, but is
-+ # this really portable?
-+ tmp_fname=`df $1/ | sed -n 's%.*\(/dev/[^ ]*\).*%\1%p'`
-+
-+ if test -z "$tmp_fname"; then
-+ echo "Could not find device for $1" 2>&1
-+ exit 1
-+ fi
-+
-+ tmp_fname=`resolve_symlink $tmp_fname`
-+
-+ echo "$tmp_fname"
-+}
-+
-+# Check the arguments.
-+for option in "$@"; do
-+ case "$option" in
-+ -h | --help)
-+ usage
-+ exit 0 ;;
-+ -v | --version)
-+ echo "grub-install (GNU GRUB ${VERSION})"
-+ exit 0 ;;
-+ --root-directory=*)
-+ rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
-+ --grub-shell=*)
-+ grub_shell=`echo "$option" | sed 's/--grub-shell=//'` ;;
-+ --no-floppy)
-+ no_floppy="--no-floppy" ;;
-+ --force-lba)
-+ force_lba="--force-lba" ;;
-+ --recheck)
-+ recheck=yes ;;
-+ # This is an undocumented feature...
-+ --debug)
-+ debug=yes ;;
-+ -*)
-+ echo "Unrecognized option \`$option'" 1>&2
-+ usage
-+ exit 1
-+ ;;
-+ *)
-+ if test "x$install_device" != x; then
-+ echo "More than one install_devices?" 1>&2
-+ usage
-+ exit 1
-+ fi
-+ install_device="${option}" ;;
-+ esac
-+done
-+
-+if test "x$install_device" = x; then
-+ echo "install_device not specified." 1>&2
-+ usage
-+ exit 1
-+fi
-+
-+# If the debugging feature is enabled, print commands.
-+if test $debug = yes; then
-+ set -x
-+fi
-+
-+# Initialize these directories here, since ROOTDIR was initialized.
-+case "$host_os" in
-+netbsd* | openbsd*)
-+ # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub
-+ # instead of /boot/grub.
-+ grub_prefix=/grub
-+ bootdir=${rootdir}
-+ ;;
-+*)
-+ # Use /boot/grub by default.
-+ bootdir=${rootdir}/boot
-+ ;;
-+esac
-+
-+grubdir=${bootdir}/grub
-+device_map=${grubdir}/device.map
-+
-+# Check if GRUB is installed.
-+# This is necessary, because the user can specify "grub --read-only".
-+set $grub_shell dummy
-+if test -f "$1"; then
-+ :
-+else
-+ echo "$1: Not found." 1>&2
-+ exit 1
-+fi
-+
-+if test -f "$pkglibdir/stage1"; then
-+ :
-+else
-+ echo "${pkglibdir}/stage1: Not found." 1>&2
-+ exit 1
-+fi
-+
-+if test -f "$pkglibdir/stage2"; then
-+ :
-+else
-+ echo "${pkglibdir}/stage2: Not found." 1>&2
-+ exit 1
-+fi
-+
-+# Don't check for *stage1_5, because it is not fatal even if any
-+# Stage 1.5 does not exist.
-+
-+# Create the GRUB directory if it is not present.
-+test -d "$bootdir" || mkdir "$bootdir" || exit 1
-+test -d "$grubdir" || mkdir "$grubdir" || exit 1
-+
-+# If --recheck is specified, remove the device map, if present.
-+if test $recheck = yes; then
-+ rm -f $device_map
-+fi
-+
-+# Create the device map file if it is not present.
-+if test -f "$device_map"; then
-+ :
-+else
-+ # Create a safe temporary file.
-+ test -n "$mklog" && log_file=`$mklog`
-+
-+ $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
-+quit
-+EOF
-+ if grep "Error [0-9]*: " $log_file >/dev/null; then
-+ cat $log_file 1>&2
-+ exit 1
-+ fi
-+
-+ rm -f $log_file
-+fi
-+
-+# Make sure that there is no duplicated entry.
-+tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
-+ | sort | uniq -d | sed -n 1p`
-+if test -n "$tmp"; then
-+ echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
-+ exit 1
-+fi
-+
-+# Check for INSTALL_DEVICE.
-+case "$install_device" in
-+/dev/*)
-+ install_device=`resolve_symlink "$install_device"`
-+ install_drive=`convert "$install_device"`
-+ # I don't know why, but some shells wouldn't die if exit is
-+ # called in a function.
-+ if test "x$install_drive" = x; then
-+ exit 1
-+ fi ;;
-+\([hf]d[0-9]*\))
-+ install_drive="$install_device" ;;
-+[hf]d[0-9]*)
-+ # The GRUB format with no parenthesis.
-+ install_drive="($install_device)" ;;
-+*)
-+ echo "Format of install_device not recognized." 1>&2
-+ usage
-+ exit 1 ;;
-+esac
-+
-+# Get the root drive.
-+root_device=`find_device ${rootdir}`
-+bootdir_device=`find_device ${bootdir}`
-+
-+# Check if the boot directory is in the same device as the root directory.
-+if test "x$root_device" != "x$bootdir_device"; then
-+ # Perhaps the user has a separate boot partition.
-+ root_device=$bootdir_device
-+ grub_prefix="/grub"
-+fi
-+
-+# Convert the root device to a GRUB drive.
-+root_drive=`convert "$root_device"`
-+if test "x$root_drive" = x; then
-+ exit 1
-+fi
-+
-+# Check if the root directory exists in the same device as the grub
-+# directory.
-+grubdir_device=`find_device ${grubdir}`
-+
-+if test "x$grubdir_device" != "x$root_device"; then
-+ # For now, cannot deal with this situation.
-+ cat <<EOF 1>&2
-+You must set the root directory by the option --root-directory, because
-+$grubdir does not exist in the root device $root_device.
-+EOF
-+ exit 1
-+fi
-+
-+# Copy the GRUB images to the GRUB directory.
-+for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
-+ rm -f $file || exit 1
-+done
-+for file in \
-+ ${pkglibdir}/stage1 ${pkglibdir}/stage2 ${pkglibdir}/*stage1_5; do
-+ cp -f $file ${grubdir} || exit 1
-+done
-+
-+# Make a default file.
-+${grub_set_default} --root-directory=${rootdir} default
-+
-+# Make sure that GRUB reads the same images as the host OS.
-+test -n "$mkimg" && img_file=`$mkimg`
-+test -n "$mklog" && log_file=`$mklog`
-+
-+for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
-+ count=5
-+ tmp=`echo $file | sed "s|^${grubdir}|${grub_prefix}|"`
-+ while test $count -gt 0; do
-+ $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
-+dump ${root_drive}${tmp} ${img_file}
-+quit
-+EOF
-+ if grep "Error [0-9]*: " $log_file >/dev/null; then
-+ :
-+ elif cmp $file $img_file >/dev/null; then
-+ break
-+ fi
-+ sleep 1
-+ count=`expr $count - 1`
-+ done
-+ if test $count -eq 0; then
-+ echo "The file $file not read correctly." 1>&2
-+ exit 1
-+ fi
-+done
-+
-+rm -f $img_file
-+rm -f $log_file
-+
-+# Create a safe temporary file.
-+test -n "$mklog" && log_file=`$mklog`
-+
-+# Now perform the installation.
-+$grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
-+root $root_drive
-+setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $install_drive
-+quit
-+EOF
-+
-+if grep "Error [0-9]*: " $log_file >/dev/null || test $debug = yes; then
-+ cat $log_file 1>&2
-+ exit 1
-+fi
-+
-+rm -f $log_file
-+
-+# Prompt the user to check if the device map is correct.
-+echo "Installation finished. No error reported."
-+echo "This is the contents of the device map $device_map."
-+echo "Check if this is correct or not. If any of the lines is incorrect,"
-+echo "fix it and re-run the script \`grub-install'."
-+echo
-+
-+cat $device_map
-+
-+# Bye.
-+exit 0
-diff -Nur grub-0.97/util/mkbimage grub-0.97-patched/util/mkbimage
---- grub-0.97/util/mkbimage 2004-07-24 20:57:31.000000000 +0200
-+++ grub-0.97-patched/util/mkbimage 2012-11-11 17:07:12.744730138 +0100
-@@ -1,7 +1,7 @@
- #!/bin/sh
- # MaKe a Bootable IMAGE --- 1.44, 2.88 and El Torito no-emulation mode
- # C) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>
--# C) 2001,2002,2003 Robert Millan <robertmh@gnu.org>
-+# C) 2001,2002,2003 Robert Millan <rmh@aybabtu.com>
-
-
- # This program is free software; you can redistribute it and/or modify
-@@ -94,15 +94,13 @@
- display Version information and exit
-
- Copyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
--Copyright (c) 2001,2002 Robert Millan <zeratul2@wanadoo.es>.
- GPLed."
-
- version="mkbimage $version_number
-
--Written by Thierry Laronde and Robert Millan.
-+Written by Thierry Laronde.
-
- Copyright (c) 2001,2002,2003 Thierry Laronde <tlaronde@polynum.org>.
--Copyright (c) 2001,2002,2003 Robert Millan <zeratul2@wanadoo.es>.
-
- This is free software under the GPL version 2 or later; see the source for
- copying conditions. There is NO warranty, not even for MERCHANTABILITY or