From 614d99eba149d0fafc64dfdddc7ef04970e0d86c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 20 Apr 2021 13:28:57 +0100 Subject: [xen] Avoid infinite loop on allocation failure in xenstore_response() Signed-off-by: Michael Brown --- src/interface/xen/xenstore.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/interface') diff --git a/src/interface/xen/xenstore.c b/src/interface/xen/xenstore.c index a14881fcd..caeb4e934 100644 --- a/src/interface/xen/xenstore.c +++ b/src/interface/xen/xenstore.c @@ -68,14 +68,14 @@ static void xenstore_send ( struct xen_hypervisor *xen, const void *data, XENSTORE_RING_IDX cons; XENSTORE_RING_IDX idx; const char *bytes = data; - size_t offset = 0; + size_t offset; size_t fill; DBGCP ( intf, "XENSTORE raw request:\n" ); DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len ); /* Write one byte at a time */ - while ( offset < len ) { + for ( offset = 0 ; offset < len ; offset++ ) { /* Wait for space to become available */ while ( 1 ) { @@ -90,7 +90,7 @@ static void xenstore_send ( struct xen_hypervisor *xen, const void *data, /* Write byte */ idx = MASK_XENSTORE_IDX ( prod++ ); - writeb ( bytes[offset++], &intf->req[idx] ); + writeb ( bytes[offset], &intf->req[idx] ); } /* Update producer counter */ @@ -125,13 +125,13 @@ static void xenstore_recv ( struct xen_hypervisor *xen, void *data, XENSTORE_RING_IDX prod; XENSTORE_RING_IDX idx; char *bytes = data; - size_t offset = 0; + size_t offset; size_t fill; DBGCP ( intf, "XENSTORE raw response:\n" ); /* Read one byte at a time */ - while ( offset < len ) { + for ( offset = 0 ; offset < len ; offset++ ) { /* Wait for data to be ready */ while ( 1 ) { @@ -147,7 +147,7 @@ static void xenstore_recv ( struct xen_hypervisor *xen, void *data, /* Read byte */ idx = MASK_XENSTORE_IDX ( cons++ ); if ( data ) - bytes[offset++] = readb ( &intf->rsp[idx] ); + bytes[offset] = readb ( &intf->rsp[idx] ); } if ( data ) DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len ); -- cgit v1.2.3-55-g7522 From 3efdbef2f0dd956ce7d131ca4bdfd366f8cdc9d4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 20 Apr 2021 14:37:08 +0100 Subject: [efi] Always map full length of coherent DMA buffer allocation The EFI PCI API takes a page count as the input to AllocateBuffer() but a byte count as the input to Map(). There is nothing in the UEFI specification that requires us to map exactly the allocated length, and no systems have yet been observed that will fail if the map length does not exactly match the allocated length. However, it is plausible that some implementations may fail if asked to map a length that does not match the length of the corresponding allocation. Avoid potential future problems by always mapping the full allocated length. Signed-off-by: Michael Brown --- src/interface/efi/efi_pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/interface') diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c index 4adee0fd8..ef02c9c0e 100644 --- a/src/interface/efi/efi_pci.c +++ b/src/interface/efi/efi_pci.c @@ -523,7 +523,8 @@ static void * efipci_dma_alloc ( struct dma_device *dma, /* Map buffer */ if ( ( rc = efipci_dma_map ( dma, map, virt_to_phys ( addr ), - len, DMA_BI ) ) != 0 ) + ( pages * EFI_PAGE_SIZE ), + DMA_BI ) ) != 0 ) goto err_map; /* Increment allocation count (for debugging) */ -- cgit v1.2.3-55-g7522 From 56f7d44fde1d6ac196d115cc7dddd58e7ec098fa Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 21 Apr 2021 16:13:02 +0100 Subject: [efi] Show ACPI address space descriptor ranges in debug messages Signed-off-by: Michael Brown --- src/interface/efi/efi_pci.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/interface') diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c index ef02c9c0e..fda4aba0e 100644 --- a/src/interface/efi/efi_pci.c +++ b/src/interface/efi/efi_pci.c @@ -337,6 +337,9 @@ void * efipci_ioremap ( struct pci_device *pci, unsigned long bus_addr, offset = le64_to_cpu ( u.res->qword.offset ); start = ( offset + le64_to_cpu ( u.res->qword.min ) ); end = ( start + le64_to_cpu ( u.res->qword.len ) ); + DBGC2 ( pci, "EFIPCI " PCI_FMT " found range [%08llx,%08llx) " + "-> [%08llx,%08llx)\n", PCI_ARGS ( pci ), start, end, + ( start - offset ), ( end - offset ) ); if ( ( bus_addr < start ) || ( ( bus_addr + len ) > end ) ) continue; -- cgit v1.2.3-55-g7522 From ef9953b7122937dc12762e9f5ce797ba6859a24e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 18 May 2021 14:03:15 +0100 Subject: [efi] Allow for non-image-backed virtual files Restructure the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL implementation to allow for the existence of virtual files that are not simply backed by a single underlying image. Signed-off-by: Michael Brown --- src/interface/efi/efi_file.c | 290 +++++++++++++++++++++++++++++++++---------- 1 file changed, 221 insertions(+), 69 deletions(-) (limited to 'src/interface') diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c index 52de0987c..c67fdea54 100644 --- a/src/interface/efi/efi_file.c +++ b/src/interface/efi/efi_file.c @@ -50,18 +50,54 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** EFI media ID */ #define EFI_MEDIA_ID_MAGIC 0x69505845 -/** An image exposed as an EFI file */ +/** An EFI virtual file reader */ +struct efi_file_reader { + /** EFI file */ + struct efi_file *file; + /** Position within virtual file */ + size_t pos; + /** Output data buffer */ + void *data; + /** Length of output data buffer */ + size_t len; +}; + +/** An EFI file */ struct efi_file { + /** Reference count */ + struct refcnt refcnt; /** EFI file protocol */ EFI_FILE_PROTOCOL file; - /** Image */ + /** Image (if any) */ struct image *image; + /** Filename */ + const char *name; /** Current file position */ size_t pos; + /** + * Read from file + * + * @v reader File reader + * @ret len Length read + */ + size_t ( * read ) ( struct efi_file_reader *reader ); }; static struct efi_file efi_file_root; +/** + * Free EFI file + * + * @v refcnt Reference count + */ +static void efi_file_free ( struct refcnt *refcnt ) { + struct efi_file *file = + container_of ( refcnt, struct efi_file, refcnt ); + + image_put ( file->image ); + free ( file ); +} + /** * Get EFI file name (for debugging) * @@ -70,28 +106,140 @@ static struct efi_file efi_file_root; */ static const char * efi_file_name ( struct efi_file *file ) { - return ( file->image ? file->image->name : "" ); + return ( file == &efi_file_root ? "" : file->name ); } /** * Find EFI file image * - * @v wname Filename + * @v name Filename * @ret image Image, or NULL */ -static struct image * efi_file_find ( const CHAR16 *wname ) { - char name[ wcslen ( wname ) + 1 /* NUL */ ]; +static struct image * efi_file_find ( const char *name ) { struct image *image; /* Find image */ - snprintf ( name, sizeof ( name ), "%ls", wname ); list_for_each_entry ( image, &images, list ) { if ( strcasecmp ( image->name, name ) == 0 ) return image; } return NULL; +} + +/** + * Get length of EFI file + * + * @v file EFI file + * @ret len Length of file + */ +static size_t efi_file_len ( struct efi_file *file ) { + struct efi_file_reader reader; + + /* If this is the root directory, then treat as length zero */ + if ( ! file->read ) + return 0; + + /* Initialise reader */ + reader.file = file; + reader.pos = 0; + reader.data = NULL; + reader.len = 0; + + /* Perform dummy read to determine file length */ + file->read ( &reader ); + + return reader.pos; +} + +/** + * Read chunk of EFI file + * + * @v reader EFI file reader + * @v data Input data, or UNULL to zero-fill + * @v len Length of input data + * @ret len Length of output data + */ +static size_t efi_file_read_chunk ( struct efi_file_reader *reader, + userptr_t data, size_t len ) { + struct efi_file *file = reader->file; + size_t offset; + + /* Calculate offset into input data */ + offset = ( file->pos - reader->pos ); + + /* Consume input data range */ + reader->pos += len; + + /* Calculate output length */ + if ( offset < len ) { + len -= offset; + } else { + len = 0; + } + if ( len > reader->len ) + len = reader->len; + + /* Copy or zero output data */ + if ( data ) { + copy_from_user ( reader->data, data, offset, len ); + } else { + memset ( reader->data, 0, len ); + } + + /* Consume output buffer */ + file->pos += len; + reader->data += len; + reader->len -= len; + + return len; +} + +/** + * Read from image-backed file + * + * @v reader EFI file reader + * @ret len Length read + */ +static size_t efi_file_read_image ( struct efi_file_reader *reader ) { + struct efi_file *file = reader->file; + struct image *image = file->image; + + /* Read from file */ + return efi_file_read_chunk ( reader, image->data, image->len ); +} + +/** + * Open fixed file + * + * @v file EFI file + * @v new New EFI file + * @ret efirc EFI status code + */ +static EFI_STATUS efi_file_open_fixed ( struct efi_file *file, + EFI_FILE_PROTOCOL **new ) { + + /* Increment reference count */ + ref_get ( &file->refcnt ); + + /* Return opened file */ + *new = &file->file; + + DBGC ( file, "EFIFILE %s opened\n", efi_file_name ( file ) ); + return 0; +} +/** + * Associate file with image + * + * @v file EFI file + * @v image Image + */ +static void efi_file_image ( struct efi_file *file, struct image *image ) { + + file->image = image; + file->name = image->name; + file->read = efi_file_read_image; } /** @@ -106,50 +254,56 @@ static struct image * efi_file_find ( const CHAR16 *wname ) { */ static EFI_STATUS EFIAPI efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new, - CHAR16 *wname, UINT64 mode __unused, - UINT64 attributes __unused ) { + CHAR16 *wname, UINT64 mode, UINT64 attributes __unused ) { struct efi_file *file = container_of ( this, struct efi_file, file ); + char buf[ wcslen ( wname ) + 1 /* NUL */ ]; struct efi_file *new_file; struct image *image; + char *name; + + /* Convert name to ASCII */ + snprintf ( buf, sizeof ( buf ), "%ls", wname ); + name = buf; /* Initial '\' indicates opening from the root directory */ - while ( *wname == L'\\' ) { + while ( *name == '\\' ) { file = &efi_file_root; - wname++; + name++; } /* Allow root directory itself to be opened */ - if ( ( wname[0] == L'\0' ) || ( wname[0] == L'.' ) ) { - *new = &efi_file_root.file; - return 0; - } + if ( ( name[0] == '\0' ) || ( name[0] == '.' ) ) + return efi_file_open_fixed ( &efi_file_root, new ); /* Fail unless opening from the root */ - if ( file->image ) { + if ( file != &efi_file_root ) { DBGC ( file, "EFIFILE %s is not a directory\n", efi_file_name ( file ) ); return EFI_NOT_FOUND; } - /* Identify image */ - image = efi_file_find ( wname ); - if ( ! image ) { - DBGC ( file, "EFIFILE \"%ls\" does not exist\n", wname ); - return EFI_NOT_FOUND; - } - /* Fail unless opening read-only */ if ( mode != EFI_FILE_MODE_READ ) { DBGC ( file, "EFIFILE %s cannot be opened in mode %#08llx\n", - image->name, mode ); + name, mode ); return EFI_WRITE_PROTECTED; } + /* Identify image */ + image = efi_file_find ( name ); + if ( ! image ) { + DBGC ( file, "EFIFILE %s does not exist\n", name ); + return EFI_NOT_FOUND; + } + /* Allocate and initialise file */ new_file = zalloc ( sizeof ( *new_file ) ); + if ( ! new_file ) + return EFI_OUT_OF_RESOURCES; + ref_init ( &file->refcnt, efi_file_free ); memcpy ( &new_file->file, &efi_file_root.file, sizeof ( new_file->file ) ); - new_file->image = image_get ( image ); + efi_file_image ( new_file, image_get ( image ) ); *new = &new_file->file; DBGC ( new_file, "EFIFILE %s opened\n", efi_file_name ( new_file ) ); @@ -165,14 +319,9 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new, static EFI_STATUS EFIAPI efi_file_close ( EFI_FILE_PROTOCOL *this ) { struct efi_file *file = container_of ( this, struct efi_file, file ); - /* Do nothing if this is the root */ - if ( ! file->image ) - return 0; - /* Close file */ DBGC ( file, "EFIFILE %s closed\n", efi_file_name ( file ) ); - image_put ( file->image ); - free ( file ); + ref_put ( &file->refcnt ); return 0; } @@ -229,30 +378,29 @@ static EFI_STATUS efi_file_varlen ( UINT64 *base, size_t base_len, /** * Return file information structure * - * @v image Image, or NULL for the root directory + * @v file EFI file * @v len Length of data buffer * @v data Data buffer * @ret efirc EFI status code */ -static EFI_STATUS efi_file_info ( struct image *image, UINTN *len, +static EFI_STATUS efi_file_info ( struct efi_file *file, UINTN *len, VOID *data ) { EFI_FILE_INFO info; - const char *name; + size_t file_len; + + /* Get file length */ + file_len = efi_file_len ( file ); /* Populate file information */ memset ( &info, 0, sizeof ( info ) ); - if ( image ) { - info.FileSize = image->len; - info.PhysicalSize = image->len; - info.Attribute = EFI_FILE_READ_ONLY; - name = image->name; - } else { - info.Attribute = ( EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY ); - name = ""; - } - - return efi_file_varlen ( &info.Size, SIZE_OF_EFI_FILE_INFO, name, - len, data ); + info.FileSize = file_len; + info.PhysicalSize = file_len; + info.Attribute = EFI_FILE_READ_ONLY; + if ( file == &efi_file_root ) + info.Attribute |= EFI_FILE_DIRECTORY; + + return efi_file_varlen ( &info.Size, SIZE_OF_EFI_FILE_INFO, + file->name, len, data ); } /** @@ -266,14 +414,16 @@ static EFI_STATUS efi_file_info ( struct image *image, UINTN *len, static EFI_STATUS efi_file_read_dir ( struct efi_file *file, UINTN *len, VOID *data ) { EFI_STATUS efirc; + struct efi_file entry; struct image *image; unsigned int index; - /* Construct directory entry at current position */ + /* Construct directory entries for image-backed files */ index = file->pos; for_each_image ( image ) { if ( index-- == 0 ) { - efirc = efi_file_info ( image, len, data ); + efi_file_image ( &entry, image ); + efirc = efi_file_info ( &entry, len, data ); if ( efirc == 0 ) file->pos++; return efirc; @@ -296,21 +446,25 @@ static EFI_STATUS efi_file_read_dir ( struct efi_file *file, UINTN *len, static EFI_STATUS EFIAPI efi_file_read ( EFI_FILE_PROTOCOL *this, UINTN *len, VOID *data ) { struct efi_file *file = container_of ( this, struct efi_file, file ); - size_t remaining; + struct efi_file_reader reader; + size_t pos = file->pos; /* If this is the root directory, then construct a directory entry */ - if ( ! file->image ) + if ( ! file->read ) return efi_file_read_dir ( file, len, data ); + /* Initialise reader */ + reader.file = file; + reader.pos = 0; + reader.data = data; + reader.len = *len; + /* Read from the file */ - remaining = ( file->image->len - file->pos ); - if ( *len > remaining ) - *len = remaining; DBGC ( file, "EFIFILE %s read [%#08zx,%#08zx)\n", - efi_file_name ( file ), file->pos, - ( ( size_t ) ( file->pos + *len ) ) ); - copy_from_user ( data, file->image->data, file->pos, *len ); - file->pos += *len; + efi_file_name ( file ), pos, file->pos ); + *len = file->read ( &reader ); + assert ( ( pos + *len ) == file->pos ); + return 0; } @@ -342,24 +496,21 @@ static EFI_STATUS EFIAPI efi_file_write ( EFI_FILE_PROTOCOL *this, static EFI_STATUS EFIAPI efi_file_set_position ( EFI_FILE_PROTOCOL *this, UINT64 position ) { struct efi_file *file = container_of ( this, struct efi_file, file ); + size_t len; - /* If this is the root directory, reset to the start */ - if ( ! file->image ) { - DBGC ( file, "EFIFILE root directory rewound\n" ); - file->pos = 0; - return 0; - } + /* Get file length */ + len = efi_file_len ( file ); /* Check for the magic end-of-file value */ if ( position == 0xffffffffffffffffULL ) - position = file->image->len; + position = len; /* Fail if we attempt to seek past the end of the file (since * we do not support writes). */ - if ( position > file->image->len ) { + if ( position > len ) { DBGC ( file, "EFIFILE %s cannot seek to %#08llx of %#08zx\n", - efi_file_name ( file ), position, file->image->len ); + efi_file_name ( file ), position, len ); return EFI_UNSUPPORTED; } @@ -408,7 +559,7 @@ static EFI_STATUS EFIAPI efi_file_get_info ( EFI_FILE_PROTOCOL *this, /* Get file information */ DBGC ( file, "EFIFILE %s get file information\n", efi_file_name ( file ) ); - return efi_file_info ( file->image, len, data ); + return efi_file_info ( file, len, data ); } else if ( memcmp ( type, &efi_file_system_info_id, sizeof ( *type ) ) == 0 ) { @@ -468,6 +619,7 @@ static EFI_STATUS EFIAPI efi_file_flush ( EFI_FILE_PROTOCOL *this ) { /** Root directory */ static struct efi_file efi_file_root = { + .refcnt = REF_INIT ( ref_no_free ), .file = { .Revision = EFI_FILE_PROTOCOL_REVISION, .Open = efi_file_open, @@ -482,6 +634,7 @@ static struct efi_file efi_file_root = { .Flush = efi_file_flush, }, .image = NULL, + .name = "", }; /** @@ -496,8 +649,7 @@ efi_file_open_volume ( EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *filesystem __unused, EFI_FILE_PROTOCOL **file ) { DBGC ( &efi_file_root, "EFIFILE open volume\n" ); - *file = &efi_file_root.file; - return 0; + return efi_file_open_fixed ( &efi_file_root, file ); } /** EFI simple file system protocol */ -- cgit v1.2.3-55-g7522 From e5f02551735922eb235388bff08249a6f31ded3d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 21 May 2021 14:27:27 +0100 Subject: [efi] Provide an "initrd.magic" file for use by UEFI kernels Provide a file "initrd.magic" via the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL that contains the initrd file as constructed for BIOS bzImage kernels (including injected files with CPIO headers constructed by iPXE). This allows BIOS and UEFI kernels to obtain the exact same initramfs image, by adding "initrd=initrd.magic" to the kernel command line. For example: #!ipxe kernel boot/vmlinuz initrd=initrd.magic initrd boot/initrd.img initrd boot/modules/e1000.ko /lib/modules/e1000.ko initrd boot/modules/af_packet.ko /lib/modules/af_packet.ko boot Do not include the "initrd.magic" file within the root directory listing, since doing so would break software such as wimboot that processes all files within the root directory. Signed-off-by: Michael Brown --- src/interface/efi/efi_file.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) (limited to 'src/interface') diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c index c67fdea54..fc64b369c 100644 --- a/src/interface/efi/efi_file.c +++ b/src/interface/efi/efi_file.c @@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include #include #include @@ -84,6 +85,7 @@ struct efi_file { }; static struct efi_file efi_file_root; +static struct efi_file efi_file_initrd; /** * Free EFI file @@ -209,6 +211,67 @@ static size_t efi_file_read_image ( struct efi_file_reader *reader ) { return efi_file_read_chunk ( reader, image->data, image->len ); } +/** + * Read from magic initrd file + * + * @v reader EFI file reader + * @ret len Length read + */ +static size_t efi_file_read_initrd ( struct efi_file_reader *reader ) { + struct efi_file *file = reader->file; + struct cpio_header cpio; + struct image *image; + const char *name; + size_t pad_len; + size_t cpio_len; + size_t name_len; + size_t len; + + /* Read from file */ + len = 0; + for_each_image ( image ) { + + /* Ignore currently executing image */ + if ( image == current_image ) + continue; + + /* Pad to alignment boundary */ + pad_len = ( ( -reader->pos ) & ( INITRD_ALIGN - 1 ) ); + if ( pad_len ) { + DBGC ( file, "EFIFILE %s [%#08zx,%#08zx) pad\n", + efi_file_name ( file ), reader->pos, + ( reader->pos + pad_len ) ); + } + len += efi_file_read_chunk ( reader, UNULL, pad_len ); + + /* Read CPIO header, if applicable */ + cpio_len = cpio_header ( image, &cpio ); + if ( cpio_len ) { + name = cpio_name ( image ); + name_len = cpio_name_len ( image ); + pad_len = ( cpio_len - sizeof ( cpio ) - name_len ); + DBGC ( file, "EFIFILE %s [%#08zx,%#08zx) %s header\n", + efi_file_name ( file ), reader->pos, + ( reader->pos + cpio_len ), image->name ); + len += efi_file_read_chunk ( reader, + virt_to_user ( &cpio ), + sizeof ( cpio ) ); + len += efi_file_read_chunk ( reader, + virt_to_user ( name ), + name_len ); + len += efi_file_read_chunk ( reader, UNULL, pad_len ); + } + + /* Read file data */ + DBGC ( file, "EFIFILE %s [%#08zx,%#08zx) %s\n", + efi_file_name ( file ), reader->pos, + ( reader->pos + image->len ), image->name ); + len += efi_file_read_chunk ( reader, image->data, image->len ); + } + + return len; +} + /** * Open fixed file * @@ -289,6 +352,10 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new, return EFI_WRITE_PROTECTED; } + /* Allow magic initrd to be opened */ + if ( strcasecmp ( name, efi_file_initrd.name ) == 0 ) + return efi_file_open_fixed ( &efi_file_initrd, new ); + /* Identify image */ image = efi_file_find ( name ); if ( ! image ) { @@ -637,6 +704,27 @@ static struct efi_file efi_file_root = { .name = "", }; +/** Magic initrd file */ +static struct efi_file efi_file_initrd = { + .refcnt = REF_INIT ( ref_no_free ), + .file = { + .Revision = EFI_FILE_PROTOCOL_REVISION, + .Open = efi_file_open, + .Close = efi_file_close, + .Delete = efi_file_delete, + .Read = efi_file_read, + .Write = efi_file_write, + .GetPosition = efi_file_get_position, + .SetPosition = efi_file_set_position, + .GetInfo = efi_file_get_info, + .SetInfo = efi_file_set_info, + .Flush = efi_file_flush, + }, + .image = NULL, + .name = "initrd.magic", + .read = efi_file_read_initrd, +}; + /** * Open root directory * -- cgit v1.2.3-55-g7522 From 3c040ad387099483102708bb1839110bc788cefb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 11 Jun 2021 14:46:54 +0100 Subject: [efi] Veto the Itautec Ip4ConfigDxe driver The Ip4ConfigDxe driver bug that was observed on Dell systems in commit 64b4452 ("[efi] Blacklist the Dell Ip4ConfigDxe driver") has also been observed on systems with a manufacturer name of "Itautec S.A.". The symptoms of the bug are identical: an attempt to call DisconnectController() on the LOM device handle will lock up the system. Fix by extending the veto to cover the Ip4ConfigDxe driver for this manufacturer. Debugged-by: Celso Viana Signed-off-by: Michael Brown --- src/interface/efi/efi_veto.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src/interface') diff --git a/src/interface/efi/efi_veto.c b/src/interface/efi/efi_veto.c index 6ff7898e9..b616539d3 100644 --- a/src/interface/efi/efi_veto.c +++ b/src/interface/efi/efi_veto.c @@ -362,7 +362,7 @@ static int efi_veto_driver ( EFI_HANDLE driver ) { } /** - * Veto Dell Ip4ConfigDxe driver + * Veto Ip4ConfigDxe driver on some platforms * * @v binding Driver binding protocol * @v loaded Loaded image protocol @@ -372,19 +372,21 @@ static int efi_veto_driver ( EFI_HANDLE driver ) { * @ret vetoed Driver is to be vetoed */ static int -efi_veto_dell_ip4config ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused, - EFI_LOADED_IMAGE_PROTOCOL *loaded __unused, - EFI_COMPONENT_NAME_PROTOCOL *wtf __unused, - const char *manufacturer, const CHAR16 *name ) { +efi_veto_ip4config ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused, + EFI_LOADED_IMAGE_PROTOCOL *loaded __unused, + EFI_COMPONENT_NAME_PROTOCOL *wtf __unused, + const char *manufacturer, const CHAR16 *name ) { static const CHAR16 ip4cfg[] = L"IP4 CONFIG Network Service Driver"; static const char *dell = "Dell Inc."; + static const char *itautec = "Itautec S.A."; /* Check manufacturer and driver name */ if ( ! manufacturer ) return 0; if ( ! name ) return 0; - if ( strcmp ( manufacturer, dell ) != 0 ) + if ( ( strcmp ( manufacturer, dell ) != 0 ) && + ( strcmp ( manufacturer, itautec ) != 0 ) ) return 0; if ( memcmp ( name, ip4cfg, sizeof ( ip4cfg ) ) != 0 ) return 0; @@ -436,8 +438,8 @@ efi_veto_hp_xhci ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused, /** Driver vetoes */ static struct efi_veto efi_vetoes[] = { { - .name = "Dell Ip4Config", - .veto = efi_veto_dell_ip4config, + .name = "Ip4Config", + .veto = efi_veto_ip4config, }, { .name = "HP Xhci", -- cgit v1.2.3-55-g7522