Commit e100952f authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] EDD: read disk80 MBR signature, export through edd module

From: Matt Domsch <Matt_Domsch@dell.com>


There are 4 bytes in the MSDOS master boot record, at offset 0x1b8,
which may contain a per-system-unique signature.  By first writing a unique
signature to each disk in the system, then rebooting, and then reading the
MBR to get the signature for the boot disk (int13 dev 80h), userspace may
use it to compare against disks it knows as named /dev/[hs]d[a-z], and thus
determine which disk is the BIOS boot disk, thus where the /boot, / and
boot loaders should be placed.

This is useful in the case where the BIOS is not EDD3.0 compliant, thus
doesn't provide the PCI bus/dev/fn and IDE/SCSI location of the boot disk,
yet you need to know which disk is the boot disk.  It's most useful in OS
installers.

This patch retrieves the signature from the disk in setup.S, stores it in a
space reserved in the empty_zero_page, copies it somewhere safe in setup.c,
and exports it via /sys/firmware/edd/int13_disk80/mbr_signature in edd.c.
Code is covered under CONFIG_EDD=[ym].
parent e086c192
...@@ -72,8 +72,10 @@ Offset Type Description ...@@ -72,8 +72,10 @@ Offset Type Description
0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image 0x21c unsigned long INITRD_SIZE, size in bytes of ramdisk image
0x220 4 bytes (setup.S) 0x220 4 bytes (setup.S)
0x224 unsigned short setup.S heap end pointer 0x224 unsigned short setup.S heap end pointer
0x2cc 4 bytes DISK80_SIG_BUFFER (setup.S)
0x2d0 - 0x600 E820MAP 0x2d0 - 0x600 E820MAP
0x600 - 0x7D4 EDDBUF (setup.S) 0x600 - 0x7ff EDDBUF (setup.S) for disk signature read sector
0x600 - 0x7d3 EDDBUF (setup.S) for edd data
0x800 string, 2K max COMMAND_LINE, the kernel commandline as 0x800 string, 2K max COMMAND_LINE, the kernel commandline as
copied using CL_OFFSET. copied using CL_OFFSET.
......
...@@ -49,6 +49,8 @@ ...@@ -49,6 +49,8 @@
* by Matt Domsch <Matt_Domsch@dell.com> October 2002 * by Matt Domsch <Matt_Domsch@dell.com> October 2002
* conformant to T13 Committee www.t13.org * conformant to T13 Committee www.t13.org
* projects 1572D, 1484D, 1386D, 1226DT * projects 1572D, 1484D, 1386D, 1226DT
* disk signature read by Matt Domsch <Matt_Domsch@dell.com>
* and Andrew Wilks <Andrew_Wilks@dell.com> September 2003
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -578,6 +580,25 @@ done_apm_bios: ...@@ -578,6 +580,25 @@ done_apm_bios:
#endif #endif
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
# Read the first sector of device 80h and store the 4-byte signature
movl $0xFFFFFFFF, %eax
movl %eax, (DISK80_SIG_BUFFER) # assume failure
movb $READ_SECTORS, %ah
movb $1, %al # read 1 sector
movb $0x80, %dl # from device 80
movb $0, %dh # at head 0
movw $1, %cx # cylinder 0, sector 0
pushw %es
pushw %ds
popw %es
movw $EDDBUF, %bx
int $0x13
jc disk_sig_done
movl (EDDBUF+MBR_SIG_OFFSET), %eax
movl %eax, (DISK80_SIG_BUFFER) # store success
disk_sig_done:
popw %es
# Do the BIOS Enhanced Disk Drive calls # Do the BIOS Enhanced Disk Drive calls
# This consists of two calls: # This consists of two calls:
# int 13h ah=41h "Check Extensions Present" # int 13h ah=41h "Check Extensions Present"
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* linux/arch/i386/kernel/edd.c * linux/arch/i386/kernel/edd.c
* Copyright (C) 2002, 2003 Dell Inc. * Copyright (C) 2002, 2003 Dell Inc.
* by Matt Domsch <Matt_Domsch@dell.com> * by Matt Domsch <Matt_Domsch@dell.com>
* disk80 signature by Matt Domsch, Andrew Wilks, and Sandeep K. Shandilya
* *
* BIOS Enhanced Disk Drive Services (EDD) * BIOS Enhanced Disk Drive Services (EDD)
* conformant to T13 Committee www.t13.org * conformant to T13 Committee www.t13.org
...@@ -59,9 +60,9 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); ...@@ -59,9 +60,9 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
MODULE_DESCRIPTION("sysfs interface to BIOS EDD information"); MODULE_DESCRIPTION("sysfs interface to BIOS EDD information");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#define EDD_VERSION "0.10 2003-Oct-11" #define EDD_VERSION "0.12 2004-Jan-26"
#define EDD_DEVICE_NAME_SIZE 16 #define EDD_DEVICE_NAME_SIZE 16
#define REPORT_URL "http://domsch.com/linux/edd30/results.html" #define REPORT_URL "http://linux.dell.com/edd/results.html"
#define left (PAGE_SIZE - (p - buf) - 1) #define left (PAGE_SIZE - (p - buf) - 1)
...@@ -259,6 +260,14 @@ edd_show_version(struct edd_device *edev, char *buf) ...@@ -259,6 +260,14 @@ edd_show_version(struct edd_device *edev, char *buf)
return (p - buf); return (p - buf);
} }
static ssize_t
edd_show_disk80_sig(struct edd_device *edev, char *buf)
{
char *p = buf;
p += snprintf(p, left, "0x%08x\n", edd_disk80_sig);
return (p - buf);
}
static ssize_t static ssize_t
edd_show_extensions(struct edd_device *edev, char *buf) edd_show_extensions(struct edd_device *edev, char *buf)
{ {
...@@ -429,6 +438,15 @@ edd_has_edd30(struct edd_device *edev) ...@@ -429,6 +438,15 @@ edd_has_edd30(struct edd_device *edev)
return 1; return 1;
} }
static int
edd_has_disk80_sig(struct edd_device *edev)
{
struct edd_info *info = edd_dev_get_info(edev);
if (!edev || !info)
return 0;
return info->device == 0x80;
}
static EDD_DEVICE_ATTR(raw_data, 0444, edd_show_raw_data, NULL); static EDD_DEVICE_ATTR(raw_data, 0444, edd_show_raw_data, NULL);
static EDD_DEVICE_ATTR(version, 0444, edd_show_version, NULL); static EDD_DEVICE_ATTR(version, 0444, edd_show_version, NULL);
static EDD_DEVICE_ATTR(extensions, 0444, edd_show_extensions, NULL); static EDD_DEVICE_ATTR(extensions, 0444, edd_show_extensions, NULL);
...@@ -443,6 +461,7 @@ static EDD_DEVICE_ATTR(default_sectors_per_track, 0444, ...@@ -443,6 +461,7 @@ static EDD_DEVICE_ATTR(default_sectors_per_track, 0444,
edd_has_default_sectors_per_track); edd_has_default_sectors_per_track);
static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30); static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30);
static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30); static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30);
static EDD_DEVICE_ATTR(mbr_signature, 0444, edd_show_disk80_sig, edd_has_disk80_sig);
/* These are default attributes that are added for every edd /* These are default attributes that are added for every edd
...@@ -464,6 +483,7 @@ static struct edd_attribute * edd_attrs[] = { ...@@ -464,6 +483,7 @@ static struct edd_attribute * edd_attrs[] = {
&edd_attr_default_sectors_per_track, &edd_attr_default_sectors_per_track,
&edd_attr_interface, &edd_attr_interface,
&edd_attr_host_bus, &edd_attr_host_bus,
&edd_attr_mbr_signature,
NULL, NULL,
}; };
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/edd.h>
#include <asm/ist.h> #include <asm/ist.h>
extern void dump_thread(struct pt_regs *, struct user *); extern void dump_thread(struct pt_regs *, struct user *);
...@@ -203,11 +202,6 @@ EXPORT_SYMBOL(kunmap_atomic); ...@@ -203,11 +202,6 @@ EXPORT_SYMBOL(kunmap_atomic);
EXPORT_SYMBOL(kmap_atomic_to_page); EXPORT_SYMBOL(kmap_atomic_to_page);
#endif #endif
#ifdef CONFIG_EDD_MODULE
EXPORT_SYMBOL(edd);
EXPORT_SYMBOL(eddnr);
#endif
#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) #if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
EXPORT_SYMBOL(ist_info); EXPORT_SYMBOL(ist_info);
#endif #endif
......
...@@ -444,6 +444,12 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) ...@@ -444,6 +444,12 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
unsigned char eddnr; unsigned char eddnr;
struct edd_info edd[EDDMAXNR]; struct edd_info edd[EDDMAXNR];
unsigned int edd_disk80_sig;
#ifdef CONFIG_EDD_MODULE
EXPORT_SYMBOL(eddnr);
EXPORT_SYMBOL(edd);
EXPORT_SYMBOL(edd_disk80_sig);
#endif
/** /**
* copy_edd() - Copy the BIOS EDD information * copy_edd() - Copy the BIOS EDD information
* from empty_zero_page into a safe place. * from empty_zero_page into a safe place.
...@@ -453,6 +459,7 @@ static inline void copy_edd(void) ...@@ -453,6 +459,7 @@ static inline void copy_edd(void)
{ {
eddnr = EDD_NR; eddnr = EDD_NR;
memcpy(edd, EDD_BUF, sizeof(edd)); memcpy(edd, EDD_BUF, sizeof(edd));
edd_disk80_sig = DISK80_SIGNATURE;
} }
#else #else
#define copy_edd() do {} while (0) #define copy_edd() do {} while (0)
......
/* /*
* linux/include/asm-i386/edd.h * linux/include/asm-i386/edd.h
* Copyright (C) 2002 Dell Inc. * Copyright (C) 2002, 2003 Dell Inc.
* by Matt Domsch <Matt_Domsch@dell.com> * by Matt Domsch <Matt_Domsch@dell.com>
* *
* structures and definitions for the int 13h, ax={41,48}h * structures and definitions for the int 13h, ax={41,48}h
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
#define EDDMAGIC1 0x55AA #define EDDMAGIC1 0x55AA
#define EDDMAGIC2 0xAA55 #define EDDMAGIC2 0xAA55
#define READ_SECTORS 0x02
#define MBR_SIG_OFFSET 0x1B8
#define DISK80_SIG_BUFFER 0x2cc
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#define EDD_EXT_FIXED_DISK_ACCESS (1 << 0) #define EDD_EXT_FIXED_DISK_ACCESS (1 << 0)
...@@ -167,6 +170,7 @@ struct edd_info { ...@@ -167,6 +170,7 @@ struct edd_info {
extern struct edd_info edd[EDDMAXNR]; extern struct edd_info edd[EDDMAXNR];
extern unsigned char eddnr; extern unsigned char eddnr;
extern unsigned int edd_disk80_sig;
#endif /*!__ASSEMBLY__ */ #endif /*!__ASSEMBLY__ */
#endif /* _ASM_I386_EDD_H */ #endif /* _ASM_I386_EDD_H */
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#define INITRD_START (*(unsigned long *) (PARAM+0x218)) #define INITRD_START (*(unsigned long *) (PARAM+0x218))
#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c)) #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
#define EDID_INFO (*(struct edid_info *) (PARAM+0x440)) #define EDID_INFO (*(struct edid_info *) (PARAM+0x440))
#define DISK80_SIGNATURE (*(unsigned int*) (PARAM+DISK80_SIG_BUFFER))
#define EDD_NR (*(unsigned char *) (PARAM+EDDNR)) #define EDD_NR (*(unsigned char *) (PARAM+EDDNR))
#define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF)) #define EDD_BUF ((struct edd_info *) (PARAM+EDDBUF))
#define COMMAND_LINE ((char *) (PARAM+2048)) #define COMMAND_LINE ((char *) (PARAM+2048))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment