Merge branch 'master' into respect_cc_v4

pull/723/head
David Yeske 2023-02-02 11:23:32 -05:00 committed by GitHub
commit 3c301c6cf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
277 changed files with 23823 additions and 17529 deletions

View File

@ -369,7 +369,6 @@ endif
# Include architecture-specific include path
ifdef ARCH
INCDIRS += arch/$(ARCH)/include
INCDIRS += arch/$(ARCH)/include/$(PLATFORM)
endif
###############################################################################
@ -462,7 +461,9 @@ ifeq ($(CCTYPE),gcc)
CFLAGS += -ffreestanding
CFLAGS += -fcommon
CFLAGS += -Wall -W -Wformat-nonliteral
CFLAGS += -Wno-array-bounds -Wno-dangling-pointer
HOST_CFLAGS += -Wall -W -Wformat-nonliteral
HOST_CFLAGS += -Wno-array-bounds -Wno-dangling-pointer
endif
CFLAGS += $(WORKAROUND_CFLAGS) $(EXTRA_CFLAGS)
ASFLAGS += $(WORKAROUND_ASFLAGS) $(EXTRA_ASFLAGS)
@ -510,6 +511,10 @@ CFLAGS += -include include/compiler.h
#
CFLAGS += -DASM_TCHAR='$(ASM_TCHAR)' -DASM_TCHAR_OPS='$(ASM_TCHAR_OPS)'
# Inhibit the default -Dlinux
#
CFLAGS += -Ulinux
# CFLAGS for specific object types
#
CFLAGS_c +=

View File

@ -8,6 +8,10 @@ SYMBOL_PREFIX = _ipxe__
#
CFLAGS += -UNVALGRIND
# The Linux linker script
#
LDSCRIPT = scripts/linux.lds
# Use a two-stage link
#
LDFLAGS += -r -d

View File

@ -0,0 +1,6 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Include generic Linux Makefile
#
MAKEDEPS += Makefile.linux
include Makefile.linux

View File

@ -5,7 +5,7 @@ SRCDIRS += arch/arm32/libgcc
# ARM32-specific flags
#
CFLAGS += -mthumb -mcpu=cortex-a15 -mabi=aapcs -mfloat-abi=soft
CFLAGS += -mthumb -mcpu=cortex-a15 -mabi=aapcs
CFLAGS += -mword-relocations
ASFLAGS += -mthumb -mcpu=cortex-a15
@ -13,6 +13,11 @@ ASFLAGS += -mthumb -mcpu=cortex-a15
#
CFLAGS += -fshort-wchar
# EFI requires that enums are always 32 bits, and nothing else
# currently cares
#
CFLAGS += -fno-short-enums
# Include common ARM Makefile
MAKEDEPS += arch/arm/Makefile
include arch/arm/Makefile

View File

@ -1,8 +1,8 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# UEFI requires that enums are always 32 bits
# EFI uses the soft float ABI
#
CFLAGS += -fno-short-enums
CFLAGS += -mfloat-abi=soft
# Specify EFI image builder
#

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", %progbits
.text
.arm

View File

@ -0,0 +1,20 @@
#ifndef _IPXE_EFI_DHCPARCH_H
#define _IPXE_EFI_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
/** DHCP client architecture */
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_ARM32
/** DHCP client network device interface */
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif /* _IPXE_EFI_DHCPARCH_H */

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", %progbits
.text
.thumb

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", %progbits
.text
.arm

View File

@ -0,0 +1,10 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Starting virtual address
#
LDFLAGS += -Ttext=0x400000
# Include generic Linux Makefile
#
MAKEDEPS += arch/arm/Makefile.linux
include arch/arm/Makefile.linux

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
#define _DHCP_ARCH_H
/** @file
*
* Architecture-specific DHCP options
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_ARM64
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif

View File

@ -0,0 +1,20 @@
#ifndef _IPXE_EFI_DHCPARCH_H
#define _IPXE_EFI_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
/** DHCP client architecture */
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_ARM64
/** DHCP client network device interface */
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif /* _IPXE_EFI_DHCPARCH_H */

View File

@ -1,8 +1,8 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Linker script
# Starting virtual address
#
LDSCRIPT = arch/i386/scripts/linux.lds
LDFLAGS += -Ttext=0x08048000
# Compiler flags for building host API wrapper
#

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
#define _DHCP_ARCH_H
/** @file
*
* Architecture-specific DHCP options
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_IA32
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif

View File

@ -0,0 +1,20 @@
#ifndef _IPXE_EFI_DHCPARCH_H
#define _IPXE_EFI_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
/** DHCP client architecture */
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_IA32
/** DHCP client network device interface */
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif /* _IPXE_EFI_DHCPARCH_H */

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
#define _DHCP_ARCH_H
/** @file
*
* Architecture-specific DHCP options
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 2, 1 /* v2.1 */
#endif

View File

@ -22,9 +22,6 @@ SRCDIRS += arch/x86/drivers/xen
SRCDIRS += arch/x86/drivers/hyperv
SRCDIRS += arch/x86/transitions
# breaks building some of the linux-related objects
CFLAGS += -Ulinux
# disable valgrind
CFLAGS += -DNVALGRIND

View File

@ -1,9 +1,5 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Include x86 Linux headers
#
INCDIRS += arch/x86/include/linux
# Include generic Linux Makefile
#
MAKEDEPS += Makefile.linux

View File

@ -45,7 +45,7 @@ void pcidirect_prepare ( struct pci_device *pci, int where ) {
PCIDIRECT_CONFIG_ADDRESS );
}
PROVIDE_PCIAPI_INLINE ( direct, pci_num_bus );
PROVIDE_PCIAPI_INLINE ( direct, pci_discover );
PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word );
PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_dword );
@ -53,3 +53,5 @@ PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte );
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word );
PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword );
PROVIDE_PCIAPI_INLINE ( direct, pci_ioremap );
struct pci_api pcidirect_api = PCIAPI_RUNTIME ( direct );

View File

@ -252,13 +252,17 @@ static void bzimage_update_header ( struct image *image,
*/
static int bzimage_parse_cmdline ( struct image *image,
struct bzimage_context *bzimg,
const char *cmdline ) {
char *cmdline ) {
char *sep;
char *vga;
char *mem;
/* Look for "vga=" */
if ( ( vga = strstr ( cmdline, "vga=" ) ) ) {
vga += 4;
sep = strchr ( vga, ' ' );
if ( sep )
*sep = '\0';
if ( strcmp ( vga, "normal" ) == 0 ) {
bzimg->vid_mode = BZI_VID_MODE_NORMAL;
} else if ( strcmp ( vga, "ext" ) == 0 ) {
@ -267,11 +271,13 @@ static int bzimage_parse_cmdline ( struct image *image,
bzimg->vid_mode = BZI_VID_MODE_ASK;
} else {
bzimg->vid_mode = strtoul ( vga, &vga, 0 );
if ( *vga && ( *vga != ' ' ) ) {
if ( *vga ) {
DBGC ( image, "bzImage %p strange \"vga=\" "
"terminator '%c'\n", image, *vga );
}
}
if ( sep )
*sep = ' ';
}
/* Look for "mem=" */
@ -522,7 +528,7 @@ static void bzimage_load_initrds ( struct image *image,
*/
static int bzimage_exec ( struct image *image ) {
struct bzimage_context bzimg;
const char *cmdline = ( image->cmdline ? image->cmdline : "" );
char *cmdline = ( image->cmdline ? image->cmdline : "" );
int rc;
/* Read and parse header from image */

View File

@ -11,5 +11,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/pcibios.h>
#include <ipxe/pcidirect.h>
#include <ipxe/pcicloud.h>
#endif /* _BITS_PCI_IO_H */

View File

@ -0,0 +1,20 @@
#ifndef _IPXE_PCBIOS_DHCPARCH_H
#define _IPXE_PCBIOS_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
/** DHCP client architecture */
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86
/** DHCP client network device interface */
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 2, 1 /* v2.1 */
#endif /* _IPXE_PCBIOS_DHCPARCH_H */

View File

@ -145,4 +145,6 @@ PCIAPI_INLINE ( pcbios, pci_ioremap ) ( struct pci_device *pci __unused,
return ioremap ( bus_addr, len );
}
extern struct pci_api pcibios_api;
#endif /* _IPXE_PCIBIOS_H */

View File

@ -0,0 +1,18 @@
#ifndef _IPXE_PCICLOUD_H
#define _IPXE_PCICLOUD_H
/** @file
*
* Cloud VM PCI configuration space access
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef PCIAPI_CLOUD
#define PCIAPI_PREFIX_cloud
#else
#define PCIAPI_PREFIX_cloud __cloud_
#endif
#endif /* _IPXE_PCICLOUD_H */

View File

@ -26,14 +26,18 @@ struct pci_device;
extern void pcidirect_prepare ( struct pci_device *pci, int where );
/**
* Determine number of PCI buses within system
* Find next PCI bus:dev.fn address range in system
*
* @ret num_bus Number of buses
* @v busdevfn Starting PCI bus:dev.fn address
* @v range PCI bus:dev.fn address range to fill in
*/
static inline __always_inline int
PCIAPI_INLINE ( direct, pci_num_bus ) ( void ) {
static inline __always_inline void
PCIAPI_INLINE ( direct, pci_discover ) ( uint32_t busdevfn __unused,
struct pci_range *range ) {
/* Scan first bus and rely on bridge detection to find higher buses */
return 1;
range->start = PCI_BUSDEVFN ( 0, 0, 0, 0 );
range->count = PCI_BUSDEVFN ( 0, 1, 0, 0 );
}
/**
@ -151,4 +155,6 @@ PCIAPI_INLINE ( direct, pci_ioremap ) ( struct pci_device *pci __unused,
return ioremap ( bus_addr, len );
}
extern struct pci_api pcidirect_api;
#endif /* _PCIDIRECT_H */

View File

@ -1,41 +0,0 @@
/*
* Copyright (C) 2010 Piotr Jaroszyński <p.jaroszynski@gmail.com>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _LINUX_DHCP_ARCH_H
#define _LINUX_DHCP_ARCH_H
/** @file
*
* Architecture-specific DHCP options
*/
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL);
#include <ipxe/dhcp.h>
// Emulate one of the supported arch-platforms
#include <arch/i386/include/pcbios/ipxe/dhcp_arch.h>
//#include <arch/i386/include/efi/ipxe/dhcp_arch.h>
//#include <arch/x86_64/include/efi/ipxe/dhcp_arch.h>
#endif

View File

@ -59,7 +59,7 @@ static void cachedhcp_init ( void ) {
}
/* Record cached DHCPACK */
if ( ( rc = cachedhcp_record ( &cached_dhcpack,
if ( ( rc = cachedhcp_record ( &cached_dhcpack, 0,
phys_to_user ( cached_dhcpack_phys ),
sizeof ( BOOTPLAYER_t ) ) ) != 0 ) {
DBGC ( colour, "CACHEDHCP could not record DHCPACK: %s\n",

View File

@ -34,13 +34,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*/
/**
* Determine number of PCI buses within system
* Find next PCI bus:dev.fn address range in system
*
* @ret num_bus Number of buses
* @v busdevfn Starting PCI bus:dev.fn address
* @v range PCI bus:dev.fn address range to fill in
*/
static int pcibios_num_bus ( void ) {
static void pcibios_discover ( uint32_t busdevfn __unused,
struct pci_range *range ) {
int discard_a, discard_D;
uint8_t max_bus;
uint16_t num_bus;
/* We issue this call using flat real mode, to work around a
* bug in some HP BIOSes.
@ -48,16 +50,20 @@ static int pcibios_num_bus ( void ) {
__asm__ __volatile__ ( REAL_CODE ( "call flatten_real_mode\n\t"
"stc\n\t"
"int $0x1a\n\t"
"movzbw %%cl, %%cx\n\t"
"incw %%cx\n\t"
"jnc 1f\n\t"
"xorw %%cx, %%cx\n\t"
"\n1:\n\t" )
: "=c" ( max_bus ), "=a" ( discard_a ),
: "=c" ( num_bus ), "=a" ( discard_a ),
"=D" ( discard_D )
: "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 ),
"D" ( 0 )
: "ebx", "edx" );
return ( max_bus + 1 );
/* Populate range */
range->start = PCI_BUSDEVFN ( 0, 0, 0, 0 );
range->count = PCI_BUSDEVFN ( 0, num_bus, 0, 0 );
}
/**
@ -114,7 +120,7 @@ int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
return ( status >> 8 );
}
PROVIDE_PCIAPI ( pcbios, pci_num_bus, pcibios_num_bus );
PROVIDE_PCIAPI ( pcbios, pci_discover, pcibios_discover );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_dword );
@ -122,3 +128,5 @@ PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
PROVIDE_PCIAPI_INLINE ( pcbios, pci_ioremap );
struct pci_api pcibios_api = PCIAPI_RUNTIME ( pcbios );

View File

@ -0,0 +1,191 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/init.h>
#include <ipxe/pci.h>
#include <ipxe/ecam.h>
#include <ipxe/pcibios.h>
#include <ipxe/pcidirect.h>
#include <ipxe/pcicloud.h>
/** @file
*
* Cloud VM PCI configuration space access
*
*/
/** Selected PCI configuration space access API */
static struct pci_api *pcicloud = &ecam_api;
/**
* Find next PCI bus:dev.fn address range in system
*
* @v busdevfn Starting PCI bus:dev.fn address
* @v range PCI bus:dev.fn address range to fill in
*/
static void pcicloud_discover ( uint32_t busdevfn, struct pci_range *range ) {
pcicloud->pci_discover ( busdevfn, range );
}
/**
* Read byte from PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static int pcicloud_read_config_byte ( struct pci_device *pci,
unsigned int where, uint8_t *value ) {
return pcicloud->pci_read_config_byte ( pci, where, value );
}
/**
* Read 16-bit word from PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static int pcicloud_read_config_word ( struct pci_device *pci,
unsigned int where, uint16_t *value ) {
return pcicloud->pci_read_config_word ( pci, where, value );
}
/**
* Read 32-bit dword from PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static int pcicloud_read_config_dword ( struct pci_device *pci,
unsigned int where, uint32_t *value ) {
return pcicloud->pci_read_config_dword ( pci, where, value );
}
/**
* Write byte to PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static int pcicloud_write_config_byte ( struct pci_device *pci,
unsigned int where, uint8_t value ) {
return pcicloud->pci_write_config_byte ( pci, where, value );
}
/**
* Write 16-bit word to PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static int pcicloud_write_config_word ( struct pci_device *pci,
unsigned int where, uint16_t value ) {
return pcicloud->pci_write_config_word ( pci, where, value );
}
/**
* Write 32-bit dword to PCI configuration space
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static int pcicloud_write_config_dword ( struct pci_device *pci,
unsigned int where, uint32_t value ) {
return pcicloud->pci_write_config_dword ( pci, where, value );
}
/**
* Map PCI bus address as an I/O address
*
* @v bus_addr PCI bus address
* @v len Length of region
* @ret io_addr I/O address, or NULL on error
*/
static void * pcicloud_ioremap ( struct pci_device *pci,
unsigned long bus_addr, size_t len ) {
return pcicloud->pci_ioremap ( pci, bus_addr, len );
}
PROVIDE_PCIAPI ( cloud, pci_discover, pcicloud_discover );
PROVIDE_PCIAPI ( cloud, pci_read_config_byte, pcicloud_read_config_byte );
PROVIDE_PCIAPI ( cloud, pci_read_config_word, pcicloud_read_config_word );
PROVIDE_PCIAPI ( cloud, pci_read_config_dword, pcicloud_read_config_dword );
PROVIDE_PCIAPI ( cloud, pci_write_config_byte, pcicloud_write_config_byte );
PROVIDE_PCIAPI ( cloud, pci_write_config_word, pcicloud_write_config_word );
PROVIDE_PCIAPI ( cloud, pci_write_config_dword, pcicloud_write_config_dword );
PROVIDE_PCIAPI ( cloud, pci_ioremap, pcicloud_ioremap );
/**
* Initialise cloud VM PCI configuration space access
*
*/
static void pcicloud_init ( void ) {
static struct pci_api *apis[] = {
&ecam_api, &pcibios_api, &pcidirect_api
};
struct pci_range range;
unsigned int i;
/* Select first API that successfully discovers an address range */
for ( i = 0 ; i < ( sizeof ( apis ) / sizeof ( apis[0] ) ) ; i++ ) {
pcicloud = apis[i];
pcicloud_discover ( 0, &range );
if ( range.count != 0 ) {
DBGC ( pcicloud, "PCICLOUD selected %s API\n",
pcicloud->name );
break;
}
}
/* The PCI direct API can never fail discovery since the range
* is hardcoded.
*/
assert ( range.count != 0 );
}
/** Cloud VM PCI configuration space access initialisation function */
struct init_fn pcicloud_init_fn __init_fn ( INIT_EARLY ) = {
.initialise = pcicloud_init,
};

View File

@ -12,6 +12,7 @@
#include <ipxe/uaccess.h>
#include <ipxe/process.h>
#include <ipxe/netdevice.h>
#include <ipxe/malloc.h>
#include <realmode.h>
#include <pxe.h>
@ -482,3 +483,28 @@ struct pxe_api_call pxe_udp_api[] __pxe_api_call = {
PXE_API_CALL ( PXENV_UDP_READ, pxenv_udp_read,
struct s_PXENV_UDP_READ ),
};
/**
* Discard some cached PXE UDP data
*
* @ret discarded Number of cached items discarded
*/
static unsigned int pxe_udp_discard ( void ) {
struct io_buffer *iobuf;
unsigned int discarded = 0;
/* Try to discard the oldest received UDP packet */
iobuf = list_first_entry ( &pxe_udp.list, struct io_buffer, list );
if ( iobuf ) {
list_del ( &iobuf->list );
free_iob ( iobuf );
discarded++;
}
return discarded;
}
/** PXE UDP cache discarder */
struct cache_discarder pxe_udp_discarder __cache_discarder ( CACHE_NORMAL ) = {
.discard = pxe_udp_discard,
};

View File

@ -1,8 +1,8 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Linker script
# Starting virtual address
#
LDSCRIPT = arch/x86_64/scripts/linux.lds
LDFLAGS += -Ttext=0x400000
# Include generic Linux Makefile
#

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
#define _DHCP_ARCH_H
/** @file
*
* Architecture-specific DHCP options
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86_64
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif

View File

@ -0,0 +1,20 @@
#ifndef _IPXE_EFI_DHCPARCH_H
#define _IPXE_EFI_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
/** DHCP client architecture */
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86_64
/** DHCP client network device interface */
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 3, 10 /* v3.10 */
#endif /* _IPXE_EFI_DHCPARCH_H */

View File

@ -1,40 +0,0 @@
/*
* Copyright (C) 2010 VMware, Inc. All Rights Reserved.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
#define _DHCP_ARCH_H
/** @file
*
* Architecture-specific DHCP options
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
#define DHCP_ARCH_CLIENT_ARCHITECTURE DHCP_CLIENT_ARCHITECTURE_X86
#define DHCP_ARCH_CLIENT_NDI 1 /* UNDI */ , 2, 1 /* v2.1 */
#endif

View File

@ -1,106 +0,0 @@
/* -*- sh -*- */
/*
* Linker script for x86_64 Linux images
*
*/
OUTPUT_FORMAT ( "elf64-x86-64", "elf64-x86-64", "elf64-x86-64" )
OUTPUT_ARCH ( i386:x86-64 )
SECTIONS {
_max_align = 32;
. = 0x400000;
/*
* The text section
*
*/
. = ALIGN ( _max_align );
.text : {
_text = .;
*(.text)
*(.text.*)
_etext = .;
}
/*
* The rodata section
*
*/
. = ALIGN ( _max_align );
.rodata : {
_rodata = .;
*(.rodata)
*(.rodata.*)
_erodata = .;
}
/*
* The data section
*
* Adjust the address for the data segment. We want to adjust up to
* the same address within the page on the next page up.
*/
. = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1));
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
.data : {
_data = .;
*(.data)
*(.data.*)
KEEP(*(SORT(.tbl.*)))
KEEP(*(.provided))
KEEP(*(.provided.*))
_edata = .;
}
/*
* The bss section
*
*/
. = ALIGN ( _max_align );
.bss : {
_bss = .;
*(.bss)
*(.bss.*)
*(COMMON)
_ebss = .;
}
/*
* Weak symbols that need zero values if not otherwise defined
*
*/
.weak 0x0 : {
_weak = .;
*(.weak)
*(.weak.*)
_eweak = .;
}
_assert = ASSERT ( ( _weak == _eweak ), ".weak is non-zero length" );
/*
* Dispose of the comment and note sections to make the link map
* easier to read
*
*/
/DISCARD/ : {
*(.comment)
*(.comment.*)
*(.note)
*(.note.*)
*(.rel)
*(.rel.*)
*(.discard)
*(.discard.*)
*(.sbat)
*(.sbat.*)
}
}

View File

@ -3,5 +3,5 @@
*/
#ifdef PLATFORM_pcbios
#undef PCIAPI_PCBIOS
#define PCIAPI_DIRECT
#define PCIAPI_CLOUD
#endif

View File

@ -124,3 +124,15 @@ REQUIRE_OBJECT ( rsa_aes_cbc_sha1 );
defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( rsa_aes_cbc_sha256 );
#endif
/* RSA, AES-GCM, and SHA-256 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_GCM ) && \
defined ( CRYPTO_DIGEST_SHA256 )
REQUIRE_OBJECT ( rsa_aes_gcm_sha256 );
#endif
/* RSA, AES-GCM, and SHA-384 */
#if defined ( CRYPTO_PUBKEY_RSA ) && defined ( CRYPTO_CIPHER_AES_GCM ) && \
defined ( CRYPTO_DIGEST_SHA384 )
REQUIRE_OBJECT ( rsa_aes_gcm_sha384 );
#endif

View File

@ -18,6 +18,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** AES-CBC block cipher */
#define CRYPTO_CIPHER_AES_CBC
/** AES-GCM block cipher */
#define CRYPTO_CIPHER_AES_GCM
/** MD4 digest algorithm */
//#define CRYPTO_DIGEST_MD4

View File

@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcppkt.h>
#include <ipxe/init.h>
#include <ipxe/netdevice.h>
#include <ipxe/vlan.h>
#include <ipxe/cachedhcp.h>
/** @file
@ -43,6 +44,8 @@ struct cached_dhcp_packet {
const char *name;
/** DHCP packet (if any) */
struct dhcp_packet *dhcppkt;
/** VLAN tag (if applicable) */
unsigned int vlan;
};
/** Cached DHCPACK */
@ -136,15 +139,26 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
* matches this network device.
*/
if ( memcmp ( ll_addr, chaddr, ll_addr_len ) != 0 ) {
DBGC ( colour, "CACHEDHCP %s does not match %s\n",
cache->name, netdev->name );
DBGC ( colour, "CACHEDHCP %s %s does not match %s\n",
cache->name, ll_protocol->ntoa ( chaddr ),
netdev->name );
return 0;
}
/* Do nothing unless cached packet's VLAN tag matches
* this network device.
*/
if ( vlan_tag ( netdev ) != cache->vlan ) {
DBGC ( colour, "CACHEDHCP %s VLAN %d does not match "
"%s\n", cache->name, cache->vlan,
netdev->name );
return 0;
}
DBGC ( colour, "CACHEDHCP %s is for %s\n",
cache->name, netdev->name );
/* Use network device's settings block */
settings = netdev_settings ( netdev );
DBGC ( colour, "CACHEDHCP %s is for %s\n",
cache->name, netdev->name );
}
/* Register settings */
@ -165,12 +179,13 @@ static int cachedhcp_apply ( struct cached_dhcp_packet *cache,
* Record cached DHCP packet
*
* @v cache Cached DHCP packet
* @v vlan VLAN tag, if any
* @v data DHCPACK packet buffer
* @v max_len Maximum possible length
* @ret rc Return status code
*/
int cachedhcp_record ( struct cached_dhcp_packet *cache, userptr_t data,
size_t max_len ) {
int cachedhcp_record ( struct cached_dhcp_packet *cache, unsigned int vlan,
userptr_t data, size_t max_len ) {
struct dhcp_packet *dhcppkt;
struct dhcp_packet *tmp;
struct dhcphdr *dhcphdr;
@ -225,36 +240,55 @@ int cachedhcp_record ( struct cached_dhcp_packet *cache, userptr_t data,
DBGC ( colour, "CACHEDHCP %s at %#08lx+%#zx/%#zx\n", cache->name,
user_to_phys ( data, 0 ), len, max_len );
cache->dhcppkt = dhcppkt;
cache->vlan = vlan;
return 0;
}
/**
* Cached DHCPACK startup function
* Cached DHCP packet startup function
*
*/
static void cachedhcp_startup ( void ) {
/* Apply cached ProxyDHCPOFFER, if any */
cachedhcp_apply ( &cached_proxydhcp, NULL );
cachedhcp_free ( &cached_proxydhcp );
/* Apply cached PXEBSACK, if any */
cachedhcp_apply ( &cached_pxebs, NULL );
cachedhcp_free ( &cached_pxebs );
/* Free any remaining cached packets */
/* Report unclaimed DHCPACK, if any. Do not free yet, since
* it may still be claimed by a dynamically created device
* such as a VLAN device.
*/
if ( cached_dhcpack.dhcppkt ) {
DBGC ( colour, "CACHEDHCP %s unclaimed\n",
cached_dhcpack.name );
}
}
/**
* Cached DHCP packet shutdown function
*
* @v booting System is shutting down for OS boot
*/
static void cachedhcp_shutdown ( int booting __unused ) {
/* Free cached DHCPACK, if any */
if ( cached_dhcpack.dhcppkt ) {
DBGC ( colour, "CACHEDHCP %s never claimed\n",
cached_dhcpack.name );
}
cachedhcp_free ( &cached_dhcpack );
cachedhcp_free ( &cached_proxydhcp );
cachedhcp_free ( &cached_pxebs );
}
/** Cached DHCPACK startup function */
struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_LATE ) = {
.name = "cachedhcp",
.startup = cachedhcp_startup,
.shutdown = cachedhcp_shutdown,
};
/**

View File

@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/crypto.h>
#include <ipxe/ecb.h>
#include <ipxe/cbc.h>
#include <ipxe/gcm.h>
#include <ipxe/aes.h>
/** AES strides
@ -778,25 +779,18 @@ static int aes_setkey ( void *ctx, const void *key, size_t keylen ) {
return 0;
}
/**
* Set initialisation vector
*
* @v ctx Context
* @v iv Initialisation vector
*/
static void aes_setiv ( void *ctx __unused, const void *iv __unused ) {
/* Nothing to do */
}
/** Basic AES algorithm */
struct cipher_algorithm aes_algorithm = {
.name = "aes",
.ctxsize = sizeof ( struct aes_context ),
.blocksize = AES_BLOCKSIZE,
.alignsize = 0,
.authsize = 0,
.setkey = aes_setkey,
.setiv = aes_setiv,
.setiv = cipher_null_setiv,
.encrypt = aes_encrypt,
.decrypt = aes_decrypt,
.auth = cipher_null_auth,
};
/* AES in Electronic Codebook mode */
@ -806,3 +800,7 @@ ECB_CIPHER ( aes_ecb, aes_ecb_algorithm,
/* AES in Cipher Block Chaining mode */
CBC_CIPHER ( aes_cbc, aes_cbc_algorithm,
aes_algorithm, struct aes_context, AES_BLOCKSIZE );
/* AES in Galois/Counter mode */
GCM_CIPHER ( aes_gcm, aes_gcm_algorithm,
aes_algorithm, struct aes_context, AES_BLOCKSIZE );

View File

@ -96,12 +96,6 @@ static void arc4_xor ( void *ctxv, const void *srcv, void *dstv,
ctx->j = j;
}
static void arc4_setiv ( void *ctx __unused, const void *iv __unused )
{
/* ARC4 does not use a fixed-length IV */
}
/**
* Perform ARC4 encryption or decryption, skipping initial keystream bytes
*
@ -125,8 +119,11 @@ struct cipher_algorithm arc4_algorithm = {
.name = "ARC4",
.ctxsize = ARC4_CTX_SIZE,
.blocksize = 1,
.alignsize = 1,
.authsize = 0,
.setkey = arc4_setkey,
.setiv = arc4_setiv,
.setiv = cipher_null_setiv,
.encrypt = arc4_xor,
.decrypt = arc4_xor,
.auth = cipher_null_auth,
};

View File

@ -32,16 +32,16 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <ipxe/crypto.h>
static void digest_null_init ( void *ctx __unused ) {
void digest_null_init ( void *ctx __unused ) {
/* Do nothing */
}
static void digest_null_update ( void *ctx __unused, const void *src __unused,
void digest_null_update ( void *ctx __unused, const void *src __unused,
size_t len __unused ) {
/* Do nothing */
}
static void digest_null_final ( void *ctx __unused, void *out __unused ) {
void digest_null_final ( void *ctx __unused, void *out __unused ) {
/* Do nothing */
}
@ -55,68 +55,72 @@ struct digest_algorithm digest_null = {
.final = digest_null_final,
};
static int cipher_null_setkey ( void *ctx __unused, const void *key __unused,
int cipher_null_setkey ( void *ctx __unused, const void *key __unused,
size_t keylen __unused ) {
/* Do nothing */
return 0;
}
static void cipher_null_setiv ( void *ctx __unused,
const void *iv __unused ) {
void cipher_null_setiv ( void *ctx __unused, const void *iv __unused,
size_t ivlen __unused ) {
/* Do nothing */
}
static void cipher_null_encrypt ( void *ctx __unused, const void *src,
void *dst, size_t len ) {
void cipher_null_encrypt ( void *ctx __unused, const void *src, void *dst,
size_t len ) {
memcpy ( dst, src, len );
}
static void cipher_null_decrypt ( void *ctx __unused, const void *src,
void *dst, size_t len ) {
void cipher_null_decrypt ( void *ctx __unused, const void *src, void *dst,
size_t len ) {
memcpy ( dst, src, len );
}
void cipher_null_auth ( void *ctx __unused, void *auth __unused ) {
/* Do nothing */
}
struct cipher_algorithm cipher_null = {
.name = "null",
.ctxsize = 0,
.blocksize = 1,
.alignsize = 1,
.authsize = 0,
.setkey = cipher_null_setkey,
.setiv = cipher_null_setiv,
.encrypt = cipher_null_encrypt,
.decrypt = cipher_null_decrypt,
.auth = cipher_null_auth,
};
static int pubkey_null_init ( void *ctx __unused, const void *key __unused,
int pubkey_null_init ( void *ctx __unused, const void *key __unused,
size_t key_len __unused ) {
return 0;
}
static size_t pubkey_null_max_len ( void *ctx __unused ) {
size_t pubkey_null_max_len ( void *ctx __unused ) {
return 0;
}
static int pubkey_null_encrypt ( void *ctx __unused,
const void *plaintext __unused,
int pubkey_null_encrypt ( void *ctx __unused, const void *plaintext __unused,
size_t plaintext_len __unused,
void *ciphertext __unused ) {
return 0;
}
static int pubkey_null_decrypt ( void *ctx __unused,
const void *ciphertext __unused,
int pubkey_null_decrypt ( void *ctx __unused, const void *ciphertext __unused,
size_t ciphertext_len __unused,
void *plaintext __unused ) {
return 0;
}
static int pubkey_null_sign ( void *ctx __unused,
int pubkey_null_sign ( void *ctx __unused,
struct digest_algorithm *digest __unused,
const void *value __unused,
void *signature __unused ) {
const void *value __unused, void *signature __unused ) {
return 0;
}
static int pubkey_null_verify ( void *ctx __unused,
int pubkey_null_verify ( void *ctx __unused,
struct digest_algorithm *digest __unused,
const void *value __unused,
const void *signature __unused ,
@ -124,7 +128,7 @@ static int pubkey_null_verify ( void *ctx __unused,
return 0;
}
static void pubkey_null_final ( void *ctx __unused ) {
void pubkey_null_final ( void *ctx __unused ) {
/* Do nothing */
}

133
src/crypto/dhe.c 100644
View File

@ -0,0 +1,133 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
* Ephemeral Diffie-Hellman key exchange
*
*/
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <ipxe/bigint.h>
#include <ipxe/dhe.h>
/**
* Calculate Diffie-Hellman key
*
* @v modulus Prime modulus
* @v len Length of prime modulus
* @v generator Generator
* @v generator_len Length of generator
* @v partner Partner public key
* @v partner_len Length of partner public key
* @v private Private key
* @v private_len Length of private key
* @ret public Public key (length equal to prime modulus)
* @ret shared Shared secret (length equal to prime modulus)
* @ret rc Return status code
*/
int dhe_key ( const void *modulus, size_t len, const void *generator,
size_t generator_len, const void *partner, size_t partner_len,
const void *private, size_t private_len, void *public,
void *shared ) {
unsigned int size = bigint_required_size ( len );
unsigned int private_size = bigint_required_size ( private_len );
bigint_t ( size ) *mod;
bigint_t ( private_size ) *exp;
size_t tmp_len = bigint_mod_exp_tmp_len ( mod, exp );
struct {
bigint_t ( size ) modulus;
bigint_t ( size ) generator;
bigint_t ( size ) partner;
bigint_t ( private_size ) private;
bigint_t ( size ) result;
uint8_t tmp[tmp_len];
} __attribute__ (( packed )) *ctx;
int rc;
DBGC2 ( modulus, "DHE %p modulus:\n", modulus );
DBGC2_HDA ( modulus, 0, modulus, len );
DBGC2 ( modulus, "DHE %p generator:\n", modulus );
DBGC2_HDA ( modulus, 0, generator, generator_len );
DBGC2 ( modulus, "DHE %p partner public key:\n", modulus );
DBGC2_HDA ( modulus, 0, partner, partner_len );
DBGC2 ( modulus, "DHE %p private key:\n", modulus );
DBGC2_HDA ( modulus, 0, private, private_len );
/* Sanity checks */
if ( generator_len > len ) {
DBGC ( modulus, "DHE %p overlength generator\n", modulus );
rc = -EINVAL;
goto err_sanity;
}
if ( partner_len > len ) {
DBGC ( modulus, "DHE %p overlength partner public key\n",
modulus );
rc = -EINVAL;
goto err_sanity;
}
if ( private_len > len ) {
DBGC ( modulus, "DHE %p overlength private key\n", modulus );
rc = -EINVAL;
goto err_sanity;
}
/* Allocate context */
ctx = malloc ( sizeof ( *ctx ) );
if ( ! ctx ) {
rc = -ENOMEM;
goto err_alloc;
}
/* Initialise context */
bigint_init ( &ctx->modulus, modulus, len );
bigint_init ( &ctx->generator, generator, generator_len );
bigint_init ( &ctx->partner, partner, partner_len );
bigint_init ( &ctx->private, private, private_len );
/* Calculate public key */
bigint_mod_exp ( &ctx->generator, &ctx->modulus, &ctx->private,
&ctx->result, ctx->tmp );
bigint_done ( &ctx->result, public, len );
DBGC2 ( modulus, "DHE %p public key:\n", modulus );
DBGC2_HDA ( modulus, 0, public, len );
/* Calculate shared secret */
bigint_mod_exp ( &ctx->partner, &ctx->modulus, &ctx->private,
&ctx->result, ctx->tmp );
bigint_done ( &ctx->result, shared, len );
DBGC2 ( modulus, "DHE %p shared secret:\n", modulus );
DBGC2_HDA ( modulus, 0, shared, len );
/* Success */
rc = 0;
free ( ctx );
err_alloc:
err_sanity:
return rc;
}

535
src/crypto/gcm.c 100644
View File

@ -0,0 +1,535 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
* Galois/Counter Mode (GCM)
*
* The GCM algorithm is specified in
*
* https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
* https://csrc.nist.rip/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
*
*/
#include <stdint.h>
#include <string.h>
#include <byteswap.h>
#include <ipxe/crypto.h>
#include <ipxe/gcm.h>
/**
* Perform encryption
*
* This value is chosen to allow for ANDing with a fragment length.
*/
#define GCM_FL_ENCRYPT 0x00ff
/**
* Calculate hash over an initialisation vector value
*
* The hash calculation for a non 96-bit initialisation vector is
* identical to the calculation used for additional data, except that
* the non-additional data length counter is used.
*/
#define GCM_FL_IV 0x0100
/**
* GCM field polynomial
*
* GCM treats 128-bit blocks as polynomials in GF(2^128) with the
* field polynomial f(x) = 1 + x + x^2 + x^7 + x^128.
*
* In a somewhat bloody-minded interpretation of "big-endian", the
* constant term (with degree zero) is arbitrarily placed in the
* leftmost bit of the big-endian binary representation (i.e. the most
* significant bit of byte 0), thereby failing to correspond to the
* bit ordering in any CPU architecture in existence. This
* necessitates some wholly gratuitous byte reversals when
* constructing the multiplication tables, since all CPUs will treat
* bit 0 as being the least significant bit within a byte.
*
* The field polynomial maps to the 128-bit constant
* 0xe1000000000000000000000000000000 (with the x^128 term outside the
* 128-bit range), and can therefore be treated as a single-byte
* value.
*/
#define GCM_POLY 0xe1
/**
* Hash key for which multiplication tables are cached
*
* GCM operates much more efficiently with a cached multiplication
* table, which costs 4kB per hash key. Since this exceeds the
* available stack space, we place a single 4kB cache in .bss and
* recalculate the cached values as required. In the common case of a
* single HTTPS connection being used to download a (relatively) large
* file, the same key will be used repeatedly for almost all GCM
* operations, and so the overhead of recalculation is negligible.
*/
static const union gcm_block *gcm_cached_key;
/**
* Cached multiplication table (M0) for Shoup's method
*
* Each entry within this table represents the result of multiplying
* the cached hash key by an arbitrary 8-bit polynomial.
*/
static union gcm_block gcm_cached_mult[256];
/**
* Cached reduction table (R) for Shoup's method
*
* Each entry within this table represents the result of multiplying
* the fixed polynomial x^128 by an arbitrary 8-bit polynomial. Only
* the leftmost 16 bits are stored, since all other bits within the
* result will always be zero.
*/
static uint16_t gcm_cached_reduce[256];
/**
* Reverse bits in a byte
*
* @v byte Byte
* @ret etyb Bit-reversed byte
*/
static inline __attribute__ (( always_inline )) uint8_t
gcm_reverse ( const uint8_t byte ) {
uint8_t etyb = etyb;
uint8_t mask;
for ( mask = 1 ; mask ; mask <<= 1 ) {
etyb <<= 1;
if ( byte & mask )
etyb |= 1;
}
return etyb;
}
/**
* Update GCM counter
*
* @v ctr Counter
* @v delta Amount to add to counter
*/
static inline __attribute__ (( always_inline )) void
gcm_count ( union gcm_block *ctr, uint32_t delta ) {
uint32_t *value = &ctr->ctr.value;
/* Update counter modulo 2^32 */
*value = cpu_to_be32 ( be32_to_cpu ( *value ) + delta );
}
/**
* XOR partial data block
*
* @v src1 Source buffer 1
* @v src2 Source buffer 2
* @v dst Destination buffer
* @v len Length
*/
static inline void gcm_xor ( const void *src1, const void *src2, void *dst,
size_t len ) {
uint8_t *dst_bytes = dst;
const uint8_t *src1_bytes = src1;
const uint8_t *src2_bytes = src2;
/* XOR one byte at a time */
while ( len-- )
*(dst_bytes++) = ( *(src1_bytes++) ^ *(src2_bytes++) );
}
/**
* XOR whole data block in situ
*
* @v src Source block
* @v dst Destination block
*/
static inline void gcm_xor_block ( const union gcm_block *src,
union gcm_block *dst ) {
/* XOR whole dwords */
dst->dword[0] ^= src->dword[0];
dst->dword[1] ^= src->dword[1];
dst->dword[2] ^= src->dword[2];
dst->dword[3] ^= src->dword[3];
}
/**
* Multiply polynomial by (x)
*
* @v mult Multiplicand
* @v res Result
*/
static void gcm_multiply_x ( const union gcm_block *mult,
union gcm_block *res ) {
unsigned int i;
uint8_t byte;
uint8_t carry;
/* Multiply by (x) by shifting all bits rightward */
for ( i = 0, carry = 0 ; i < sizeof ( res->byte ) ; i++ ) {
byte = mult->byte[i];
res->byte[i] = ( ( carry << 7 ) | ( byte >> 1 ) );
carry = ( byte & 0x01 );
}
/* If result overflows, reduce modulo the field polynomial */
if ( carry )
res->byte[0] ^= GCM_POLY;
}
/**
* Construct cached tables
*
* @v key Hash key
* @v context Context
*/
static void gcm_cache ( const union gcm_block *key ) {
union gcm_block *mult;
uint16_t reduce;
unsigned int this;
unsigned int other;
unsigned int i;
/* Calculate M0[1..255] and R[1..255]
*
* The R[] values are independent of the key, but the overhead
* of recalculating them here is negligible and saves on
* overall code size since the calculations are related.
*/
for ( i = 1 ; i < 256 ; i++ ) {
/* Reverse bit order to compensate for poor life choices */
this = gcm_reverse ( i );
/* Construct entries */
mult = &gcm_cached_mult[this];
if ( this & 0x80 ) {
/* Odd number: entry[i] = entry[i - 1] + poly */
other = ( this & 0x7f ); /* bit-reversed (i - 1) */
gcm_xor ( key, &gcm_cached_mult[other], mult,
sizeof ( *mult ) );
reduce = gcm_cached_reduce[other];
reduce ^= be16_to_cpu ( GCM_POLY << 8 );
gcm_cached_reduce[this] = reduce;
} else {
/* Even number: entry[i] = entry[i/2] * (x) */
other = ( this << 1 ); /* bit-reversed (i / 2) */
gcm_multiply_x ( &gcm_cached_mult[other], mult );
reduce = be16_to_cpu ( gcm_cached_reduce[other] );
reduce >>= 1;
gcm_cached_reduce[this] = cpu_to_be16 ( reduce );
}
}
/* Record cached key */
gcm_cached_key = key;
}
/**
* Multiply polynomial by (x^8) in situ
*
* @v poly Multiplicand and result
*/
static void gcm_multiply_x_8 ( union gcm_block *poly ) {
uint8_t *byte;
uint8_t msb;
/* Reduction table must already have been calculated */
assert ( gcm_cached_key != NULL );
/* Record most significant byte */
byte = &poly->byte[ sizeof ( poly->byte ) - 1 ];
msb = *byte;
/* Multiply least significant bytes by shifting */
for ( ; byte > &poly->byte[0] ; byte-- )
*byte = *( byte - 1 );
*byte = 0;
/* Multiply most significant byte via reduction table */
poly->word[0] ^= gcm_cached_reduce[msb];
}
/**
* Multiply polynomial by hash key in situ
*
* @v key Hash key
* @v poly Multiplicand and result
*/
static void gcm_multiply_key ( const union gcm_block *key,
union gcm_block *poly ) {
union gcm_block res;
uint8_t *byte;
/* Construct tables, if necessary */
if ( gcm_cached_key != key )
gcm_cache ( key );
/* Multiply using Shoup's algorithm */
byte = &poly->byte[ sizeof ( poly->byte ) - 1 ];
memcpy ( &res, &gcm_cached_mult[ *byte ], sizeof ( res ) );
for ( byte-- ; byte >= &poly->byte[0] ; byte-- ) {
gcm_multiply_x_8 ( &res );
gcm_xor_block ( &gcm_cached_mult[ *byte ], &res );
}
/* Overwrite result */
memcpy ( poly, &res, sizeof ( *poly ) );
}
/**
* Encrypt/decrypt/authenticate data
*
* @v context Context
* @v src Input data
* @v dst Output data, or NULL to process additional data
* @v len Length of data
* @v flags Operation flags
*/
static void gcm_process ( struct gcm_context *context, const void *src,
void *dst, size_t len, unsigned int flags ) {
union gcm_block tmp;
uint64_t *total;
size_t frag_len;
unsigned int block;
/* Calculate block number (for debugging) */
block = ( ( ( context->len.len.add + 8 * sizeof ( tmp ) - 1 ) /
( 8 * sizeof ( tmp ) ) ) +
( ( context->len.len.data + 8 * sizeof ( tmp ) - 1 ) /
( 8 * sizeof ( tmp ) ) ) + 1 );
/* Update total length (in bits) */
total = ( ( dst || ( flags & GCM_FL_IV ) ) ?
&context->len.len.data : &context->len.len.add );
*total += ( len * 8 );
/* Process data */
for ( ; len ; src += frag_len, len -= frag_len, block++ ) {
/* Calculate fragment length */
frag_len = len;
if ( frag_len > sizeof ( tmp ) )
frag_len = sizeof ( tmp );
/* Update hash with input data */
gcm_xor ( src, &context->hash, &context->hash, frag_len );
/* Encrypt/decrypt block, if applicable */
if ( dst ) {
/* Increment counter */
gcm_count ( &context->ctr, 1 );
/* Encrypt counter */
DBGC2 ( context, "GCM %p Y[%d]:\n", context, block );
DBGC2_HDA ( context, 0, &context->ctr,
sizeof ( context->ctr ) );
cipher_encrypt ( context->raw_cipher, &context->raw_ctx,
&context->ctr, &tmp, sizeof ( tmp ) );
DBGC2 ( context, "GCM %p E(K,Y[%d]):\n",
context, block );
DBGC2_HDA ( context, 0, &tmp, sizeof ( tmp ) );
/* Encrypt/decrypt data */
gcm_xor ( src, &tmp, dst, frag_len );
dst += frag_len;
/* Update hash with encrypted data, if applicable */
gcm_xor ( &tmp, &context->hash, &context->hash,
( frag_len & flags ) );
}
/* Update hash */
gcm_multiply_key ( &context->key, &context->hash );
DBGC2 ( context, "GCM %p X[%d]:\n", context, block );
DBGC2_HDA ( context, 0, &context->hash,
sizeof ( context->hash ) );
}
}
/**
* Construct hash
*
* @v context Context
* @v hash Hash to fill in
*/
static void gcm_hash ( struct gcm_context *context, union gcm_block *hash ) {
/* Construct big-endian lengths block */
hash->len.add = cpu_to_be64 ( context->len.len.add );
hash->len.data = cpu_to_be64 ( context->len.len.data );
DBGC2 ( context, "GCM %p len(A)||len(C):\n", context );
DBGC2_HDA ( context, 0, hash, sizeof ( *hash ) );
/* Update hash */
gcm_xor_block ( &context->hash, hash );
gcm_multiply_key ( &context->key, hash );
DBGC2 ( context, "GCM %p GHASH(H,A,C):\n", context );
DBGC2_HDA ( context, 0, hash, sizeof ( *hash ) );
}
/**
* Construct tag
*
* @v context Context
* @v tag Tag
*/
void gcm_tag ( struct gcm_context *context, union gcm_block *tag ) {
union gcm_block tmp;
uint32_t offset;
/* Construct hash */
gcm_hash ( context, tag );
/* Construct encrypted initial counter value */
memcpy ( &tmp, &context->ctr, sizeof ( tmp ) );
offset = ( ( -context->len.len.data ) / ( 8 * sizeof ( tmp ) ) );
gcm_count ( &tmp, offset );
cipher_encrypt ( context->raw_cipher, &context->raw_ctx, &tmp,
&tmp, sizeof ( tmp ) );
DBGC2 ( context, "GCM %p E(K,Y[0]):\n", context );
DBGC2_HDA ( context, 0, &tmp, sizeof ( tmp ) );
/* Construct tag */
gcm_xor_block ( &tmp, tag );
DBGC2 ( context, "GCM %p T:\n", context );
DBGC2_HDA ( context, 0, tag, sizeof ( *tag ) );
}
/**
* Set key
*
* @v context Context
* @v key Key
* @v keylen Key length
* @v raw_cipher Underlying cipher
* @ret rc Return status code
*/
int gcm_setkey ( struct gcm_context *context, const void *key, size_t keylen,
struct cipher_algorithm *raw_cipher ) {
int rc;
/* Initialise GCM context */
memset ( context, 0, sizeof ( *context ) );
context->raw_cipher = raw_cipher;
/* Set underlying block cipher key */
if ( ( rc = cipher_setkey ( raw_cipher, context->raw_ctx, key,
keylen ) ) != 0 )
return rc;
/* Construct GCM hash key */
cipher_encrypt ( raw_cipher, context->raw_ctx, &context->ctr,
&context->key, sizeof ( context->key ) );
DBGC2 ( context, "GCM %p H:\n", context );
DBGC2_HDA ( context, 0, &context->key, sizeof ( context->key ) );
/* Reset counter */
context->ctr.ctr.value = cpu_to_be32 ( 1 );
/* Construct cached tables */
gcm_cache ( &context->key );
return 0;
}
/**
* Set initialisation vector
*
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
*/
void gcm_setiv ( struct gcm_context *context, const void *iv, size_t ivlen ) {
union gcm_block *check = ( ( void * ) context );
/* Sanity checks */
linker_assert ( &context->hash == check, gcm_bad_layout );
linker_assert ( &context->len == check + 1, gcm_bad_layout );
linker_assert ( &context->ctr == check + 2, gcm_bad_layout );
linker_assert ( &context->key == check + 3, gcm_bad_layout );
/* Reset non-key state */
memset ( context, 0, offsetof ( typeof ( *context ), key ) );
/* Reset counter */
context->ctr.ctr.value = cpu_to_be32 ( 1 );
/* Process initialisation vector */
if ( ivlen == sizeof ( context->ctr.ctr.iv ) ) {
/* Initialisation vector is exactly 96 bits, use it as-is */
memcpy ( context->ctr.ctr.iv, iv, ivlen );
} else {
/* Calculate hash over initialisation vector */
gcm_process ( context, iv, NULL, ivlen, GCM_FL_IV );
gcm_hash ( context, &context->ctr );
assert ( context->len.len.add == 0 );
/* Reset non-key, non-counter state */
memset ( context, 0, offsetof ( typeof ( *context ), ctr ) );
}
DBGC2 ( context, "GCM %p Y[0]:\n", context );
DBGC2_HDA ( context, 0, &context->ctr, sizeof ( context->ctr ) );
}
/**
* Encrypt data
*
* @v context Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data, or NULL for additional data
* @v len Length of data
*/
void gcm_encrypt ( struct gcm_context *context, const void *src, void *dst,
size_t len ) {
/* Process data */
gcm_process ( context, src, dst, len, GCM_FL_ENCRYPT );
}
/**
* Decrypt data
*
* @v context Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data, or NULL for additional data
* @v len Length of data
*/
void gcm_decrypt ( struct gcm_context *context, const void *src, void *dst,
size_t len ) {
/* Process data */
gcm_process ( context, src, dst, len, 0 );
}

View File

@ -46,94 +46,62 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/crypto.h>
#include <ipxe/hmac.h>
/**
* Reduce HMAC key length
*
* @v digest Digest algorithm to use
* @v digest_ctx Digest context
* @v key Key
* @v key_len Length of key
*/
static void hmac_reduce_key ( struct digest_algorithm *digest,
void *key, size_t *key_len ) {
uint8_t digest_ctx[digest->ctxsize];
digest_init ( digest, digest_ctx );
digest_update ( digest, digest_ctx, key, *key_len );
digest_final ( digest, digest_ctx, key );
*key_len = digest->digestsize;
}
/**
* Initialise HMAC
*
* @v digest Digest algorithm to use
* @v digest_ctx Digest context
* @v ctx HMAC context
* @v key Key
* @v key_len Length of key
*
* The length of the key should be less than the block size of the
* digest algorithm being used. (If the key length is greater, it
* will be replaced with its own digest, and key_len will be updated
* accordingly).
*/
void hmac_init ( struct digest_algorithm *digest, void *digest_ctx,
void *key, size_t *key_len ) {
unsigned char k_ipad[digest->blocksize];
void hmac_init ( struct digest_algorithm *digest, void *ctx, const void *key,
size_t key_len ) {
hmac_context_t ( digest ) *hctx = ctx;
unsigned int i;
/* Reduce key if necessary */
if ( *key_len > sizeof ( k_ipad ) )
hmac_reduce_key ( digest, key, key_len );
/* Construct input pad */
memset ( k_ipad, 0, sizeof ( k_ipad ) );
memcpy ( k_ipad, key, *key_len );
for ( i = 0 ; i < sizeof ( k_ipad ) ; i++ ) {
k_ipad[i] ^= 0x36;
memset ( hctx->pad, 0, sizeof ( hctx->pad ) );
if ( key_len <= sizeof ( hctx->pad ) ) {
memcpy ( hctx->pad, key, key_len );
} else {
digest_init ( digest, hctx->ctx );
digest_update ( digest, hctx->ctx, key, key_len );
digest_final ( digest, hctx->ctx, hctx->pad );
}
for ( i = 0 ; i < sizeof ( hctx->pad ) ; i++ ) {
hctx->pad[i] ^= 0x36;
}
/* Start inner hash */
digest_init ( digest, digest_ctx );
digest_update ( digest, digest_ctx, k_ipad, sizeof ( k_ipad ) );
digest_init ( digest, hctx->ctx );
digest_update ( digest, hctx->ctx, hctx->pad, sizeof ( hctx->pad ) );
}
/**
* Finalise HMAC
*
* @v digest Digest algorithm to use
* @v digest_ctx Digest context
* @v key Key
* @v key_len Length of key
* @v ctx HMAC context
* @v hmac HMAC digest to fill in
*
* The length of the key should be less than the block size of the
* digest algorithm being used. (If the key length is greater, it
* will be replaced with its own digest, and key_len will be updated
* accordingly).
*/
void hmac_final ( struct digest_algorithm *digest, void *digest_ctx,
void *key, size_t *key_len, void *hmac ) {
unsigned char k_opad[digest->blocksize];
void hmac_final ( struct digest_algorithm *digest, void *ctx, void *hmac ) {
hmac_context_t ( digest ) *hctx = ctx;
unsigned int i;
/* Reduce key if necessary */
if ( *key_len > sizeof ( k_opad ) )
hmac_reduce_key ( digest, key, key_len );
/* Construct output pad */
memset ( k_opad, 0, sizeof ( k_opad ) );
memcpy ( k_opad, key, *key_len );
for ( i = 0 ; i < sizeof ( k_opad ) ; i++ ) {
k_opad[i] ^= 0x5c;
/* Construct output pad from input pad */
for ( i = 0 ; i < sizeof ( hctx->pad ) ; i++ ) {
hctx->pad[i] ^= 0x6a;
}
/* Finish inner hash */
digest_final ( digest, digest_ctx, hmac );
digest_final ( digest, hctx->ctx, hmac );
/* Perform outer hash */
digest_init ( digest, digest_ctx );
digest_update ( digest, digest_ctx, k_opad, sizeof ( k_opad ) );
digest_update ( digest, digest_ctx, hmac, digest->digestsize );
digest_final ( digest, digest_ctx, hmac );
digest_init ( digest, hctx->ctx );
digest_update ( digest, hctx->ctx, hctx->pad, sizeof ( hctx->pad ) );
digest_update ( digest, hctx->ctx, hmac, digest->digestsize );
digest_final ( digest, hctx->ctx, hmac );
/* Erase output pad (from which the key may be derivable) */
memset ( hctx->pad, 0, sizeof ( hctx->pad ) );
}

View File

@ -79,7 +79,7 @@ static void hmac_drbg_update_key ( struct digest_algorithm *hash,
struct hmac_drbg_state *state,
const void *data, size_t len,
const uint8_t single ) {
uint8_t context[ hash->ctxsize ];
uint8_t context[ hmac_ctxsize ( hash ) ];
size_t out_len = hash->digestsize;
DBGC ( state, "HMAC_DRBG_%s %p provided data :\n", hash->name, state );
@ -92,13 +92,11 @@ static void hmac_drbg_update_key ( struct digest_algorithm *hash,
assert ( ( single == 0x00 ) || ( single == 0x01 ) );
/* K = HMAC ( K, V || single || provided_data ) */
hmac_init ( hash, context, state->key, &out_len );
assert ( out_len == hash->digestsize );
hmac_init ( hash, context, state->key, out_len );
hmac_update ( hash, context, state->value, out_len );
hmac_update ( hash, context, &single, sizeof ( single ) );
hmac_update ( hash, context, data, len );
hmac_final ( hash, context, state->key, &out_len, state->key );
assert ( out_len == hash->digestsize );
hmac_final ( hash, context, state->key );
DBGC ( state, "HMAC_DRBG_%s %p K = HMAC ( K, V || %#02x || "
"provided_data ) :\n", hash->name, state, single );
@ -122,7 +120,7 @@ static void hmac_drbg_update_key ( struct digest_algorithm *hash,
*/
static void hmac_drbg_update_value ( struct digest_algorithm *hash,
struct hmac_drbg_state *state ) {
uint8_t context[ hash->ctxsize ];
uint8_t context[ hmac_ctxsize ( hash ) ];
size_t out_len = hash->digestsize;
/* Sanity checks */
@ -130,11 +128,9 @@ static void hmac_drbg_update_value ( struct digest_algorithm *hash,
assert ( state != NULL );
/* V = HMAC ( K, V ) */
hmac_init ( hash, context, state->key, &out_len );
assert ( out_len == hash->digestsize );
hmac_init ( hash, context, state->key, out_len );
hmac_update ( hash, context, state->value, out_len );
hmac_final ( hash, context, state->key, &out_len, state->value );
assert ( out_len == hash->digestsize );
hmac_final ( hash, context, state->value );
DBGC ( state, "HMAC_DRBG_%s %p V = HMAC ( K, V ) :\n",
hash->name, state );

View File

@ -27,22 +27,65 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha1.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_RSA_WITH_AES_128_CBC_SHA cipher suite */
struct tls_cipher_suite tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite (03) = {
.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ),
/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 05 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 06 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_RSA_WITH_AES_128_CBC_SHA cipher suite */
struct tls_cipher_suite
tls_rsa_with_aes_128_cbc_sha __tls_cipher_suite ( 15 ) = {
.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_pubkey_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_RSA_WITH_AES_256_CBC_SHA cipher suite */
struct tls_cipher_suite tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite (04) = {
struct tls_cipher_suite
tls_rsa_with_aes_256_cbc_sha __tls_cipher_suite ( 16 ) = {
.code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA1_DIGEST_SIZE,
.exchange = &tls_pubkey_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha1_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -29,20 +29,62 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_RSA_WITH_AES_128_CBC_SHA256 cipher suite */
struct tls_cipher_suite tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite(01)={
.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ),
/** TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 03 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA256_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 04 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA256_DIGEST_SIZE,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_RSA_WITH_AES_128_CBC_SHA256 cipher suite */
struct tls_cipher_suite
tls_rsa_with_aes_128_cbc_sha256 __tls_cipher_suite ( 13 ) = {
.code = htons ( TLS_RSA_WITH_AES_128_CBC_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA256_DIGEST_SIZE,
.exchange = &tls_pubkey_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_RSA_WITH_AES_256_CBC_SHA256 cipher suite */
struct tls_cipher_suite tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite(02)={
struct tls_cipher_suite
tls_rsa_with_aes_256_cbc_sha256 __tls_cipher_suite ( 14 ) = {
.code = htons ( TLS_RSA_WITH_AES_256_CBC_SHA256 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 0,
.record_iv_len = AES_BLOCKSIZE,
.mac_len = SHA256_DIGEST_SIZE,
.exchange = &tls_pubkey_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_cbc_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha256.h>
#include <ipxe/tls.h>
/** TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 01 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};
/** TLS_RSA_WITH_AES_128_GCM_SHA256 cipher suite */
struct tls_cipher_suite
tls_rsa_with_aes_128_gcm_sha256 __tls_cipher_suite ( 11 ) = {
.code = htons ( TLS_RSA_WITH_AES_128_GCM_SHA256 ),
.key_len = ( 128 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_pubkey_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha256_algorithm,
.handshake = &sha256_algorithm,
};

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <byteswap.h>
#include <ipxe/rsa.h>
#include <ipxe/aes.h>
#include <ipxe/sha512.h>
#include <ipxe/tls.h>
/** TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 cipher suite */
struct tls_cipher_suite
tls_dhe_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 02 ) = {
.code = htons ( TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_dhe_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha384_algorithm,
.handshake = &sha384_algorithm,
};
/** TLS_RSA_WITH_AES_256_GCM_SHA384 cipher suite */
struct tls_cipher_suite
tls_rsa_with_aes_256_gcm_sha384 __tls_cipher_suite ( 12 ) = {
.code = htons ( TLS_RSA_WITH_AES_256_GCM_SHA384 ),
.key_len = ( 256 / 8 ),
.fixed_iv_len = 4,
.record_iv_len = 8,
.mac_len = 0,
.exchange = &tls_pubkey_exchange_algorithm,
.pubkey = &rsa_algorithm,
.cipher = &aes_gcm_algorithm,
.digest = &sha384_algorithm,
.handshake = &sha384_algorithm,
};

View File

@ -117,10 +117,9 @@ void ntlm_key ( const char *domain, const char *username,
struct digest_algorithm *md5 = &md5_algorithm;
union {
uint8_t md4[MD4_CTX_SIZE];
uint8_t md5[MD5_CTX_SIZE];
uint8_t md5[ MD5_CTX_SIZE + MD5_BLOCK_SIZE ];
} ctx;
uint8_t digest[MD4_DIGEST_SIZE];
size_t digest_len;
uint8_t c;
uint16_t wc;
@ -141,8 +140,7 @@ void ntlm_key ( const char *domain, const char *username,
digest_final ( md4, ctx.md4, digest );
/* Construct HMAC-MD5 of (Unicode) upper-case username */
digest_len = sizeof ( digest );
hmac_init ( md5, ctx.md5, digest, &digest_len );
hmac_init ( md5, ctx.md5, digest, sizeof ( digest ) );
while ( ( c = *(username++) ) ) {
wc = cpu_to_le16 ( toupper ( c ) );
hmac_update ( md5, ctx.md5, &wc, sizeof ( wc ) );
@ -151,7 +149,7 @@ void ntlm_key ( const char *domain, const char *username,
wc = cpu_to_le16 ( c );
hmac_update ( md5, ctx.md5, &wc, sizeof ( wc ) );
}
hmac_final ( md5, ctx.md5, digest, &digest_len, key->raw );
hmac_final ( md5, ctx.md5, key->raw );
DBGC ( key, "NTLM key:\n" );
DBGC_HDA ( key, 0, key, sizeof ( *key ) );
}
@ -170,8 +168,7 @@ void ntlm_response ( struct ntlm_challenge_info *info, struct ntlm_key *key,
struct ntlm_nt_response *nt ) {
struct digest_algorithm *md5 = &md5_algorithm;
struct ntlm_nonce tmp_nonce;
uint8_t ctx[MD5_CTX_SIZE];
size_t key_len = sizeof ( *key );
uint8_t ctx[ MD5_CTX_SIZE + MD5_BLOCK_SIZE ];
unsigned int i;
/* Generate random nonce, if needed */
@ -183,10 +180,10 @@ void ntlm_response ( struct ntlm_challenge_info *info, struct ntlm_key *key,
/* Construct LAN Manager response */
memcpy ( &lm->nonce, nonce, sizeof ( lm->nonce ) );
hmac_init ( md5, ctx, key->raw, &key_len );
hmac_init ( md5, ctx, key->raw, sizeof ( *key ) );
hmac_update ( md5, ctx, info->nonce, sizeof ( *info->nonce ) );
hmac_update ( md5, ctx, &lm->nonce, sizeof ( lm->nonce ) );
hmac_final ( md5, ctx, key->raw, &key_len, lm->digest );
hmac_final ( md5, ctx, lm->digest );
DBGC ( key, "NTLM LAN Manager response:\n" );
DBGC_HDA ( key, 0, lm, sizeof ( *lm ) );
@ -195,14 +192,14 @@ void ntlm_response ( struct ntlm_challenge_info *info, struct ntlm_key *key,
nt->version = NTLM_VERSION_NTLMV2;
nt->high = NTLM_VERSION_NTLMV2;
memcpy ( &nt->nonce, nonce, sizeof ( nt->nonce ) );
hmac_init ( md5, ctx, key->raw, &key_len );
hmac_init ( md5, ctx, key->raw, sizeof ( *key ) );
hmac_update ( md5, ctx, info->nonce, sizeof ( *info->nonce ) );
hmac_update ( md5, ctx, &nt->version,
( sizeof ( *nt ) -
offsetof ( typeof ( *nt ), version ) ) );
hmac_update ( md5, ctx, info->target, info->len );
hmac_update ( md5, ctx, &nt->zero, sizeof ( nt->zero ) );
hmac_final ( md5, ctx, key->raw, &key_len, nt->digest );
hmac_final ( md5, ctx, nt->digest );
DBGC ( key, "NTLM NT response prefix:\n" );
DBGC_HDA ( key, 0, nt, sizeof ( *nt ) );
}

View File

@ -49,7 +49,7 @@ void prf_sha1 ( const void *key, size_t key_len, const char *label,
u8 in[strlen ( label ) + 1 + data_len + 1]; /* message to HMAC */
u8 *in_blknr; /* pointer to last byte of in, block number */
u8 out[SHA1_DIGEST_SIZE]; /* HMAC-SHA1 result */
u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */
u8 ctx[SHA1_CTX_SIZE + SHA1_BLOCK_SIZE]; /* HMAC-SHA1 context */
const size_t label_len = strlen ( label );
/* The HMAC-SHA-1 is calculated using the given key on the
@ -65,9 +65,9 @@ void prf_sha1 ( const void *key, size_t key_len, const char *label,
for ( blk = 0 ;; blk++ ) {
*in_blknr = blk;
hmac_init ( &sha1_algorithm, sha1_ctx, keym, &key_len );
hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) );
hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out );
hmac_init ( &sha1_algorithm, ctx, keym, key_len );
hmac_update ( &sha1_algorithm, ctx, in, sizeof ( in ) );
hmac_final ( &sha1_algorithm, ctx, out );
if ( prf_len <= sizeof ( out ) ) {
memcpy ( prf, out, prf_len );
@ -100,7 +100,7 @@ static void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len,
u8 pass[pass_len]; /* modifiable passphrase */
u8 in[salt_len + 4]; /* input buffer to first round */
u8 last[SHA1_DIGEST_SIZE]; /* output of round N, input of N+1 */
u8 sha1_ctx[SHA1_CTX_SIZE];
u8 ctx[SHA1_CTX_SIZE + SHA1_BLOCK_SIZE];
u8 *next_in = in; /* changed to `last' after first round */
int next_size = sizeof ( in );
int i;
@ -114,9 +114,9 @@ static void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len,
memset ( block, 0, sizeof ( last ) );
for ( i = 0; i < iterations; i++ ) {
hmac_init ( &sha1_algorithm, sha1_ctx, pass, &pass_len );
hmac_update ( &sha1_algorithm, sha1_ctx, next_in, next_size );
hmac_final ( &sha1_algorithm, sha1_ctx, pass, &pass_len, last );
hmac_init ( &sha1_algorithm, ctx, pass, pass_len );
hmac_update ( &sha1_algorithm, ctx, next_in, next_size );
hmac_final ( &sha1_algorithm, ctx, last );
for ( j = 0; j < sizeof ( last ); j++ ) {
block[j] ^= last[j];

View File

@ -0,0 +1,267 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h>
#include <ipxe/uaccess.h>
#include <ipxe/ecam.h>
/** @file
*
* PCI Enhanced Configuration Access Mechanism (ECAM)
*
*/
/** Cached mapped ECAM allocation */
static struct ecam_mapping ecam;
/**
* Find lowest ECAM allocation not below a given PCI bus:dev.fn address
*
* @v busdevfn PCI bus:dev.fn address
* @v range PCI device address range to fill in
* @v alloc ECAM allocation to fill in, or NULL
* @ret rc Return status code
*/
static int ecam_find ( uint32_t busdevfn, struct pci_range *range,
struct ecam_allocation *alloc ) {
struct ecam_allocation tmp;
unsigned int best = 0;
unsigned int offset;
unsigned int count;
unsigned int index;
userptr_t mcfg;
uint32_t length;
uint32_t start;
/* Return empty range on error */
range->count = 0;
/* Locate MCFG table */
mcfg = acpi_table ( ECAM_SIGNATURE, 0 );
if ( ! mcfg ) {
DBGC ( &ecam, "ECAM found no MCFG table\n" );
return -ENOTSUP;
}
/* Get length of table */
copy_from_user ( &length, mcfg,
offsetof ( struct ecam_table, acpi.length ),
sizeof ( length ) );
/* Iterate over allocations */
for ( offset = offsetof ( struct ecam_table, alloc ) ;
( offset + sizeof ( tmp ) ) <= le32_to_cpu ( length ) ;
offset += sizeof ( tmp ) ) {
/* Read allocation */
copy_from_user ( &tmp, mcfg, offset, sizeof ( tmp ) );
DBGC2 ( &ecam, "ECAM %04x:[%02x-%02x] has base %08llx\n",
le16_to_cpu ( tmp.segment ), tmp.start, tmp.end,
( ( unsigned long long ) le64_to_cpu ( tmp.base ) ) );
start = PCI_BUSDEVFN ( le16_to_cpu ( tmp.segment ),
tmp.start, 0, 0 );
count = PCI_BUSDEVFN ( 0, ( tmp.end - tmp.start + 1 ), 0, 0 );
/* Check for a matching or new closest allocation */
index = ( busdevfn - start );
if ( ( index < count ) || ( index > best ) ) {
if ( alloc )
memcpy ( alloc, &tmp, sizeof ( *alloc ) );
range->start = start;
range->count = count;
best = index;
}
/* Stop if this range contains the target bus:dev.fn address */
if ( index < count )
return 0;
}
return ( best ? 0 : -ENOENT );
}
/**
* Find next PCI bus:dev.fn address range in system
*
* @v busdevfn Starting PCI bus:dev.fn address
* @v range PCI bus:dev.fn address range to fill in
*/
static void ecam_discover ( uint32_t busdevfn, struct pci_range *range ) {
/* Find new range, if any */
ecam_find ( busdevfn, range, NULL );
}
/**
* Access configuration space for PCI device
*
* @v pci PCI device
* @ret rc Return status code
*/
static int ecam_access ( struct pci_device *pci ) {
uint64_t base;
size_t len;
int rc;
/* Reuse mapping if possible */
if ( ( pci->busdevfn - ecam.range.start ) < ecam.range.count )
return 0;
/* Clear any existing mapping */
if ( ecam.regs ) {
iounmap ( ecam.regs );
ecam.regs = NULL;
}
/* Find allocation for this PCI device */
if ( ( rc = ecam_find ( pci->busdevfn, &ecam.range,
&ecam.alloc ) ) != 0 ) {
DBGC ( &ecam, "ECAM found no allocation for " PCI_FMT ": %s\n",
PCI_ARGS ( pci ), strerror ( rc ) );
goto err_find;
}
if ( ecam.range.start > pci->busdevfn ) {
DBGC ( &ecam, "ECAM found no allocation for " PCI_FMT "\n",
PCI_ARGS ( pci ) );
goto err_find;
}
/* Map configuration space for this allocation */
base = le64_to_cpu ( ecam.alloc.base );
len = ( ecam.range.count * ECAM_SIZE );
ecam.regs = ioremap ( base, len );
if ( ! ecam.regs ) {
DBGC ( &ecam, "ECAM %04x:[%02x-%02x] could not map "
"[%08llx,%08llx)\n", le16_to_cpu ( ecam.alloc.segment ),
ecam.alloc.start, ecam.alloc.end, base, ( base + len ) );
rc = -ENODEV;
goto err_ioremap;
}
/* Populate cached mapping */
DBGC ( &ecam, "ECAM %04x:[%02x-%02x] mapped [%08llx,%08llx) -> %p\n",
le16_to_cpu ( ecam.alloc.segment ), ecam.alloc.start,
ecam.alloc.end, base, ( base + len ), ecam.regs );
return 0;
iounmap ( ecam.regs );
err_ioremap:
err_find:
ecam.range.count = 0;
return rc;
}
/**
* Read from PCI configuration space
*
* @v pci PCI device
* @v location Offset and length within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
int ecam_read ( struct pci_device *pci, unsigned int location, void *value ) {
unsigned int where = ECAM_WHERE ( location );
unsigned int len = ECAM_LEN ( location );
unsigned int index;
void *addr;
int rc;
/* Return all-ones on error */
memset ( value, 0xff, len );
/* Access configuration space */
if ( ( rc = ecam_access ( pci ) ) != 0 )
return rc;
/* Read from address */
index = ( pci->busdevfn - ecam.range.start );
addr = ( ecam.regs + ( index * ECAM_SIZE ) + where );
switch ( len ) {
case 4:
*( ( uint32_t *) value ) = readl ( addr );
break;
case 2:
*( ( uint16_t *) value ) = readw ( addr );
break;
case 1:
*( ( uint8_t *) value ) = readb ( addr );
break;
default:
assert ( 0 );
}
return 0;
}
/**
* Write to PCI configuration space
*
* @v pci PCI device
* @v location Offset and length within PCI configuration space
* @v value Value to write
* @ret rc Return status code
*/
int ecam_write ( struct pci_device *pci, unsigned int location,
unsigned long value ) {
unsigned int where = ECAM_WHERE ( location );
unsigned int len = ECAM_LEN ( location );
unsigned int index;
void *addr;
int rc;
/* Access configuration space */
if ( ( rc = ecam_access ( pci ) ) != 0 )
return rc;
/* Read from address */
index = ( pci->busdevfn - ecam.range.start );
addr = ( ecam.regs + ( index * ECAM_SIZE ) + where );
switch ( len ) {
case 4:
writel ( value, addr );
break;
case 2:
writew ( value, addr );
break;
case 1:
writeb ( value, addr );
break;
default:
assert ( 0 );
}
return 0;
}
PROVIDE_PCIAPI ( ecam, pci_discover, ecam_discover );
PROVIDE_PCIAPI_INLINE ( ecam, pci_read_config_byte );
PROVIDE_PCIAPI_INLINE ( ecam, pci_read_config_word );
PROVIDE_PCIAPI_INLINE ( ecam, pci_read_config_dword );
PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_byte );
PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_word );
PROVIDE_PCIAPI_INLINE ( ecam, pci_write_config_dword );
PROVIDE_PCIAPI_INLINE ( ecam, pci_ioremap );
struct pci_api ecam_api = PCIAPI_RUNTIME ( ecam );

View File

@ -229,46 +229,55 @@ int pci_read_config ( struct pci_device *pci ) {
*
* @v pci PCI device to fill in
* @v busdevfn Starting bus:dev.fn address
* @ret busdevfn Bus:dev.fn address of next PCI device, or negative error
* @ret busdevfn Bus:dev.fn address of next PCI device
* @ret rc Return status code
*/
int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) {
static unsigned int end;
unsigned int sub_end;
int pci_find_next ( struct pci_device *pci, uint32_t *busdevfn ) {
static struct pci_range range;
uint8_t hdrtype;
uint8_t sub;
uint32_t end;
unsigned int count;
int rc;
/* Determine number of PCI buses */
if ( ! end )
end = PCI_BUSDEVFN ( 0, pci_num_bus(), 0, 0 );
/* Find next PCI device, if any */
for ( ; busdevfn < end ; busdevfn++ ) {
do {
/* Find next PCI bus:dev.fn address range, if necessary */
if ( ( *busdevfn - range.start ) >= range.count ) {
pci_discover ( *busdevfn, &range );
if ( *busdevfn < range.start )
*busdevfn = range.start;
if ( ( *busdevfn - range.start ) >= range.count )
break;
}
/* Check for PCI device existence */
memset ( pci, 0, sizeof ( *pci ) );
pci_init ( pci, busdevfn );
pci_init ( pci, *busdevfn );
if ( ( rc = pci_read_config ( pci ) ) != 0 )
continue;
/* If device is a bridge, expand the number of PCI
* buses as needed.
/* If device is a bridge, expand the PCI bus:dev.fn
* address range as needed.
*/
pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdrtype );
hdrtype &= PCI_HEADER_TYPE_MASK;
if ( hdrtype == PCI_HEADER_TYPE_BRIDGE ) {
pci_read_config_byte ( pci, PCI_SUBORDINATE, &sub );
sub_end = PCI_BUSDEVFN ( 0, ( sub + 1 ), 0, 0 );
if ( end < sub_end ) {
end = PCI_BUSDEVFN ( PCI_SEG ( *busdevfn ),
( sub + 1 ), 0, 0 );
count = ( end - range.start );
if ( count > range.count ) {
DBGC ( pci, PCI_FMT " found subordinate bus "
"%#02x\n", PCI_ARGS ( pci ), sub );
end = sub_end;
range.count = count;
}
}
/* Return this device */
return busdevfn;
}
return 0;
} while ( ++(*busdevfn) );
return -ENODEV;
}
@ -348,11 +357,10 @@ void pci_remove ( struct pci_device *pci ) {
*/
static int pcibus_probe ( struct root_device *rootdev ) {
struct pci_device *pci = NULL;
int busdevfn = 0;
uint32_t busdevfn = 0;
int rc;
for ( busdevfn = 0 ; 1 ; busdevfn++ ) {
do {
/* Allocate struct pci_device */
if ( ! pci )
pci = malloc ( sizeof ( *pci ) );
@ -362,8 +370,7 @@ static int pcibus_probe ( struct root_device *rootdev ) {
}
/* Find next PCI device, if any */
busdevfn = pci_find_next ( pci, busdevfn );
if ( busdevfn < 0 )
if ( ( rc = pci_find_next ( pci, &busdevfn ) ) != 0 )
break;
/* Look for a driver */
@ -386,7 +393,8 @@ static int pcibus_probe ( struct root_device *rootdev ) {
/* Not registered; re-use struct pci_device */
list_del ( &pci->dev.siblings );
}
}
} while ( ++busdevfn );
free ( pci );
return 0;

View File

@ -61,14 +61,15 @@ pci_backup_excluded ( struct pci_device *pci, unsigned int offset,
*
* @v pci PCI device
* @v backup PCI configuration space backup
* @v limit Maximum offset in PCI configuration space
* @v exclude PCI configuration space backup exclusion list, or NULL
*/
void pci_backup ( struct pci_device *pci, struct pci_config_backup *backup,
const uint8_t *exclude ) {
unsigned int limit, const uint8_t *exclude ) {
unsigned int offset;
uint32_t *dword;
for ( offset = 0, dword = backup->dwords ; offset < 0x100 ;
for ( offset = 0, dword = backup->dwords ; offset < limit ;
offset += sizeof ( *dword ) , dword++ ) {
if ( ! pci_backup_excluded ( pci, offset, exclude ) )
pci_read_config_dword ( pci, offset, dword );
@ -80,14 +81,15 @@ void pci_backup ( struct pci_device *pci, struct pci_config_backup *backup,
*
* @v pci PCI device
* @v backup PCI configuration space backup
* @v limit Maximum offset in PCI configuration space
* @v exclude PCI configuration space backup exclusion list, or NULL
*/
void pci_restore ( struct pci_device *pci, struct pci_config_backup *backup,
const uint8_t *exclude ) {
unsigned int limit, const uint8_t *exclude ) {
unsigned int offset;
uint32_t *dword;
for ( offset = 0, dword = backup->dwords ; offset < 0x100 ;
for ( offset = 0, dword = backup->dwords ; offset < limit ;
offset += sizeof ( *dword ) , dword++ ) {
if ( ! pci_backup_excluded ( pci, offset, exclude ) )
pci_write_config_dword ( pci, offset, *dword );

View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2022 Michael Brown <mbrown@fensystems.co.uk>.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/pci.h>
#include <ipxe/pcibridge.h>
/** @file
*
* PCI-to-PCI bridge
*
*/
/** List of all PCI bridges */
static LIST_HEAD ( pcibridges );
/**
* Find bridge attached to a PCI device
*
* @v pci PCI device
* @ret bridge PCI bridge, or NULL
*/
struct pci_bridge * pcibridge_find ( struct pci_device *pci ) {
unsigned int bus = PCI_BUS ( pci->busdevfn );
struct pci_bridge *bridge;
/* Find matching bridge */
list_for_each_entry ( bridge, &pcibridges, list ) {
if ( bus == bridge->secondary )
return bridge;
}
return NULL;
}
/**
* Probe PCI device
*
* @v pci PCI device
* @ret rc Return status code
*/
static int pcibridge_probe ( struct pci_device *pci ) {
struct pci_bridge *bridge;
uint16_t base;
uint16_t limit;
int rc;
/* Allocate and initialise structure */
bridge = zalloc ( sizeof ( *bridge ) );
if ( ! bridge ) {
rc = -ENOMEM;
goto err_alloc;
}
bridge->pci = pci;
/* Read configuration */
pci_read_config_dword ( pci, PCI_PRIMARY, &bridge->buses );
cpu_to_le32s ( &buses );
pci_read_config_word ( pci, PCI_MEM_BASE, &base );
bridge->membase = ( ( base & ~PCI_MEM_MASK ) << 16 );
pci_read_config_word ( pci, PCI_MEM_LIMIT, &limit );
bridge->memlimit = ( ( ( ( limit | PCI_MEM_MASK ) + 1 ) << 16 ) - 1 );
DBGC ( bridge, "BRIDGE " PCI_FMT " bus %02x to [%02x,%02x) mem "
"[%08x,%08x)\n", PCI_ARGS ( pci ), bridge->primary,
bridge->secondary, bridge->subordinate, bridge->membase,
bridge->memlimit );
/* Add to list of PCI bridges */
list_add ( &bridge->list, &pcibridges );
pci_set_drvdata ( pci, bridge );
return 0;
free ( bridge );
err_alloc:
return rc;
}
/**
* Remove PCI device
*
* @v pci PCI device
*/
static void pcibridge_remove ( struct pci_device *pci ) {
struct pci_bridge *bridge = pci_get_drvdata ( pci );
/* Remove from list of bridges */
list_del ( &bridge->list );
/* Free device */
free ( bridge );
}
/** Bridge PCI device IDs */
static struct pci_device_id pcibridge_ids[] = {
PCI_ROM ( 0xffff, 0xffff, "bridge", "Bridge", 0 ),
};
/** Bridge PCI driver */
struct pci_driver pcibridge_driver __pci_driver = {
.ids = pcibridge_ids,
.id_count = ( sizeof ( pcibridge_ids ) / sizeof ( pcibridge_ids[0] ) ),
.class = PCI_CLASS_ID ( PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_PCI,
PCI_ANY_ID ),
.probe = pcibridge_probe,
.remove = pcibridge_remove,
};

View File

@ -3,6 +3,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/timer.h>
#include <ipxe/pci.h>
#include <ipxe/pcibackup.h>
static int pci_find_capability_common ( struct pci_device *pci,
uint8_t pos, int cap ) {
@ -121,8 +122,12 @@ unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) {
* @v exp PCI Express Capability address
*/
void pci_reset ( struct pci_device *pci, unsigned int exp ) {
struct pci_config_backup backup;
uint16_t control;
/* Back up configuration space */
pci_backup ( pci, &backup, PCI_CONFIG_BACKUP_STANDARD, NULL );
/* Perform a PCIe function-level reset */
pci_read_config_word ( pci, ( exp + PCI_EXP_DEVCTL ), &control );
control |= PCI_EXP_DEVCTL_FLR;
@ -131,6 +136,6 @@ void pci_reset ( struct pci_device *pci, unsigned int exp ) {
/* Allow time for reset to complete */
mdelay ( PCI_EXP_FLR_DELAY_MS );
/* Re-enable device */
adjust_pci_device ( pci );
/* Restore configuration */
pci_restore ( pci, &backup, PCI_CONFIG_BACKUP_STANDARD, NULL );
}

View File

@ -2561,7 +2561,7 @@ static void arbel_reset ( struct arbel *arbel ) {
unsigned int i;
/* Perform device reset and preserve PCI configuration */
pci_backup ( pci, &backup, backup_exclude );
pci_backup ( pci, &backup, PCI_CONFIG_BACKUP_ALL, backup_exclude );
writel ( ARBEL_RESET_MAGIC,
( arbel->config + ARBEL_RESET_OFFSET ) );
for ( i = 0 ; i < ARBEL_RESET_WAIT_TIME_MS ; i++ ) {
@ -2570,7 +2570,7 @@ static void arbel_reset ( struct arbel *arbel ) {
if ( vendor != 0xffff )
break;
}
pci_restore ( pci, &backup, backup_exclude );
pci_restore ( pci, &backup, PCI_CONFIG_BACKUP_ALL, backup_exclude );
}
/**

View File

@ -2647,6 +2647,7 @@ static struct pci_device_id golan_nics[] = {
PCI_ROM ( 0x15b3, 0x1021, "ConnectX-7", "ConnectX-7 HCA driver, DevID 4129", 0 ),
PCI_ROM ( 0x15b3, 0xa2d2, "BlueField", "BlueField integrated ConnectX-5 network controller HCA driver, DevID 41682", 0 ),
PCI_ROM ( 0x15b3, 0xa2d6, "BlueField-2", "BlueField-2 network controller HCA driver, DevID 41686", 0 ),
PCI_ROM ( 0x15b3, 0xa2dc, "BlueField-3", "BlueField-3 network controller HCA driver, DevID 41692", 0 ),
};
struct pci_driver golan_driver __pci_driver = {

View File

@ -2840,7 +2840,7 @@ static int hermon_reset ( struct hermon *hermon ) {
hermon->toggle = 0;
/* Perform device reset and preserve PCI configuration */
pci_backup ( pci, &backup, backup_exclude );
pci_backup ( pci, &backup, PCI_CONFIG_BACKUP_ALL, backup_exclude );
writel ( HERMON_RESET_MAGIC,
( hermon->config + HERMON_RESET_OFFSET ) );
@ -2852,7 +2852,8 @@ static int hermon_reset ( struct hermon *hermon ) {
if ( vendor == pci->vendor ) {
/* Restore PCI configuration */
pci_restore ( pci, &backup, backup_exclude );
pci_restore ( pci, &backup, PCI_CONFIG_BACKUP_ALL,
backup_exclude );
DBGC ( hermon, "Hermon %p reset after %dms\n",
hermon, i );

View File

@ -2256,7 +2256,7 @@ static void qib7322_reset ( struct qib7322 *qib7322, struct pci_device *pci ) {
struct pci_config_backup backup;
/* Back up PCI configuration space */
pci_backup ( pci, &backup, NULL );
pci_backup ( pci, &backup, PCI_CONFIG_BACKUP_ALL, NULL );
/* Assert reset */
memset ( &control, 0, sizeof ( control ) );
@ -2267,7 +2267,7 @@ static void qib7322_reset ( struct qib7322 *qib7322, struct pci_device *pci ) {
mdelay ( 1000 );
/* Restore PCI configuration space */
pci_restore ( pci, &backup, NULL );
pci_restore ( pci, &backup, PCI_CONFIG_BACKUP_ALL, NULL );
}
/**

View File

@ -121,10 +121,9 @@ int ecm_fetch_mac ( struct usb_function *func,
}
/* Apply system-specific MAC address as current link-layer
* address, if present and not already used.
* address, if present.
*/
if ( ( ( rc = acpi_mac ( amac ) ) == 0 ) &&
! find_netdev_by_ll_addr ( &ethernet_protocol, amac ) ) {
if ( ( rc = acpi_mac ( amac ) ) == 0 ) {
memcpy ( netdev->ll_addr, amac, ETH_ALEN );
DBGC ( usb, "USB %s using system-specific MAC %s\n",
func->name, eth_ntoa ( netdev->ll_addr ) );

View File

@ -222,7 +222,7 @@ static int nii_pci_open ( struct nii_nic *nii ) {
/* Locate PCI I/O protocol */
if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid,
&pci_device ) ) != 0 ) {
&pci_device, 0 ) ) != 0 ) {
DBGC ( nii, "NII %s could not locate PCI I/O protocol: %s\n",
nii->dev.name, strerror ( rc ) );
goto err_locate;
@ -921,18 +921,17 @@ static int nii_set_station_address ( struct nii_nic *nii,
* Set receive filters
*
* @v nii NII NIC
* @v flags Flags
* @ret rc Return status code
*/
static int nii_set_rx_filters ( struct nii_nic *nii ) {
static int nii_set_rx_filters ( struct nii_nic *nii, unsigned int flags ) {
uint32_t implementation = nii->undi->Implementation;
unsigned int flags;
unsigned int op;
int stat;
int rc;
/* Construct receive filter set */
flags = ( PXE_OPFLAGS_RECEIVE_FILTER_ENABLE |
PXE_OPFLAGS_RECEIVE_FILTER_UNICAST );
flags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
if ( implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED )
flags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
if ( implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED )
@ -944,14 +943,40 @@ static int nii_set_rx_filters ( struct nii_nic *nii ) {
op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS, flags );
if ( ( stat = nii_issue ( nii, op ) ) < 0 ) {
rc = -EIO_STAT ( stat );
DBGC ( nii, "NII %s could not set receive filters %#04x: %s\n",
nii->dev.name, flags, strerror ( rc ) );
DBGC ( nii, "NII %s could not %s%sable receive filters "
"%#04x: %s\n", nii->dev.name,
( ( flags & PXE_OPFLAGS_RECEIVE_FILTER_ENABLE ) ?
"en" : "" ),
( ( flags & PXE_OPFLAGS_RECEIVE_FILTER_DISABLE ) ?
"dis" : "" ), flags, strerror ( rc ) );
return rc;
}
return 0;
}
/**
* Enable receive filters
*
* @v nii NII NIC
* @ret rc Return status code
*/
static int nii_enable_rx_filters ( struct nii_nic *nii ) {
return nii_set_rx_filters ( nii, PXE_OPFLAGS_RECEIVE_FILTER_ENABLE );
}
/**
* Disable receive filters
*
* @v nii NII NIC
* @ret rc Return status code
*/
static int nii_disable_rx_filters ( struct nii_nic *nii ) {
return nii_set_rx_filters ( nii, PXE_OPFLAGS_RECEIVE_FILTER_DISABLE );
}
/**
* Transmit packet
*
@ -1175,13 +1200,25 @@ static int nii_open ( struct net_device *netdev ) {
/* Treat as non-fatal */
}
/* Set receive filters */
if ( ( rc = nii_set_rx_filters ( nii ) ) != 0 )
goto err_set_rx_filters;
/* Disable receive filters
*
* We have no reason to disable receive filters here (or
* anywhere), but some NII drivers have a bug which prevents
* packets from being received unless we attempt to disable
* the receive filters.
*
* Ignore any failures, since we genuinely don't care if the
* NII driver cannot disable the filters.
*/
nii_disable_rx_filters ( nii );
/* Enable receive filters */
if ( ( rc = nii_enable_rx_filters ( nii ) ) != 0 )
goto err_enable_rx_filters;
return 0;
err_set_rx_filters:
err_enable_rx_filters:
nii_shutdown ( nii );
err_initialise:
return rc;

View File

@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/efi/efi.h>
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_snp.h>
#include <ipxe/efi/efi_utils.h>
#include "snpnet.h"
#include "nii.h"
@ -40,34 +41,60 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
* Check to see if driver supports a device
*
* @v device EFI device handle
* @v protocol Protocol GUID
* @ret rc Return status code
*/
static int snp_supported ( EFI_HANDLE device ) {
static int snp_nii_supported ( EFI_HANDLE device, EFI_GUID *protocol ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE parent;
EFI_STATUS efirc;
int rc;
/* Check that this is not a device we are providing ourselves */
if ( find_snpdev ( device ) != NULL ) {
DBGCP ( device, "SNP %s is provided by this binary\n",
DBGCP ( device, "HANDLE %s is provided by this binary\n",
efi_handle_name ( device ) );
return -ENOTTY;
}
/* Test for presence of simple network protocol */
if ( ( efirc = bs->OpenProtocol ( device,
&efi_simple_network_protocol_guid,
/* Test for presence of protocol */
if ( ( efirc = bs->OpenProtocol ( device, protocol,
NULL, efi_image_handle, device,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
DBGCP ( device, "SNP %s is not an SNP device\n",
efi_handle_name ( device ) );
DBGCP ( device, "HANDLE %s is not a %s device\n",
efi_handle_name ( device ),
efi_guid_ntoa ( protocol ) );
return -EEFI ( efirc );
}
DBGC ( device, "SNP %s is an SNP device\n",
efi_handle_name ( device ) );
/* Check that there are no instances of this protocol further
* up this device path.
*/
if ( ( rc = efi_locate_device ( device, protocol,
&parent, 1 ) ) == 0 ) {
DBGC2 ( device, "HANDLE %s has %s-supporting parent ",
efi_handle_name ( device ),
efi_guid_ntoa ( protocol ) );
DBGC2 ( device, "%s\n", efi_handle_name ( parent ) );
return -ENOTTY;
}
DBGC ( device, "HANDLE %s is a %s device\n",
efi_handle_name ( device ), efi_guid_ntoa ( protocol ) );
return 0;
}
/**
* Check to see if driver supports a device
*
* @v device EFI device handle
* @ret rc Return status code
*/
static int snp_supported ( EFI_HANDLE device ) {
return snp_nii_supported ( device, &efi_simple_network_protocol_guid );
}
/**
* Check to see if driver supports a device
*
@ -75,29 +102,8 @@ static int snp_supported ( EFI_HANDLE device ) {
* @ret rc Return status code
*/
static int nii_supported ( EFI_HANDLE device ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_STATUS efirc;
/* Check that this is not a device we are providing ourselves */
if ( find_snpdev ( device ) != NULL ) {
DBGCP ( device, "NII %s is provided by this binary\n",
efi_handle_name ( device ) );
return -ENOTTY;
}
/* Test for presence of NII protocol */
if ( ( efirc = bs->OpenProtocol ( device,
&efi_nii31_protocol_guid,
NULL, efi_image_handle, device,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
DBGCP ( device, "NII %s is not an NII device\n",
efi_handle_name ( device ) );
return -EEFI ( efirc );
}
DBGC ( device, "NII %s is an NII device\n",
efi_handle_name ( device ) );
return 0;
return snp_nii_supported ( device, &efi_nii31_protocol_guid );
}
/** EFI SNP driver */

View File

@ -80,7 +80,7 @@ static int chained_locate ( struct chained_protocol *chained ) {
/* Locate handle supporting this protocol */
if ( ( rc = efi_locate_device ( device, chained->protocol,
&parent ) ) != 0 ) {
&parent, 0 ) ) != 0 ) {
DBGC ( device, "CHAINED %s does not support %s: %s\n",
efi_handle_name ( device ),
efi_guid_ntoa ( chained->protocol ), strerror ( rc ) );

View File

@ -24,6 +24,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
@ -34,6 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/iobuf.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
#include <ipxe/pcibridge.h>
#include <ipxe/version.h>
#include "ena.h"
/** @file
@ -347,6 +350,90 @@ static int ena_admin ( struct ena_nic *ena, union ena_aq_req *req,
return rc;
}
/**
* Set async event notification queue config
*
* @v ena ENA device
* @v enabled Bitmask of the groups to enable
* @ret rc Return status code
*/
static int ena_set_aenq_config ( struct ena_nic *ena, uint32_t enabled ) {
union ena_aq_req *req;
union ena_acq_rsp *rsp;
union ena_feature *feature;
int rc;
/* Construct request */
req = ena_admin_req ( ena );
req->header.opcode = ENA_SET_FEATURE;
req->set_feature.id = ENA_AENQ_CONFIG;
feature = &req->set_feature.feature;
feature->aenq.enabled = cpu_to_le32 ( enabled );
/* Issue request */
if ( ( rc = ena_admin ( ena, req, &rsp ) ) != 0 )
return rc;
return 0;
}
/**
* Create async event notification queue
*
* @v ena ENA device
* @ret rc Return status code
*/
static int ena_create_async ( struct ena_nic *ena ) {
size_t aenq_len = ( ENA_AENQ_COUNT * sizeof ( ena->aenq.evt[0] ) );
int rc;
/* Allocate async event notification queue */
ena->aenq.evt = malloc_phys ( aenq_len, aenq_len );
if ( ! ena->aenq.evt ) {
rc = -ENOMEM;
goto err_alloc_aenq;
}
memset ( ena->aenq.evt, 0, aenq_len );
/* Program queue address and capabilities */
ena_set_base ( ena, ENA_AENQ_BASE, ena->aenq.evt );
ena_set_caps ( ena, ENA_AENQ_CAPS, ENA_AENQ_COUNT,
sizeof ( ena->aenq.evt[0] ) );
DBGC ( ena, "ENA %p AENQ [%08lx,%08lx)\n",
ena, virt_to_phys ( ena->aenq.evt ),
( virt_to_phys ( ena->aenq.evt ) + aenq_len ) );
/* Disable all events */
if ( ( rc = ena_set_aenq_config ( ena, 0 ) ) != 0 )
goto err_set_aenq_config;
return 0;
err_set_aenq_config:
ena_clear_caps ( ena, ENA_AENQ_CAPS );
free_phys ( ena->aenq.evt, aenq_len );
err_alloc_aenq:
return rc;
}
/**
* Destroy async event notification queue
*
* @v ena ENA device
*/
static void ena_destroy_async ( struct ena_nic *ena ) {
size_t aenq_len = ( ENA_AENQ_COUNT * sizeof ( ena->aenq.evt[0] ) );
/* Clear queue capabilities */
ena_clear_caps ( ena, ENA_AENQ_CAPS );
wmb();
/* Free queue */
free_phys ( ena->aenq.evt, aenq_len );
DBGC ( ena, "ENA %p AENQ destroyed\n", ena );
}
/**
* Create submission queue
*
@ -359,6 +446,7 @@ static int ena_create_sq ( struct ena_nic *ena, struct ena_sq *sq,
struct ena_cq *cq ) {
union ena_aq_req *req;
union ena_acq_rsp *rsp;
unsigned int i;
int rc;
/* Allocate submission queue entries */
@ -391,11 +479,20 @@ static int ena_create_sq ( struct ena_nic *ena, struct ena_sq *sq,
sq->prod = 0;
sq->phase = ENA_SQE_PHASE;
DBGC ( ena, "ENA %p %s SQ%d at [%08lx,%08lx) db +%04x CQ%d\n",
/* Calculate fill level */
sq->fill = sq->max;
if ( sq->fill > cq->actual )
sq->fill = cq->actual;
/* Initialise buffer ID ring */
for ( i = 0 ; i < sq->count ; i++ )
sq->ids[i] = i;
DBGC ( ena, "ENA %p %s SQ%d at [%08lx,%08lx) fill %d db +%04x CQ%d\n",
ena, ena_direction ( sq->direction ), sq->id,
virt_to_phys ( sq->sqe.raw ),
( virt_to_phys ( sq->sqe.raw ) + sq->len ),
sq->doorbell, cq->id );
sq->fill, sq->doorbell, cq->id );
return 0;
err_admin:
@ -459,6 +556,7 @@ static int ena_create_cq ( struct ena_nic *ena, struct ena_cq *cq ) {
req->header.opcode = ENA_CREATE_CQ;
req->create_cq.size = cq->size;
req->create_cq.count = cpu_to_le16 ( cq->requested );
req->create_cq.vector = cpu_to_le32 ( ENA_MSIX_NONE );
req->create_cq.address = cpu_to_le64 ( virt_to_bus ( cq->cqe.raw ) );
/* Issue request */
@ -596,6 +694,32 @@ static int ena_get_device_attributes ( struct net_device *netdev ) {
return 0;
}
/**
* Set host attributes
*
* @v ena ENA device
* @ret rc Return status code
*/
static int ena_set_host_attributes ( struct ena_nic *ena ) {
union ena_aq_req *req;
union ena_acq_rsp *rsp;
union ena_feature *feature;
int rc;
/* Construct request */
req = ena_admin_req ( ena );
req->header.opcode = ENA_SET_FEATURE;
req->set_feature.id = ENA_HOST_ATTRIBUTES;
feature = &req->set_feature.feature;
feature->host.info = cpu_to_le64 ( virt_to_bus ( ena->info ) );
/* Issue request */
if ( ( rc = ena_admin ( ena, req, &rsp ) ) != 0 )
return rc;
return 0;
}
/**
* Get statistics (for debugging)
*
@ -652,13 +776,14 @@ static void ena_refill_rx ( struct net_device *netdev ) {
struct ena_nic *ena = netdev->priv;
struct io_buffer *iobuf;
struct ena_rx_sqe *sqe;
unsigned int index;
physaddr_t address;
size_t len = netdev->max_pkt_len;
unsigned int refilled = 0;
unsigned int index;
unsigned int id;
/* Refill queue */
while ( ( ena->rx.sq.prod - ena->rx.cq.cons ) < ENA_RX_COUNT ) {
while ( ( ena->rx.sq.prod - ena->rx.cq.cons ) < ena->rx.sq.fill ) {
/* Allocate I/O buffer */
iobuf = alloc_iob ( len );
@ -667,14 +792,15 @@ static void ena_refill_rx ( struct net_device *netdev ) {
break;
}
/* Get next submission queue entry */
/* Get next submission queue entry and buffer ID */
index = ( ena->rx.sq.prod % ENA_RX_COUNT );
sqe = &ena->rx.sq.sqe.rx[index];
id = ena->rx_ids[index];
/* Construct submission queue entry */
address = virt_to_bus ( iobuf->data );
sqe->len = cpu_to_le16 ( len );
sqe->id = cpu_to_le16 ( ena->rx.sq.prod );
sqe->id = cpu_to_le16 ( id );
sqe->address = cpu_to_le64 ( address );
wmb();
sqe->flags = ( ENA_SQE_FIRST | ENA_SQE_LAST | ENA_SQE_CPL |
@ -686,10 +812,10 @@ static void ena_refill_rx ( struct net_device *netdev ) {
ena->rx.sq.phase ^= ENA_SQE_PHASE;
/* Record I/O buffer */
assert ( ena->rx_iobuf[index] == NULL );
ena->rx_iobuf[index] = iobuf;
assert ( ena->rx_iobuf[id] == NULL );
ena->rx_iobuf[id] = iobuf;
DBGC2 ( ena, "ENA %p RX %d at [%08llx,%08llx)\n", ena, sqe->id,
DBGC2 ( ena, "ENA %p RX %d at [%08llx,%08llx)\n", ena, id,
( ( unsigned long long ) address ),
( ( unsigned long long ) address + len ) );
refilled++;
@ -778,23 +904,25 @@ static void ena_close ( struct net_device *netdev ) {
static int ena_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
struct ena_nic *ena = netdev->priv;
struct ena_tx_sqe *sqe;
unsigned int index;
physaddr_t address;
unsigned int index;
unsigned int id;
size_t len;
/* Get next submission queue entry */
if ( ( ena->tx.sq.prod - ena->tx.cq.cons ) >= ENA_TX_COUNT ) {
if ( ( ena->tx.sq.prod - ena->tx.cq.cons ) >= ena->tx.sq.fill ) {
DBGC ( ena, "ENA %p out of transmit descriptors\n", ena );
return -ENOBUFS;
}
index = ( ena->tx.sq.prod % ENA_TX_COUNT );
sqe = &ena->tx.sq.sqe.tx[index];
id = ena->tx_ids[index];
/* Construct submission queue entry */
address = virt_to_bus ( iobuf->data );
len = iob_len ( iobuf );
sqe->len = cpu_to_le16 ( len );
sqe->id = ena->tx.sq.prod;
sqe->id = cpu_to_le16 ( id );
sqe->address = cpu_to_le64 ( address );
wmb();
sqe->flags = ( ENA_SQE_FIRST | ENA_SQE_LAST | ENA_SQE_CPL |
@ -806,10 +934,14 @@ static int ena_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
if ( ( ena->tx.sq.prod % ENA_TX_COUNT ) == 0 )
ena->tx.sq.phase ^= ENA_SQE_PHASE;
/* Record I/O buffer */
assert ( ena->tx_iobuf[id] == NULL );
ena->tx_iobuf[id] = iobuf;
/* Ring doorbell */
writel ( ena->tx.sq.prod, ( ena->regs + ena->tx.sq.doorbell ) );
DBGC2 ( ena, "ENA %p TX %d at [%08llx,%08llx)\n", ena, sqe->id,
DBGC2 ( ena, "ENA %p TX %d at [%08llx,%08llx)\n", ena, id,
( ( unsigned long long ) address ),
( ( unsigned long long ) address + len ) );
return 0;
@ -823,7 +955,9 @@ static int ena_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
static void ena_poll_tx ( struct net_device *netdev ) {
struct ena_nic *ena = netdev->priv;
struct ena_tx_cqe *cqe;
struct io_buffer *iobuf;
unsigned int index;
unsigned int id;
/* Check for completed packets */
while ( ena->tx.cq.cons != ena->tx.sq.prod ) {
@ -835,16 +969,24 @@ static void ena_poll_tx ( struct net_device *netdev ) {
/* Stop if completion queue entry is empty */
if ( ( cqe->flags ^ ena->tx.cq.phase ) & ENA_CQE_PHASE )
return;
DBGC2 ( ena, "ENA %p TX %d complete\n", ena,
( le16_to_cpu ( cqe->id ) >> 2 /* Don't ask */ ) );
/* Increment consumer counter */
ena->tx.cq.cons++;
if ( ! ( ena->tx.cq.cons & ena->tx.cq.mask ) )
ena->tx.cq.phase ^= ENA_CQE_PHASE;
/* Identify and free buffer ID */
id = ENA_TX_CQE_ID ( le16_to_cpu ( cqe->id ) );
ena->tx_ids[index] = id;
/* Identify I/O buffer */
iobuf = ena->tx_iobuf[id];
assert ( iobuf != NULL );
ena->tx_iobuf[id] = NULL;
/* Complete transmit */
netdev_tx_complete_next ( netdev );
DBGC2 ( ena, "ENA %p TX %d complete\n", ena, id );
netdev_tx_complete ( netdev, iobuf );
}
}
@ -858,13 +1000,14 @@ static void ena_poll_rx ( struct net_device *netdev ) {
struct ena_rx_cqe *cqe;
struct io_buffer *iobuf;
unsigned int index;
unsigned int id;
size_t len;
/* Check for received packets */
while ( ena->rx.cq.cons != ena->rx.sq.prod ) {
/* Get next completion queue entry */
index = ( ena->rx.cq.cons % ENA_RX_COUNT );
index = ( ena->rx.cq.cons & ena->rx.cq.mask );
cqe = &ena->rx.cq.cqe.rx[index];
/* Stop if completion queue entry is empty */
@ -876,15 +1019,20 @@ static void ena_poll_rx ( struct net_device *netdev ) {
if ( ! ( ena->rx.cq.cons & ena->rx.cq.mask ) )
ena->rx.cq.phase ^= ENA_CQE_PHASE;
/* Identify and free buffer ID */
id = le16_to_cpu ( cqe->id );
ena->rx_ids[index] = id;
/* Populate I/O buffer */
iobuf = ena->rx_iobuf[index];
ena->rx_iobuf[index] = NULL;
iobuf = ena->rx_iobuf[id];
assert ( iobuf != NULL );
ena->rx_iobuf[id] = NULL;
len = le16_to_cpu ( cqe->len );
iob_put ( iobuf, len );
/* Hand off to network stack */
DBGC2 ( ena, "ENA %p RX %d complete (length %zd)\n",
ena, le16_to_cpu ( cqe->id ), len );
ena, id, len );
netdev_rx ( netdev, iobuf );
}
}
@ -921,6 +1069,45 @@ static struct net_device_operations ena_operations = {
******************************************************************************
*/
/**
* Assign memory BAR
*
* @v ena ENA device
* @v pci PCI device
* @ret rc Return status code
*
* Some BIOSes in AWS EC2 are observed to fail to assign a base
* address to the ENA device. The device is the only device behind
* its bridge, and the BIOS does assign a memory window to the bridge.
* We therefore place the device at the start of the memory window.
*/
static int ena_membase ( struct ena_nic *ena, struct pci_device *pci ) {
struct pci_bridge *bridge;
/* Locate PCI bridge */
bridge = pcibridge_find ( pci );
if ( ! bridge ) {
DBGC ( ena, "ENA %p found no PCI bridge\n", ena );
return -ENOTCONN;
}
/* Sanity check */
if ( PCI_SLOT ( pci->busdevfn ) || PCI_FUNC ( pci->busdevfn ) ) {
DBGC ( ena, "ENA %p at " PCI_FMT " may not be only device "
"on bus\n", ena, PCI_ARGS ( pci ) );
return -ENOTSUP;
}
/* Place device at start of memory window */
pci_write_config_dword ( pci, PCI_BASE_ADDRESS_0, bridge->membase );
pci->membase = bridge->membase;
DBGC ( ena, "ENA %p at " PCI_FMT " claiming bridge " PCI_FMT " mem "
"%08x\n", ena, PCI_ARGS ( pci ), PCI_ARGS ( bridge->pci ),
bridge->membase );
return 0;
}
/**
* Probe PCI device
*
@ -930,6 +1117,7 @@ static struct net_device_operations ena_operations = {
static int ena_probe ( struct pci_device *pci ) {
struct net_device *netdev;
struct ena_nic *ena;
struct ena_host_info *info;
int rc;
/* Allocate and initialise net device */
@ -946,16 +1134,20 @@ static int ena_probe ( struct pci_device *pci ) {
ena->acq.phase = ENA_ACQ_PHASE;
ena_cq_init ( &ena->tx.cq, ENA_TX_COUNT,
sizeof ( ena->tx.cq.cqe.tx[0] ) );
ena_sq_init ( &ena->tx.sq, ENA_SQ_TX, ENA_TX_COUNT,
sizeof ( ena->tx.sq.sqe.tx[0] ) );
ena_sq_init ( &ena->tx.sq, ENA_SQ_TX, ENA_TX_COUNT, ENA_TX_COUNT,
sizeof ( ena->tx.sq.sqe.tx[0] ), ena->tx_ids );
ena_cq_init ( &ena->rx.cq, ENA_RX_COUNT,
sizeof ( ena->rx.cq.cqe.rx[0] ) );
ena_sq_init ( &ena->rx.sq, ENA_SQ_RX, ENA_RX_COUNT,
sizeof ( ena->rx.sq.sqe.rx[0] ) );
ena_sq_init ( &ena->rx.sq, ENA_SQ_RX, ENA_RX_COUNT, ENA_RX_FILL,
sizeof ( ena->rx.sq.sqe.rx[0] ), ena->rx_ids );
/* Fix up PCI device */
adjust_pci_device ( pci );
/* Fix up PCI BAR if left unassigned by BIOS */
if ( ( ! pci->membase ) && ( ( rc = ena_membase ( ena, pci ) ) != 0 ) )
goto err_membase;
/* Map registers */
ena->regs = pci_ioremap ( pci, pci->membase, ENA_BAR_SIZE );
if ( ! ena->regs ) {
@ -963,6 +1155,25 @@ static int ena_probe ( struct pci_device *pci ) {
goto err_ioremap;
}
/* Allocate and initialise host info */
info = malloc_phys ( PAGE_SIZE, PAGE_SIZE );
if ( ! info ) {
rc = -ENOMEM;
goto err_info;
}
ena->info = info;
memset ( info, 0, PAGE_SIZE );
info->type = cpu_to_le32 ( ENA_HOST_INFO_TYPE_LINUX );
snprintf ( info->dist_str, sizeof ( info->dist_str ), "%s",
( product_name[0] ? product_name : product_short_name ) );
snprintf ( info->kernel_str, sizeof ( info->kernel_str ), "%s",
product_version );
info->version = cpu_to_le32 ( ENA_HOST_INFO_VERSION_WTF );
info->spec = cpu_to_le16 ( ENA_HOST_INFO_SPEC_2_0 );
info->busdevfn = cpu_to_le16 ( pci->busdevfn );
DBGC2 ( ena, "ENA %p host info:\n", ena );
DBGC2_HDA ( ena, virt_to_phys ( info ), info, sizeof ( *info ) );
/* Reset the NIC */
if ( ( rc = ena_reset ( ena ) ) != 0 )
goto err_reset;
@ -971,6 +1182,14 @@ static int ena_probe ( struct pci_device *pci ) {
if ( ( rc = ena_create_admin ( ena ) ) != 0 )
goto err_create_admin;
/* Create async event notification queue */
if ( ( rc = ena_create_async ( ena ) ) != 0 )
goto err_create_async;
/* Set host attributes */
if ( ( rc = ena_set_host_attributes ( ena ) ) != 0 )
goto err_set_host_attributes;
/* Fetch MAC address */
if ( ( rc = ena_get_device_attributes ( netdev ) ) != 0 )
goto err_get_device_attributes;
@ -989,12 +1208,18 @@ static int ena_probe ( struct pci_device *pci ) {
unregister_netdev ( netdev );
err_register_netdev:
err_get_device_attributes:
err_set_host_attributes:
ena_destroy_async ( ena );
err_create_async:
ena_destroy_admin ( ena );
err_create_admin:
ena_reset ( ena );
err_reset:
free_phys ( ena->info, PAGE_SIZE );
err_info:
iounmap ( ena->regs );
err_ioremap:
err_membase:
netdev_nullify ( netdev );
netdev_put ( netdev );
err_alloc:
@ -1013,12 +1238,18 @@ static void ena_remove ( struct pci_device *pci ) {
/* Unregister network device */
unregister_netdev ( netdev );
/* Destroy async event notification queue */
ena_destroy_async ( ena );
/* Destroy admin queues */
ena_destroy_admin ( ena );
/* Reset card */
ena_reset ( ena );
/* Free host info */
free_phys ( ena->info, PAGE_SIZE );
/* Free network device */
iounmap ( ena->regs );
netdev_nullify ( netdev );

View File

@ -24,11 +24,17 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Number of admin completion queue entries */
#define ENA_ACQ_COUNT 2
/** Number of async event notification queue entries */
#define ENA_AENQ_COUNT 2
/** Number of transmit queue entries */
#define ENA_TX_COUNT 16
/** Number of receive queue entries */
#define ENA_RX_COUNT 16
#define ENA_RX_COUNT 128
/** Receive queue maximum fill level */
#define ENA_RX_FILL 16
/** Base address low register offset */
#define ENA_BASE_LO 0x0
@ -57,6 +63,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Maximum time to wait for admin requests */
#define ENA_ADMIN_MAX_WAIT_MS 5000
/** Async event notification queue capabilities register */
#define ENA_AENQ_CAPS 0x34
/** Async event notification queue base address register */
#define ENA_AENQ_BASE 0x38
/** Device control register */
#define ENA_CTRL 0x54
#define ENA_CTRL_RESET 0x00000001UL /**< Reset */
@ -127,10 +139,99 @@ struct ena_device_attributes {
uint32_t mtu;
} __attribute__ (( packed ));
/** Async event notification queue config */
#define ENA_AENQ_CONFIG 26
/** Async event notification queue config */
struct ena_aenq_config {
/** Bitmask of supported AENQ groups (device -> host) */
uint32_t supported;
/** Bitmask of enabled AENQ groups (host -> device) */
uint32_t enabled;
} __attribute__ (( packed ));
/** Host attributes */
#define ENA_HOST_ATTRIBUTES 28
/** Host attributes */
struct ena_host_attributes {
/** Host info base address */
uint64_t info;
/** Debug area base address */
uint64_t debug;
/** Debug area size */
uint32_t debug_len;
} __attribute__ (( packed ));
/** Host information */
struct ena_host_info {
/** Operating system type */
uint32_t type;
/** Operating system distribution (string) */
char dist_str[128];
/** Operating system distribution (numeric) */
uint32_t dist;
/** Kernel version (string) */
char kernel_str[32];
/** Kernel version (numeric) */
uint32_t kernel;
/** Driver version */
uint32_t version;
/** Linux network device features */
uint64_t linux_features;
/** ENA specification version */
uint16_t spec;
/** PCI bus:dev.fn address */
uint16_t busdevfn;
/** Number of CPUs */
uint16_t cpus;
/** Reserved */
uint8_t reserved_a[2];
/** Supported features */
uint32_t features;
} __attribute__ (( packed ));
/** Linux operating system type
*
* There is a defined "iPXE" operating system type (with value 5).
* However, some very broken versions of the ENA firmware will refuse
* to allow a completion queue to be created if the "iPXE" type is
* used.
*/
#define ENA_HOST_INFO_TYPE_LINUX 1
/** Driver version
*
* The driver version field is nominally used to report a version
* number outside of the VM for consumption by humans (and potentially
* by automated monitoring tools that could e.g. check for outdated
* versions with known security flaws).
*
* However, at some point in the development of the ENA firmware, some
* unknown person at AWS thought it would be sensible to apply a
* machine interpretation to this field and adjust the behaviour of
* the firmware based on its value, thereby creating a maintenance and
* debugging nightmare for all existing and future drivers.
*
* Hint to engineers: if you ever find yourself writing code of the
* form "if (version == SOME_MAGIC_NUMBER)" then something has gone
* very, very wrong. This *always* indicates that something is
* broken, either in your own code or in the code with which you are
* forced to interact.
*/
#define ENA_HOST_INFO_VERSION_WTF 0x00000002UL
/** ENA specification version */
#define ENA_HOST_INFO_SPEC_2_0 0x0200
/** Feature */
union ena_feature {
/** Device attributes */
struct ena_device_attributes device;
/** Async event notification queue config */
struct ena_aenq_config aenq;
/** Host attributes */
struct ena_host_attributes host;
};
/** Submission queue direction */
@ -230,6 +331,14 @@ struct ena_create_cq_req {
uint64_t address;
} __attribute__ (( packed ));
/** Empty MSI-X vector
*
* Some versions of the ENA firmware will complain if the completion
* queue's MSI-X vector field is left empty, even though the queue
* configuration specifies that interrupts are not used.
*/
#define ENA_MSIX_NONE 0xffffffffUL
/** Create completion queue response */
struct ena_create_cq_rsp {
/** Header */
@ -292,6 +401,27 @@ struct ena_get_feature_rsp {
union ena_feature feature;
} __attribute__ (( packed ));
/** Set feature */
#define ENA_SET_FEATURE 9
/** Set feature request */
struct ena_set_feature_req {
/** Header */
struct ena_aq_header header;
/** Length */
uint32_t len;
/** Address */
uint64_t address;
/** Flags */
uint8_t flags;
/** Feature identifier */
uint8_t id;
/** Reserved */
uint8_t reserved[2];
/** Feature */
union ena_feature feature;
} __attribute__ (( packed ));
/** Get statistics */
#define ENA_GET_STATS 11
@ -352,6 +482,8 @@ union ena_aq_req {
struct ena_destroy_cq_req destroy_cq;
/** Get feature */
struct ena_get_feature_req get_feature;
/** Set feature */
struct ena_set_feature_req set_feature;
/** Get statistics */
struct ena_get_stats_req get_stats;
/** Padding */
@ -396,6 +528,28 @@ struct ena_acq {
unsigned int phase;
};
/** Async event notification queue event */
struct ena_aenq_event {
/** Type of event */
uint16_t group;
/** ID of event */
uint16_t syndrome;
/** Phase */
uint8_t flags;
/** Reserved */
uint8_t reserved[3];
/** Timestamp */
uint64_t timestamp;
/** Additional event data */
uint8_t data[48];
} __attribute__ (( packed ));
/** Async event notification queue */
struct ena_aenq {
/** Events */
struct ena_aenq_event *evt;
};
/** Transmit submission queue entry */
struct ena_tx_sqe {
/** Length */
@ -454,6 +608,9 @@ struct ena_tx_cqe {
uint16_t cons;
} __attribute__ (( packed ));
/** Transmit completion request identifier */
#define ENA_TX_CQE_ID(id) ( (id) >> 2 )
/** Receive completion queue entry */
struct ena_rx_cqe {
/** Reserved */
@ -482,6 +639,8 @@ struct ena_sq {
/** Raw data */
void *raw;
} sqe;
/** Buffer IDs */
uint8_t *ids;
/** Doorbell register offset */
unsigned int doorbell;
/** Total length of entries */
@ -496,6 +655,10 @@ struct ena_sq {
uint8_t direction;
/** Number of entries */
uint8_t count;
/** Maximum fill level */
uint8_t max;
/** Fill level (limited to completion queue size) */
uint8_t fill;
};
/**
@ -504,15 +667,19 @@ struct ena_sq {
* @v sq Submission queue
* @v direction Direction
* @v count Number of entries
* @v max Maximum fill level
* @v size Size of each entry
* @v ids Buffer IDs
*/
static inline __attribute__ (( always_inline )) void
ena_sq_init ( struct ena_sq *sq, unsigned int direction, unsigned int count,
size_t size ) {
unsigned int max, size_t size, uint8_t *ids ) {
sq->len = ( count * size );
sq->direction = direction;
sq->count = count;
sq->max = max;
sq->ids = ids;
}
/** Completion queue */
@ -573,15 +740,25 @@ struct ena_qp {
struct ena_nic {
/** Registers */
void *regs;
/** Host info */
struct ena_host_info *info;
/** Admin queue */
struct ena_aq aq;
/** Admin completion queue */
struct ena_acq acq;
/** Async event notification queue */
struct ena_aenq aenq;
/** Transmit queue */
struct ena_qp tx;
/** Receive queue */
struct ena_qp rx;
/** Receive I/O buffers */
/** Transmit buffer IDs */
uint8_t tx_ids[ENA_TX_COUNT];
/** Transmit I/O buffers, indexed by buffer ID */
struct io_buffer *tx_iobuf[ENA_TX_COUNT];
/** Receive buffer IDs */
uint8_t rx_ids[ENA_RX_COUNT];
/** Receive I/O buffers, indexed by buffer ID */
struct io_buffer *rx_iobuf[ENA_RX_COUNT];
};

View File

@ -1173,6 +1173,10 @@ static struct pci_device_id intel_nics[] = {
PCI_ROM ( 0x8086, 0x15fa, "i219v-14", "I219-V (14)", INTEL_I219 ),
PCI_ROM ( 0x8086, 0x15fb, "i219lm-13", "I219-LM (13)", INTEL_I219 ),
PCI_ROM ( 0x8086, 0x15fc, "i219v-13", "I219-V (13)", INTEL_I219 ),
PCI_ROM ( 0x8086, 0x1a1c, "i219lm-17", "I219-LM (17)", INTEL_I219 ),
PCI_ROM ( 0x8086, 0x1a1d, "i219v-17", "I219-V (17)", INTEL_I219 ),
PCI_ROM ( 0x8086, 0x1a1e, "i219lm-16", "I219-LM (16)", INTEL_I219 ),
PCI_ROM ( 0x8086, 0x1a1f, "i219v-16", "I219-V (16)", INTEL_I219 ),
PCI_ROM ( 0x8086, 0x1f41, "i354", "I354", INTEL_NO_ASDE ),
PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ),
PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ),

View File

@ -59,6 +59,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
EUNIQ ( EINFO_EIO, ( -(status) & 0x1f ), \
EIO_NETIF_RSP_ERROR, EIO_NETIF_RSP_DROPPED )
/** List of netfront devices */
static LIST_HEAD ( netfront_devices );
/******************************************************************************
*
* XenStore interface
@ -952,6 +955,7 @@ static int netfront_probe ( struct xen_device *xendev ) {
netdev->dev = &xendev->dev;
netfront = netdev->priv;
netfront->xendev = xendev;
netfront->netdev = netdev;
INIT_LIST_HEAD ( &netfront->rx_partial );
DBGC ( netfront, "NETFRONT %s backend=\"%s\" in domain %ld\n",
xendev->key, xendev->backend, xendev->backend_id );
@ -991,9 +995,13 @@ static int netfront_probe ( struct xen_device *xendev ) {
/* Set initial link state */
netdev_link_down ( netdev );
/* Add to list of netfront devices */
list_add_tail ( &netfront->list, &netfront_devices );
xen_set_drvdata ( xendev, netdev );
return 0;
list_del ( &netfront->list );
unregister_netdev ( netdev );
err_register_netdev:
err_read_mac:
@ -1015,6 +1023,9 @@ static void netfront_remove ( struct xen_device *xendev ) {
struct netfront_nic *netfront = netdev->priv;
struct xen_hypervisor *xen = xendev->xen;
/* Remove from list of netfront devices */
list_del ( &netfront->list );
/* Unregister network device */
unregister_netdev ( netdev );
@ -1033,3 +1044,41 @@ struct xen_driver netfront_driver __xen_driver = {
.probe = netfront_probe,
.remove = netfront_remove,
};
/******************************************************************************
*
* Emulated PCI device inhibitor
*
******************************************************************************
*/
/**
* Inhibit emulated PCI devices
*
* @v netdev Network device
* @ret rc Return status code
*/
static int netfront_net_probe ( struct net_device *netdev ) {
struct netfront_nic *netfront;
/* Inhibit emulated PCI devices matching an existing netfront device */
list_for_each_entry ( netfront, &netfront_devices, list ) {
if ( ( netdev->dev != netfront->netdev->dev ) &&
( netdev->ll_protocol->ll_addr_len == ETH_ALEN ) &&
( memcmp ( netdev->hw_addr, netfront->netdev->hw_addr,
ETH_ALEN ) == 0 ) ) {
DBGC ( netfront, "NETFRONT %s inhibiting emulated %s "
"%s\n", netfront->xendev->key,
netdev->dev->driver_name, netdev->dev->name );
return -EEXIST;
}
}
return 0;
}
/** Emulated PCI device inhibitor driver */
struct net_driver netfront_net_driver __net_driver = {
.name = "netfront",
.probe = netfront_net_probe,
};

View File

@ -159,6 +159,11 @@ struct netfront_nic {
/** Grant references */
grant_ref_t refs[NETFRONT_REF_COUNT];
/** Network device */
struct net_device *netdev;
/** List of netfront NICs */
struct list_head list;
/** Transmit ring */
struct netfront_ring tx;
/** Transmit front ring */

View File

@ -1067,11 +1067,15 @@ static void realtek_detect ( struct realtek_nic *rtl ) {
* Note that enabling DAC seems to cause bizarre behaviour
* (lockups, garbage data on the wire) on some systems, even
* if only 32-bit addresses are used.
*
* Disable VLAN offload, since some cards seem to have it
* enabled by default.
*/
cpcr = readw ( rtl->regs + RTL_CPCR );
cpcr |= ( RTL_CPCR_MULRW | RTL_CPCR_CPRX | RTL_CPCR_CPTX );
if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) )
cpcr |= RTL_CPCR_DAC;
cpcr &= ~RTL_CPCR_VLAN;
writew ( cpcr, rtl->regs + RTL_CPCR );
check_cpcr = readw ( rtl->regs + RTL_CPCR );

View File

@ -228,8 +228,9 @@ enum realtek_legacy_status {
/** C+ Command Register (word) */
#define RTL_CPCR 0xe0
#define RTL_CPCR_DAC 0x0010 /**< PCI Dual Address Cycle Enable */
#define RTL_CPCR_MULRW 0x0008 /**< PCI Multiple Read/Write Enable */
#define RTL_CPCR_VLAN 0x0040 /**< VLAN tag stripping enable */
#define RTL_CPCR_DAC 0x0010 /**< PCI Dual Address Cycle enable */
#define RTL_CPCR_MULRW 0x0008 /**< PCI Multiple Read/Write enable */
#define RTL_CPCR_CPRX 0x0002 /**< C+ receive enable */
#define RTL_CPCR_CPTX 0x0001 /**< C+ transmit enable */

View File

@ -22,6 +22,7 @@
*/
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <ipxe/pci.h>
#include <ipxe/command.h>
@ -58,7 +59,7 @@ static int pciscan_exec ( int argc, char **argv ) {
struct named_setting setting;
struct pci_device pci;
unsigned long prev;
int next;
uint32_t busdevfn;
int len;
int rc;
@ -75,17 +76,19 @@ static int pciscan_exec ( int argc, char **argv ) {
if ( ( len = fetchn_setting ( setting.settings, &setting.setting,
NULL, &setting.setting, &prev ) ) < 0 ) {
/* Setting not yet defined: start searching from 00:00.0 */
prev = 0;
busdevfn = 0;
} else {
/* Setting is defined: start searching from next location */
prev++;
busdevfn = ( prev + 1 );
if ( ! busdevfn ) {
rc = -ENOENT;
goto err_end;
}
}
/* Find next existent PCI device */
if ( ( next = pci_find_next ( &pci, prev ) ) < 0 ) {
rc = next;
if ( ( rc = pci_find_next ( &pci, &busdevfn ) ) != 0 )
goto err_find_next;
}
/* Apply default type if necessary. Use ":uint16" rather than
* ":busdevfn" to allow for easy inclusion within a
@ -96,13 +99,14 @@ static int pciscan_exec ( int argc, char **argv ) {
/* Store setting */
if ( ( rc = storen_setting ( setting.settings, &setting.setting,
next ) ) != 0 ) {
busdevfn ) ) != 0 ) {
printf ( "Could not store \"%s\": %s\n",
setting.setting.name, strerror ( rc ) );
goto err_store;
}
err_store:
err_end:
err_find_next:
err_parse_setting:
err_parse_options:

View File

@ -96,9 +96,7 @@ efi_image_path ( struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent ) {
efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ),
"%s", image->name );
end = ( ( ( void * ) filepath ) + filepath_len );
end->Type = END_DEVICE_PATH_TYPE;
end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
end->Length[0] = sizeof ( *end );
efi_path_terminate ( end );
return path;
}

View File

@ -755,6 +755,53 @@ char __debug_disable(OBJECT) = ( DBGLVL_MAX & ~DBGLVL_DFLT );
#define FILE_LICENCE_BSD2 \
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__bsd2__ ) )
/** Declare a file as being under the two-clause BSD plus patent licence
*
* This licence declaration is applicable when a file states itself to
* be licensed under terms allowing redistribution in source and
* binary forms (with or without modification) provided that:
*
* redistributions of source code retain the copyright notice,
* list of conditions and any attached disclaimers
*
* redistributions in binary form reproduce the copyright notice,
* list of conditions and any attached disclaimers in the
* documentation and/or other materials provided with the
* distribution
*
* and in addition states that
*
* Subject to the terms and conditions of this license, each
* copyright holder and contributor hereby grants to those
* receiving rights under this license a perpetual, worldwide,
* non-exclusive, no-charge, royalty-free, irrevocable (except for
* failure to satisfy the conditions of this license) patent
* license to make, have made, use, offer to sell, sell, import,
* and otherwise transfer this software, where such license
* applies only to those patent claims, already acquired or
* hereafter acquired, licensable by such copyright holder or
* contributor that are necessarily infringed by:
*
* their Contribution(s) (the licensed copyrights of copyright
* holders and non-copyrightable additions of contributors, in
* source or binary form) alone; or
*
* combination of their Contribution(s) with the work of
* authorship to which such Contribution(s) was added by such
* copyright holder or contributor, if, at the time the
* Contribution is added, such addition causes such combination
* to be necessarily infringed. The patent license shall not
* apply to any other combinations which include the
* Contribution.
*
* It is not necessary for the file to explicitly state that it is
* under a "BSD" licence; only that the licensing terms be
* functionally equivalent to the standard two-clause BSD licence with
* patent grant.
*/
#define FILE_LICENCE_BSD2_PATENT \
PROVIDE_SYMBOL ( PREFIX_OBJECT ( __licence__bsd2_patent__ ) )
/** Declare a file as being under the one-clause MIT-style licence
*
* This licence declaration is applicable when a file states itself to

View File

@ -47,6 +47,7 @@ struct aes_context {
extern struct cipher_algorithm aes_algorithm;
extern struct cipher_algorithm aes_ecb_algorithm;
extern struct cipher_algorithm aes_cbc_algorithm;
extern struct cipher_algorithm aes_gcm_algorithm;
int aes_wrap ( const void *kek, const void *src, void *dest, int nblk );
int aes_unwrap ( const void *kek, const void *src, void *dest, int nblk );

View File

@ -18,7 +18,8 @@ extern struct cached_dhcp_packet cached_dhcpack;
extern struct cached_dhcp_packet cached_proxydhcp;
extern struct cached_dhcp_packet cached_pxebs;
extern int cachedhcp_record ( struct cached_dhcp_packet *cache, userptr_t data,
extern int cachedhcp_record ( struct cached_dhcp_packet *cache,
unsigned int vlan, userptr_t data,
size_t max_len );
#endif /* _IPXE_CACHEDHCP_H */

View File

@ -33,12 +33,15 @@ static inline int cbc_setkey ( void *ctx, const void *key, size_t keylen,
*
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
* @v raw_cipher Underlying cipher algorithm
* @v cbc_ctx CBC context
*/
static inline void cbc_setiv ( void *ctx __unused, const void *iv,
static inline void cbc_setiv ( void *ctx __unused,
const void *iv, size_t ivlen,
struct cipher_algorithm *raw_cipher,
void *cbc_ctx ) {
assert ( ivlen == raw_cipher->blocksize );
memcpy ( cbc_ctx, iv, raw_cipher->blocksize );
}
@ -70,9 +73,10 @@ static int _cbc_name ## _setkey ( void *ctx, const void *key, \
return cbc_setkey ( &_cbc_name ## _ctx->raw_ctx, key, keylen, \
&_raw_cipher, &_cbc_name ## _ctx->cbc_ctx );\
} \
static void _cbc_name ## _setiv ( void *ctx, const void *iv ) { \
static void _cbc_name ## _setiv ( void *ctx, const void *iv, \
size_t ivlen ) { \
struct _cbc_name ## _context * _cbc_name ## _ctx = ctx; \
cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, \
cbc_setiv ( &_cbc_name ## _ctx->raw_ctx, iv, ivlen, \
&_raw_cipher, &aes_cbc_ctx->cbc_ctx ); \
} \
static void _cbc_name ## _encrypt ( void *ctx, const void *src, \
@ -91,10 +95,13 @@ struct cipher_algorithm _cbc_cipher = { \
.name = #_cbc_name, \
.ctxsize = sizeof ( struct _cbc_name ## _context ), \
.blocksize = _blocksize, \
.alignsize = _blocksize, \
.authsize = 0, \
.setkey = _cbc_name ## _setkey, \
.setiv = _cbc_name ## _setiv, \
.encrypt = _cbc_name ## _encrypt, \
.decrypt = _cbc_name ## _decrypt, \
.auth = cipher_null_auth, \
};
#endif /* _IPXE_CBC_H */

View File

@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
/** A message digest algorithm */
struct digest_algorithm {
@ -50,8 +51,26 @@ struct cipher_algorithm {
const char *name;
/** Context size */
size_t ctxsize;
/** Block size */
/** Block size
*
* Every call to encrypt() or decrypt() must be for a multiple
* of this size.
*/
size_t blocksize;
/** Alignment size
*
* Every call to encrypt() or decrypt() must begin at a
* multiple of this offset from the start of the stream.
* (Equivalently: all but the last call to encrypt() or
* decrypt() must be for a multiple of this size.)
*
* For ciphers supporting additional data, the main data
* stream and additional data stream are both considered to
* begin at offset zero.
*/
size_t alignsize;
/** Authentication tag size */
size_t authsize;
/** Set key
*
* @v ctx Context
@ -64,13 +83,14 @@ struct cipher_algorithm {
*
* @v ctx Context
* @v iv Initialisation vector
* @v ivlen Initialisation vector length
*/
void ( * setiv ) ( void *ctx, const void *iv );
void ( * setiv ) ( void *ctx, const void *iv, size_t ivlen );
/** Encrypt data
*
* @v ctx Context
* @v src Data to encrypt
* @v dst Buffer for encrypted data
* @v dst Buffer for encrypted data, or NULL for additional data
* @v len Length of data
*
* @v len is guaranteed to be a multiple of @c blocksize.
@ -81,13 +101,19 @@ struct cipher_algorithm {
*
* @v ctx Context
* @v src Data to decrypt
* @v dst Buffer for decrypted data
* @v dst Buffer for decrypted data, or NULL for additional data
* @v len Length of data
*
* @v len is guaranteed to be a multiple of @c blocksize.
*/
void ( * decrypt ) ( void *ctx, const void *src, void *dst,
size_t len );
/** Generate authentication tag
*
* @v ctx Context
* @v auth Authentication tag
*/
void ( * auth ) ( void *ctx, void *auth );
};
/** A public key algorithm */
@ -190,8 +216,8 @@ static inline int cipher_setkey ( struct cipher_algorithm *cipher,
}
static inline void cipher_setiv ( struct cipher_algorithm *cipher,
void *ctx, const void *iv ) {
cipher->setiv ( ctx, iv );
void *ctx, const void *iv, size_t ivlen ) {
cipher->setiv ( ctx, iv, ivlen );
}
static inline void cipher_encrypt ( struct cipher_algorithm *cipher,
@ -214,10 +240,23 @@ static inline void cipher_decrypt ( struct cipher_algorithm *cipher,
cipher_decrypt ( (cipher), (ctx), (src), (dst), (len) ); \
} while ( 0 )
static inline void cipher_auth ( struct cipher_algorithm *cipher, void *ctx,
void *auth ) {
cipher->auth ( ctx, auth );
}
static inline int is_stream_cipher ( struct cipher_algorithm *cipher ) {
return ( cipher->blocksize == 1 );
}
static inline int is_block_cipher ( struct cipher_algorithm *cipher ) {
return ( cipher->blocksize > 1 );
}
static inline int is_auth_cipher ( struct cipher_algorithm *cipher ) {
return cipher->authsize;
}
static inline int pubkey_init ( struct pubkey_algorithm *pubkey, void *ctx,
const void *key, size_t key_len ) {
return pubkey->init ( ctx, key, key_len );
@ -263,6 +302,30 @@ static inline int pubkey_match ( struct pubkey_algorithm *pubkey,
public_key_len );
}
extern void digest_null_init ( void *ctx );
extern void digest_null_update ( void *ctx, const void *src, size_t len );
extern void digest_null_final ( void *ctx, void *out );
extern int cipher_null_setkey ( void *ctx, const void *key, size_t keylen );
extern void cipher_null_setiv ( void *ctx, const void *iv, size_t ivlen );
extern void cipher_null_encrypt ( void *ctx, const void *src, void *dst,
size_t len );
extern void cipher_null_decrypt ( void *ctx, const void *src, void *dst,
size_t len );
extern void cipher_null_auth ( void *ctx, void *auth );
extern int pubkey_null_init ( void *ctx, const void *key, size_t key_len );
extern size_t pubkey_null_max_len ( void *ctx );
extern int pubkey_null_encrypt ( void *ctx, const void *plaintext,
size_t plaintext_len, void *ciphertext );
extern int pubkey_null_decrypt ( void *ctx, const void *ciphertext,
size_t ciphertext_len, void *plaintext );
extern int pubkey_null_sign ( void *ctx, struct digest_algorithm *digest,
const void *value, void *signature );
extern int pubkey_null_verify ( void *ctx, struct digest_algorithm *digest,
const void *value, const void *signature ,
size_t signature_len );
extern struct digest_algorithm digest_null;
extern struct cipher_algorithm cipher_null;
extern struct pubkey_algorithm pubkey_null;

View File

@ -274,8 +274,9 @@ struct dhcp_client_architecture {
/** DHCP client architecture values
*
* These are defined by the PXE specification and redefined by
* RFC4578.
* These are originally defined by the PXE specification, redefined by
* RFC4578, redefined again by RFC5970, and now maintained in the IANA
* DHCPv6 parameters registry.
*/
enum dhcp_client_architecture_values {
/** Intel x86 PC */
@ -302,6 +303,24 @@ enum dhcp_client_architecture_values {
DHCP_CLIENT_ARCHITECTURE_ARM32 = 0x000a,
/** EFI 64-bit ARM */
DHCP_CLIENT_ARCHITECTURE_ARM64 = 0x000b,
/** EFI 32-bit RISC-V */
DHCP_CLIENT_ARCHITECTURE_RISCV32 = 0x0019,
/** EFI 64-bit RISC-V */
DHCP_CLIENT_ARCHITECTURE_RISCV64 = 0x001b,
/** EFI 128-bit RISC-V */
DHCP_CLIENT_ARCHITECTURE_RISCV128 = 0x001d,
/** EFI 32-bit MIPS */
DHCP_CLIENT_ARCHITECTURE_MIPS32 = 0x0021,
/** EFI 64-bit MIPS */
DHCP_CLIENT_ARCHITECTURE_MIPS64 = 0x0022,
/** EFI 32-bit Sunway */
DHCP_CLIENT_ARCHITECTURE_SUNWAY32 = 0x0023,
/** EFI 64-bit Sunway */
DHCP_CLIENT_ARCHITECTURE_SUNWAY64 = 0x0024,
/** EFI 32-bit LoongArch */
DHCP_CLIENT_ARCHITECTURE_LOONG32 = 0x0025,
/** EFI 64-bit LoongArch */
DHCP_CLIENT_ARCHITECTURE_LOONG64 = 0x0027,
};
/** Client network device interface */

View File

@ -0,0 +1,16 @@
#ifndef _IPXE_DHCPARCH_H
#define _IPXE_DHCPARCH_H
/** @file
*
* DHCP client architecture definitions
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/* Include platform-specific client architecture definitions */
#define PLATFORM_DHCPARCH(_platform) <ipxe/_platform/dhcparch.h>
#include PLATFORM_DHCPARCH(PLATFORM)
#endif /* _IPXE_DHCPARCH_H */

View File

@ -0,0 +1,19 @@
#ifndef _IPXE_DHE_H
#define _IPXE_DHE_H
/** @file
*
* Ephemeral Diffie-Hellman key exchange
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
extern int dhe_key ( const void *modulus, size_t len, const void *generator,
size_t generator_len, const void *partner,
size_t partner_len, const void *private,
size_t private_len, void *public, void *shared );
#endif /* _IPXE_DHE_H */

View File

@ -0,0 +1,57 @@
#ifndef _IPXE_ECAM_H
#define _IPXE_ECAM_H
/** @file
*
* PCI I/O API for Enhanced Configuration Access Mechanism (ECAM)
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/acpi.h>
#include <ipxe/pci.h>
/** Enhanced Configuration Access Mechanism per-device size */
#define ECAM_SIZE 4096
/** Enhanced Configuration Access Mechanism table signature */
#define ECAM_SIGNATURE ACPI_SIGNATURE ( 'M', 'C', 'F', 'G' )
/** An Enhanced Configuration Access Mechanism allocation */
struct ecam_allocation {
/** Base address */
uint64_t base;
/** PCI segment number */
uint16_t segment;
/** Start PCI bus number */
uint8_t start;
/** End PCI bus number */
uint8_t end;
/** Reserved */
uint8_t reserved[4];
} __attribute__ (( packed ));
/** An Enhanced Configuration Access Mechanism table */
struct ecam_table {
/** ACPI header */
struct acpi_header acpi;
/** Reserved */
uint8_t reserved[8];
/** Allocation structures */
struct ecam_allocation alloc[0];
} __attribute__ (( packed ));
/** A mapped Enhanced Configuration Access Mechanism allocation */
struct ecam_mapping {
/** Allocation */
struct ecam_allocation alloc;
/** PCI bus:dev.fn address range */
struct pci_range range;
/** MMIO base address */
void *regs;
};
extern struct pci_api ecam_api;
#endif /* _IPXE_ECAM_H */

View File

@ -0,0 +1,139 @@
#ifndef _IPXE_ECAM_IO_H
#define _IPXE_ECAM_IO_H
/** @file
*
* PCI I/O API for Enhanced Configuration Access Mechanism (ECAM)
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#ifdef PCIAPI_ECAM
#define PCIAPI_PREFIX_ecam
#else
#define PCIAPI_PREFIX_ecam __ecam_
#endif
struct pci_device;
/** Construct ECAM location */
#define ECAM_LOC( where, len ) ( ( (len) << 16 ) | where )
/** Extract offset from ECAM location */
#define ECAM_WHERE( location ) ( (location) & 0xffff )
/** Extract length from ECAM location */
#define ECAM_LEN( location ) ( (location) >> 16 )
extern int ecam_read ( struct pci_device *pci, unsigned int location,
void *value );
extern int ecam_write ( struct pci_device *pci, unsigned int location,
unsigned long value );
/**
* Read byte from PCI configuration space via ECAM
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( ecam, pci_read_config_byte ) ( struct pci_device *pci,
unsigned int where,
uint8_t *value ) {
return ecam_read ( pci, ECAM_LOC ( where, sizeof ( *value ) ), value );
}
/**
* Read word from PCI configuration space via ECAM
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( ecam, pci_read_config_word ) ( struct pci_device *pci,
unsigned int where,
uint16_t *value ) {
return ecam_read ( pci, ECAM_LOC ( where, sizeof ( *value ) ), value );
}
/**
* Read dword from PCI configuration space via ECAM
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value read
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( ecam, pci_read_config_dword ) ( struct pci_device *pci,
unsigned int where,
uint32_t *value ) {
return ecam_read ( pci, ECAM_LOC ( where, sizeof ( *value ) ), value );
}
/**
* Write byte to PCI configuration space via ECAM
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( ecam, pci_write_config_byte ) ( struct pci_device *pci,
unsigned int where,
uint8_t value ) {
return ecam_write ( pci, ECAM_LOC ( where, sizeof ( value ) ), value );
}
/**
* Write word to PCI configuration space via ECAM
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( ecam, pci_write_config_word ) ( struct pci_device *pci,
unsigned int where,
uint16_t value ) {
return ecam_write ( pci, ECAM_LOC ( where, sizeof ( value ) ), value );
}
/**
* Write dword to PCI configuration space via ECAM
*
* @v pci PCI device
* @v where Location within PCI configuration space
* @v value Value to be written
* @ret rc Return status code
*/
static inline __always_inline int
PCIAPI_INLINE ( ecam, pci_write_config_dword ) ( struct pci_device *pci,
unsigned int where,
uint32_t value ) {
return ecam_write ( pci, ECAM_LOC ( where, sizeof ( value ) ), value );
}
/**
* Map PCI bus address as an I/O address
*
* @v bus_addr PCI bus address
* @v len Length of region
* @ret io_addr I/O address, or NULL on error
*/
static inline __always_inline void *
PCIAPI_INLINE ( ecam, pci_ioremap ) ( struct pci_device *pci __unused,
unsigned long bus_addr, size_t len ) {
return ioremap ( bus_addr, len );
}
#endif /* _IPXE_ECAM_IO_H */

View File

@ -31,8 +31,9 @@ static int _ecb_name ## _setkey ( void *ctx, const void *key, \
size_t keylen ) { \
return cipher_setkey ( &_raw_cipher, ctx, key, keylen ); \
} \
static void _ecb_name ## _setiv ( void *ctx, const void *iv ) { \
cipher_setiv ( &_raw_cipher, ctx, iv ); \
static void _ecb_name ## _setiv ( void *ctx, const void *iv, \
size_t ivlen ) { \
cipher_setiv ( &_raw_cipher, ctx, iv, ivlen ); \
} \
static void _ecb_name ## _encrypt ( void *ctx, const void *src, \
void *dst, size_t len ) { \
@ -46,10 +47,13 @@ struct cipher_algorithm _ecb_cipher = { \
.name = #_ecb_name, \
.ctxsize = sizeof ( _raw_context ), \
.blocksize = _blocksize, \
.alignsize = _blocksize, \
.authsize = 0, \
.setkey = _ecb_name ## _setkey, \
.setiv = _ecb_name ## _setiv, \
.encrypt = _ecb_name ## _encrypt, \
.decrypt = _ecb_name ## _decrypt, \
.auth = cipher_null_auth, \
};
#endif /* _IPXE_ECB_H */

View File

@ -1,24 +1,18 @@
/** @file
Processor or Compiler specific defines and types for AArch64.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __PROCESSOR_BIND_H__
#define __PROCESSOR_BIND_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
///
/// Define the processor type so other code can make processor based choices
@ -28,11 +22,57 @@ FILE_LICENCE ( BSD3 );
//
// Make sure we are using the correct packing rules per EFI specification
//
#ifndef __GNUC__
#if !defined (__GNUC__) && !defined (__ASSEMBLER__)
#pragma pack()
#endif
#if _MSC_EXTENSIONS
#if defined (_MSC_EXTENSIONS)
//
// Disable some level 4 compilation warnings (same as IA32 and X64)
//
//
// Disabling bitfield type checking warnings.
//
#pragma warning ( disable : 4214 )
//
// Disabling the unreferenced formal parameter warnings.
//
#pragma warning ( disable : 4100 )
//
// Disable slightly different base types warning as CHAR8 * can not be set
// to a constant string.
//
#pragma warning ( disable : 4057 )
//
// ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning
//
#pragma warning ( disable : 4127 )
//
// This warning is caused by functions defined but not used. For precompiled header only.
//
#pragma warning ( disable : 4505 )
//
// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
//
#pragma warning ( disable : 4206 )
//
// Disable 'potentially uninitialized local variable X used' warnings
//
#pragma warning ( disable : 4701 )
//
// Disable 'potentially uninitialized local pointer variable X used' warnings
//
#pragma warning ( disable : 4703 )
//
// use Microsoft* C compiler dependent integer width types
//
@ -47,7 +87,9 @@ FILE_LICENCE ( BSD3 );
typedef unsigned char UINT8;
typedef char CHAR8;
typedef signed char INT8;
#else
//
// Assume standard AARCH64 alignment.
//
@ -62,6 +104,7 @@ FILE_LICENCE ( BSD3 );
typedef unsigned char UINT8;
typedef char CHAR8;
typedef signed char INT8;
#endif
///
@ -95,12 +138,22 @@ typedef INT64 INTN;
///
#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL
///
/// Maximum usable address at boot time (48 bits using 4 KB pages)
///
#define MAX_ALLOC_ADDRESS 0xFFFFFFFFFFFFULL
///
/// Maximum legal AArch64 INTN and UINTN values.
///
#define MAX_INTN ((INTN)0x7FFFFFFFFFFFFFFFULL)
#define MAX_UINTN ((UINTN)0xFFFFFFFFFFFFFFFFULL)
///
/// Minimum legal AArch64 INTN value.
///
#define MIN_INTN (((INTN)-9223372036854775807LL) - 1)
///
/// The stack alignment required for AARCH64
///

View File

@ -1,22 +1,16 @@
/** @file
Processor or Compiler specific defines and types for ARM.
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __PROCESSOR_BIND_H__
#define __PROCESSOR_BIND_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
///
/// Define the processor type so other code can make processor based choices
@ -26,18 +20,67 @@ FILE_LICENCE ( BSD3 );
//
// Make sure we are using the correct packing rules per EFI specification
//
#ifndef __GNUC__
#if !defined (__GNUC__) && !defined (__ASSEMBLER__)
#pragma pack()
#endif
#if defined (_MSC_EXTENSIONS)
//
// RVCT does not support the __builtin_unreachable() macro
// Disable some level 4 compilation warnings (same as IA32 and X64)
//
#ifdef __ARMCC_VERSION
//
// Disabling bitfield type checking warnings.
//
#pragma warning ( disable : 4214 )
//
// Disabling the unreferenced formal parameter warnings.
//
#pragma warning ( disable : 4100 )
//
// Disable slightly different base types warning as CHAR8 * can not be set
// to a constant string.
//
#pragma warning ( disable : 4057 )
//
// ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning
//
#pragma warning ( disable : 4127 )
//
// This warning is caused by functions defined but not used. For precompiled header only.
//
#pragma warning ( disable : 4505 )
//
// This warning is caused by empty (after preprocessing) source file. For precompiled header only.
//
#pragma warning ( disable : 4206 )
//
// Disable 'potentially uninitialized local variable X used' warnings
//
#pragma warning ( disable : 4701 )
//
// Disable 'potentially uninitialized local pointer variable X used' warnings
//
#pragma warning ( disable : 4703 )
#endif
//
// MSFT doesn't support the __builtin_unreachable() macro
//
#if defined (_MSC_EXTENSIONS)
#define UNREACHABLE()
#endif
#if _MSC_EXTENSIONS
#if defined (_MSC_EXTENSIONS)
//
// use Microsoft* C compiler dependent integer width types
//
@ -101,12 +144,22 @@ typedef INT32 INTN;
///
#define MAX_ADDRESS 0xFFFFFFFF
///
/// Maximum usable address at boot time
///
#define MAX_ALLOC_ADDRESS MAX_ADDRESS
///
/// Maximum legal ARM INTN and UINTN values.
///
#define MAX_INTN ((INTN)0x7FFFFFFF)
#define MAX_UINTN ((UINTN)0xFFFFFFFF)
///
/// Minimum legal ARM INTN value.
///
#define MIN_INTN (((INTN)-2147483647) - 1)
///
/// The stack alignment required for ARM
///
@ -161,6 +214,11 @@ typedef INT32 INTN;
#define GCC_ASM_IMPORT(name)
#endif
#elif defined (_MSC_EXTENSIONS)
//
// PRESERVE8 is not supported by the MSFT assembler.
//
#define PRESERVE8
#endif
/**
@ -180,5 +238,3 @@ typedef INT32 INTN;
#endif
#endif

View File

@ -6,23 +6,16 @@
environment. There are a set of base libraries in the Mde Package that can
be used to implement base modules.
Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __BASE_H__
#define __BASE_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
//
// Include processor specific binding
@ -36,64 +29,12 @@ FILE_LICENCE ( BSD3 );
#pragma warning ( disable : 4200 )
#endif
/**
Verifies the storage size of a given data type.
This macro generates a divide by zero error or a zero size array declaration in
the preprocessor if the size is incorrect. These are declared as "extern" so
the space for these arrays will not be in the modules.
@param TYPE The date type to determine the size of.
@param Size The expected size for the TYPE.
**/
#define VERIFY_SIZE_OF(TYPE, Size) extern UINT8 _VerifySizeof##TYPE[(sizeof(TYPE) == (Size)) / (sizeof(TYPE) == (Size))]
//
// Verify that ProcessorBind.h produced UEFI Data Types that are compliant with
// Section 2.3.1 of the UEFI 2.3 Specification.
//
VERIFY_SIZE_OF (BOOLEAN, 1);
VERIFY_SIZE_OF (INT8, 1);
VERIFY_SIZE_OF (UINT8, 1);
VERIFY_SIZE_OF (INT16, 2);
VERIFY_SIZE_OF (UINT16, 2);
VERIFY_SIZE_OF (INT32, 4);
VERIFY_SIZE_OF (UINT32, 4);
VERIFY_SIZE_OF (INT64, 8);
VERIFY_SIZE_OF (UINT64, 8);
VERIFY_SIZE_OF (CHAR8, 1);
VERIFY_SIZE_OF (CHAR16, 2);
//
// The following three enum types are used to verify that the compiler
// configuration for enum types is compliant with Section 2.3.1 of the
// UEFI 2.3 Specification. These enum types and enum values are not
// intended to be used. A prefix of '__' is used avoid conflicts with
// other types.
//
typedef enum {
__VerifyUint8EnumValue = 0xff
} __VERIFY_UINT8_ENUM_SIZE;
typedef enum {
__VerifyUint16EnumValue = 0xffff
} __VERIFY_UINT16_ENUM_SIZE;
typedef enum {
__VerifyUint32EnumValue = 0xffffffff
} __VERIFY_UINT32_ENUM_SIZE;
VERIFY_SIZE_OF (__VERIFY_UINT8_ENUM_SIZE, 4);
VERIFY_SIZE_OF (__VERIFY_UINT16_ENUM_SIZE, 4);
VERIFY_SIZE_OF (__VERIFY_UINT32_ENUM_SIZE, 4);
//
// The Microsoft* C compiler can removed references to unreferenced data items
// if the /OPT:REF linker option is used. We defined a macro as this is a
// a non standard extension
//
#if defined(_MSC_EXTENSIONS) && !defined (MDE_CPU_EBC)
#if defined (_MSC_VER) && _MSC_VER < 1800 && !defined (MDE_CPU_EBC)
///
/// Remove global variable from the linked image if there are no references to
/// it after all compiler and linker optimizations have been performed.
@ -114,11 +55,10 @@ VERIFY_SIZE_OF (__VERIFY_UINT32_ENUM_SIZE, 4);
// warnings.
//
#ifndef UNREACHABLE
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)
#ifdef __GNUC__
///
/// Signal compilers and analyzers that this call is not reachable. It is
/// up to the compiler to remove any code past that point.
/// Not implemented by GCC 4.4 or earlier.
///
#define UNREACHABLE() __builtin_unreachable ()
#elif defined (__has_feature)
@ -220,6 +160,26 @@ VERIFY_SIZE_OF (__VERIFY_UINT32_ENUM_SIZE, 4);
#endif
#endif
///
/// Tell the code optimizer that the function will return twice.
/// This prevents wrong optimizations which can cause bugs.
///
#ifndef RETURNS_TWICE
#if defined (__GNUC__) || defined (__clang__)
///
/// Tell the code optimizer that the function will return twice.
/// This prevents wrong optimizations which can cause bugs.
///
#define RETURNS_TWICE __attribute__((returns_twice))
#else
///
/// Tell the code optimizer that the function will return twice.
/// This prevents wrong optimizations which can cause bugs.
///
#define RETURNS_TWICE
#endif
#endif
//
// For symbol name in assembly code, an extra "_" is sometimes necessary
//
@ -236,7 +196,7 @@ VERIFY_SIZE_OF (__VERIFY_UINT32_ENUM_SIZE, 4);
///
#define ASM_PFX(name) _CONCATENATE (__USER_LABEL_PREFIX__, name)
#if __APPLE__
#ifdef __APPLE__
//
// Apple extension that is used by the linker to optimize code size
// with assembly functions. Put at the end of your .S files
@ -246,15 +206,7 @@ VERIFY_SIZE_OF (__VERIFY_UINT32_ENUM_SIZE, 4);
#define ASM_FUNCTION_REMOVE_IF_UNREFERENCED
#endif
#ifdef __CC_ARM
//
// Older RVCT ARM compilers don't fully support #pragma pack and require __packed
// as a prefix for the structure.
//
#define PACKED __packed
#else
#define PACKED
#endif
///
/// 128 bit buffer containing a unique identifier value.
@ -359,7 +311,15 @@ struct _LIST_ENTRY {
///
/// NULL pointer (VOID *)
///
#if defined (__cplusplus)
#if defined (_MSC_EXTENSIONS)
#define NULL nullptr
#else
#define NULL __null
#endif
#else
#define NULL ((VOID *) 0)
#endif
//
// Null character
@ -378,6 +338,14 @@ struct _LIST_ENTRY {
#define MAX_INT64 ((INT64)0x7FFFFFFFFFFFFFFFULL)
#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL)
///
/// Minimum values for the signed UEFI Data Types
///
#define MIN_INT8 (((INT8) -127) - 1)
#define MIN_INT16 (((INT16) -32767) - 1)
#define MIN_INT32 (((INT32) -2147483647) - 1)
#define MIN_INT64 (((INT64) -9223372036854775807LL) - 1)
#define BIT0 0x00000001
#define BIT1 0x00000002
#define BIT2 0x00000004
@ -554,21 +522,24 @@ struct _LIST_ENTRY {
#define BASE_8EB 0x8000000000000000ULL
//
// Support for variable length argument lists using the ANSI standard.
// Support for variable argument lists in freestanding edk2 modules.
//
// Since we are using the ANSI standard we used the standard naming and
// did not follow the coding convention
// For modules that use the ISO C library interfaces for variable
// argument lists, refer to "StdLib/Include/stdarg.h".
//
// VA_LIST - typedef for argument list.
// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use.
// VA_END (VA_LIST Marker) - Clear Marker
// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argument from
// the ... list. You must know the size and pass it in this macro.
// VA_ARG (VA_LIST Marker, var arg type) - Use Marker to get an argument from
// the ... list. You must know the type and pass it in this macro. Type
// must be compatible with the type of the actual next argument (as promoted
// according to the default argument promotions.)
// VA_COPY (VA_LIST Dest, VA_LIST Start) - Initialize Dest as a copy of Start.
//
// example:
// Example:
//
// UINTN
// EFIAPI
// ExampleVarArg (
// IN UINTN NumberOfArgs,
// ...
@ -584,15 +555,21 @@ struct _LIST_ENTRY {
// VA_START (Marker, NumberOfArgs);
// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) {
// //
// // The ... list is a series of UINTN values, so average them up.
// // The ... list is a series of UINTN values, so sum them up.
// //
// Result += VA_ARG (Marker, UINTN);
// }
//
// VA_END (Marker);
// return Result
// return Result;
// }
//
// Notes:
// - Functions that call VA_START() / VA_END() must have a variable
// argument list and must be declared EFIAPI.
// - Functions that call VA_COPY() / VA_END() must be declared EFIAPI.
// - Functions that only use VA_LIST and VA_ARG() need not be EFIAPI.
//
/**
Return the size of argument that has been aligned to sizeof (UINTN).
@ -603,37 +580,19 @@ struct _LIST_ENTRY {
**/
#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
#if defined(__CC_ARM)
#if defined (_M_ARM) || defined (_M_ARM64)
//
// RVCT ARM variable argument list support.
// MSFT ARM variable argument list support.
//
///
/// Variable used to traverse the list of arguments. This type can vary by
/// implementation and could be an array or structure.
///
#ifdef __APCS_ADSABI
typedef int *va_list[1];
#define VA_LIST va_list
#else
typedef struct __va_list { void *__ap; } va_list;
#define VA_LIST va_list
#endif
typedef char *VA_LIST;
#define VA_START(Marker, Parameter) __va_start(Marker, Parameter)
#define VA_START(Marker, Parameter) __va_start (&Marker, &Parameter, _INT_SIZE_OF (Parameter), __alignof(Parameter), &Parameter)
#define VA_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE) + ((-(INTN)Marker) & (sizeof(TYPE) - 1))) - _INT_SIZE_OF (TYPE)))
#define VA_END(Marker) (Marker = (VA_LIST) 0)
#define VA_COPY(Dest, Start) ((void)((Dest) = (Start)))
#define VA_ARG(Marker, TYPE) __va_arg(Marker, TYPE)
#define VA_END(Marker) ((void)0)
// For some ARM RVCT compilers, __va_copy is not defined
#ifndef __va_copy
#define __va_copy(dest, src) ((void)((dest) = (src)))
#endif
#define VA_COPY(Dest, Start) __va_copy (Dest, Start)
#elif defined(__GNUC__)
#elif defined (__GNUC__) || defined (__clang__)
#if defined (MDE_CPU_X64) && !defined (NO_MSABI_VA_FUNCS)
//
@ -793,16 +752,72 @@ typedef UINTN *BASE_LIST;
@return Offset, in bytes, of field.
**/
#ifdef __GNUC__
#if __GNUC__ >= 4
#if (defined (__GNUC__) && __GNUC__ >= 4) || defined (__clang__)
#define OFFSET_OF(TYPE, Field) ((UINTN) __builtin_offsetof(TYPE, Field))
#endif
#endif
#ifndef OFFSET_OF
#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
#endif
/**
Portable definition for compile time assertions.
Equivalent to C11 static_assert macro from assert.h.
@param Expression Boolean expression.
@param Message Raised compiler diagnostic message when expression is false.
**/
#ifdef MDE_CPU_EBC
#define STATIC_ASSERT(Expression, Message)
#elif defined (_MSC_EXTENSIONS) || defined (__cplusplus)
#define STATIC_ASSERT static_assert
#else
#define STATIC_ASSERT _Static_assert
#endif
//
// Verify that ProcessorBind.h produced UEFI Data Types that are compliant with
// Section 2.3.1 of the UEFI 2.3 Specification.
//
STATIC_ASSERT (sizeof (BOOLEAN) == 1, "sizeof (BOOLEAN) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (INT8) == 1, "sizeof (INT8) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (UINT8) == 1, "sizeof (UINT8) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (INT16) == 2, "sizeof (INT16) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (UINT16) == 2, "sizeof (UINT16) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (INT32) == 4, "sizeof (INT32) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (UINT32) == 4, "sizeof (UINT32) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (INT64) == 8, "sizeof (INT64) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (UINT64) == 8, "sizeof (UINT64) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (CHAR8) == 1, "sizeof (CHAR8) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (CHAR16) == 2, "sizeof (CHAR16) does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (L'A') == 2, "sizeof (L'A') does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (L"A") == 4, "sizeof (L\"A\") does not meet UEFI Specification Data Type requirements");
//
// The following three enum types are used to verify that the compiler
// configuration for enum types is compliant with Section 2.3.1 of the
// UEFI 2.3 Specification. These enum types and enum values are not
// intended to be used. A prefix of '__' is used avoid conflicts with
// other types.
//
typedef enum {
__VerifyUint8EnumValue = 0xff
} __VERIFY_UINT8_ENUM_SIZE;
typedef enum {
__VerifyUint16EnumValue = 0xffff
} __VERIFY_UINT16_ENUM_SIZE;
typedef enum {
__VerifyUint32EnumValue = 0xffffffff
} __VERIFY_UINT32_ENUM_SIZE;
STATIC_ASSERT (sizeof (__VERIFY_UINT8_ENUM_SIZE) == 4, "Size of enum does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (__VERIFY_UINT16_ENUM_SIZE) == 4, "Size of enum does not meet UEFI Specification Data Type requirements");
STATIC_ASSERT (sizeof (__VERIFY_UINT32_ENUM_SIZE) == 4, "Size of enum does not meet UEFI Specification Data Type requirements");
/**
Macro that returns a pointer to the data structure that contains a specified field of
that data structure. This is a lightweight method to hide information by placing a
@ -822,7 +837,7 @@ typedef UINTN *BASE_LIST;
@return A pointer to the structure from one of it's elements.
**/
#define BASE_CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field)))
#define BASE_CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - OFFSET_OF (TYPE, Field)))
/**
Rounds a value up to the next boundary using a specified alignment.
@ -867,7 +882,6 @@ typedef UINTN *BASE_LIST;
**/
#define ALIGN_VARIABLE(Value) ALIGN_VALUE ((Value), sizeof (UINTN))
/**
Return the maximum of two operands.
@ -955,7 +969,7 @@ typedef UINTN RETURN_STATUS;
///
/// The operation completed successfully.
///
#define RETURN_SUCCESS 0
#define RETURN_SUCCESS (RETURN_STATUS)(0)
///
/// The image failed to load.
@ -1160,7 +1174,6 @@ typedef UINTN RETURN_STATUS;
///
#define RETURN_WARN_FILE_SYSTEM ENCODE_WARNING (6)
/**
Returns a 16-bit signature built from 2 ASCII characters.
@ -1215,7 +1228,13 @@ typedef UINTN RETURN_STATUS;
(SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32))
#if defined (_MSC_EXTENSIONS) && !defined (__INTEL_COMPILER) && !defined (MDE_CPU_EBC)
void *
_ReturnAddress (
void
);
#pragma intrinsic(_ReturnAddress)
/**
Get the return address of the calling function.
@ -1229,8 +1248,8 @@ typedef UINTN RETURN_STATUS;
**/
#define RETURN_ADDRESS(L) ((L == 0) ? _ReturnAddress() : (VOID *) 0)
#elif defined(__GNUC__)
void * __builtin_return_address (unsigned int level);
#elif defined (__GNUC__) || defined (__clang__)
/**
Get the return address of the calling function.
@ -1244,6 +1263,7 @@ typedef UINTN RETURN_STATUS;
**/
#define RETURN_ADDRESS(L) __builtin_return_address (L)
#else
/**
Get the return address of the calling function.
@ -1269,4 +1289,3 @@ typedef UINTN RETURN_STATUS;
#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0]))
#endif

View File

@ -5,14 +5,8 @@
ACPI 2.0 specification defines the ACPI 2.0 GUID. UEFI 2.0 defines the
ACPI 2.0 Table GUID and ACPI Table GUID.
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
GUIDs defined in UEFI 2.0 spec.
@ -22,7 +16,7 @@
#ifndef __ACPI_GUID_H__
#define __ACPI_GUID_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define ACPI_TABLE_GUID \
{ \

View File

@ -3,21 +3,15 @@
and EFI_FILE_PROTOCOL.GetInfo() to set or get generic file information.
This GUID is defined in UEFI specification.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __FILE_INFO_H__
#define __FILE_INFO_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define EFI_FILE_INFO_ID \
{ \

View File

@ -3,21 +3,15 @@
or EFI_FILE_PROTOCOL.SetInfo() to get or set information about the system's volume.
This GUID is defined in UEFI specification.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __FILE_SYSTEM_INFO_H__
#define __FILE_SYSTEM_INFO_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define EFI_FILE_SYSTEM_INFO_ID \
{ \

View File

@ -1,14 +1,8 @@
/** @file
Guid used to identify HII FormMap configuration method.
Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
GUID defined in UEFI 2.2 spec.
@ -17,7 +11,7 @@
#ifndef __EFI_HII_FORMMAP_GUID_H__
#define __EFI_HII_FORMMAP_GUID_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define EFI_HII_STANDARD_FORM_GUID \
{ 0x3bd2f4ec, 0xe524, 0x46e4, { 0xa9, 0xd8, 0x51, 0x1, 0x17, 0x42, 0x55, 0x62 } }

View File

@ -2,14 +2,8 @@
GUID indicates that the form set contains forms designed to be used
for platform configuration and this form set will be displayed.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
GUID defined in UEFI 2.1.
@ -19,7 +13,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __HII_PLATFORM_SETUP_FORMSET_GUID_H__
#define __HII_PLATFORM_SETUP_FORMSET_GUID_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \
{ 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } }
@ -30,8 +24,12 @@ FILE_LICENCE ( BSD3 );
#define EFI_HII_USER_CREDENTIAL_FORMSET_GUID \
{ 0x337f4407, 0x5aee, 0x4b83, { 0xb2, 0xa7, 0x4e, 0xad, 0xca, 0x30, 0x88, 0xcd } }
#define EFI_HII_REST_STYLE_FORMSET_GUID \
{ 0x790217bd, 0xbecf, 0x485b, { 0x91, 0x70, 0x5f, 0xf7, 0x11, 0x31, 0x8b, 0x27 } }
extern EFI_GUID gEfiHiiPlatformSetupFormsetGuid;
extern EFI_GUID gEfiHiiDriverHealthFormsetGuid;
extern EFI_GUID gEfiHiiUserCredentialFormsetGuid;
extern EFI_GUID gEfiHiiRestStyleFormsetGuid;
#endif

View File

@ -1,21 +1,15 @@
/** @file
EDKII extented HII IFR guid opcodes.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __MDEMODULE_HII_H__
#define __MDEMODULE_HII_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define NARROW_CHAR 0xFFF0
#define WIDE_CHAR 0xFFF1
@ -213,10 +207,27 @@ typedef struct _EFI_IFR_GUID_VAREQNAME {
UINT16 NameId;
} EFI_IFR_GUID_VAREQNAME;
///
/// EDKII implementation extension GUID, used to indaicate there are bit fields in the varstore.
///
#define EDKII_IFR_BIT_VARSTORE_GUID \
{0x82DDD68B, 0x9163, 0x4187, {0x9B, 0x27, 0x20, 0xA8, 0xFD, 0x60,0xA7, 0x1D}}
///
/// EDKII implementation extension flags, used to indaicate the disply style and bit width for bit filed storage.
/// Two high bits for display style and the low six bits for bit width.
///
#define EDKII_IFR_DISPLAY_BIT 0xC0
#define EDKII_IFR_DISPLAY_INT_DEC_BIT 0x00
#define EDKII_IFR_DISPLAY_UINT_DEC_BIT 0x40
#define EDKII_IFR_DISPLAY_UINT_HEX_BIT 0x80
#define EDKII_IFR_NUMERIC_SIZE_BIT 0x3F
#pragma pack()
extern EFI_GUID gEfiIfrTianoGuid;
extern EFI_GUID gEfiIfrFrameworkGuid;
extern EFI_GUID gEdkiiIfrBitVarstoreGuid;
#endif

View File

@ -1,14 +1,8 @@
/** @file
Terminal Device Path Vendor Guid.
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
GUIDs defined in UEFI 2.0 spec.
@ -18,7 +12,7 @@
#ifndef __PC_ANSI_H__
#define __PC_ANSI_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define EFI_PC_ANSI_GUID \
{ \

View File

@ -5,14 +5,8 @@
locate the SMBIOS tables. Do not search the 0xF0000 segment to find SMBIOS
tables.
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
GUIDs defined in UEFI 2.5 spec.
@ -22,7 +16,7 @@
#ifndef __SMBIOS_GUID_H__
#define __SMBIOS_GUID_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#define SMBIOS_TABLE_GUID \
{ \

View File

@ -2,13 +2,7 @@
GUID for UEFI WIN_CERTIFICATE structure.
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
GUID defined in UEFI 2.0 spec.
@ -17,7 +11,7 @@
#ifndef __EFI_WIN_CERTIFICATE_H__
#define __EFI_WIN_CERTIFICATE_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
//
// _WIN_CERTIFICATE.wCertificateType
@ -69,7 +63,6 @@ typedef struct {
UINT8 Signature[256];
} EFI_CERT_BLOCK_RSA_2048_SHA256;
///
/// Certificate which encapsulates a GUID-specific digital signature
///
@ -93,7 +86,6 @@ typedef struct {
UINT8 CertData[1];
} WIN_CERTIFICATE_UEFI_GUID;
///
/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature.
///

View File

@ -1,21 +1,15 @@
/** @file
Processor or Compiler specific defines and types for IA-32 architecture.
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __PROCESSOR_BIND_H__
#define __PROCESSOR_BIND_H__
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
///
/// Define the processor type so other code can make processor based choices.
@ -56,7 +50,6 @@ FILE_LICENCE ( BSD3 );
#endif
#if defined (_MSC_EXTENSIONS)
//
@ -95,7 +88,7 @@ FILE_LICENCE ( BSD3 );
//
#pragma warning ( disable : 4206 )
#if _MSC_VER == 1800 || _MSC_VER == 1900
#if defined (_MSC_VER) && _MSC_VER >= 1800
//
// Disable these warnings for VS2013.
@ -117,7 +110,6 @@ FILE_LICENCE ( BSD3 );
#endif
#if defined (_MSC_EXTENSIONS)
//
@ -248,12 +240,22 @@ typedef INT32 INTN;
///
#define MAX_ADDRESS 0xFFFFFFFF
///
/// Maximum usable address at boot time
///
#define MAX_ALLOC_ADDRESS MAX_ADDRESS
///
/// Maximum legal IA-32 INTN and UINTN values.
///
#define MAX_INTN ((INTN)0x7FFFFFFF)
#define MAX_UINTN ((UINTN)0xFFFFFFFF)
///
/// Minimum legal IA-32 INTN value.
///
#define MIN_INTN (((INTN)-2147483647) - 1)
///
/// The stack alignment required for IA-32.
///
@ -279,7 +281,7 @@ typedef INT32 INTN;
/// Microsoft* compiler specific method for EFIAPI calling convention.
///
#define EFIAPI __cdecl
#elif defined(__GNUC__)
#elif defined (__GNUC__) || defined (__clang__)
///
/// GCC specific method for EFIAPI calling convention.
///
@ -292,7 +294,7 @@ typedef INT32 INTN;
#define EFIAPI
#endif
#if defined(__GNUC__)
#if defined (__GNUC__) || defined (__clang__)
///
/// For GNU assembly code, .global or .globl can declare global symbols.
/// Define this macro to unify the usage.
@ -317,4 +319,3 @@ typedef INT32 INTN;
#endif
#endif

View File

@ -1,20 +1,15 @@
/** @file
ACPI 1.0b definitions from the ACPI Specification, revision 1.0b
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _ACPI_1_0_H_
#define _ACPI_1_0_H_
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#include <ipxe/efi/IndustryStandard/AcpiAml.h>
@ -45,7 +40,7 @@ typedef struct {
#pragma pack()
//
// Define for Desriptor
// Define for Descriptor
//
#define ACPI_SMALL_ITEM_FLAG 0x00
#define ACPI_LARGE_ITEM_FLAG 0x01
@ -117,7 +112,7 @@ typedef struct {
#pragma pack(1)
///
/// The commond definition of QWORD, DWORD, and WORD
/// The common definition of QWORD, DWORD, and WORD
/// Address Space Descriptors.
///
typedef PACKED struct {
@ -366,7 +361,7 @@ typedef struct {
#define EFI_ACPI_DMA_TRANSFER_TYPE_MASK 0x03
#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x00
#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x01
#define EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x10
#define EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x02
//
// IO Information
@ -384,6 +379,16 @@ typedef struct {
#define EFI_ACPI_MEMORY_WRITABLE 0x01
#define EFI_ACPI_MEMORY_NON_WRITABLE 0x00
//
// Interrupt Vector Flags definitions for Extended Interrupt Descriptor
// Ref ACPI specification 6.4.3.6
//
#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK BIT0
#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_MODE_MASK BIT1
#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_POLARITY_MASK BIT2
#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_SHARABLE_MASK BIT3
#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_WAKE_CAPABLITY_MASK BIT4
//
// Ensure proper structure formats
//

View File

@ -1,25 +1,19 @@
/** @file
ACPI 2.0 definitions from the ACPI Specification, revision 2.0
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _ACPI_2_0_H_
#define _ACPI_2_0_H_
FILE_LICENCE ( BSD3 );
FILE_LICENCE ( BSD2_PATENT );
#include <ipxe/efi/IndustryStandard/Acpi10.h>
//
// Define for Desriptor
// Define for Descriptor
//
#define ACPI_LARGE_GENERIC_REGISTER_DESCRIPTOR_NAME 0x02
@ -513,7 +507,7 @@ typedef struct {
#define EFI_ACPI_2_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE SIGNATURE_32('S', 'L', 'I', 'T')
///
/// "SPCR" Serial Port Concole Redirection Table
/// "SPCR" Serial Port Console Redirection Table
///
#define EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE SIGNATURE_32('S', 'P', 'C', 'R')

Some files were not shown because too many files have changed in this diff Show More