Jan Beulich
2007-Jun-19 09:50 UTC
[Xen-devel] [PATCH] add hypercall function for retrieving EDD info
Signed-off-by: Jan Beulich <jbeulich@novell.com> Index: 2007-06-18/xen/arch/x86/boot/edd.S ==================================================================--- 2007-06-18.orig/xen/arch/x86/boot/edd.S 2007-06-18 11:10:07.000000000 +0200 +++ 2007-06-18/xen/arch/x86/boot/edd.S 2007-06-18 11:10:37.000000000 +0200 @@ -16,17 +16,13 @@ * Updated and ported for Xen by Keir Fraser <keir@xensource.com> June 2007 */ +#include <asm/edd.h> + .code16 /* Offset of disc signature in the MBR. */ #define EDD_MBR_SIG_OFFSET 0x1B8 -/* Maximum number of EDD information structures at boot_edd_info. */ -#define EDD_INFO_MAX 6 - -/* Maximum number of MBR signatures at boot_edd_signature. */ -#define EDD_MBR_SIG_MAX 16 - /* Size of components of EDD information structure. */ #define EDDEXTSIZE 8 #define EDDPARMSIZE 74 @@ -151,6 +147,7 @@ opt_edd: .byte 0 # edd=on/off/skipmbr .globl boot_edd_info_nr, boot_edd_signature_nr +.globl boot_edd_info, boot_edd_signature boot_edd_info_nr: .byte 0 boot_edd_signature_nr: Index: 2007-06-18/xen/arch/x86/platform_hypercall.c ==================================================================--- 2007-06-18.orig/xen/arch/x86/platform_hypercall.c 2007-06-18 11:10:07.000000000 +0200 +++ 2007-06-18/xen/arch/x86/platform_hypercall.c 2007-06-18 11:05:17.000000000 +0200 @@ -20,14 +20,28 @@ #include <xen/guest_access.h> #include <asm/current.h> #include <public/platform.h> +#include <asm/edd.h> #include <asm/mtrr.h> #include "cpu/mtrr/mtrr.h" +struct edd { + unsigned int mbr_signature[EDD_MBR_SIG_MAX]; + struct edd_info edd_info[EDD_INFO_MAX]; + unsigned char mbr_signature_nr; + unsigned char edd_info_nr; +}; + #ifndef COMPAT typedef long ret_t; DEFINE_SPINLOCK(xenpf_lock); +struct edd edd; +# undef copy_from_compat +# define copy_from_compat copy_from_guest +# undef copy_to_compat +# define copy_to_compat copy_to_guest #else extern spinlock_t xenpf_lock; +extern struct edd edd; #endif ret_t do_platform_op(XEN_GUEST_HANDLE(xen_platform_op_t) u_xenpf_op) @@ -151,6 +165,73 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe } break; + case XENPF_firmware_info: + switch ( op->u.firmware_info.type ) + { + case XEN_FW_DISK_INFO: + if ( op->u.firmware_info.index < edd.edd_info_nr ) + { + const struct edd_info *info = edd.edd_info + op->u.firmware_info.index; + + op->u.firmware_info.u.disk_info.max_cylinder = info->legacy_max_cylinder; + op->u.firmware_info.u.disk_info.max_head = info->legacy_max_head; + op->u.firmware_info.u.disk_info.sectors_per_track = info->legacy_sectors_per_track; + if ( copy_field_to_guest(u_xenpf_op, op, u.firmware_info.u.disk_info) ) + ret = -EFAULT; + } + else + ret = -ESRCH; + break; + case XEN_FW_EDD_INFO: + if ( op->u.firmware_info.index < edd.edd_info_nr ) + { + const struct edd_info *info = edd.edd_info + op->u.firmware_info.index; + + op->u.firmware_info.u.edd_info.device = info->device; + op->u.firmware_info.u.edd_info.version = info->version; + op->u.firmware_info.u.edd_info.interface = info->interface_support; + if ( copy_field_to_guest(u_xenpf_op, op, u.firmware_info.u.edd_info) ) + ret = -EFAULT; + } + else + ret = -ESRCH; + break; + case XEN_FW_EDD_PARAMS: + if ( op->u.firmware_info.index < edd.edd_info_nr ) + { + u16 length; + + if ( copy_from_compat(&length, op->u.firmware_info.u.edd_params, 1) == 0 ) + { + if ( length > edd.edd_info[op->u.firmware_info.index].params.length ) + length = edd.edd_info[op->u.firmware_info.index].params.length; + if ( copy_to_compat(op->u.firmware_info.u.edd_params, + (u8*)&edd.edd_info[op->u.firmware_info.index].params, + length) ) + ret = -EFAULT; + } + else + ret = -EFAULT; + } + else + ret = -ESRCH; + break; + case XEN_FW_MBR_SIGNATURE: + if ( op->u.firmware_info.index < edd.mbr_signature_nr ) + { + op->u.firmware_info.u.mbr_signature = edd.mbr_signature[op->u.firmware_info.index]; + if ( copy_field_to_guest(u_xenpf_op, op, u.firmware_info.u.mbr_signature) ) + ret = -EFAULT; + } + else + ret = -ESRCH; + break; + default: + ret = -EINVAL; + break; + } + break; + default: ret = -ENOSYS; break; @@ -161,6 +242,19 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe return ret; } +#ifndef COMPAT +static int __init firmware_init(void) +{ + memcpy(edd.mbr_signature, bootsym(boot_edd_signature), sizeof(edd.mbr_signature)); + memcpy(edd.edd_info, bootsym(boot_edd_info), sizeof(edd.edd_info)); + edd.mbr_signature_nr = bootsym(boot_edd_signature_nr); + edd.edd_info_nr = bootsym(boot_edd_info_nr); + + return 0; +} +__initcall(firmware_init); +#endif + /* * Local variables: * mode: C Index: 2007-06-18/xen/include/asm-x86/edd.h ==================================================================--- 2007-06-18.orig/xen/include/asm-x86/edd.h 2007-06-18 11:10:07.000000000 +0200 +++ 2007-06-18/xen/include/asm-x86/edd.h 2007-06-18 11:01:50.000000000 +0200 @@ -23,6 +23,109 @@ #ifndef __XEN_EDD_H__ #define __XEN_EDD_H__ +#ifndef __ASSEMBLY__ + +struct edd_device_params { + u16 length; + u16 info_flags; + u32 num_default_cylinders; + u32 num_default_heads; + u32 sectors_per_track; + u64 number_of_sectors; + u16 bytes_per_sector; + u32 dpte_ptr; /* 0xFFFFFFFF for our purposes */ + u16 key; /* = 0xBEDD */ + u8 device_path_info_length; /* = 44 */ + u8 reserved2; + u16 reserved3; + u8 host_bus_type[4]; + u8 interface_type[8]; + union { + struct { + u16 base_address; + u16 reserved1; + u32 reserved2; + } __attribute__ ((packed)) isa; + struct { + u8 bus; + u8 slot; + u8 function; + u8 channel; + u32 reserved; + } __attribute__ ((packed)) pci; + /* pcix is same as pci */ + struct { + u64 reserved; + } __attribute__ ((packed)) ibnd; + struct { + u64 reserved; + } __attribute__ ((packed)) xprs; + struct { + u64 reserved; + } __attribute__ ((packed)) htpt; + struct { + u64 reserved; + } __attribute__ ((packed)) unknown; + } interface_path; + union { + struct { + u8 device; + u8 reserved1; + u16 reserved2; + u32 reserved3; + u64 reserved4; + } __attribute__ ((packed)) ata; + struct { + u8 device; + u8 lun; + u8 reserved1; + u8 reserved2; + u32 reserved3; + u64 reserved4; + } __attribute__ ((packed)) atapi; + struct { + u16 id; + u64 lun; + u16 reserved1; + u32 reserved2; + } __attribute__ ((packed)) scsi; + struct { + u64 serial_number; + u64 reserved; + } __attribute__ ((packed)) usb; + struct { + u64 eui; + u64 reserved; + } __attribute__ ((packed)) i1394; + struct { + u64 wwid; + u64 lun; + } __attribute__ ((packed)) fibre; + struct { + u64 identity_tag; + u64 reserved; + } __attribute__ ((packed)) i2o; + struct { + u32 array_number; + u32 reserved1; + u64 reserved2; + } __attribute__ ((packed)) raid; + struct { + u8 device; + u8 reserved1; + u16 reserved2; + u32 reserved3; + u64 reserved4; + } __attribute__ ((packed)) sata; + struct { + u64 reserved1; + u64 reserved2; + } __attribute__ ((packed)) unknown; + } device_path; + u8 reserved4; + u8 checksum; +} __attribute__ ((packed)); + struct edd_info { /* Int13, Fn48: Check Extensions Present. */ u8 device; /* %dl: device */ @@ -33,12 +136,24 @@ struct edd_info { u8 legacy_max_head; /* %dh: maximum head number */ u8 legacy_sectors_per_track; /* %cl[5:0]: maximum sector number */ /* Int13, Fn41: Get Device Parameters */ - u8 edd_device_params[74]; /* as filled into %ds:%si */ + struct edd_device_params params; /* as filled into %ds:%si */ } __attribute__ ((packed)); -extern u32 boot_edd_signature[]; +#endif + +/* Maximum number of MBR signatures at boot_edd_signature. */ +#define EDD_MBR_SIG_MAX 16 + +/* Maximum number of EDD information structures at boot_edd_info. */ +#define EDD_INFO_MAX 6 + +#ifndef __ASSEMBLY__ + +extern u32 boot_edd_signature[EDD_MBR_SIG_MAX]; extern u8 boot_edd_signature_nr; -extern struct edd_info boot_edd_info[]; +extern struct edd_info boot_edd_info[EDD_INFO_MAX]; extern u8 boot_edd_info_nr; +#endif + #endif /* __XEN_EDD_H__ */ Index: 2007-06-18/xen/include/public/platform.h ==================================================================--- 2007-06-18.orig/xen/include/public/platform.h 2007-06-18 11:10:07.000000000 +0200 +++ 2007-06-18/xen/include/public/platform.h 2007-06-18 11:05:17.000000000 +0200 @@ -114,6 +114,35 @@ struct xenpf_platform_quirk { typedef struct xenpf_platform_quirk xenpf_platform_quirk_t; DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t); +#define XENPF_firmware_info 50 +#define XEN_FW_DISK_INFO 1 /* from int 13 AH=08 */ +#define XEN_FW_EDD_INFO 2 /* from int 13 AH=41 */ +#define XEN_FW_EDD_PARAMS 3 /* from int 13 AH=48 */ +#define XEN_FW_MBR_SIGNATURE 4 +struct xenpf_firmware_info { + /* IN variables. */ + uint32_t type; + uint32_t index; + /* OUT variables. */ + union { + struct { + uint16_t max_cylinder; + uint8_t max_head; + uint8_t sectors_per_track; + } disk_info; + struct { + uint8_t device; + uint8_t version; + uint16_t interface; + } edd_info; + /* first uint16_t of buffer must be set to buffer size */ + XEN_GUEST_HANDLE(void) edd_params; + uint32_t mbr_signature; + } u; +}; +typedef struct xenpf_firmware_info xenpf_firmware_info_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t); + struct xen_platform_op { uint32_t cmd; uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ @@ -124,6 +153,7 @@ struct xen_platform_op { struct xenpf_read_memtype read_memtype; struct xenpf_microcode_update microcode; struct xenpf_platform_quirk platform_quirk; + struct xenpf_firmware_info firmware_info; uint8_t pad[128]; } u; }; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel