diff --git a/contrib/errdb/errdb.pl b/contrib/errdb/errdb.pl index fc1919f6..6423d834 100755 --- a/contrib/errdb/errdb.pl +++ b/contrib/errdb/errdb.pl @@ -73,6 +73,7 @@ my $xrefs = {}; while ( <> ) { chomp; ( my $errno, my $filename, my $line, my $description ) = split ( /\t/ ); + $errno = substr ( $errno, 0, 6 ) unless $errno =~ /^7f/; $errors->{$errno} = $description; $xrefs->{$errno} ||= {}; $xrefs->{$errno}->{$filename} ||= {}; diff --git a/src/Makefile b/src/Makefile index 6564f8fc..2fce34f9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -49,6 +49,7 @@ ICCFIX := ./util/iccfix EINFO := ./util/einfo GENKEYMAP := ./util/genkeymap.pl DOXYGEN := doxygen +LCAB := lcab BINUTILS_DIR := /usr BFD_DIR := $(BINUTILS_DIR) ZLIB_DIR := /usr diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index d40f226f..80b70f5c 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -113,6 +113,18 @@ $(warning Use GNU ld instead) $(error Unsuitable build environment found) endif +############################################################################### +# +# Check if $(eval ...) is available to use +# + +HAVE_EVAL := +ifndef NO_EVAL +$(eval HAVE_EVAL := yes) +endif +eval : + @$(ECHO) $(HAVE_EVAL) + ############################################################################### # # Check for various tool workarounds @@ -128,6 +140,11 @@ WORKAROUND_LDFLAGS := COMMA := , EMPTY := SPACE := $(EMPTY) $(EMPTY) +HASH := \# +define NEWLINE + + +endef # Check for an old version of gas (binutils 2.9.1) # @@ -200,6 +217,16 @@ Q := @ QM := @ endif +############################################################################### +# +# Checker +# +ifeq ($(C),1) +export REAL_CC := $(CC) +CC := cgcc +CFLAGS += -Wno-decl +endif + ############################################################################### # # Set BIN according to whatever was specified on the command line as @@ -475,7 +502,7 @@ LDFLAGS += --gc-sections # compiler.h is needed for our linking and debugging system # -CFLAGS += -include compiler.h +CFLAGS += -include include/compiler.h # CFLAGS for specific object types # @@ -665,84 +692,119 @@ $(BIN)/version.o : ../.git/index endif # We automatically generate rules for any file mentioned in AUTO_SRCS -# using the following set of templates. It would be cleaner to use -# $(eval ...), but this function exists only in GNU make >= 3.80. +# using the following set of templates. We use $(eval ...) if +# available, otherwise we generate separate Makefile fragments and +# include them. # deps_template : generate dependency list for a given source file # # $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# +define deps_template_file +$(call deps_template_parts,$(1),$(subst .,,$(suffix $(1))),$(basename $(notdir $(1)))) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") # $(2) is the source type (e.g. "c") # $(3) is the source base name (e.g. "rtl8139") # -define deps_template +define deps_template_parts @$(ECHO) " [DEPS] $(1)" @$(MKDIR) -p $(BIN)/deps/$(dir $(1)) $(Q)$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \ -Wno-error -M $(1) -MG -MP | \ sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d + $(Q)$(if $(findstring drivers/,$(1)),\ + $(PERL) $(PARSEROM) $(1) >> $(BIN)/deps/$(1).d) endef # rules_template : generate rules for a given source file # # $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# +define rules_template +$(call rules_template_parts,$(1),$(subst .,,$(suffix $(1))),$(basename $(notdir $(1)))) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") # $(2) is the source type (e.g. "c") # $(3) is the source base name (e.g. "rtl8139") # -define rules_template +define rules_template_parts +$$(BIN)/$(3).o : $(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS) + $$(QM)$(ECHO) " [BUILD] $$@" + $$(RULE_$(2)) +BOBJS += $$(BIN)/$(3).o +$(foreach TGT,$(DEBUG_TARGETS),$(if $(RULE_$(2)_to_$(TGT)),$(NEWLINE)$(call rules_template_target,$(1),$(2),$(3),$(TGT)))) +$$(BIN)/deps/$(1).d : $$($(3)_DEPS) +TAGS : $$($(3)_DEPS) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# $(2) is the source type (e.g. "c") +# $(3) is the source base name (e.g. "rtl8139") +# $(4) is the destination type (e.g. "dbg%.o") +# +define rules_template_target +$$(BIN)/$(3).$(4) : $(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS) + $$(QM)$(ECHO) " [BUILD] $$@" + $$(RULE_$(2)_to_$(4)) +$(TGT)_OBJS += $$(BIN)/$(3).$(4) +endef +# +# $(1) is the full path to the source file (e.g. "drivers/net/rtl8139.c") +# +define rules_template_file @$(ECHO) " [RULES] $(1)" @$(MKDIR) -p $(BIN)/rules/$(dir $(1)) - @$(ECHO_E) '\n$$(BIN)/$(3).o :' \ - '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS)' \ - '\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \ - '\n\t$$(RULE_$(2))\n' \ - '\nBOBJS += $$(BIN)/$(3).o\n' \ - $(foreach TGT,$(DEBUG_TARGETS), \ - $(if $(RULE_$(2)_to_$(TGT)), \ - '\n$$(BIN)/$(3).$(TGT) :' \ - '$(1) $$(MAKEDEPS) $$(POST_O_DEPS) $$($(3)_DEPS)' \ - '\n\t$$(QM)$(ECHO) " [BUILD] $$@"' \ - '\n\t$$(RULE_$(2)_to_$(TGT))\n' \ - '\n$(TGT)_OBJS += $$(BIN)/$(3).$(TGT)\n' ) ) \ - '\n$(BIN)/deps/$(1).d : $$($(3)_DEPS)\n' \ - '\nTAGS : $$($(3)_DEPS)\n' > $(BIN)/rules/$(1).r - @$(if $(findstring drivers/,$(1)),\ - $(PERL) $(PARSEROM) $(1) >> $(BIN)/rules/$(1).r) + @$(ECHO_E) '$(subst $(NEWLINE),\n,$(call rules_template,$(1)))' \ + > $(BIN)/rules/$(1).r endef -# Rule to generate the dependency list file +# Generate the dependency files # -$(BIN)/deps/%.d : % $(MAKEDEPS) - $(call deps_template,$<,$(subst .,,$(suffix $<)),$(basename $(notdir $<))) +$(BIN)/deps/%.d : % $(MAKEDEPS) $(PARSEROM) + $(call deps_template_file,$<) -# Calculate and include the list of dependency list files +# Calculate list of dependency files # AUTO_DEPS = $(patsubst %,$(BIN)/deps/%.d,$(AUTO_SRCS)) +autodeps : + @$(ECHO) $(AUTO_DEPS) +VERYCLEANUP += $(BIN)/deps + +# Include dependency files +# ifdef NEED_DEPS ifneq ($(AUTO_DEPS),) -include $(AUTO_DEPS) endif endif -autodeps : - @$(ECHO) $(AUTO_DEPS) -VERYCLEANUP += $(BIN)/deps -# Rule to generate the rules file +# Generate the rules files # -$(BIN)/rules/%.r : % $(MAKEDEPS) $(PARSEROM) - $(call rules_template,$<,$(subst .,,$(suffix $<)),$(basename $(notdir $<))) +$(BIN)/rules/%.r : % $(MAKEDEPS) + $(call rules_template_file,$<) -# Calculate and include the list of rules files +# Calculate list of rules files # AUTO_RULES = $(patsubst %,$(BIN)/rules/%.r,$(AUTO_SRCS)) -ifdef NEED_DEPS -ifneq ($(AUTO_RULES),) --include $(AUTO_RULES) -endif -endif autorules : @$(ECHO) $(AUTO_RULES) VERYCLEANUP += $(BIN)/rules +# Evaluate rules (or include rules files) +# +ifdef NEED_DEPS +ifneq ($(AUTO_RULES),) +ifneq ($(HAVE_EVAL),) +$(foreach SRC,$(AUTO_SRCS),$(eval $(call rules_template,$(SRC)))) +else +-include $(AUTO_RULES) +endif +endif +endif + # The following variables are created by the rules files # bobjs : @@ -1018,36 +1080,61 @@ AUTO_MEDIA = $(filter-out $(NON_AUTO_MEDIA),$(MEDIA)) automedia : @$(ECHO) $(AUTO_MEDIA) -# media_template : create Makefile rules for specified media +# media_template : create media rules # # $(1) is the media name (e.g. "rom") # define media_template +$(if $(filter $(1),$(AUTO_MEDIA)),$(call auto_media_template,$(1))) +LIST_$(1) := $$(if $$(LIST_NAME_$(1)),$$($$(LIST_NAME_$(1))),$$(DRIVERS)) +ALL_$(1) = $$(foreach ITEM,$$(LIST_$(1)),$$(BIN)/$$(ITEM).$(1)) +$$(BIN)/all$(1)s : $$(ALL_$(1)) +$$(BIN)/allall : $$(BIN)/all$(1)s +all$(1)s : $$(BIN)/all$(1)s +allall : $$(BIN)/allall +endef +# +# $(1) is the media name (e.g. "rom") +# +define auto_media_template +$$(BIN)/%.$(1) : $$(BIN)/%.$(1).zbin + $$(QM)echo " [FINISH] $$@" + $$(Q)$$(CP) $$< $$@ + $$(Q)$$(if $$(PAD_$(1)),$$(PAD_$(1)) $$@) + $$(Q)$$(if $$(FINALISE_$(1)),$$(FINALISE_$(1)) $$@) +endef +# +# $(1) is the media name (e.g. "rom") +# +define media_template_file @$(ECHO) " [MEDIARULES] $(1)" @$(MKDIR) -p $(BIN)/rules/$(dir $(1)) - @$(ECHO_E) '$$(BIN)/%.$(1) : $$(BIN)/%.$(1).zbin' \ - '\n\t$$(QM)$(ECHO) " [FINISH] $$@"' \ - '\n\t$$(Q)$$(CP) $$< $$@' \ - '\n\t$$(Q)$$(PAD_$(1))' \ - '\n\t$$(Q)$$(FINALISE_$(1))' \ + @$(ECHO_E) '$(subst $(NEWLINE),\n,$(call media_template,$(1)))' \ > $(BIN)/rules/$(1).media.r endef -# Rule to generate the Makefile rules to be included +# Generate media rules files # $(BIN)/rules/%.media.r : $(MAKEDEPS) - $(call media_template,$*) + $(call media_template_file,$*) -# Calculate and include the list of Makefile rules files +# Calculate list of media rules files # -MEDIA_RULES = $(patsubst %,$(BIN)/rules/%.media.r,$(AUTO_MEDIA)) +MEDIA_RULES = $(patsubst %,$(BIN)/rules/%.media.r,$(MEDIA)) mediarules : @$(ECHO) $(MEDIA_RULES) + +# Evaluate media rules (or include media rules files) +# ifdef NEED_DEPS ifneq ($(MEDIA_RULES),) +ifneq ($(HAVE_EVAL),) +$(foreach MEDIUM,$(MEDIA),$(eval $(call media_template,$(MEDIUM)))) +else -include $(MEDIA_RULES) endif endif +endif # Wrap up binary blobs (for embedded images) # @@ -1058,12 +1145,6 @@ $(BIN)/%.o : payload/%.img BOBJS += $(patsubst payload/%.img,$(BIN)/%.o,$(wildcard payload/*.img)) -# The "allXXXs" targets for each suffix -# -allall: allroms allmroms allpxes allisos alldsks -allroms allmroms : all%s : $(foreach ROM,$(ROMS),$(BIN)/$(ROM).%) -allpxes allisos alldsks : all%s : $(foreach DRIVER,$(DRIVERS),$(BIN)/$(DRIVER).%) - # Alias for ipxe.% # $(BIN)/etherboot.% : $(BIN)/ipxe.% diff --git a/src/arch/i386/Makefile.pcbios b/src/arch/i386/Makefile.pcbios index e1b226f5..d3fe8b9e 100644 --- a/src/arch/i386/Makefile.pcbios +++ b/src/arch/i386/Makefile.pcbios @@ -29,17 +29,22 @@ MEDIA += exe # Padding rules # -PAD_rom = $(PERL) $(PADIMG) --blksize=512 --byte=0xff $@ +PAD_rom = $(PERL) $(PADIMG) --blksize=512 --byte=0xff PAD_mrom = $(PAD_rom) -PAD_dsk = $(PERL) $(PADIMG) --blksize=512 $@ -PAD_hd = $(PERL) $(PADIMG) --blksize=32768 $@ -PAD_exe = $(PERL) $(PADIMG) --blksize=512 $@ +PAD_dsk = $(PERL) $(PADIMG) --blksize=512 +PAD_hd = $(PERL) $(PADIMG) --blksize=32768 +PAD_exe = $(PERL) $(PADIMG) --blksize=512 # Finalisation rules # -FINALISE_rom = $(PERL) $(FIXROM) $@ +FINALISE_rom = $(PERL) $(FIXROM) FINALISE_mrom = $(FINALISE_rom) +# Use $(ROMS) rather than $(DRIVERS) for "allroms" and "allmroms" +# +LIST_NAME_rom := ROMS +LIST_NAME_mrom := ROMS + # rule to make a non-emulation ISO boot image NON_AUTO_MEDIA += iso %iso: %lkrn util/geniso diff --git a/src/arch/i386/drivers/net/undiload.c b/src/arch/i386/drivers/net/undiload.c index 0edfa35d..f0f15e6a 100644 --- a/src/arch/i386/drivers/net/undiload.c +++ b/src/arch/i386/drivers/net/undiload.c @@ -38,6 +38,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* Disambiguate the various error causes */ +#define EINFO_EUNDILOAD \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "UNDI loader error" ) +#define EUNDILOAD( status ) EPLATFORM ( EINFO_EUNDILOAD, status ) + /** Parameter block for calling UNDI loader */ static struct s_UNDI_LOADER __bss16 ( undi_loader ); #define undi_loader __use_data16 ( undi_loader ) @@ -109,9 +115,7 @@ int undi_load ( struct undi_device *undi, struct undi_rom *undirom ) { /* Clear entry point */ memset ( &undi_loader_entry, 0, sizeof ( undi_loader_entry ) ); - rc = -undi_loader.Status; - if ( rc == 0 ) /* Paranoia */ - rc = -EIO; + rc = -EUNDILOAD ( undi_loader.Status ); DBGC ( undi, "UNDI %p loader failed: %s\n", undi, strerror ( rc ) ); return rc; diff --git a/src/arch/i386/firmware/pcbios/bios_console.c b/src/arch/i386/firmware/pcbios/bios_console.c index 25c8dad2..213ebd92 100644 --- a/src/arch/i386/firmware/pcbios/bios_console.c +++ b/src/arch/i386/firmware/pcbios/bios_console.c @@ -97,7 +97,7 @@ static void bios_handle_ed ( unsigned int count __unused, "int $0x10\n\t" "cli\n\t" ) : : "a" ( 0x0600 ), "b" ( bios_attr << 8 ), - "c" ( 0 ), "d" ( 0xffff ) ); + "c" ( 0 ), "d" ( 0xfefe ) ); } /** diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index 12be1779..0618dbf4 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -360,7 +360,7 @@ static size_t bzimage_load_initrd ( struct image *image, char *filename = initrd->cmdline; char *cmdline; struct cpio_header cpio; - size_t offset = 0; + size_t offset; size_t name_len; size_t pad_len; @@ -368,7 +368,7 @@ static size_t bzimage_load_initrd ( struct image *image, if ( initrd == image ) return 0; - /* Create cpio header before non-prebuilt images */ + /* Create cpio header for non-prebuilt images */ if ( filename && filename[0] ) { cmdline = strchr ( filename, ' ' ); name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) ) @@ -383,24 +383,21 @@ static size_t bzimage_load_initrd ( struct image *image, bzimage_parse_cpio_cmdline ( image, &cpio, ( cmdline + 1 /* ' ' */ )); } - if ( address ) { - copy_to_user ( address, offset, &cpio, - sizeof ( cpio ) ); - } - offset += sizeof ( cpio ); - if ( address ) { - memset_user ( address, offset, 0, name_len ); - copy_to_user ( address, offset, filename, - ( name_len - 1 /* NUL (or space) */ ) ); - } - offset += name_len; - offset = ( ( offset + 0x03 ) & ~0x03 ); + offset = ( ( sizeof ( cpio ) + name_len + 0x03 ) & ~0x03 ); + } else { + offset = 0; + name_len = 0; } - /* Copy in initrd image body */ - if ( address ) - memmove_user ( address, offset, initrd->data, 0, initrd->len ); + /* Copy in initrd image body (and cpio header if applicable) */ if ( address ) { + memmove_user ( address, offset, initrd->data, 0, initrd->len ); + if ( offset ) { + memset_user ( address, 0, 0, offset ); + copy_to_user ( address, 0, &cpio, sizeof ( cpio ) ); + copy_to_user ( address, sizeof ( cpio ), filename, + ( name_len - 1 /* NUL (or space) */ ) ); + } DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)" "%s%s\n", image, initrd, user_to_phys ( address, 0 ), user_to_phys ( address, offset ), diff --git a/src/arch/i386/include/initrd.h b/src/arch/i386/include/initrd.h index c25d0924..a5659f43 100644 --- a/src/arch/i386/include/initrd.h +++ b/src/arch/i386/include/initrd.h @@ -13,9 +13,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** Minimum alignment for initrds * - * Chosen to maximise memcpy() speeds + * Some versions of Linux complain about initrds that are not + * page-aligned. */ -#define INITRD_ALIGN 4 +#define INITRD_ALIGN 4096 /** Minimum free space required to reshuffle initrds * diff --git a/src/arch/i386/include/ipxe/errno/pcbios.h b/src/arch/i386/include/ipxe/errno/pcbios.h new file mode 100644 index 00000000..3a9eb249 --- /dev/null +++ b/src/arch/i386/include/ipxe/errno/pcbios.h @@ -0,0 +1,115 @@ +#ifndef _IPXE_ERRNO_PCBIOS_H +#define _IPXE_ERRNO_PCBIOS_H + +/** + * @file + * + * PC-BIOS platform error codes + * + * We use the PXE-specified error codes as the platform error codes + * for the PC-BIOS platform. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** + * Convert platform error code to platform component of iPXE error code + * + * @v platform Platform error code + * @ret errno Platform component of iPXE error code + */ +#define PLATFORM_TO_ERRNO( platform ) ( (platform) & 0xff ) + +/** + * Convert iPXE error code to platform error code + * + * @v errno iPXE error code + * @ret platform Platform error code + */ +#define ERRNO_TO_PLATFORM( errno ) ( (errno) & 0xff ) + +/* Platform-specific error codes */ +#define PLATFORM_ENOERR PXENV_STATUS_SUCCESS +#define PLATFORM_E2BIG PXENV_STATUS_BAD_FUNC +#define PLATFORM_EACCES PXENV_STATUS_TFTP_ACCESS_VIOLATION +#define PLATFORM_EADDRINUSE PXENV_STATUS_UDP_OPEN +#define PLATFORM_EADDRNOTAVAIL PXENV_STATUS_UDP_OPEN +#define PLATFORM_EAFNOSUPPORT PXENV_STATUS_UNSUPPORTED +#define PLATFORM_EAGAIN PXENV_STATUS_FAILURE +#define PLATFORM_EALREADY PXENV_STATUS_UDP_OPEN +#define PLATFORM_EBADF PXENV_STATUS_TFTP_CLOSED +#define PLATFORM_EBADMSG PXENV_STATUS_FAILURE +#define PLATFORM_EBUSY PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ECANCELED PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE +#define PLATFORM_ECHILD PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ECONNABORTED PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION +#define PLATFORM_ECONNREFUSED PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION +#define PLATFORM_ECONNRESET PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION +#define PLATFORM_EDEADLK PXENV_STATUS_FAILURE +#define PLATFORM_EDESTADDRREQ PXENV_STATUS_BAD_FUNC +#define PLATFORM_EDOM PXENV_STATUS_FAILURE +#define PLATFORM_EDQUOT PXENV_STATUS_FAILURE +#define PLATFORM_EEXIST PXENV_STATUS_FAILURE +#define PLATFORM_EFAULT PXENV_STATUS_MCOPY_PROBLEM +#define PLATFORM_EFBIG PXENV_STATUS_MCOPY_PROBLEM +#define PLATFORM_EHOSTUNREACH PXENV_STATUS_ARP_TIMEOUT +#define PLATFORM_EIDRM PXENV_STATUS_FAILURE +#define PLATFORM_EILSEQ PXENV_STATUS_FAILURE +#define PLATFORM_EINPROGRESS PXENV_STATUS_FAILURE +#define PLATFORM_EINTR PXENV_STATUS_FAILURE +#define PLATFORM_EINVAL PXENV_STATUS_BAD_FUNC +#define PLATFORM_EIO PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION +#define PLATFORM_EISCONN PXENV_STATUS_UDP_OPEN +#define PLATFORM_EISDIR PXENV_STATUS_FAILURE +#define PLATFORM_ELOOP PXENV_STATUS_FAILURE +#define PLATFORM_EMFILE PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_EMLINK PXENV_STATUS_FAILURE +#define PLATFORM_EMSGSIZE PXENV_STATUS_BAD_FUNC +#define PLATFORM_EMULTIHOP PXENV_STATUS_FAILURE +#define PLATFORM_ENAMETOOLONG PXENV_STATUS_FAILURE +#define PLATFORM_ENETDOWN PXENV_STATUS_ARP_TIMEOUT +#define PLATFORM_ENETRESET PXENV_STATUS_FAILURE +#define PLATFORM_ENETUNREACH PXENV_STATUS_ARP_TIMEOUT +#define PLATFORM_ENFILE PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOBUFS PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENODATA PXENV_STATUS_FAILURE +#define PLATFORM_ENODEV PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ENOENT PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ENOEXEC PXENV_STATUS_FAILURE +#define PLATFORM_ENOLCK PXENV_STATUS_FAILURE +#define PLATFORM_ENOLINK PXENV_STATUS_FAILURE +#define PLATFORM_ENOMEM PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOMSG PXENV_STATUS_FAILURE +#define PLATFORM_ENOPROTOOPT PXENV_STATUS_UNSUPPORTED +#define PLATFORM_ENOSPC PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOSR PXENV_STATUS_OUT_OF_RESOURCES +#define PLATFORM_ENOSTR PXENV_STATUS_FAILURE +#define PLATFORM_ENOSYS PXENV_STATUS_UNSUPPORTED +#define PLATFORM_ENOTCONN PXENV_STATUS_FAILURE +#define PLATFORM_ENOTDIR PXENV_STATUS_FAILURE +#define PLATFORM_ENOTEMPTY PXENV_STATUS_FAILURE +#define PLATFORM_ENOTSOCK PXENV_STATUS_FAILURE +#define PLATFORM_ENOTSUP PXENV_STATUS_UNSUPPORTED +#define PLATFORM_ENOTTY PXENV_STATUS_FAILURE +#define PLATFORM_ENXIO PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_EOPNOTSUPP PXENV_STATUS_UNSUPPORTED +#define PLATFORM_EOVERFLOW PXENV_STATUS_FAILURE +#define PLATFORM_EPERM PXENV_STATUS_TFTP_ACCESS_VIOLATION +#define PLATFORM_EPIPE PXENV_STATUS_FAILURE +#define PLATFORM_EPROTO PXENV_STATUS_FAILURE +#define PLATFORM_EPROTONOSUPPORT PXENV_STATUS_UNSUPPORTED +#define PLATFORM_EPROTOTYPE PXENV_STATUS_FAILURE +#define PLATFORM_ERANGE PXENV_STATUS_FAILURE +#define PLATFORM_EROFS PXENV_STATUS_FAILURE +#define PLATFORM_ESPIPE PXENV_STATUS_FAILURE +#define PLATFORM_ESRCH PXENV_STATUS_TFTP_FILE_NOT_FOUND +#define PLATFORM_ESTALE PXENV_STATUS_FAILURE +#define PLATFORM_ETIME PXENV_STATUS_FAILURE +#define PLATFORM_ETIMEDOUT PXENV_STATUS_TFTP_READ_TIMEOUT +#define PLATFORM_ETXTBSY PXENV_STATUS_FAILURE +#define PLATFORM_EWOULDBLOCK PXENV_STATUS_TFTP_OPEN +#define PLATFORM_EXDEV PXENV_STATUS_FAILURE + +#endif /* _IPXE_ERRNO_PCBIOS_H */ diff --git a/src/arch/i386/include/pxe.h b/src/arch/i386/include/pxe.h index 0206f683..b95b0cce 100644 --- a/src/arch/i386/include/pxe.h +++ b/src/arch/i386/include/pxe.h @@ -4,6 +4,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include "pxe_types.h" +#include "pxe_error.h" #include "pxe_api.h" #include #include diff --git a/src/arch/i386/include/pxe_error.h b/src/arch/i386/include/pxe_error.h new file mode 100644 index 00000000..a1398cbd --- /dev/null +++ b/src/arch/i386/include/pxe_error.h @@ -0,0 +1,123 @@ +#ifndef PXE_ERROR_H +#define PXE_ERROR_H + +/** @file + * + * Preboot eXecution Environment (PXE) error definitions + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @defgroup pxeerrors PXE error codes + * + * @{ + */ + +/* Generic errors */ +#define PXENV_STATUS_SUCCESS 0x0000 +#define PXENV_STATUS_FAILURE 0x0001 +#define PXENV_STATUS_BAD_FUNC 0x0002 +#define PXENV_STATUS_UNSUPPORTED 0x0003 +#define PXENV_STATUS_KEEP_UNDI 0x0004 +#define PXENV_STATUS_KEEP_ALL 0x0005 +#define PXENV_STATUS_OUT_OF_RESOURCES 0x0006 + +/* ARP errors (0x0010 to 0x001f) */ +#define PXENV_STATUS_ARP_TIMEOUT 0x0011 + +/* Base-Code state errors */ +#define PXENV_STATUS_UDP_CLOSED 0x0018 +#define PXENV_STATUS_UDP_OPEN 0x0019 +#define PXENV_STATUS_TFTP_CLOSED 0x001a +#define PXENV_STATUS_TFTP_OPEN 0x001b + +/* BIOS/system errors (0x0020 to 0x002f) */ +#define PXENV_STATUS_MCOPY_PROBLEM 0x0020 +#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x0021 +#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x0022 +#define PXENV_STATUS_BIS_INIT_FAILURE 0x0023 +#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x0024 +#define PXENV_STATUS_BIS_GBOA_FAILURE 0x0025 +#define PXENV_STATUS_BIS_FREE_FAILURE 0x0026 +#define PXENV_STATUS_BIS_GSI_FAILURE 0x0027 +#define PXENV_STATUS_BIS_BAD_CKSUM 0x0028 + +/* TFTP/MTFTP errors (0x0030 to 0x003f) */ +#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x0030 +#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x0032 +#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x0033 +#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x0035 +#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x0036 +#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x0038 +#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x0039 +#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x003a +#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x003b +#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x003c +#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x003d +#define PXENV_STATUS_TFTP_NO_FILESIZE 0x003e +#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x003f + +/* Reserved errors 0x0040 to 0x004f) */ + +/* DHCP/BOOTP errors (0x0050 to 0x005f) */ +#define PXENV_STATUS_DHCP_TIMEOUT 0x0051 +#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x0052 +#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x0053 +#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x0054 + +/* Driver errors (0x0060 to 0x006f) */ +#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x0060 +#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x0061 +#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x0062 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x0063 +#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x0064 +#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x0065 +#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x0066 +#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x0067 +#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x0068 +#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x0069 +#define PXENV_STATUS_UNDI_INVALID_STATE 0x006a +#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x006b +#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x006c + +/* ROM and NBP bootstrap errors (0x0070 to 0x007f) */ +#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x0074 +#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x0076 +#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x0077 +#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x0078 +#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x0079 + +/* Environment NBP errors (0x0080 to 0x008f) */ + +/* Reserved errors (0x0090 to 0x009f) */ + +/* Miscellaneous errors (0x00a0 to 0x00af) */ +#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0x00a0 +#define PXENV_STATUS_BINL_NO_PXE_SERVER 0x00a1 +#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0x00a2 +#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0x00a3 + +/* BUSD errors (0x00b0 to 0x00bf) */ +#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0x00b0 + +/* Loader errors (0x00c0 to 0x00cf) */ +#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0x00c0 +#define PXENV_STATUS_LOADER_NO_BC_ROMID 0x00c1 +#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0x00c2 +#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0x00c3 +#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0x00c4 +#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0x00c5 +#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0x00c6 +#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0x00c8 +#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0x00c9 +#define PXENV_STATUS_LOADER_UNDI_START 0x00ca +#define PXENV_STATUS_LOADER_BC_START 0x00cb + +/** @} */ + +/** Derive PXENV_STATUS code from iPXE error number */ +#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff ) + +#endif /* PXE_ERROR_H */ diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c index b8e73a06..a0743336 100644 --- a/src/arch/i386/interface/pxe/pxe_call.c +++ b/src/arch/i386/interface/pxe/pxe_call.c @@ -32,6 +32,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * PXE API entry point */ +/* Disambiguate the various error causes */ +#define EINFO_EPXENBP \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "External PXE NBP error" ) +#define EPXENBP( status ) EPLATFORM ( EINFO_EPXENBP, status ) + /** Vector for chaining INT 1A */ extern struct segoff __text16 ( pxe_int_1a_vector ); #define pxe_int_1a_vector __use_text16 ( pxe_int_1a_vector ) @@ -257,7 +263,7 @@ rmjmp_buf pxe_restart_nbp; int pxe_start_nbp ( void ) { int jmp; int discard_b, discard_c, discard_d, discard_D; - uint16_t rc; + uint16_t status; /* Allow restarting NBP via PXENV_RESTART_TFTP */ jmp = rmsetjmp ( pxe_restart_nbp ); @@ -265,22 +271,26 @@ int pxe_start_nbp ( void ) { DBG ( "Restarting NBP (%x)\n", jmp ); /* Far call to PXE NBP */ - __asm__ __volatile__ ( REAL_CODE ( "movw %%cx, %%es\n\t" + __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */ + "movw %%cx, %%es\n\t" "pushw %%es\n\t" "pushw %%di\n\t" "sti\n\t" "lcall $0, $0x7c00\n\t" - "addw $4, %%sp\n\t" ) - : "=a" ( rc ), "=b" ( discard_b ), + "popl %%ebp\n\t" /* discard */ + "popl %%ebp\n\t" /* gcc bug */ ) + : "=a" ( status ), "=b" ( discard_b ), "=c" ( discard_c ), "=d" ( discard_d ), "=D" ( discard_D ) : "a" ( 0 ), "b" ( __from_text16 ( &pxenv ) ), "c" ( rm_cs ), "d" ( virt_to_phys ( &pxenv ) ), "D" ( __from_text16 ( &ppxe ) ) - : "esi", "ebp", "memory" ); + : "esi", "memory" ); + if ( status ) + return -EPXENBP ( status ); - return rc; + return 0; } REQUIRE_OBJECT ( pxe_preboot ); diff --git a/src/arch/i386/interface/pxeparent/pxeparent.c b/src/arch/i386/interface/pxeparent/pxeparent.c index 8b2a2c88..b2c6ffba 100644 --- a/src/arch/i386/interface/pxeparent/pxeparent.c +++ b/src/arch/i386/interface/pxeparent/pxeparent.c @@ -31,6 +31,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* Disambiguate the various error causes */ +#define EINFO_EPXECALL \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "External PXE API error" ) +#define EPXECALL( status ) EPLATFORM ( EINFO_EPXECALL, status ) + /** * Name PXE API call * @@ -151,16 +157,8 @@ int pxeparent_call ( SEGOFF16_t entry, unsigned int function, /* Determine return status code based on PXENV_EXIT and * PXENV_STATUS */ - if ( exit == PXENV_EXIT_SUCCESS ) { - rc = 0; - } else { - rc = -pxeparent_params.Status; - /* Paranoia; don't return success for the combination - * of PXENV_EXIT_FAILURE but PXENV_STATUS_SUCCESS - */ - if ( rc == 0 ) - rc = -EIO; - } + rc = ( ( exit == PXENV_EXIT_SUCCESS ) ? + 0 : -EPXECALL ( pxeparent_params.Status ) ); /* If anything goes wrong, print as much debug information as * it's possible to give. diff --git a/src/arch/i386/interface/vmware/guestinfo.c b/src/arch/i386/interface/vmware/guestinfo.c index 5e08d947..da013ca2 100644 --- a/src/arch/i386/interface/vmware/guestinfo.c +++ b/src/arch/i386/interface/vmware/guestinfo.c @@ -224,7 +224,7 @@ static int guestinfo_net_probe ( struct net_device *netdev ) { rc = -ENOMEM; goto err_alloc; } - settings_init ( settings, &guestinfo_settings_operations, NULL, 0 ); + settings_init ( settings, &guestinfo_settings_operations, NULL, NULL ); /* Register settings */ if ( ( rc = register_settings ( settings, netdev_settings ( netdev ), diff --git a/src/arch/i386/prefix/mromprefix.S b/src/arch/i386/prefix/mromprefix.S index 058663c4..0f0847e5 100644 --- a/src/arch/i386/prefix/mromprefix.S +++ b/src/arch/i386/prefix/mromprefix.S @@ -98,6 +98,7 @@ find_mem_bar: cmpw $PCI_BAR_5, %di jle 1f stc + movl $0xbabababa, %esi /* Report "No suitable BAR" */ jmp 99f 1: movw $4, %bp @@ -157,15 +158,17 @@ find_mem_bar: /* Locate our ROM image */ 1: addr32 es cmpw $0xaa55, (%eax) - stc - jne 99f - addr32 es cmpl $_build_id, build_id(%eax) je 2f + stc + movl %eax, %esi /* Report failure address */ + jmp 99f +2: addr32 es cmpl $_build_id, build_id(%eax) + je 3f addr32 es movzbl 2(%eax), %ecx shll $9, %ecx addl %ecx, %eax jmp 1b -2: +3: /* Copy payload to buffer, or set buffer address to BAR address */ testl %esi, %esi diff --git a/src/arch/i386/prefix/undiloader.S b/src/arch/i386/prefix/undiloader.S index ccdd816e..74bb5904 100644 --- a/src/arch/i386/prefix/undiloader.S +++ b/src/arch/i386/prefix/undiloader.S @@ -23,8 +23,8 @@ undiloader: popw %ds /* UNDI loader parameter structure address into %es:%di */ movw %sp, %bx - movw %ss:18(%bx), %di - movw %ss:20(%bx), %es + movw %ss:22(%bx), %di + movw %ss:24(%bx), %es /* Install to specified real-mode addresses */ pushw %di movw %es:12(%di), %bx diff --git a/src/arch/x86/Makefile.efi b/src/arch/x86/Makefile.efi index bef8d59d..3e3fbe3c 100644 --- a/src/arch/x86/Makefile.efi +++ b/src/arch/x86/Makefile.efi @@ -12,6 +12,8 @@ LDFLAGS += -q -S # NON_AUTO_MEDIA += efi NON_AUTO_MEDIA += efidrv +NON_AUTO_MEDIA += drv.efi +NON_AUTO_MEDIA += efirom # Rules for building EFI files # @@ -23,6 +25,14 @@ $(BIN)/%.efidrv : $(BIN)/%.efidrv.tmp $(ELF2EFI) $(QM)$(ECHO) " [FINISH] $@" $(Q)$(ELF2EFI) --subsystem=11 $< $@ +$(BIN)/%.drv.efi : $(BIN)/%.efidrv + $(QM)$(ECHO) " [FINISH] $@" + $(Q)$(CP) $< $@ + $(BIN)/%.efirom : $(BIN)/%.efidrv $(EFIROM) $(QM)$(ECHO) " [FINISH] $@" $(Q)$(EFIROM) -v $(TGT_PCI_VENDOR) -d $(TGT_PCI_DEVICE) $< $@ + +$(BIN)/efidrv.cab : $(BIN)/alldrv.efis # $(ALL_drv.efi) is not yet defined + $(QM)$(ECHO) " [CAB] $@" + $(Q)$(LCAB) -n -q $(ALL_drv.efi) $@ diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index 7b9f3702..5f676c87 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 ) #define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 ) #define ERRFILE_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 ) +#define ERRFILE_pxe_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000d0000 ) #define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 ) #define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 ) diff --git a/src/arch/x86/prefix/efiprefix.c b/src/arch/x86/prefix/efiprefix.c index bfa94d40..a847045a 100644 --- a/src/arch/x86/prefix/efiprefix.c +++ b/src/arch/x86/prefix/efiprefix.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include /** @@ -38,5 +39,5 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle, return efirc; /* Call to main() */ - return RC_TO_EFIRC ( main () ); + return EFIRC ( main () ); } diff --git a/src/core/nvo.c b/src/core/nvo.c index 5383fe5c..4c871b2f 100644 --- a/src/core/nvo.c +++ b/src/core/nvo.c @@ -195,7 +195,8 @@ static int nvo_save ( struct nvo_block *nvo ) { int nvo_applies ( struct settings *settings __unused, struct setting *setting ) { - return dhcpopt_applies ( setting->tag ); + return ( ( setting->scope == NULL ) && + dhcpopt_applies ( setting->tag ) ); } /** @@ -274,7 +275,8 @@ void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs, nvo->len = len; nvo->resize = resize; dhcpopt_init ( &nvo->dhcpopts, NULL, 0, nvo_realloc_dhcpopt ); - settings_init ( &nvo->settings, &nvo_settings_operations, refcnt, 0 ); + settings_init ( &nvo->settings, &nvo_settings_operations, + refcnt, NULL ); } /** diff --git a/src/core/settings.c b/src/core/settings.c index 43715fbd..54d48d32 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -984,7 +984,7 @@ void clear_settings ( struct settings *settings ) { int setting_cmp ( struct setting *a, struct setting *b ) { /* If the settings have tags, compare them */ - if ( a->tag && ( a->tag == b->tag ) ) + if ( a->tag && ( a->tag == b->tag ) && ( a->scope == b->scope ) ) return 0; /* Otherwise, if the settings have names, compare them */ @@ -1099,19 +1099,17 @@ struct setting * find_setting ( const char *name ) { /** * Parse setting name as tag number * - * @v settings Settings block * @v name Name * @ret tag Tag number, or 0 if not a valid number */ -static unsigned int parse_setting_tag ( struct settings *settings, - const char *name ) { +static unsigned int parse_setting_tag ( const char *name ) { char *tmp = ( ( char * ) name ); unsigned int tag = 0; while ( 1 ) { tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) ); if ( *tmp == 0 ) - return ( tag | settings->tag_magic ); + return tag; if ( *tmp != '.' ) return 0; tmp++; @@ -1193,7 +1191,8 @@ parse_setting_name ( const char *name, } /* Identify setting */ - setting->tag = parse_setting_tag ( *settings, setting_name ); + setting->tag = parse_setting_tag ( setting_name ); + setting->scope = (*settings)->default_scope; setting->name = setting_name; for_each_table_entry ( named_setting, SETTINGS ) { /* Matches a defined named setting; use that setting */ @@ -1998,26 +1997,15 @@ struct builtin_setting_operation { int ( * fetch ) ( void *data, size_t len ); }; -/** Built-in setting tag magic */ -#define BUILTIN_SETTING_TAG_MAGIC 0xb1 - -/** - * Construct built-in setting tag - * - * @v id Unique identifier - * @ret tag Setting tag - */ -#define BUILTIN_SETTING_TAG( id ) ( ( BUILTIN_SETTING_TAG_MAGIC << 24 ) | (id) ) - -/** "errno" setting tag */ -#define BUILTIN_SETTING_TAG_ERRNO BUILTIN_SETTING_TAG ( 0x01 ) +/** Built-in setting scope */ +static struct settings_scope builtin_scope; /** Error number setting */ struct setting errno_setting __setting ( SETTING_MISC ) = { .name = "errno", .description = "Last error", - .tag = BUILTIN_SETTING_TAG_ERRNO, .type = &setting_type_uint32, + .scope = &builtin_scope, }; /** @@ -2038,15 +2026,12 @@ static int errno_fetch ( void *data, size_t len ) { return sizeof ( content ); } -/** "buildarch" setting tag */ -#define BUILTIN_SETTING_TAG_BUILDARCH BUILTIN_SETTING_TAG ( 0x02 ) - /** Build architecture setting */ struct setting buildarch_setting __setting ( SETTING_MISC ) = { .name = "buildarch", .description = "Build architecture", - .tag = BUILTIN_SETTING_TAG_BUILDARCH, .type = &setting_type_string, + .scope = &builtin_scope, }; /** @@ -2063,15 +2048,12 @@ static int buildarch_fetch ( void *data, size_t len ) { return ( sizeof ( buildarch ) - 1 /* NUL */ ); } -/** "platform" setting tag */ -#define BUILTIN_SETTING_TAG_PLATFORM BUILTIN_SETTING_TAG ( 0x03 ) - /** Platform setting */ struct setting platform_setting __setting ( SETTING_MISC ) = { .name = "platform", .description = "Platform", - .tag = BUILTIN_SETTING_TAG_PLATFORM, .type = &setting_type_string, + .scope = &builtin_scope, }; /** @@ -2128,11 +2110,8 @@ static int builtin_fetch ( struct settings *settings __unused, */ static int builtin_applies ( struct settings *settings __unused, struct setting *setting ) { - unsigned int tag_magic; - /* Check tag magic */ - tag_magic = ( setting->tag >> 24 ); - return ( tag_magic == BUILTIN_SETTING_TAG_MAGIC ); + return ( setting->scope == &builtin_scope ); } /** Built-in settings operations */ @@ -2144,7 +2123,6 @@ static struct settings_operations builtin_settings_operations = { /** Built-in settings */ static struct settings builtin_settings = { .refcnt = NULL, - .tag_magic = BUILTIN_SETTING_TAG ( 0 ), .siblings = LIST_HEAD_INIT ( builtin_settings.siblings ), .children = LIST_HEAD_INIT ( builtin_settings.children ), .op = &builtin_settings_operations, diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c index ab75dea3..20287c0b 100644 --- a/src/crypto/ocsp.c +++ b/src/crypto/ocsp.c @@ -58,6 +58,21 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_EACCES_STALE \ __einfo_uniqify ( EINFO_EACCES, 0x04, \ "Stale (or premature) OCSP repsonse" ) +#define EACCES_NO_RESPONDER \ + __einfo_error ( EINFO_EACCES_NO_RESPONDER ) +#define EINFO_EACCES_NO_RESPONDER \ + __einfo_uniqify ( EINFO_EACCES, 0x05, \ + "Missing OCSP responder certificate" ) +#define ENOTSUP_RESPONSE_TYPE \ + __einfo_error ( EINFO_ENOTSUP_RESPONSE_TYPE ) +#define EINFO_ENOTSUP_RESPONSE_TYPE \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \ + "Unsupported OCSP response type" ) +#define ENOTSUP_RESPONDER_ID \ + __einfo_error ( EINFO_ENOTSUP_RESPONDER_ID ) +#define EINFO_ENOTSUP_RESPONDER_ID \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \ + "Unsupported OCSP responder ID" ) #define EPROTO_MALFORMED_REQUEST \ __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST ) #define EINFO_EPROTO_MALFORMED_REQUEST \ @@ -84,7 +99,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_UNAUTHORIZED, \ "Request unauthorized" ) #define EPROTO_STATUS( status ) \ - EUNIQ ( EPROTO, (status), EPROTO_MALFORMED_REQUEST, \ + EUNIQ ( EINFO_EPROTO, (status), EPROTO_MALFORMED_REQUEST, \ EPROTO_INTERNAL_ERROR, EPROTO_TRY_LATER, \ EPROTO_SIG_REQUIRED, EPROTO_UNAUTHORIZED ) @@ -355,12 +370,94 @@ static int ocsp_parse_response_type ( struct ocsp_check *ocsp, DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n", ocsp, ocsp->cert->subject.name ); DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return -ENOTSUP; + return -ENOTSUP_RESPONSE_TYPE; } return 0; } +/** + * Compare responder's certificate name + * + * @v ocsp OCSP check + * @v cert Certificate + * @ret difference Difference as returned by memcmp() + */ +static int ocsp_compare_responder_name ( struct ocsp_check *ocsp, + struct x509_certificate *cert ) { + struct ocsp_responder *responder = &ocsp->response.responder; + + /* Compare responder ID with certificate's subject */ + return asn1_compare ( &responder->id, &cert->subject.raw ); +} + +/** + * Compare responder's certificate public key hash + * + * @v ocsp OCSP check + * @v cert Certificate + * @ret difference Difference as returned by memcmp() + */ +static int ocsp_compare_responder_key_hash ( struct ocsp_check *ocsp, + struct x509_certificate *cert ) { + struct ocsp_responder *responder = &ocsp->response.responder; + uint8_t ctx[SHA1_CTX_SIZE]; + uint8_t digest[SHA1_DIGEST_SIZE]; + int difference; + + /* Sanity check */ + difference = ( sizeof ( digest ) - responder->id.len ); + if ( difference ) + return difference; + + /* Generate SHA1 hash of certificate's public key */ + digest_init ( &sha1_algorithm, ctx ); + digest_update ( &sha1_algorithm, ctx, + cert->subject.public_key.raw_bits.data, + cert->subject.public_key.raw_bits.len ); + digest_final ( &sha1_algorithm, ctx, digest ); + + /* Compare responder ID with SHA1 hash of certificate's public key */ + return memcmp ( digest, responder->id.data, sizeof ( digest ) ); +} + +/** + * Parse OCSP responder ID + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_responder_id ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct ocsp_responder *responder = &ocsp->response.responder; + struct asn1_cursor *responder_id = &responder->id; + unsigned int type; + + /* Enter responder ID */ + memcpy ( responder_id, raw, sizeof ( *responder_id ) ); + type = asn1_type ( responder_id ); + asn1_enter_any ( responder_id ); + + /* Identify responder ID type */ + switch ( type ) { + case ASN1_EXPLICIT_TAG ( 1 ) : + DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by name\n", + ocsp, ocsp->cert->subject.name ); + responder->compare = ocsp_compare_responder_name; + return 0; + case ASN1_EXPLICIT_TAG ( 2 ) : + DBGC2 ( ocsp, "OCSP %p \"%s\" responder identified by key " + "hash\n", ocsp, ocsp->cert->subject.name ); + responder->compare = ocsp_compare_responder_key_hash; + return 0; + default: + DBGC ( ocsp, "OCSP %p \"%s\" unsupported responder ID type " + "%d\n", ocsp, ocsp->cert->subject.name, type ); + return -ENOTSUP_RESPONDER_ID; + } +} + /** * Parse OCSP certificate ID * @@ -484,7 +581,9 @@ static int ocsp_parse_tbs_response_data ( struct ocsp_check *ocsp, /* Skip version, if present */ asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); - /* Skip responderID */ + /* Parse responderID */ + if ( ( rc = ocsp_parse_responder_id ( ocsp, &cursor ) ) != 0 ) + return rc; asn1_skip_any ( &cursor ); /* Skip producedAt */ @@ -508,6 +607,7 @@ static int ocsp_parse_certs ( struct ocsp_check *ocsp, const struct asn1_cursor *raw ) { struct ocsp_response *response = &ocsp->response; struct asn1_cursor cursor; + struct x509_certificate *cert; int rc; /* Enter certs */ @@ -519,20 +619,39 @@ static int ocsp_parse_certs ( struct ocsp_check *ocsp, * multiple certificates, but the protocol requires that the * OCSP signing certificate must either be the issuer itself, * or must be directly issued by the issuer (see RFC2560 - * section 4.2.2.2 "Authorized Responders"). + * section 4.2.2.2 "Authorized Responders"). We therefore + * need to identify only the single certificate matching the + * Responder ID. */ - if ( ( cursor.len != 0 ) && - ( ( rc = x509_certificate ( cursor.data, cursor.len, - &response->signer ) ) != 0 ) ) { - DBGC ( ocsp, "OCSP %p \"%s\" could not parse certificate: " - "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc )); - DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); - return rc; - } - DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by \"%s\"\n", ocsp, - ocsp->cert->subject.name, response->signer->subject.name ); + while ( cursor.len ) { - return 0; + /* Parse certificate */ + if ( ( rc = x509_certificate ( cursor.data, cursor.len, + &cert ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not parse " + "certificate: %s\n", ocsp, + ocsp->cert->subject.name, strerror ( rc ) ); + DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); + return rc; + } + + /* Use if this certificate matches the responder ID */ + if ( response->responder.compare ( ocsp, cert ) == 0 ) { + response->signer = cert; + DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by " + "\"%s\"\n", ocsp, ocsp->cert->subject.name, + response->signer->subject.name ); + return 0; + } + + /* Otherwise, discard this certificate */ + x509_put ( cert ); + asn1_skip_any ( &cursor ); + } + + DBGC ( ocsp, "OCSP %p \"%s\" missing responder certificate\n", + ocsp, ocsp->cert->subject.name ); + return -EACCES_NO_RESPONDER; } /** diff --git a/src/crypto/x509.c b/src/crypto/x509.c index df3c5c0d..d54124c5 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -1552,11 +1552,8 @@ int x509_validate_chain ( struct x509_chain *chain, time_t time, struct x509_link *link; int rc; - /* Sanity check */ - if ( list_empty ( &chain->links ) ) { - DBGC ( chain, "X509 chain %p is empty\n", chain ); - return -EACCES_EMPTY; - } + /* Error to be used if chain contains no certifictes */ + rc = -EACCES_EMPTY; /* Find first certificate that can be validated as a * standalone (i.e. is already valid, or can be validated as @@ -1586,6 +1583,7 @@ int x509_validate_chain ( struct x509_chain *chain, time_t time, return 0; } - DBGC ( chain, "X509 chain %p found no valid certificates\n", chain ); - return -EACCES_UNTRUSTED; + DBGC ( chain, "X509 chain %p found no valid certificates: %s\n", + chain, strerror ( rc ) ); + return rc; } diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c index b45ae630..4245f019 100644 --- a/src/drivers/block/scsi.c +++ b/src/drivers/block/scsi.c @@ -89,7 +89,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_EIO_COMPLETED \ __einfo_uniqify ( EINFO_EIO, 0x0f, "Completed" ) #define EIO_SENSE( key ) \ - EUNIQ ( EIO, (key), EIO_NO_SENSE, EIO_RECOVERED_ERROR, \ + EUNIQ ( EINFO_EIO, (key), EIO_NO_SENSE, EIO_RECOVERED_ERROR, \ EIO_NOT_READY, EIO_MEDIUM_ERROR, EIO_HARDWARE_ERROR, \ EIO_ILLEGAL_REQUEST, EIO_UNIT_ATTENTION, \ EIO_DATA_PROTECT, EIO_BLANK_CHECK, EIO_VENDOR_SPECIFIC, \ diff --git a/src/drivers/block/srp.c b/src/drivers/block/srp.c index 098a973e..70a97b2f 100644 --- a/src/drivers/block/srp.c +++ b/src/drivers/block/srp.c @@ -93,7 +93,7 @@ FEATURE ( FEATURE_PROTOCOL, "SRP", DHCP_EB_FEATURE_SRP, 1 ); SRP_LOGIN_REJ_REASON_NO_MORE_CHANNELS, \ "RDMA channel limit reached for this initiator" ) #define EPERM_LOGIN_REJ( reason_nibble ) \ - EUNIQ ( EPERM, (reason_nibble), EPERM_UNKNOWN, \ + EUNIQ ( EINFO_EPERM, (reason_nibble), EPERM_UNKNOWN, \ EPERM_INSUFFICIENT_RESOURCES, EPERM_BAD_MAX_I_T_IU_LEN, \ EPERM_CANNOT_ASSOCIATE, EPERM_UNSUPPORTED_BUFFER_FORMAT, \ EPERM_NO_MULTIPLE_CHANNELS, EPERM_NO_MORE_CHANNELS ) diff --git a/src/drivers/net/3c515.c b/src/drivers/net/3c515.c index 0aa68b1a..1591e061 100644 --- a/src/drivers/net/3c515.c +++ b/src/drivers/net/3c515.c @@ -389,7 +389,7 @@ static void t515_reset(struct nic *nic) outb(PKT_BUF_SZ >> 8, nic->ioaddr + TxFreeThreshold); /* Room for a packet. */ /* Clear the Tx ring. */ for (i = 0; i < TX_RING_SIZE; i++) - vp->tx_skbuff[i] = 0; + vp->tx_skbuff[i] = NULL; outl(0, nic->ioaddr + DownListPtr); } /* Set receiver mode: presumably accept b-case and phys addr only. */ diff --git a/src/drivers/net/3c595.c b/src/drivers/net/3c595.c index 1aa8ed64..2338c54b 100644 --- a/src/drivers/net/3c595.c +++ b/src/drivers/net/3c595.c @@ -399,7 +399,7 @@ vxsetlink(void) i = vx_connector; /* default in EEPROM */ reason = "default"; - warning = 0; + warning = NULL; if ((vx_connectors & conn_tab[vx_connector].bit) == 0) { warning = "strange connector type in EEPROM."; @@ -407,7 +407,7 @@ vxsetlink(void) i = CONNECTOR_UTP; } - if (warning != 0) { + if (warning) { printf("warning: %s\n", warning); } printf("selected %s. (%s)\n", conn_tab[i].name, reason); diff --git a/src/drivers/net/bnx2.c b/src/drivers/net/bnx2.c index a986bdef..4ebcc52a 100644 --- a/src/drivers/net/bnx2.c +++ b/src/drivers/net/bnx2.c @@ -2617,9 +2617,6 @@ bnx2_probe(struct nic *nic, struct pci_device *pdev) struct bnx2 *bp = &bnx2; int i, rc; - if (pdev == 0) - return 0; - memset(bp, 0, sizeof(*bp)); rc = bnx2_init_board(pdev, nic); diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c index 97790815..cd9e7e38 100644 --- a/src/drivers/net/efi/snpnet.c +++ b/src/drivers/net/efi/snpnet.c @@ -56,20 +56,21 @@ static int snpnet_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; - EFI_STATUS efirc; void *txbuf=NULL; size_t len = iob_len ( iobuf ); + EFI_STATUS efirc; + int rc; - efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL, NULL ); - if (efirc) { - return EFIRC_TO_RC ( efirc ); + if ( ( efirc = snp->Transmit ( snp, 0, len, iobuf->data, NULL, NULL, + NULL ) ) != 0 ) { + return -EEFI ( efirc ); } /* since GetStatus is so inconsistent, don't try more than one outstanding transmit at a time */ while ( txbuf == NULL ) { - efirc = snp->GetStatus ( snp, NULL, &txbuf ); - if ( efirc ) { + if ( ( efirc = snp->GetStatus ( snp, NULL, &txbuf ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not get status %s\n", snp, - efi_strerror ( efirc ) ); + strerror ( rc ) ); break; } @@ -86,9 +87,10 @@ static int snpnet_transmit ( struct net_device *netdev, static void snpnet_poll ( struct net_device *netdev ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; - EFI_STATUS efirc; struct io_buffer *iobuf = NULL; UINTN len; + EFI_STATUS efirc; + int rc; /* Process received packets */ while ( 1 ) { @@ -115,12 +117,13 @@ static void snpnet_poll ( struct net_device *netdev ) { } /* Other error? */ - if ( efirc ) { + if ( efirc != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p receive packet error: %s " "(len was %zd, is now %zd)\n", - snp, efi_strerror ( efirc ), iob_len(iobuf), + snp, strerror ( rc ), iob_len(iobuf), (size_t)len ); - netdev_rx_err ( netdev, iobuf, efirc ); + netdev_rx_err ( netdev, iobuf, rc ); break; } @@ -139,25 +142,27 @@ static void snpnet_poll ( struct net_device *netdev ) { static int snpnet_open ( struct net_device *netdev ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; - EFI_STATUS efirc; + EFI_MAC_ADDRESS *mac; UINT32 enableFlags, disableFlags; + EFI_STATUS efirc; + int rc; snpnetdev->close_state = snp->Mode->State; if ( snp->Mode->State != EfiSimpleNetworkInitialized ) { - efirc = snp->Initialize ( snp, 0, 0 ); - if ( efirc ) { + if ( ( efirc = snp->Initialize ( snp, 0, 0 ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not initialize: %s\n", - snp, efi_strerror ( efirc ) ); - return EFIRC_TO_RC ( efirc ); + snp, strerror ( rc ) ); + return rc; } } /* Use the default MAC address */ - efirc = snp->StationAddress ( snp, FALSE, - (EFI_MAC_ADDRESS *)netdev->ll_addr ); - if ( efirc ) { + mac = ( ( void * ) netdev->ll_addr ); + if ( ( efirc = snp->StationAddress ( snp, FALSE, mac ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not reset station address: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } /* Set up receive filters to receive unicast and broadcast packets @@ -179,11 +184,11 @@ static int snpnet_open ( struct net_device *netdev ) { enableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; } disableFlags &= ~enableFlags; - efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags, - FALSE, 0, NULL ); - if ( efirc ) { + if ( ( efirc = snp->ReceiveFilters ( snp, enableFlags, disableFlags, + FALSE, 0, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not set receive filters: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } DBGC ( snp, "SNP %p opened\n", snp ); @@ -199,12 +204,13 @@ static void snpnet_close ( struct net_device *netdev ) { struct snpnet_device *snpnetdev = netdev->priv; EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpnetdev->snp; EFI_STATUS efirc; + int rc; if ( snpnetdev->close_state != EfiSimpleNetworkInitialized ) { - efirc = snp->Shutdown ( snp ); - if ( efirc ) { + if ( ( efirc = snp->Shutdown ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not shut down: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } } } @@ -264,11 +270,10 @@ int snpnet_probe ( struct snp_device *snpdev ) { /* Start the interface */ if ( snp->Mode->State == EfiSimpleNetworkStopped ) { - efirc = snp->Start ( snp ); - if ( efirc ) { + if ( ( efirc = snp->Start ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not start: %s\n", snp, - efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + strerror ( rc ) ); goto err_start; } } @@ -310,25 +315,27 @@ err_start: */ void snpnet_remove ( struct snp_device *snpdev ) { EFI_SIMPLE_NETWORK_PROTOCOL *snp = snpdev->snp; - EFI_STATUS efirc; struct net_device *netdev = snpdev->netdev; + EFI_STATUS efirc; + int rc; if ( snp->Mode->State == EfiSimpleNetworkInitialized && snpdev->removal_state != EfiSimpleNetworkInitialized ) { DBGC ( snp, "SNP %p shutting down\n", snp ); - efirc = snp->Shutdown ( snp ); - if ( efirc ) { + if ( ( efirc = snp->Shutdown ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snp, "SNP %p could not shut down: %s\n", - snp, efi_strerror ( efirc ) ); + snp, strerror ( rc ) ); } } if ( snp->Mode->State == EfiSimpleNetworkStarted && snpdev->removal_state == EfiSimpleNetworkStopped ) { DBGC ( snp, "SNP %p stopping\n", snp ); - efirc = snp->Stop ( snp ); - if ( efirc ) { - DBGC ( snp, "SNP %p could not be stopped\n", snp ); + if ( ( efirc = snp->Stop ( snp ) ) != 0 ) { + rc = -EEFI ( efirc ); + DBGC ( snp, "SNP %p could not be stopped: %s\n", + snp, strerror ( rc ) ); } } diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c index 6036d321..5e0efb1e 100644 --- a/src/drivers/net/etherfabric.c +++ b/src/drivers/net/etherfabric.c @@ -3798,7 +3798,8 @@ falcon_clear_interrupts ( struct efab_nic *efab ) } else { /* write to the INT_ACK register */ - falcon_writel ( efab, 0, FCN_INT_ACK_KER_REG_A1 ); + EFAB_ZERO_DWORD ( reg ); + falcon_writel ( efab, ®, FCN_INT_ACK_KER_REG_A1 ); mb(); falcon_readl ( efab, ®, WORK_AROUND_BROKEN_PCI_READS_REG_KER_A1 ); diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index ce17e9f2..c3a7d407 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -248,10 +248,10 @@ static int intel_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) { static void __attribute__ (( unused )) intel_diag ( struct intel_nic *intel ) { DBGC ( intel, "INTEL %p TDH=%04x TDT=%04x RDH=%04x RDT=%04x\n", intel, - readl ( intel->regs + INTEL_TDH ), - readl ( intel->regs + INTEL_TDT ), - readl ( intel->regs + INTEL_RDH ), - readl ( intel->regs + INTEL_RDT ) ); + readl ( intel->regs + intel->tx.reg + INTEL_xDH ), + readl ( intel->regs + intel->tx.reg + INTEL_xDT ), + readl ( intel->regs + intel->rx.reg + INTEL_xDH ), + readl ( intel->regs + intel->rx.reg + INTEL_xDT ) ); } /****************************************************************************** @@ -360,8 +360,7 @@ static void intel_check_link ( struct net_device *netdev ) { * @v ring Descriptor ring * @ret rc Return status code */ -static int intel_create_ring ( struct intel_nic *intel, - struct intel_ring *ring ) { +int intel_create_ring ( struct intel_nic *intel, struct intel_ring *ring ) { physaddr_t address; uint32_t dctl; @@ -412,8 +411,7 @@ static int intel_create_ring ( struct intel_nic *intel, * @v intel Intel device * @v ring Descriptor ring */ -static void intel_destroy_ring ( struct intel_nic *intel, - struct intel_ring *ring ) { +void intel_destroy_ring ( struct intel_nic *intel, struct intel_ring *ring ) { /* Clear ring length */ writel ( 0, ( intel->regs + ring->reg + INTEL_xDLEN ) ); @@ -434,7 +432,7 @@ static void intel_destroy_ring ( struct intel_nic *intel, * * @v intel Intel device */ -static void intel_refill_rx ( struct intel_nic *intel ) { +void intel_refill_rx ( struct intel_nic *intel ) { struct intel_descriptor *rx; struct io_buffer *iobuf; unsigned int rx_idx; @@ -468,7 +466,7 @@ static void intel_refill_rx ( struct intel_nic *intel ) { intel->rx_iobuf[rx_idx] = iobuf; /* Push descriptor to card */ - writel ( rx_tail, intel->regs + INTEL_RDT ); + writel ( rx_tail, intel->regs + intel->rx.reg + INTEL_xDT ); DBGC2 ( intel, "INTEL %p RX %d is [%llx,%llx)\n", intel, rx_idx, ( ( unsigned long long ) address ), @@ -476,6 +474,21 @@ static void intel_refill_rx ( struct intel_nic *intel ) { } } +/** + * Discard unused receive I/O buffers + * + * @v intel Intel device + */ +void intel_empty_rx ( struct intel_nic *intel ) { + unsigned int i; + + for ( i = 0 ; i < INTEL_NUM_RX_DESC ; i++ ) { + if ( intel->rx_iobuf[i] ) + free_iob ( intel->rx_iobuf[i] ); + intel->rx_iobuf[i] = NULL; + } +} + /** * Open network device * @@ -540,7 +553,6 @@ static int intel_open ( struct net_device *netdev ) { */ static void intel_close ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; - unsigned int i; /* Disable receiver */ writel ( 0, intel->regs + INTEL_RCTL ); @@ -552,11 +564,7 @@ static void intel_close ( struct net_device *netdev ) { intel_destroy_ring ( intel, &intel->rx ); /* Discard any unused receive buffers */ - for ( i = 0 ; i < INTEL_NUM_RX_DESC ; i++ ) { - if ( intel->rx_iobuf[i] ) - free_iob ( intel->rx_iobuf[i] ); - intel->rx_iobuf[i] = NULL; - } + intel_empty_rx ( intel ); /* Destroy transmit descriptor ring */ intel_destroy_ring ( intel, &intel->tx ); @@ -572,8 +580,7 @@ static void intel_close ( struct net_device *netdev ) { * @v iobuf I/O buffer * @ret rc Return status code */ -static int intel_transmit ( struct net_device *netdev, - struct io_buffer *iobuf ) { +int intel_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { struct intel_nic *intel = netdev->priv; struct intel_descriptor *tx; unsigned int tx_idx; @@ -599,7 +606,7 @@ static int intel_transmit ( struct net_device *netdev, wmb(); /* Notify card that there are packets ready to transmit */ - writel ( tx_tail, intel->regs + INTEL_TDT ); + writel ( tx_tail, intel->regs + intel->tx.reg + INTEL_xDT ); DBGC2 ( intel, "INTEL %p TX %d is [%llx,%llx)\n", intel, tx_idx, ( ( unsigned long long ) address ), @@ -613,7 +620,7 @@ static int intel_transmit ( struct net_device *netdev, * * @v netdev Network device */ -static void intel_poll_tx ( struct net_device *netdev ) { +void intel_poll_tx ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; struct intel_descriptor *tx; unsigned int tx_idx; @@ -642,7 +649,7 @@ static void intel_poll_tx ( struct net_device *netdev ) { * * @v netdev Network device */ -static void intel_poll_rx ( struct net_device *netdev ) { +void intel_poll_rx ( struct net_device *netdev ) { struct intel_nic *intel = netdev->priv; struct intel_descriptor *rx; struct io_buffer *iobuf; diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h index e9e9052b..20b4255e 100644 --- a/src/drivers/net/intel.h +++ b/src/drivers/net/intel.h @@ -175,18 +175,6 @@ enum intel_descriptor_status { #define INTEL_xDCTL 0x28 #define INTEL_xDCTL_ENABLE 0x02000000UL /**< Queue enable */ -/** Receive Descriptor Head */ -#define INTEL_RDH ( INTEL_RD + INTEL_xDH ) - -/** Receive Descriptor Tail */ -#define INTEL_RDT ( INTEL_RD + INTEL_xDT ) - -/** Transmit Descriptor Head */ -#define INTEL_TDH ( INTEL_TD + INTEL_xDH ) - -/** Transmit Descriptor Tail */ -#define INTEL_TDT ( INTEL_TD + INTEL_xDT ) - /** Receive Address Low */ #define INTEL_RAL0 0x05400UL @@ -254,4 +242,15 @@ struct intel_nic { struct io_buffer *rx_iobuf[INTEL_NUM_RX_DESC]; }; +extern int intel_create_ring ( struct intel_nic *intel, + struct intel_ring *ring ); +extern void intel_destroy_ring ( struct intel_nic *intel, + struct intel_ring *ring ); +extern void intel_refill_rx ( struct intel_nic *intel ); +extern void intel_empty_rx ( struct intel_nic *intel ); +extern int intel_transmit ( struct net_device *netdev, + struct io_buffer *iobuf ); +extern void intel_poll_tx ( struct net_device *netdev ); +extern void intel_poll_rx ( struct net_device *netdev ); + #endif /* _INTEL_H */ diff --git a/src/drivers/net/intelx.c b/src/drivers/net/intelx.c new file mode 100644 index 00000000..e60f36b6 --- /dev/null +++ b/src/drivers/net/intelx.c @@ -0,0 +1,465 @@ +/* + * Copyright (C) 2013 Michael Brown . + * + * 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. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "intelx.h" + +/** @file + * + * Intel 10 Gigabit Ethernet network card driver + * + */ + +/****************************************************************************** + * + * MAC address + * + ****************************************************************************** + */ + +/** + * Try to fetch initial MAC address + * + * @v intel Intel device + * @v ral0 RAL0 register address + * @v hw_addr Hardware address to fill in + * @ret rc Return status code + */ +static int intelx_try_fetch_mac ( struct intel_nic *intel, unsigned int ral0, + uint8_t *hw_addr ) { + union intel_receive_address mac; + + /* Read current address from RAL0/RAH0 */ + mac.reg.low = cpu_to_le32 ( readl ( intel->regs + ral0 ) ); + mac.reg.high = cpu_to_le32 ( readl ( intel->regs + ral0 + + ( INTELX_RAH0 - INTELX_RAL0 ) ) ); + + /* Use current address if valid */ + if ( is_valid_ether_addr ( mac.raw ) ) { + DBGC ( intel, "INTEL %p has autoloaded MAC address %s at " + "%#05x\n", intel, eth_ntoa ( mac.raw ), ral0 ); + memcpy ( hw_addr, mac.raw, ETH_ALEN ); + return 0; + } + + return -ENOENT; +} + +/** + * Fetch initial MAC address + * + * @v intel Intel device + * @v hw_addr Hardware address to fill in + * @ret rc Return status code + */ +static int intelx_fetch_mac ( struct intel_nic *intel, uint8_t *hw_addr ) { + int rc; + + /* Try to fetch address from INTELX_RAL0 */ + if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0, + hw_addr ) ) == 0 ) { + return 0; + } + + /* Try to fetch address from INTELX_RAL0_ALT */ + if ( ( rc = intelx_try_fetch_mac ( intel, INTELX_RAL0_ALT, + hw_addr ) ) == 0 ) { + return 0; + } + + DBGC ( intel, "INTEL %p has no MAC address to use\n", intel ); + return -ENOENT; +} + +/****************************************************************************** + * + * Device reset + * + ****************************************************************************** + */ + +/** + * Reset hardware + * + * @v intel Intel device + * @ret rc Return status code + */ +static int intelx_reset ( struct intel_nic *intel ) { + uint32_t ctrl; + + /* Perform a global software reset */ + ctrl = readl ( intel->regs + INTELX_CTRL ); + writel ( ( ctrl | INTELX_CTRL_RST | INTELX_CTRL_LRST ), + intel->regs + INTELX_CTRL ); + mdelay ( INTELX_RESET_DELAY_MS ); + + DBGC ( intel, "INTEL %p reset (ctrl %08x)\n", intel, ctrl ); + return 0; +} + +/****************************************************************************** + * + * Link state + * + ****************************************************************************** + */ + +/** + * Check link state + * + * @v netdev Network device + */ +static void intelx_check_link ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + uint32_t links; + + /* Read link status */ + links = readl ( intel->regs + INTELX_LINKS ); + DBGC ( intel, "INTEL %p link status is %08x\n", intel, links ); + + /* Update network device */ + if ( links & INTELX_LINKS_UP ) { + netdev_link_up ( netdev ); + } else { + netdev_link_down ( netdev ); + } +} + +/****************************************************************************** + * + * Network device interface + * + ****************************************************************************** + */ + +/** + * Open network device + * + * @v netdev Network device + * @ret rc Return status code + */ +static int intelx_open ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + union intel_receive_address mac; + uint32_t ral0; + uint32_t rah0; + uint32_t dmatxctl; + uint32_t fctrl; + uint32_t srrctl; + uint32_t hlreg0; + uint32_t maxfrs; + uint32_t rdrxctl; + uint32_t rxctrl; + uint32_t dca_rxctrl; + int rc; + + /* Create transmit descriptor ring */ + if ( ( rc = intel_create_ring ( intel, &intel->tx ) ) != 0 ) + goto err_create_tx; + + /* Create receive descriptor ring */ + if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 ) + goto err_create_rx; + + /* Program MAC address */ + memset ( &mac, 0, sizeof ( mac ) ); + memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) ); + ral0 = le32_to_cpu ( mac.reg.low ); + rah0 = ( le32_to_cpu ( mac.reg.high ) | INTELX_RAH0_AV ); + writel ( ral0, intel->regs + INTELX_RAL0 ); + writel ( rah0, intel->regs + INTELX_RAH0 ); + writel ( ral0, intel->regs + INTELX_RAL0_ALT ); + writel ( rah0, intel->regs + INTELX_RAH0_ALT ); + + /* Allocate interrupt vectors */ + writel ( ( INTELX_IVAR_RX0_DEFAULT | INTELX_IVAR_RX0_VALID | + INTELX_IVAR_TX0_DEFAULT | INTELX_IVAR_TX0_VALID ), + intel->regs + INTELX_IVAR ); + + /* Enable transmitter */ + dmatxctl = readl ( intel->regs + INTELX_DMATXCTL ); + dmatxctl |= INTELX_DMATXCTL_TE; + writel ( dmatxctl, intel->regs + INTELX_DMATXCTL ); + + /* Configure receive filter */ + fctrl = readl ( intel->regs + INTELX_FCTRL ); + fctrl |= ( INTELX_FCTRL_BAM | INTELX_FCTRL_UPE | INTELX_FCTRL_MPE ); + writel ( fctrl, intel->regs + INTELX_FCTRL ); + + /* Configure receive buffer sizes */ + srrctl = readl ( intel->regs + INTELX_SRRCTL ); + srrctl &= ~INTELX_SRRCTL_BSIZE_MASK; + srrctl |= INTELX_SRRCTL_BSIZE_DEFAULT; + writel ( srrctl, intel->regs + INTELX_SRRCTL ); + + /* Configure jumbo frames. Required to allow the extra 4-byte + * headroom for VLANs, since we don't use the hardware's + * native VLAN offload. + */ + hlreg0 = readl ( intel->regs + INTELX_HLREG0 ); + hlreg0 |= INTELX_HLREG0_JUMBOEN; + writel ( hlreg0, intel->regs + INTELX_HLREG0 ); + + /* Configure frame size */ + maxfrs = readl ( intel->regs + INTELX_MAXFRS ); + maxfrs &= ~INTELX_MAXFRS_MFS_MASK; + maxfrs |= INTELX_MAXFRS_MFS_DEFAULT; + writel ( maxfrs, intel->regs + INTELX_MAXFRS ); + + /* Configure receive DMA */ + rdrxctl = readl ( intel->regs + INTELX_RDRXCTL ); + rdrxctl |= INTELX_RDRXCTL_SECRC; + writel ( rdrxctl, intel->regs + INTELX_RDRXCTL ); + + /* Clear "must-be-zero" bit for direct cache access (DCA). We + * leave DCA disabled anyway, but if we do not clear this bit + * then the received packets contain garbage data. + */ + dca_rxctrl = readl ( intel->regs + INTELX_DCA_RXCTRL ); + dca_rxctrl &= ~INTELX_DCA_RXCTRL_MUST_BE_ZERO; + writel ( dca_rxctrl, intel->regs + INTELX_DCA_RXCTRL ); + + /* Enable receiver */ + rxctrl = readl ( intel->regs + INTELX_RXCTRL ); + rxctrl |= INTELX_RXCTRL_RXEN; + writel ( rxctrl, intel->regs + INTELX_RXCTRL ); + + /* Fill receive ring */ + intel_refill_rx ( intel ); + + /* Update link state */ + intelx_check_link ( netdev ); + + return 0; + + intel_destroy_ring ( intel, &intel->rx ); + err_create_rx: + intel_destroy_ring ( intel, &intel->tx ); + err_create_tx: + return rc; +} + +/** + * Close network device + * + * @v netdev Network device + */ +static void intelx_close ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + uint32_t rxctrl; + uint32_t dmatxctl; + + /* Disable receiver */ + rxctrl = readl ( intel->regs + INTELX_RXCTRL ); + rxctrl &= ~INTELX_RXCTRL_RXEN; + writel ( rxctrl, intel->regs + INTELX_RXCTRL ); + + /* Disable transmitter */ + dmatxctl = readl ( intel->regs + INTELX_DMATXCTL ); + dmatxctl &= ~INTELX_DMATXCTL_TE; + writel ( dmatxctl, intel->regs + INTELX_DMATXCTL ); + + /* Destroy receive descriptor ring */ + intel_destroy_ring ( intel, &intel->rx ); + + /* Discard any unused receive buffers */ + intel_empty_rx ( intel ); + + /* Destroy transmit descriptor ring */ + intel_destroy_ring ( intel, &intel->tx ); + + /* Reset the NIC, to flush the transmit and receive FIFOs */ + intelx_reset ( intel ); +} + +/** + * Poll for completed and received packets + * + * @v netdev Network device + */ +static void intelx_poll ( struct net_device *netdev ) { + struct intel_nic *intel = netdev->priv; + uint32_t eicr; + + /* Check for and acknowledge interrupts */ + eicr = readl ( intel->regs + INTELX_EICR ); + if ( ! eicr ) + return; + + /* Poll for TX completions, if applicable */ + if ( eicr & INTELX_EIRQ_TX0 ) + intel_poll_tx ( netdev ); + + /* Poll for RX completions, if applicable */ + if ( eicr & ( INTELX_EIRQ_RX0 | INTELX_EIRQ_RXO ) ) + intel_poll_rx ( netdev ); + + /* Report receive overruns */ + if ( eicr & INTELX_EIRQ_RXO ) + netdev_rx_err ( netdev, NULL, -ENOBUFS ); + + /* Check link state, if applicable */ + if ( eicr & INTELX_EIRQ_LSC ) + intelx_check_link ( netdev ); + + /* Refill RX ring */ + intel_refill_rx ( intel ); +} + +/** + * Enable or disable interrupts + * + * @v netdev Network device + * @v enable Interrupts should be enabled + */ +static void intelx_irq ( struct net_device *netdev, int enable ) { + struct intel_nic *intel = netdev->priv; + uint32_t mask; + + mask = ( INTELX_EIRQ_LSC | INTELX_EIRQ_RXO | INTELX_EIRQ_TX0 | + INTELX_EIRQ_RX0 ); + if ( enable ) { + writel ( mask, intel->regs + INTELX_EIMS ); + } else { + writel ( mask, intel->regs + INTELX_EIMC ); + } +} + +/** Network device operations */ +static struct net_device_operations intelx_operations = { + .open = intelx_open, + .close = intelx_close, + .transmit = intel_transmit, + .poll = intelx_poll, + .irq = intelx_irq, +}; + +/****************************************************************************** + * + * PCI interface + * + ****************************************************************************** + */ + +/** + * Probe PCI device + * + * @v pci PCI device + * @ret rc Return status code + */ +static int intelx_probe ( struct pci_device *pci ) { + struct net_device *netdev; + struct intel_nic *intel; + int rc; + + /* Allocate and initialise net device */ + netdev = alloc_etherdev ( sizeof ( *intel ) ); + if ( ! netdev ) { + rc = -ENOMEM; + goto err_alloc; + } + netdev_init ( netdev, &intelx_operations ); + intel = netdev->priv; + pci_set_drvdata ( pci, netdev ); + netdev->dev = &pci->dev; + memset ( intel, 0, sizeof ( *intel ) ); + intel->port = PCI_FUNC ( pci->busdevfn ); + intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTELX_TD ); + intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTELX_RD ); + + /* Fix up PCI device */ + adjust_pci_device ( pci ); + + /* Map registers */ + intel->regs = ioremap ( pci->membase, INTEL_BAR_SIZE ); + + /* Reset the NIC */ + if ( ( rc = intelx_reset ( intel ) ) != 0 ) + goto err_reset; + + /* Fetch MAC address */ + if ( ( rc = intelx_fetch_mac ( intel, netdev->hw_addr ) ) != 0 ) + goto err_fetch_mac; + + /* Register network device */ + if ( ( rc = register_netdev ( netdev ) ) != 0 ) + goto err_register_netdev; + + /* Set initial link state */ + intelx_check_link ( netdev ); + + return 0; + + unregister_netdev ( netdev ); + err_register_netdev: + err_fetch_mac: + intelx_reset ( intel ); + err_reset: + iounmap ( intel->regs ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); + err_alloc: + return rc; +} + +/** + * Remove PCI device + * + * @v pci PCI device + */ +static void intelx_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); + struct intel_nic *intel = netdev->priv; + + /* Unregister network device */ + unregister_netdev ( netdev ); + + /* Reset the NIC */ + intelx_reset ( intel ); + + /* Free network device */ + iounmap ( intel->regs ); + netdev_nullify ( netdev ); + netdev_put ( netdev ); +} + +/** PCI device IDs */ +static struct pci_device_id intelx_nics[] = { + PCI_ROM ( 0x8086, 0x10fb, "82599", "82599", 0 ), +}; + +/** PCI driver */ +struct pci_driver intelx_driver __pci_driver = { + .ids = intelx_nics, + .id_count = ( sizeof ( intelx_nics ) / sizeof ( intelx_nics[0] ) ), + .probe = intelx_probe, + .remove = intelx_remove, +}; diff --git a/src/drivers/net/intelx.h b/src/drivers/net/intelx.h new file mode 100644 index 00000000..60bb294d --- /dev/null +++ b/src/drivers/net/intelx.h @@ -0,0 +1,114 @@ +#ifndef _INTELX_H +#define _INTELX_H + +/** @file + * + * Intel 10 Gigabit Ethernet network card driver + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include "intel.h" + +/** Device Control Register */ +#define INTELX_CTRL 0x00000UL +#define INTELX_CTRL_LRST 0x00000008UL /**< Link reset */ +#define INTELX_CTRL_RST 0x04000000UL /**< Device reset */ + +/** Time to delay for device reset, in milliseconds */ +#define INTELX_RESET_DELAY_MS 20 + +/** Extended Interrupt Cause Read Register */ +#define INTELX_EICR 0x00800UL +#define INTELX_EIRQ_RX0 0x00000001UL /**< RX0 (via IVAR) */ +#define INTELX_EIRQ_TX0 0x00000002UL /**< RX0 (via IVAR) */ +#define INTELX_EIRQ_RXO 0x00020000UL /**< Receive overrun */ +#define INTELX_EIRQ_LSC 0x00100000UL /**< Link status change */ + +/** Interrupt Mask Set/Read Register */ +#define INTELX_EIMS 0x00880UL + +/** Interrupt Mask Clear Register */ +#define INTELX_EIMC 0x00888UL + +/** Interrupt Vector Allocation Register */ +#define INTELX_IVAR 0x00900UL +#define INTELX_IVAR_RX0(bit) ( (bit) << 0 ) /**< RX queue 0 allocation */ +#define INTELX_IVAR_RX0_DEFAULT INTELX_IVAR_RX0 ( 0x00 ) +#define INTELX_IVAR_RX0_MASK INTELX_IVAR_RX0 ( 0x3f ) +#define INTELX_IVAR_RX0_VALID 0x00000080UL /**< RX queue 0 valid */ +#define INTELX_IVAR_TX0(bit) ( (bit) << 8 ) /**< TX queue 0 allocation */ +#define INTELX_IVAR_TX0_DEFAULT INTELX_IVAR_TX0 ( 0x01 ) +#define INTELX_IVAR_TX0_MASK INTELX_IVAR_TX0 ( 0x3f ) +#define INTELX_IVAR_TX0_VALID 0x00008000UL /**< TX queue 0 valid */ + +/** Receive Filter Control Register */ +#define INTELX_FCTRL 0x05080UL +#define INTELX_FCTRL_MPE 0x00000100UL /**< Multicast promiscuous */ +#define INTELX_FCTRL_UPE 0x00000200UL /**< Unicast promiscuous mode */ +#define INTELX_FCTRL_BAM 0x00000400UL /**< Broadcast accept mode */ + +/** Receive Address Low + * + * The MAC address registers RAL0/RAH0 exist at address 0x05400 for + * the 82598 and 0x0a200 for the 82599, according to the datasheet. + * In practice, the 82599 seems to also provide a copy of these + * registers at 0x05400. To aim for maximum compatibility, we try + * both addresses when reading the initial MAC address, and set both + * addresses when setting the MAC address. + */ +#define INTELX_RAL0 0x05400UL +#define INTELX_RAL0_ALT 0x0a200UL + +/** Receive Address High */ +#define INTELX_RAH0 0x05404UL +#define INTELX_RAH0_ALT 0x0a204UL +#define INTELX_RAH0_AV 0x80000000UL /**< Address valid */ + +/** Receive Descriptor register block */ +#define INTELX_RD 0x01000UL + +/** Split Receive Control Register */ +#define INTELX_SRRCTL 0x02100UL +#define INTELX_SRRCTL_BSIZE(kb) ( (kb) << 0 ) /**< Receive buffer size */ +#define INTELX_SRRCTL_BSIZE_DEFAULT INTELX_SRRCTL_BSIZE ( 0x02 ) +#define INTELX_SRRCTL_BSIZE_MASK INTELX_SRRCTL_BSIZE ( 0x1f ) + +/** Receive DMA Control Register */ +#define INTELX_RDRXCTL 0x02f00UL +#define INTELX_RDRXCTL_SECRC 0x00000001UL /**< Strip CRC */ + +/** Receive Control Register */ +#define INTELX_RXCTRL 0x03000UL +#define INTELX_RXCTRL_RXEN 0x00000001UL /**< Receive enable */ + +/** Transmit DMA Control Register */ +#define INTELX_DMATXCTL 0x04a80UL +#define INTELX_DMATXCTL_TE 0x00000001UL /**< Transmit enable */ + +/** Transmit Descriptor register block */ +#define INTELX_TD 0x06000UL + +/** RX DCA Control Register */ +#define INTELX_DCA_RXCTRL 0x02200UL +#define INTELX_DCA_RXCTRL_MUST_BE_ZERO 0x00001000UL /**< Must be zero */ + +/** MAC Core Control 0 Register */ +#define INTELX_HLREG0 0x04240UL +#define INTELX_HLREG0_JUMBOEN 0x00000004UL /**< Jumbo frame enable */ + +/** Maximum Frame Size Register */ +#define INTELX_MAXFRS 0x04268UL +#define INTELX_MAXFRS_MFS(len) ( (len) << 16 ) /**< Maximum frame size */ +#define INTELX_MAXFRS_MFS_DEFAULT \ + INTELX_MAXFRS_MFS ( ETH_FRAME_LEN + 4 /* VLAN */ + 4 /* CRC */ ) +#define INTELX_MAXFRS_MFS_MASK INTELX_MAXFRS_MFS ( 0xffff ) + +/** Link Status Register */ +#define INTELX_LINKS 0x042a4UL +#define INTELX_LINKS_UP 0x40000000UL /**< Link up */ + +#endif /* _INTELX_H */ diff --git a/src/drivers/net/ns8390.c b/src/drivers/net/ns8390.c index a30f9361..0ffc6216 100644 --- a/src/drivers/net/ns8390.c +++ b/src/drivers/net/ns8390.c @@ -895,7 +895,7 @@ static int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused) #endif 0 }; /* if no addresses supplied, fall back on defaults */ - if (probe_addrs == 0 || probe_addrs[0] == 0) + if (probe_addrs == NULL || probe_addrs[0] == 0) probe_addrs = base; eth_bmem = 0; /* No shared memory */ for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) { diff --git a/src/drivers/net/phantom/phantom.c b/src/drivers/net/phantom/phantom.c index 1c798e04..7f2fe0b6 100644 --- a/src/drivers/net/phantom/phantom.c +++ b/src/drivers/net/phantom/phantom.c @@ -1454,11 +1454,8 @@ static struct net_device_operations phantom_operations = { * */ -/** Phantom CLP settings tag magic */ -#define PHN_CLP_TAG_MAGIC 0xc19c1900UL - -/** Phantom CLP settings tag magic mask */ -#define PHN_CLP_TAG_MAGIC_MASK 0xffffff00UL +/** Phantom CLP settings scope */ +static struct settings_scope phantom_settings_scope; /** Phantom CLP data * @@ -1689,8 +1686,8 @@ phantom_clp_setting ( struct phantom_nic *phantom, struct setting *setting ) { } /* Allow for use of numbered settings */ - if ( ( setting->tag & PHN_CLP_TAG_MAGIC_MASK ) == PHN_CLP_TAG_MAGIC ) - return ( setting->tag & ~PHN_CLP_TAG_MAGIC_MASK ); + if ( setting->scope == &phantom_settings_scope ) + return setting->tag; DBGC2 ( phantom, "Phantom %p has no \"%s\" setting\n", phantom, setting->name ); @@ -2075,7 +2072,7 @@ static int phantom_probe ( struct pci_device *pci ) { assert ( phantom->port < PHN_MAX_NUM_PORTS ); settings_init ( &phantom->settings, &phantom_settings_operations, - &netdev->refcnt, PHN_CLP_TAG_MAGIC ); + &netdev->refcnt, &phantom_settings_scope ); /* Fix up PCI device */ adjust_pci_device ( pci ); diff --git a/src/drivers/net/prism2.c b/src/drivers/net/prism2.c index ad388074..ab974264 100644 --- a/src/drivers/net/prism2.c +++ b/src/drivers/net/prism2.c @@ -130,9 +130,7 @@ typedef struct hfa384x } hfa384x_t; /* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */ -static hfa384x_t hw_global = { - 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0} -}; +static hfa384x_t hw_global; /* * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 76fa47bb..498c233f 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -74,6 +74,7 @@ static void realtek_spi_open_bit ( struct bit_basher *basher ) { /* Enable EEPROM access */ writeb ( RTL_9346CR_EEM_EEPROM, rtl->regs + RTL_9346CR ); + readb ( rtl->regs + RTL_9346CR ); /* Ensure write reaches chip */ } /** @@ -87,6 +88,7 @@ static void realtek_spi_close_bit ( struct bit_basher *basher ) { /* Disable EEPROM access */ writeb ( RTL_9346CR_EEM_NORMAL, rtl->regs + RTL_9346CR ); + readb ( rtl->regs + RTL_9346CR ); /* Ensure write reaches chip */ } /** @@ -129,6 +131,7 @@ static void realtek_spi_write_bit ( struct bit_basher *basher, reg &= ~mask; reg |= ( data & mask ); writeb ( reg, rtl->regs + RTL_9346CR ); + readb ( rtl->regs + RTL_9346CR ); /* Ensure write reaches chip */ DBG_ENABLE ( DBGLVL_IO ); } @@ -144,9 +147,12 @@ static struct bit_basher_operations realtek_basher_ops = { * Initialise EEPROM * * @v netdev Network device + * @ret rc Return status code */ -static void realtek_init_eeprom ( struct net_device *netdev ) { +static int realtek_init_eeprom ( struct net_device *netdev ) { struct realtek_nic *rtl = netdev->priv; + uint16_t id; + int rc; /* Initialise SPI bit-bashing interface */ rtl->spibit.basher.op = &realtek_basher_ops; @@ -163,6 +169,22 @@ static void realtek_init_eeprom ( struct net_device *netdev ) { } rtl->eeprom.bus = &rtl->spibit.bus; + /* Check for EEPROM presence. Some onboard NICs will have no + * EEPROM connected, with the BIOS being responsible for + * programming the initial register values. + */ + if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_ID, + &id, sizeof ( id ) ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not read EEPROM ID: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + if ( id != cpu_to_le16 ( RTL_EEPROM_ID_MAGIC ) ) { + DBGC ( rtl, "REALTEK %p EEPROM ID incorrect (%#04x); assuming " + "no EEPROM\n", rtl, le16_to_cpu ( id ) ); + return -ENODEV; + } + /* Initialise space for non-volatile options, if available * * We use offset 0x40 (i.e. address 0x20), length 0x40. This @@ -176,6 +198,8 @@ static void realtek_init_eeprom ( struct net_device *netdev ) { nvo_init ( &rtl->nvo, &rtl->eeprom.nvs, RTL_EEPROM_VPD, RTL_EEPROM_VPD_LEN, NULL, &netdev->refcnt ); } + + return 0; } /****************************************************************************** @@ -525,7 +549,11 @@ static int realtek_create_ring ( struct realtek_nic *rtl, static void realtek_destroy_ring ( struct realtek_nic *rtl, struct realtek_ring *ring ) { - /* Do nothing in legacy mode */ + /* Reset producer and consumer counters */ + ring->prod = 0; + ring->cons = 0; + + /* Do nothing more if in legacy mode */ if ( rtl->legacy ) return; @@ -536,8 +564,6 @@ static void realtek_destroy_ring ( struct realtek_nic *rtl, /* Free descriptor ring */ free_dma ( ring->desc, ring->len ); ring->desc = NULL; - ring->prod = 0; - ring->cons = 0; } /** @@ -700,8 +726,8 @@ static int realtek_transmit ( struct net_device *netdev, /* Get next transmit descriptor */ if ( ( rtl->tx.prod - rtl->tx.cons ) >= RTL_NUM_TX_DESC ) { - DBGC ( rtl, "REALTEK %p out of transmit descriptors\n", rtl ); - return -ENOBUFS; + netdev_tx_defer ( netdev, iobuf ); + return 0; } tx_idx = ( rtl->tx.prod++ % RTL_NUM_TX_DESC ); @@ -785,8 +811,8 @@ static void realtek_poll_tx ( struct net_device *netdev ) { DBGC2 ( rtl, "REALTEK %p TX %d complete\n", rtl, tx_idx ); /* Complete TX descriptor */ - netdev_tx_complete_next ( netdev ); rtl->tx.cons++; + netdev_tx_complete_next ( netdev ); } } @@ -840,6 +866,9 @@ static void realtek_legacy_poll_rx ( struct net_device *netdev ) { rtl->rx_offset = ( ( rtl->rx_offset + 3 ) & ~3 ); rtl->rx_offset = ( rtl->rx_offset % RTL_RXBUF_LEN ); writew ( ( rtl->rx_offset - 16 ), rtl->regs + RTL_CAPR ); + + /* Give chip time to react before rechecking RTL_CR */ + readw ( rtl->regs + RTL_CAPR ); } } @@ -1045,22 +1074,22 @@ static int realtek_probe ( struct pci_device *pci ) { realtek_detect ( rtl ); /* Initialise EEPROM */ - realtek_init_eeprom ( netdev ); + if ( ( rc = realtek_init_eeprom ( netdev ) ) == 0 ) { - /* Read MAC address from EEPROM */ - if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_MAC, - netdev->hw_addr, ETH_ALEN ) ) != 0 ) { - DBGC ( rtl, "REALTEK %p could not read MAC address: %s\n", - rtl, strerror ( rc ) ); - goto err_nvs_read; - } + /* Read MAC address from EEPROM */ + if ( ( rc = nvs_read ( &rtl->eeprom.nvs, RTL_EEPROM_MAC, + netdev->hw_addr, ETH_ALEN ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not read MAC address: " + "%s\n", rtl, strerror ( rc ) ); + goto err_nvs_read; + } - /* The EEPROM may not be present for onboard NICs. Fall back - * to reading the current ID register value, which will - * hopefully have been programmed by the platform firmware. - */ - if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) { - DBGC ( rtl, "REALTEK %p seems to have no EEPROM\n", rtl ); + } else { + + /* EEPROM not present. Fall back to reading the + * current ID register value, which will hopefully + * have been programmed by the platform firmware. + */ for ( i = 0 ; i < ETH_ALEN ; i++ ) netdev->hw_addr[i] = readb ( rtl->regs + RTL_IDR0 + i ); } diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h index 6a7b10a9..1cd85d95 100644 --- a/src/drivers/net/realtek.h +++ b/src/drivers/net/realtek.h @@ -166,6 +166,12 @@ enum realtek_legacy_status { #define RTL_9346CR_EEDI 0x02 /**< Data in */ #define RTL_9346CR_EEDO 0x01 /**< Data out */ +/** Word offset of ID code word within EEPROM */ +#define RTL_EEPROM_ID ( 0x00 / 2 ) + +/** EEPROM code word magic value */ +#define RTL_EEPROM_ID_MAGIC 0x8129 + /** Word offset of MAC address within EEPROM */ #define RTL_EEPROM_MAC ( 0x0e / 2 ) diff --git a/src/drivers/net/rtl818x/rtl8185_rtl8225.c b/src/drivers/net/rtl818x/rtl8185_rtl8225.c index 50cc84ad..ae92531c 100644 --- a/src/drivers/net/rtl818x/rtl8185_rtl8225.c +++ b/src/drivers/net/rtl818x/rtl8185_rtl8225.c @@ -71,7 +71,7 @@ static void rtl8225_write(struct net80211_device *dev, u8 addr, u16 data) udelay(10); for (i = 15; i >= 0; i--) { - u16 reg = reg80 | !!(bangdata & (1 << i)); + u16 reg = ( reg80 | ( ( bangdata >> i ) & 1 ) ); if (i & 1) rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); diff --git a/src/drivers/net/sis900.c b/src/drivers/net/sis900.c index 75e9ef96..72451567 100644 --- a/src/drivers/net/sis900.c +++ b/src/drivers/net/sis900.c @@ -111,7 +111,7 @@ static struct mii_chip_info { // {"NS 83851 PHY",0x2000, 0x5C20, MIX }, {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8200,rtl8201_read_mode}, {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode}, - {0,0,0,0} + {NULL,0,0,NULL} }; static struct mii_phy { diff --git a/src/drivers/net/tlan.c b/src/drivers/net/tlan.c index 74398df4..7742f6d8 100644 --- a/src/drivers/net/tlan.c +++ b/src/drivers/net/tlan.c @@ -94,7 +94,7 @@ static void TLan_MiiWriteReg(struct nic *nic __unused, u16, u16, u16); static const char *media[] = { "10BaseT-HD ", "10BaseT-FD ", "100baseTx-HD ", - "100baseTx-FD", "100baseT4", 0 + "100baseTx-FD", "100baseT4", NULL }; /* This much match tlan_pci_tbl[]! */ @@ -164,7 +164,7 @@ static const struct pci_id_info tlan_pci_tbl[] = { {"Compaq NetFlex-3/E", 0, /* EISA card */ {0, 0, 0, 0, 0, 0}, TLAN_ADAPTER_ACTIVITY_LED, 0x83}, - {0, 0, + {NULL, 0, {0, 0, 0, 0, 0, 0}, 0, 0}, }; diff --git a/src/drivers/net/tulip.c b/src/drivers/net/tulip.c index 7a23b7e9..e4e6ffa8 100644 --- a/src/drivers/net/tulip.c +++ b/src/drivers/net/tulip.c @@ -228,7 +228,7 @@ static const struct pci_id_info pci_id_tbl[] = { TULIP_IOTYPE, TULIP_SIZE, COMET }, { "SG Thomson STE10/100A", { 0x2774104a, 0xffffffff, 0, 0, 0, 0 }, TULIP_IOTYPE, 256, COMET }, /*Ramesh Chander*/ - { 0, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 }, + { NULL, { 0, 0, 0, 0, 0, 0 }, 0, 0, 0 }, }; enum tbl_flag { @@ -264,7 +264,7 @@ static struct tulip_chip_table { { "Xircom tulip work-alike", HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_PWRDWN | HAS_NWAY }, { "SGThomson STE10/100A", HAS_MII | MC_HASH_ONLY }, /*Ramesh Chander*/ - { 0, 0 }, + { NULL, 0 }, }; /* A full-duplex map for media types. */ @@ -475,7 +475,7 @@ static struct fixups { 0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */ 0x1B05, 0x006D, /* 100baseTx-FD CSR12 0x1B */ }}, - {0, 0, 0, 0, {}}}; + {NULL, 0, 0, 0, {}}}; static const char * block_name[] = {"21140 non-MII", "21140 MII PHY", "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"}; @@ -720,7 +720,7 @@ static void parse_eeprom(struct nic *nic) whereami("parse_eeprom\n"); - tp->mtable = 0; + tp->mtable = NULL; /* Detect an old-style (SA only) EEPROM layout: memcmp(ee_data, ee_data+16, 8). */ for (i = 0; i < 8; i ++) diff --git a/src/drivers/net/via-velocity.c b/src/drivers/net/via-velocity.c index 9ba0b093..e98e81a2 100644 --- a/src/drivers/net/via-velocity.c +++ b/src/drivers/net/via-velocity.c @@ -1230,7 +1230,7 @@ static int velocity_open(struct nic *nic, struct pci_device *pci __unused) u32 TxPhyAddr, RxPhyAddr; u32 TxBufPhyAddr, RxBufPhyAddr; vptr->TxDescArrays = tx_ring; - if (vptr->TxDescArrays == 0) + if (vptr->TxDescArrays == NULL) printf("Allot Error"); /* Tx Descriptor needs 64 bytes alignment; */ diff --git a/src/hci/linux_args.c b/src/hci/linux_args.c index 0bce4af9..58eeb063 100644 --- a/src/hci/linux_args.c +++ b/src/hci/linux_args.c @@ -45,9 +45,9 @@ __asmcall void save_args(int argc, char **argv) /** Supported command-line options */ static struct option options[] = { - {"net", 1, 0, 'n'}, - {"settings", 1, 0, 's'}, - {0, 0, 0, 0} + {"net", 1, NULL, 'n'}, + {"settings", 1, NULL, 's'}, + {NULL, 0, NULL, 0} }; /** diff --git a/src/hci/mucurses/kb.c b/src/hci/mucurses/kb.c index cada7291..b38c8c14 100644 --- a/src/hci/mucurses/kb.c +++ b/src/hci/mucurses/kb.c @@ -88,7 +88,7 @@ int wgetnstr ( WINDOW *win, char *str, int n ) { int c; if ( n == 0 ) { - str = '\0'; + *str = '\0'; return OK; } diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 0368b82c..1c1ee0c3 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -35,6 +35,22 @@ FILE_LICENCE ( GPL2_OR_LATER ); FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 ); +/* Disambiguate the various error causes */ +#define EINFO_EEFI_LOAD \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \ + "Could not load image" ) +#define EINFO_EEFI_LOAD_PROHIBITED \ + __einfo_platformify ( EINFO_EEFI_LOAD, EFI_SECURITY_VIOLATION, \ + "Image prohibited by security policy" ) +#define EEFI_LOAD_PROHIBITED \ + __einfo_error ( EINFO_EEFI_LOAD_PROHIBITED ) +#define EEFI_LOAD( efirc ) EPLATFORM ( EINFO_EEFI_LOAD, efirc, \ + EEFI_LOAD_PROHIBITED ) +#define EINFO_EEFI_START \ + __einfo_uniqify ( EINFO_EPLATFORM, 0x02, \ + "Could not start image" ) +#define EEFI_START( efirc ) EPLATFORM ( EINFO_EEFI_START, efirc ) + /** EFI loaded image protocol GUID */ static EFI_GUID efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; @@ -176,9 +192,9 @@ static int efi_image_exec ( struct image *image ) { user_to_virt ( image->data, 0 ), image->len, &handle ) ) != 0 ) { /* Not an EFI image */ + rc = -EEFI_LOAD ( efirc ); DBGC ( image, "EFIIMAGE %p could not load: %s\n", - image, efi_strerror ( efirc ) ); - rc = -ENOEXEC; + image, strerror ( rc ) ); goto err_load_image; } @@ -188,7 +204,7 @@ static int efi_image_exec ( struct image *image ) { NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if ( efirc ) { /* Should never happen */ - rc = EFIRC_TO_RC ( efirc ); + rc = -EEFI ( efirc ); goto err_open_protocol; } @@ -205,9 +221,9 @@ static int efi_image_exec ( struct image *image ) { /* Start the image */ if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) { + rc = -EEFI_START ( efirc ); DBGC ( image, "EFIIMAGE %p returned with status %s\n", - image, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + image, strerror ( rc ) ); goto err_start_image; } @@ -220,8 +236,9 @@ static int efi_image_exec ( struct image *image ) { * have no "unload" operation. */ if ( ( efirc = bs->UnloadImage ( handle ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( image, "EFIIMAGE %p could not unload: %s\n", - image, efi_strerror ( efirc ) ); + image, strerror ( rc ) ); } err_load_image: free ( cmdline ); @@ -246,15 +263,17 @@ static int efi_image_probe ( struct image *image ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_HANDLE handle; EFI_STATUS efirc; + int rc; /* Attempt loading image */ if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL, user_to_virt ( image->data, 0 ), image->len, &handle ) ) != 0 ) { /* Not an EFI image */ + rc = -EEFI_LOAD ( efirc ); DBGC ( image, "EFIIMAGE %p could not load: %s\n", - image, efi_strerror ( efirc ) ); - return -ENOEXEC; + image, strerror ( rc ) ); + return rc; } /* Unload the image. We can't leave it loaded, because we diff --git a/src/include/bootp.h b/src/include/bootp.h deleted file mode 100644 index 0e65477a..00000000 --- a/src/include/bootp.h +++ /dev/null @@ -1,230 +0,0 @@ -#ifndef _BOOTP_H -#define _BOOTP_H - -#ifdef ALTERNATE_DHCP_PORTS_1067_1068 -#undef NON_STANDARD_BOOTP_SERVER -#define NON_STANDARD_BOOTP_SERVER 1067 -#undef NON_STANDARD_BOOTP_CLIENT -#define NON_STANDARD_BOOTP_CLIENT 1068 -#endif - -#ifdef NON_STANDARD_BOOTP_SERVER -#define BOOTP_SERVER NON_STANDARD_BOOTP_SERVER -#else -#define BOOTP_SERVER 67 -#endif -#ifdef NON_STANDARD_BOOTP_CLIENT -#define BOOTP_CLIENT NON_STANDARD_BOOTP_CLIENT -#else -#define BOOTP_CLIENT 68 -#endif -#define PROXYDHCP_SERVER 4011 /* For PXE */ - -#define BOOTP_REQUEST 1 -#define BOOTP_REPLY 2 - -#define TAG_LEN(p) (*((p)+1)) -#define RFC1533_COOKIE 99, 130, 83, 99 -#define RFC1533_PAD 0 -#define RFC1533_NETMASK 1 -#define RFC1533_TIMEOFFSET 2 -#define RFC1533_GATEWAY 3 -#define RFC1533_TIMESERVER 4 -#define RFC1533_IEN116NS 5 -#define RFC1533_DNS 6 -#define RFC1533_LOGSERVER 7 -#define RFC1533_COOKIESERVER 8 -#define RFC1533_LPRSERVER 9 -#define RFC1533_IMPRESSSERVER 10 -#define RFC1533_RESOURCESERVER 11 -#define RFC1533_HOSTNAME 12 -#define RFC1533_BOOTFILESIZE 13 -#define RFC1533_MERITDUMPFILE 14 -#define RFC1533_DOMAINNAME 15 -#define RFC1533_SWAPSERVER 16 -#define RFC1533_ROOTPATH 17 -#define RFC1533_EXTENSIONPATH 18 -#define RFC1533_IPFORWARDING 19 -#define RFC1533_IPSOURCEROUTING 20 -#define RFC1533_IPPOLICYFILTER 21 -#define RFC1533_IPMAXREASSEMBLY 22 -#define RFC1533_IPTTL 23 -#define RFC1533_IPMTU 24 -#define RFC1533_IPMTUPLATEAU 25 -#define RFC1533_INTMTU 26 -#define RFC1533_INTLOCALSUBNETS 27 -#define RFC1533_INTBROADCAST 28 -#define RFC1533_INTICMPDISCOVER 29 -#define RFC1533_INTICMPRESPOND 30 -#define RFC1533_INTROUTEDISCOVER 31 -#define RFC1533_INTROUTESOLICIT 32 -#define RFC1533_INTSTATICROUTES 33 -#define RFC1533_LLTRAILERENCAP 34 -#define RFC1533_LLARPCACHETMO 35 -#define RFC1533_LLETHERNETENCAP 36 -#define RFC1533_TCPTTL 37 -#define RFC1533_TCPKEEPALIVETMO 38 -#define RFC1533_TCPKEEPALIVEGB 39 -#define RFC1533_NISDOMAIN 40 -#define RFC1533_NISSERVER 41 -#define RFC1533_NTPSERVER 42 -#define RFC1533_VENDOR 43 -#define RFC1533_NBNS 44 -#define RFC1533_NBDD 45 -#define RFC1533_NBNT 46 -#define RFC1533_NBSCOPE 47 -#define RFC1533_XFS 48 -#define RFC1533_XDM 49 -#ifndef NO_DHCP_SUPPORT -#define RFC2132_REQ_ADDR 50 -#define RFC2132_MSG_TYPE 53 -#define RFC2132_SRV_ID 54 -#define RFC2132_PARAM_LIST 55 -#define RFC2132_MAX_SIZE 57 -#define RFC2132_VENDOR_CLASS_ID 60 -#define RFC2132_CLIENT_ID 61 -#define RFC2132_TFTP_SERVER_NAME 66 -#define RFC2132_BOOTFILE_NAME 67 -#define RFC3004_USER_CLASS 77 - -#ifdef PXE_DHCP_STRICT -/* - * The following options are acknowledged in RFC3679 because they are - * widely used by PXE implementations, but have never been properly - * allocated. Despite other PXE options being correctly packed in a - * vendor encapsulated field, these are exposed. Sigh. Note that the - * client UUID (option 97) is also noted in the PXE spec as using - * option 61. - */ -#define RFC3679_PXE_CLIENT_ARCH 93 -#define RFC3679_PXE_CLIENT_NDI 94 -#define RFC3679_PXE_CLIENT_UUID 97 - -/* The lengths are fixed. */ -#define RFC3679_PXE_CLIENT_ARCH_LENGTH 2 -#define RFC3679_PXE_CLIENT_NDI_LENGTH 3 -#define RFC3679_PXE_CLIENT_UUID_LENGTH 17 - -/* - * Values of RFC3679_PXE_CLIENT_ARCH can apparently be one of the - * following, according to the PXE spec. The spec only actually - * described the 2nd octet, not the first. Duh... assume 0. - */ -#define RFC3679_PXE_CLIENT_ARCH_IAX86PC 0,0 -#define RFC3679_PXE_CLIENT_ARCH_NECPC98 0,1 -#define RFC3679_PXE_CLIENT_ARCH_IA64PC 0,2 -#define RFC3679_PXE_CLIENT_ARCH_DECALPHA 0,3 -#define RFC3679_PXE_CLIENT_ARCH_ARCX86 0,4 -#define RFC3679_PXE_CLIENT_ARCH_INTELLEAN 0,5 - -/* - * Only one valid value of NDI type (must be 1) and UNDI version (must - * be 2.1) - */ -#define RFC3679_PXE_CLIENT_NDI_21 1,2,1 - -/* - * UUID - type must be 1 and then 16 octets of UID, as with the client ID. - * The value is a default for testing only - */ -#define RFC3679_PXE_CLIENT_UUID_TYPE 0 -#warning "UUID is a default for testing ONLY!" -#define RFC3679_PXE_CLIENT_UUID_DEFAULT \ - RFC3679_PXE_CLIENT_UUID_TYPE, \ - 0xDE,0xAD,0xBE,0xEF, \ - 0xDE,0xAD,0xBE,0xEF, \ - 0xDE,0xAD,0xBE,0xEF, \ - 0xDE,0xAD,0xBE,0xEF -/* - * The Vendor Class ID. Note that the Arch and UNDI version numbers - * are fixed and must be same as the ARCH and NDI above. - */ -#define RFC2132_VENDOR_CLASS_ID_PXE_LENGTH 32 -#define RFC2132_VENDOR_CLASS_ID_PXE \ - 'P','X','E','C','l','i','e','n','t',':', \ - 'A','r','c','h',':','0','0','0','0','0',':', \ - 'U','N','D','I',':','0','0','2','0','0','1' - -/* - * The following vendor options are required in the PXE spec to pull - * options for the *next* image. The PXE spec doesn't help us with - * this (like explaining why). - */ -#define RFC1533_VENDOR_PXE_OPT128 128 -#define RFC1533_VENDOR_PXE_OPT129 129 -#define RFC1533_VENDOR_PXE_OPT130 130 -#define RFC1533_VENDOR_PXE_OPT131 131 -#define RFC1533_VENDOR_PXE_OPT132 132 -#define RFC1533_VENDOR_PXE_OPT133 133 -#define RFC1533_VENDOR_PXE_OPT134 134 -#define RFC1533_VENDOR_PXE_OPT135 135 - -#endif /* PXE_DHCP_STRICT */ - -#define DHCPDISCOVER 1 -#define DHCPOFFER 2 -#define DHCPREQUEST 3 -#define DHCPACK 5 -#endif /* NO_DHCP_SUPPORT */ - -#define RFC1533_VENDOR_MAJOR 0 -#define RFC1533_VENDOR_MINOR 0 - -#define RFC1533_VENDOR_MAGIC 128 -#define RFC1533_VENDOR_ADDPARM 129 -#define RFC1533_VENDOR_ETHDEV 130 -/* We should really apply for an official Etherboot encap option */ -#define RFC1533_VENDOR_ETHERBOOT_ENCAP 150 -/* I'll leave it to FREEBSD to decide if they want to renumber */ -#ifdef IMAGE_FREEBSD -#define RFC1533_VENDOR_HOWTO 132 -#define RFC1533_VENDOR_KERNEL_ENV 133 -#endif -#define RFC1533_VENDOR_NIC_DEV_ID 175 -#define RFC1533_VENDOR_ARCH 177 - -#define RFC1533_END 255 - -#define BOOTP_VENDOR_LEN 64 -#ifndef NO_DHCP_SUPPORT -#define DHCP_OPT_LEN 312 -#endif /* NO_DHCP_SUPPORT */ - -/* Format of a bootp packet */ -struct bootp_t { - uint8_t bp_op; - uint8_t bp_htype; - uint8_t bp_hlen; - uint8_t bp_hops; - uint32_t bp_xid; - uint16_t bp_secs; - uint16_t unused; - in_addr bp_ciaddr; - in_addr bp_yiaddr; - in_addr bp_siaddr; - in_addr bp_giaddr; - uint8_t bp_hwaddr[16]; - uint8_t bp_sname[64]; - char bp_file[128]; -#ifdef NO_DHCP_SUPPORT - uint8_t bp_vend[BOOTP_VENDOR_LEN]; -#else - uint8_t bp_vend[DHCP_OPT_LEN]; -#endif /* NO_DHCP_SUPPORT */ -}; - -/* Format of a bootp IP packet */ -struct bootpip_t -{ - struct iphdr ip; - struct udphdr udp; - struct bootp_t bp; -}; - -/* Format of bootp packet with extensions */ -struct bootpd_t { - struct bootp_t bootp_reply; - uint8_t bootp_extension[MAX_BOOTP_EXTLEN]; -}; - -#endif /* _BOOTP_H */ diff --git a/src/include/compiler.h b/src/include/compiler.h index ed9af237..e5559245 100644 --- a/src/include/compiler.h +++ b/src/include/compiler.h @@ -64,6 +64,7 @@ .comm _sym, 0 #else /* ASSEMBLY */ #define PROVIDE_SYMBOL( _sym ) \ + extern char _sym[]; \ char _sym[0] #endif /* ASSEMBLY */ diff --git a/src/include/errno.h b/src/include/errno.h index bd4ddaf4..bcc4a881 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -30,16 +30,16 @@ FILE_LICENCE ( GPL2_OR_LATER ); * maximum visibility into the source of an error even in an end-user * build with no debugging. They are constructed as follows: * - * Bits 7-0 : PXE error code + * Bits 7-0 : Platform-specific error code * - * This is the closest equivalent PXE error code - * (e.g. PXENV_STATUS_OUT_OF_RESOURCES), and is the only part of the - * error that will be returned via the PXE API, since PXE has - * predefined error codes. + * This is a losslessly compressed representation of the closest + * equivalent error code defined by the platform (e.g. BIOS/PXE or + * EFI). It is used to generate errors to be returned to external + * code. * * Bits 12-8 : Per-file disambiguator * - * When the same error number can be generated from multiple points + * When the same error code can be generated from multiple points * within a file, this field can be used to identify the unique * instance. * @@ -54,7 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * Bit 31 : Reserved * - * Errors are usually return as negative error numbers (e.g. -EINVAL); + * Errors are usually return as negative error codes (e.g. -EINVAL); * bit 31 is therefore unusable. * * @@ -63,9 +63,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * return -EINVAL; * - * By various bits of preprocessor magic, the PXE error code and file - * identifier are already incorporated into the definition of the - * POSIX error macro, which keeps the code relatively clean. + * By various bits of preprocessor magic, the platform-specific error + * code and file identifier are already incorporated into the + * definition of the POSIX error macro, which keeps the code + * relatively clean. * * * Functions that wish to return failures should be declared as @@ -99,6 +100,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* Get definitions for platform-specific error codes */ +#define PLATFORM_ERRNO(_platform) +#include PLATFORM_ERRNO(PLATFORM) + /* Get definitions for file identifiers */ #include @@ -110,37 +115,37 @@ FILE_LICENCE ( GPL2_OR_LATER ); #if ! ERRFILE extern char missing_errfile_declaration[] __attribute__ (( deprecated )); #undef ERRFILE -#define ERRFILE ( 0 * ( ( int ) missing_errfile_declaration ) ) +#define ERRFILE ( ( int ) ( 0 * ( ( intptr_t ) missing_errfile_declaration ) ) ) #endif /** * Declare error information * - * @v pxe PXE error number (0x00-0xff) - * @v posix POSIX error number (0x00-0x7f) + * @v platform Platform error code (uncompressed) + * @v posix POSIX error code (0x00-0x7f) * @v uniq Error disambiguator (0x00-0x1f) * @v desc Error description * @ret einfo Error information */ -#define __einfo( pxe, posix, uniq, desc ) ( pxe, posix, uniq, desc ) +#define __einfo( platform, posix, uniq, desc ) ( platform, posix, uniq, desc ) /** - * Get PXE error number + * Get platform error code * * @v einfo Error information - * @ret pxe PXE error number + * @ret platform Platform error code (uncompressed) */ -#define __einfo_pxe( einfo ) __einfo_extract_pxe einfo -#define __einfo_extract_pxe( pxe, posix, uniq, desc ) pxe +#define __einfo_platform( einfo ) __einfo_extract_platform einfo +#define __einfo_extract_platform( platform, posix, uniq, desc ) platform /** - * Get POSIX error number + * Get POSIX error code * * @v einfo Error information - * @ret posix POSIX error number + * @ret posix POSIX error code */ #define __einfo_posix( einfo ) __einfo_extract_posix einfo -#define __einfo_extract_posix( pxe, posix, uniq, desc ) posix +#define __einfo_extract_posix( platform, posix, uniq, desc ) posix /** * Get error disambiguator @@ -149,7 +154,7 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); * @ret uniq Error disambiguator */ #define __einfo_uniq( einfo ) __einfo_extract_uniq einfo -#define __einfo_extract_uniq( pxe, posix, uniq, desc ) uniq +#define __einfo_extract_uniq( platform, posix, uniq, desc ) uniq /** * Get error description @@ -158,37 +163,50 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); * @ret desc Error description */ #define __einfo_desc( einfo ) __einfo_extract_desc einfo -#define __einfo_extract_desc( pxe, posix, uniq, desc ) desc +#define __einfo_extract_desc( platform, posix, uniq, desc ) desc /** * Declare disambiguated error * * @v einfo_base Base error information - * @v uniq Error disambiguator + * @v uniq Error disambiguator (0x00-0x1f) * @v desc Error description * @ret einfo Error information */ #define __einfo_uniqify( einfo_base, uniq, desc ) \ - __einfo ( __einfo_pxe ( einfo_base ), \ + __einfo ( __einfo_platform ( einfo_base ), \ __einfo_posix ( einfo_base ), \ uniq, desc ) /** - * Get error number + * Declare platform-generated error + * + * @v einfo_base Base error information + * @v platform Platform error code (uncompressed) + * @v desc Error description + * @ret einfo Error information + */ +#define __einfo_platformify( einfo_base, platform, desc ) \ + __einfo ( platform, __einfo_posix ( einfo_base ), \ + __einfo_uniq ( einfo_base ), desc ) + +/** + * Get error code * * @v einfo Error information - * @ret errno Error number + * @ret errno Error code */ #define __einfo_errno( einfo ) \ - ( ( __einfo_posix ( einfo ) << 24 ) | ( ERRFILE ) | \ - ( __einfo_uniq ( einfo ) << 8 ) | \ - ( __einfo_pxe ( einfo ) << 0 ) ) + ( ( int ) \ + ( ( __einfo_posix ( einfo ) << 24 ) | ( ERRFILE ) | \ + ( __einfo_uniq ( einfo ) << 8 ) | \ + ( PLATFORM_TO_ERRNO ( __einfo_platform ( einfo ) ) << 0 ) ) ) /** * Disambiguate a base error based on non-constant information * - * @v error_base Base error - * @v uniq Error disambiguator + * @v einfo_base Base error information + * @v uniq Error disambiguator (0x00-0x1f) * @v ... List of expected possible disambiguated errors * @ret error Error * @@ -200,11 +218,35 @@ extern char missing_errfile_declaration[] __attribute__ (( deprecated )); * EUNIQ() should not be used for constant error disambiguators; use * __einfo_uniqify() instead. */ -#define EUNIQ( errno, uniq, ... ) ( { \ - euniq_discard ( 0, ##__VA_ARGS__); \ - ( ( int ) ( (errno) | ( (uniq) << 8 ) ) ); } ) +#define EUNIQ( einfo_base, uniq, ... ) ( { \ + euniq_discard ( 0, ##__VA_ARGS__ ); \ + ( ( int ) ( __einfo_error ( einfo_base ) | \ + ( (uniq) << 8 ) ) ); } ) static inline void euniq_discard ( int dummy __unused, ... ) {} +/** + * Generate an error based on an external platform error code + * + * @v einfo_base Base error information + * @v platform Platform error code (uncompressed) + * @v ... List of expected possible platform-generated errors + * @ret error Error + * + * EPLATFORM() should be used when a platform error code resulting + * from an external platform API call is being incorporated into an + * error. For example, EFI code uses EPLATFORM() to generate errors + * resulting from calls to EFI APIs such as + * InstallMultipleProtocolInterfaces(). + * + * EPLATFORM() should not be used for constant platform-generated + * errors; use __einfo_platformify() instead. + */ +#define EPLATFORM( einfo_base, platform, ... ) ( { \ + eplatform_discard ( 0, ##__VA_ARGS__ ); \ + ( ( int ) ( __einfo_error ( einfo_base ) | \ + PLATFORM_TO_ERRNO ( platform ) ) ); } ) +static inline void eplatform_discard ( int dummy __unused, ... ) {} + /** * Declare error * @@ -225,124 +267,10 @@ static inline void euniq_discard ( int dummy __unused, ... ) {} ".align 8\n\t" \ "\n4:\n\t" \ ".previous\n\t" : : \ - "i" ( __einfo_errno ( einfo) ), \ + "i" ( __einfo_errno ( einfo ) ), \ "i" ( __LINE__ ) ); \ __einfo_errno ( einfo ); } ) -/** - * @defgroup pxeerrors PXE error codes - * - * The names, meanings and values of these error codes are defined by - * the PXE specification. - * - * @{ - */ - -/* Generic errors */ -#define PXENV_STATUS_SUCCESS 0x0000 -#define PXENV_STATUS_FAILURE 0x0001 -#define PXENV_STATUS_BAD_FUNC 0x0002 -#define PXENV_STATUS_UNSUPPORTED 0x0003 -#define PXENV_STATUS_KEEP_UNDI 0x0004 -#define PXENV_STATUS_KEEP_ALL 0x0005 -#define PXENV_STATUS_OUT_OF_RESOURCES 0x0006 - -/* ARP errors (0x0010 to 0x001f) */ -#define PXENV_STATUS_ARP_TIMEOUT 0x0011 - -/* Base-Code state errors */ -#define PXENV_STATUS_UDP_CLOSED 0x0018 -#define PXENV_STATUS_UDP_OPEN 0x0019 -#define PXENV_STATUS_TFTP_CLOSED 0x001a -#define PXENV_STATUS_TFTP_OPEN 0x001b - -/* BIOS/system errors (0x0020 to 0x002f) */ -#define PXENV_STATUS_MCOPY_PROBLEM 0x0020 -#define PXENV_STATUS_BIS_INTEGRITY_FAILURE 0x0021 -#define PXENV_STATUS_BIS_VALIDATE_FAILURE 0x0022 -#define PXENV_STATUS_BIS_INIT_FAILURE 0x0023 -#define PXENV_STATUS_BIS_SHUTDOWN_FAILURE 0x0024 -#define PXENV_STATUS_BIS_GBOA_FAILURE 0x0025 -#define PXENV_STATUS_BIS_FREE_FAILURE 0x0026 -#define PXENV_STATUS_BIS_GSI_FAILURE 0x0027 -#define PXENV_STATUS_BIS_BAD_CKSUM 0x0028 - -/* TFTP/MTFTP errors (0x0030 to 0x003f) */ -#define PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS 0x0030 -#define PXENV_STATUS_TFTP_OPEN_TIMEOUT 0x0032 -#define PXENV_STATUS_TFTP_UNKNOWN_OPCODE 0x0033 -#define PXENV_STATUS_TFTP_READ_TIMEOUT 0x0035 -#define PXENV_STATUS_TFTP_ERROR_OPCODE 0x0036 -#define PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION 0x0038 -#define PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION 0x0039 -#define PXENV_STATUS_TFTP_TOO_MANY_PACKAGES 0x003a -#define PXENV_STATUS_TFTP_FILE_NOT_FOUND 0x003b -#define PXENV_STATUS_TFTP_ACCESS_VIOLATION 0x003c -#define PXENV_STATUS_TFTP_NO_MCAST_ADDRESS 0x003d -#define PXENV_STATUS_TFTP_NO_FILESIZE 0x003e -#define PXENV_STATUS_TFTP_INVALID_PACKET_SIZE 0x003f - -/* Reserved errors 0x0040 to 0x004f) */ - -/* DHCP/BOOTP errors (0x0050 to 0x005f) */ -#define PXENV_STATUS_DHCP_TIMEOUT 0x0051 -#define PXENV_STATUS_DHCP_NO_IP_ADDRESS 0x0052 -#define PXENV_STATUS_DHCP_NO_BOOTFILE_NAME 0x0053 -#define PXENV_STATUS_DHCP_BAD_IP_ADDRESS 0x0054 - -/* Driver errors (0x0060 to 0x006f) */ -#define PXENV_STATUS_UNDI_INVALID_FUNCTION 0x0060 -#define PXENV_STATUS_UNDI_MEDIATEST_FAILED 0x0061 -#define PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST 0x0062 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC 0x0063 -#define PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY 0x0064 -#define PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA 0x0065 -#define PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA 0x0066 -#define PXENV_STATUS_UNDI_BAD_MAC_ADDRESS 0x0067 -#define PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM 0x0068 -#define PXENV_STATUS_UNDI_ERROR_SETTING_ISR 0x0069 -#define PXENV_STATUS_UNDI_INVALID_STATE 0x006a -#define PXENV_STATUS_UNDI_TRANSMIT_ERROR 0x006b -#define PXENV_STATUS_UNDI_INVALID_PARAMETER 0x006c - -/* ROM and NBP bootstrap errors (0x0070 to 0x007f) */ -#define PXENV_STATUS_BSTRAP_PROMPT_MENU 0x0074 -#define PXENV_STATUS_BSTRAP_MCAST_ADDR 0x0076 -#define PXENV_STATUS_BSTRAP_MISSING_LIST 0x0077 -#define PXENV_STATUS_BSTRAP_NO_RESPONSE 0x0078 -#define PXENV_STATUS_BSTRAP_FILE_TOO_BIG 0x0079 - -/* Environment NBP errors (0x0080 to 0x008f) */ - -/* Reserved errors (0x0090 to 0x009f) */ - -/* Miscellaneous errors (0x00a0 to 0x00af) */ -#define PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE 0x00a0 -#define PXENV_STATUS_BINL_NO_PXE_SERVER 0x00a1 -#define PXENV_STATUS_NOT_AVAILABLE_IN_PMODE 0x00a2 -#define PXENV_STATUS_NOT_AVAILABLE_IN_RMODE 0x00a3 - -/* BUSD errors (0x00b0 to 0x00bf) */ -#define PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED 0x00b0 - -/* Loader errors (0x00c0 to 0x00cf) */ -#define PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY 0x00c0 -#define PXENV_STATUS_LOADER_NO_BC_ROMID 0x00c1 -#define PXENV_STATUS_LOADER_BAD_BC_ROMID 0x00c2 -#define PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE 0x00c3 -#define PXENV_STATUS_LOADER_NO_UNDI_ROMID 0x00c4 -#define PXENV_STATUS_LOADER_BAD_UNDI_ROMID 0x00c5 -#define PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE 0x00c6 -#define PXENV_STATUS_LOADER_NO_PXE_STRUCT 0x00c8 -#define PXENV_STATUS_LOADER_NO_PXENV_STRUCT 0x00c9 -#define PXENV_STATUS_LOADER_UNDI_START 0x00ca -#define PXENV_STATUS_LOADER_BC_START 0x00cb - -/** @} */ - -/** Derive PXENV_STATUS code from iPXE error number */ -#define PXENV_STATUS( rc ) ( (-(rc)) & 0x00ff ) - /** * @defgroup posixerrors POSIX error codes * @@ -354,409 +282,410 @@ static inline void euniq_discard ( int dummy __unused, ... ) {} /** Operation completed successfully */ #define ENOERR __einfo_error ( EINFO_ENOERR ) -#define EINFO_ENOERR __einfo ( PXENV_STATUS_SUCCESS, 0x00, 0, \ +#define EINFO_ENOERR __einfo ( PLATFORM_ENOERR, 0x00, 0, \ "Operation completed successfully" ) /** Argument list too long */ #define E2BIG __einfo_error ( EINFO_E2BIG ) -#define EINFO_E2BIG __einfo ( PXENV_STATUS_BAD_FUNC, 0x01, 0, \ +#define EINFO_E2BIG __einfo ( PLATFORM_E2BIG, 0x01, 0, \ "Argument list too long" ) /** Permission denied */ #define EACCES __einfo_error ( EINFO_EACCES ) -#define EINFO_EACCES __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x02, 0, \ +#define EINFO_EACCES __einfo ( PLATFORM_EACCES, 0x02, 0, \ "Permission denied" ) /** Address already in use */ #define EADDRINUSE __einfo_error ( EINFO_EADDRINUSE ) -#define EINFO_EADDRINUSE __einfo ( PXENV_STATUS_UDP_OPEN, 0x03, 0, \ +#define EINFO_EADDRINUSE __einfo ( PLATFORM_EADDRINUSE, 0x03, 0, \ "Address already in use" ) /** Address not available */ #define EADDRNOTAVAIL __einfo_error ( EINFO_EADDRNOTAVAIL ) -#define EINFO_EADDRNOTAVAIL __einfo ( PXENV_STATUS_UDP_OPEN, 0x04, 0, \ +#define EINFO_EADDRNOTAVAIL __einfo ( PLATFORM_EADDRNOTAVAIL, 0x04, 0, \ "Address not available" ) /** Address family not supported */ #define EAFNOSUPPORT __einfo_error ( EINFO_EAFNOSUPPORT ) -#define EINFO_EAFNOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x05, 0, \ +#define EINFO_EAFNOSUPPORT __einfo ( PLATFORM_EAFNOSUPPORT, 0x05, 0, \ "Address family not supported" ) /** Resource temporarily unavailable */ #define EAGAIN __einfo_error ( EINFO_EAGAIN ) -#define EINFO_EAGAIN __einfo ( PXENV_STATUS_FAILURE, 0x06, 0, \ +#define EINFO_EAGAIN __einfo ( PLATFORM_EAGAIN, 0x06, 0, \ "Resource temporarily unavailable" ) /** Connection already in progress */ #define EALREADY __einfo_error ( EINFO_EALREADY ) -#define EINFO_EALREADY __einfo ( PXENV_STATUS_UDP_OPEN, 0x07, 0, \ +#define EINFO_EALREADY __einfo ( PLATFORM_EALREADY, 0x07, 0, \ "Connection already in progress" ) /** Bad file descriptor */ #define EBADF __einfo_error ( EINFO_EBADF ) -#define EINFO_EBADF __einfo ( PXENV_STATUS_TFTP_CLOSED, 0x08, 0, \ +#define EINFO_EBADF __einfo ( PLATFORM_EBADF, 0x08, 0, \ "Bad file descriptor" ) /** Bad message */ #define EBADMSG __einfo_error ( EINFO_EBADMSG ) -#define EINFO_EBADMSG __einfo ( PXENV_STATUS_FAILURE, 0x09, 0, \ +#define EINFO_EBADMSG __einfo ( PLATFORM_EBADMSG, 0x09, 0, \ "Bad message" ) /** Device or resource busy */ #define EBUSY __einfo_error ( EINFO_EBUSY ) -#define EINFO_EBUSY __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x0a, 0, \ +#define EINFO_EBUSY __einfo ( PLATFORM_EBUSY, 0x0a, 0, \ "Device or resource busy" ) /** Operation canceled */ #define ECANCELED __einfo_error ( EINFO_ECANCELED ) -#define EINFO_ECANCELED __einfo ( PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE, \ - 0x0b, 0, "Operation canceled" ) +#define EINFO_ECANCELED __einfo ( PLATFORM_ECANCELED, 0x0b, 0, \ + "Operation canceled" ) /** No child processes */ #define ECHILD __einfo_error ( EINFO_ECHILD ) -#define EINFO_ECHILD __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x0c, 0, \ +#define EINFO_ECHILD __einfo ( PLATFORM_ECHILD, 0x0c, 0, \ "No child processes" ) /** Connection aborted */ #define ECONNABORTED __einfo_error ( EINFO_ECONNABORTED ) -#define EINFO_ECONNABORTED \ - __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0d, 0, \ - "Connection aborted" ) +#define EINFO_ECONNABORTED __einfo ( PLATFORM_ECONNABORTED, 0x0d, 0, \ + "Connection aborted" ) /** Connection refused */ #define ECONNREFUSED __einfo_error ( EINFO_ECONNREFUSED ) -#define EINFO_ECONNREFUSED __einfo ( PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION, \ - 0x0e, 0, "Connection refused" ) +#define EINFO_ECONNREFUSED __einfo ( PLATFORM_ECONNREFUSED, 0x0e, 0, \ + "Connection refused" ) /** Connection reset */ #define ECONNRESET __einfo_error ( EINFO_ECONNRESET ) -#define EINFO_ECONNRESET \ - __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, 0x0f, 0, \ - "Connection reset" ) +#define EINFO_ECONNRESET __einfo ( PLATFORM_ECONNRESET, 0x0f, 0, \ + "Connection reset" ) /** Resource deadlock avoided */ #define EDEADLK __einfo_error ( EINFO_EDEADLK ) -#define EINFO_EDEADLK __einfo ( PXENV_STATUS_FAILURE, 0x10, 0, \ +#define EINFO_EDEADLK __einfo ( PLATFORM_EDEADLK, 0x10, 0, \ "Resource deadlock avoided" ) /** Destination address required */ #define EDESTADDRREQ __einfo_error ( EINFO_EDESTADDRREQ ) -#define EINFO_EDESTADDRREQ __einfo ( PXENV_STATUS_BAD_FUNC, 0x11, 0, \ +#define EINFO_EDESTADDRREQ __einfo ( PLATFORM_EDESTADDRREQ, 0x11, 0, \ "Destination address required" ) /** Mathematics argument out of domain of function */ #define EDOM __einfo_error ( EINFO_EDOM ) -#define EINFO_EDOM __einfo ( PXENV_STATUS_FAILURE, 0x12, 0, \ +#define EINFO_EDOM __einfo ( PLATFORM_EDOM, 0x12, 0, \ "Mathematics argument out of domain of function" ) /** Disk quota exceeded */ #define EDQUOT __einfo_error ( EINFO_EDQUOT ) -#define EINFO_EDQUOT __einfo ( PXENV_STATUS_FAILURE, 0x13, 0, \ +#define EINFO_EDQUOT __einfo ( PLATFORM_EDQUOT, 0x13, 0, \ "Disk quote exceeded" ) /** File exists */ #define EEXIST __einfo_error ( EINFO_EEXIST ) -#define EINFO_EEXIST __einfo ( PXENV_STATUS_FAILURE, 0x14, 0, \ +#define EINFO_EEXIST __einfo ( PLATFORM_EEXIST, 0x14, 0, \ "File exists" ) /** Bad address */ #define EFAULT __einfo_error ( EINFO_EFAULT ) -#define EINFO_EFAULT __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x15, 0, \ +#define EINFO_EFAULT __einfo ( PLATFORM_EFAULT, 0x15, 0, \ "Bad address" ) /** File too large */ #define EFBIG __einfo_error ( EINFO_EFBIG ) -#define EINFO_EFBIG __einfo ( PXENV_STATUS_MCOPY_PROBLEM, 0x16, 0, \ +#define EINFO_EFBIG __einfo ( PLATFORM_EFBIG, 0x16, 0, \ "File too large" ) /** Host is unreachable */ #define EHOSTUNREACH __einfo_error ( EINFO_EHOSTUNREACH ) -#define EINFO_EHOSTUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x17, 0, \ +#define EINFO_EHOSTUNREACH __einfo ( PLATFORM_EHOSTUNREACH, 0x17, 0, \ "Host is unreachable" ) /** Identifier removed */ #define EIDRM __einfo_error ( EINFO_EIDRM ) -#define EINFO_EIDRM __einfo ( PXENV_STATUS_FAILURE, 0x18, 0, \ +#define EINFO_EIDRM __einfo ( PLATFORM_EIDRM, 0x18, 0, \ "Identifier removed" ) /** Illegal byte sequence */ #define EILSEQ __einfo_error ( EINFO_EILSEQ ) -#define EINFO_EILSEQ __einfo ( PXENV_STATUS_FAILURE, 0x19, 0, \ +#define EINFO_EILSEQ __einfo ( PLATFORM_EILSEQ, 0x19, 0, \ "Illegal byte sequence" ) /** Operation in progress */ #define EINPROGRESS __einfo_error ( EINFO_EINPROGRESS ) -#define EINFO_EINPROGRESS __einfo ( PXENV_STATUS_FAILURE, 0x1a, 0, \ +#define EINFO_EINPROGRESS __einfo ( PLATFORM_EINPROGRESS, 0x1a, 0, \ "Operation in progress" ) /** Interrupted function call */ #define EINTR __einfo_error ( EINFO_EINTR ) -#define EINFO_EINTR __einfo ( PXENV_STATUS_FAILURE, 0x1b, 0, \ +#define EINFO_EINTR __einfo ( PLATFORM_EINTR, 0x1b, 0, \ "Interrupted function call" ) /** Invalid argument */ #define EINVAL __einfo_error ( EINFO_EINVAL ) -#define EINFO_EINVAL __einfo ( PXENV_STATUS_BAD_FUNC, 0x1c, 0, \ +#define EINFO_EINVAL __einfo ( PLATFORM_EINVAL, 0x1c, 0, \ "Invalid argument" ) /** Input/output error */ #define EIO __einfo_error ( EINFO_EIO ) -#define EINFO_EIO __einfo ( PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION, \ - 0x1d, 0, "Input/output error" ) +#define EINFO_EIO __einfo ( PLATFORM_EIO, 0x1d, 0, \ + "Input/output error" ) /** Socket is connected */ #define EISCONN __einfo_error ( EINFO_EISCONN ) -#define EINFO_EISCONN __einfo ( PXENV_STATUS_UDP_OPEN, 0x1e, 0, \ +#define EINFO_EISCONN __einfo ( PLATFORM_EISCONN, 0x1e, 0, \ "Socket is connected" ) /** Is a directory */ #define EISDIR __einfo_error ( EINFO_EISDIR ) -#define EINFO_EISDIR __einfo ( PXENV_STATUS_FAILURE, 0x1f, 0, \ +#define EINFO_EISDIR __einfo ( PLATFORM_EISDIR, 0x1f, 0, \ "Is a directory" ) /** Too many levels of symbolic links */ #define ELOOP __einfo_error ( EINFO_ELOOP ) -#define EINFO_ELOOP __einfo ( PXENV_STATUS_FAILURE, 0x20, 0, \ +#define EINFO_ELOOP __einfo ( PLATFORM_ELOOP, 0x20, 0, \ "Too many levels of symbolic links" ) /** Too many open files */ #define EMFILE __einfo_error ( EINFO_EMFILE ) -#define EINFO_EMFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x21, 0, \ +#define EINFO_EMFILE __einfo ( PLATFORM_EMFILE, 0x21, 0, \ "Too many open files" ) /** Too many links */ #define EMLINK __einfo_error ( EINFO_EMLINK ) -#define EINFO_EMLINK __einfo ( PXENV_STATUS_FAILURE, 0x22, 0, \ +#define EINFO_EMLINK __einfo ( PLATFORM_EMLINK, 0x22, 0, \ "Too many links" ) /** Message too long */ #define EMSGSIZE __einfo_error ( EINFO_EMSGSIZE ) -#define EINFO_EMSGSIZE __einfo ( PXENV_STATUS_BAD_FUNC, 0x23, 0, \ +#define EINFO_EMSGSIZE __einfo ( PLATFORM_EMSGSIZE, 0x23, 0, \ "Message too long" ) /** Multihop attempted */ #define EMULTIHOP __einfo_error ( EINFO_EMULTIHOP ) -#define EINFO_EMULTIHOP __einfo ( PXENV_STATUS_FAILURE, 0x24, 0, \ +#define EINFO_EMULTIHOP __einfo ( PLATFORM_EMULTIHOP, 0x24, 0, \ "Multihop attempted" ) /** Filename too long */ #define ENAMETOOLONG __einfo_error ( EINFO_ENAMETOOLONG ) -#define EINFO_ENAMETOOLONG __einfo ( PXENV_STATUS_FAILURE, 0x25, 0, \ +#define EINFO_ENAMETOOLONG __einfo ( PLATFORM_ENAMETOOLONG, 0x25, 0, \ "Filename too long" ) /** Network is down */ #define ENETDOWN __einfo_error ( EINFO_ENETDOWN ) -#define EINFO_ENETDOWN __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x26, 0, \ +#define EINFO_ENETDOWN __einfo ( PLATFORM_ENETDOWN, 0x26, 0, \ "Network is down" ) /** Connection aborted by network */ #define ENETRESET __einfo_error ( EINFO_ENETRESET ) -#define EINFO_ENETRESET __einfo ( PXENV_STATUS_FAILURE, 0x27, 0, \ +#define EINFO_ENETRESET __einfo ( PLATFORM_ENETRESET, 0x27, 0, \ "Connection aborted by network" ) /** Network unreachable */ #define ENETUNREACH __einfo_error ( EINFO_ENETUNREACH ) -#define EINFO_ENETUNREACH __einfo ( PXENV_STATUS_ARP_TIMEOUT, 0x28, 0, \ +#define EINFO_ENETUNREACH __einfo ( PLATFORM_ENETUNREACH, 0x28, 0, \ "Network unreachable" ) /** Too many open files in system */ #define ENFILE __einfo_error ( EINFO_ENFILE ) -#define EINFO_ENFILE __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x29, 0, \ +#define EINFO_ENFILE __einfo ( PLATFORM_ENFILE, 0x29, 0, \ "Too many open files in system" ) /** No buffer space available */ #define ENOBUFS __einfo_error ( EINFO_ENOBUFS ) -#define EINFO_ENOBUFS __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x2a, 0, \ +#define EINFO_ENOBUFS __einfo ( PLATFORM_ENOBUFS, 0x2a, 0, \ "No buffer space available" ) /** No message is available on the STREAM head read queue */ #define ENODATA __einfo_error ( EINFO_ENODATA ) -#define EINFO_ENODATA \ - __einfo ( PXENV_STATUS_FAILURE, 0x2b, 0, \ - "No message is available on the STREAM head read queue" ) +#define EINFO_ENODATA __einfo ( PLATFORM_ENODATA, 0x2b, 0, \ + "No message is available on the STREAM " \ + "head read queue" ) /** No such device */ #define ENODEV __einfo_error ( EINFO_ENODEV ) -#define EINFO_ENODEV __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2c, 0, \ +#define EINFO_ENODEV __einfo ( PLATFORM_ENODEV, 0x2c, 0, \ "No such device" ) /** No such file or directory */ #define ENOENT __einfo_error ( EINFO_ENOENT ) -#define EINFO_ENOENT __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x2d, 0, \ +#define EINFO_ENOENT __einfo ( PLATFORM_ENOENT, 0x2d, 0, \ "No such file or directory" ) /** Exec format error */ #define ENOEXEC __einfo_error ( EINFO_ENOEXEC ) -#define EINFO_ENOEXEC __einfo ( PXENV_STATUS_FAILURE, 0x2e, 0, \ +#define EINFO_ENOEXEC __einfo ( PLATFORM_ENOEXEC, 0x2e, 0, \ "Exec format error" ) /** No locks available */ #define ENOLCK __einfo_error ( EINFO_ENOLCK ) -#define EINFO_ENOLCK __einfo ( PXENV_STATUS_FAILURE, 0x2f, 0, \ +#define EINFO_ENOLCK __einfo ( PLATFORM_ENOLCK, 0x2f, 0, \ "No locks available" ) /** Link has been severed */ #define ENOLINK __einfo_error ( EINFO_ENOLINK ) -#define EINFO_ENOLINK __einfo ( PXENV_STATUS_FAILURE, 0x30, 0, \ +#define EINFO_ENOLINK __einfo ( PLATFORM_ENOLINK, 0x30, 0, \ "Link has been severed" ) /** Not enough space */ #define ENOMEM __einfo_error ( EINFO_ENOMEM ) -#define EINFO_ENOMEM __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x31, 0, \ +#define EINFO_ENOMEM __einfo ( PLATFORM_ENOMEM, 0x31, 0, \ "Not enough space" ) /** No message of the desired type */ #define ENOMSG __einfo_error ( EINFO_ENOMSG ) -#define EINFO_ENOMSG __einfo ( PXENV_STATUS_FAILURE, 0x32, 0, \ +#define EINFO_ENOMSG __einfo ( PLATFORM_ENOMSG, 0x32, 0, \ "No message of the desired type" ) /** Protocol not available */ #define ENOPROTOOPT __einfo_error ( EINFO_ENOPROTOOPT ) -#define EINFO_ENOPROTOOPT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x33, 0, \ +#define EINFO_ENOPROTOOPT __einfo ( PLATFORM_ENOPROTOOPT, 0x33, 0, \ "Protocol not available" ) /** No space left on device */ #define ENOSPC __einfo_error ( EINFO_ENOSPC ) -#define EINFO_ENOSPC __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x34, 0, \ +#define EINFO_ENOSPC __einfo ( PLATFORM_ENOSPC, 0x34, 0, \ "No space left on device" ) /** No STREAM resources */ #define ENOSR __einfo_error ( EINFO_ENOSR ) -#define EINFO_ENOSR __einfo ( PXENV_STATUS_OUT_OF_RESOURCES, 0x35, 0, \ +#define EINFO_ENOSR __einfo ( PLATFORM_ENOSR, 0x35, 0, \ "No STREAM resources" ) /** Not a STREAM */ #define ENOSTR __einfo_error ( EINFO_ENOSTR ) -#define EINFO_ENOSTR __einfo ( PXENV_STATUS_FAILURE, 0x36, 0, \ +#define EINFO_ENOSTR __einfo ( PLATFORM_ENOSTR, 0x36, 0, \ "Not a STREAM" ) /** Function not implemented */ #define ENOSYS __einfo_error ( EINFO_ENOSYS ) -#define EINFO_ENOSYS __einfo ( PXENV_STATUS_UNSUPPORTED, 0x37, 0, \ +#define EINFO_ENOSYS __einfo ( PLATFORM_ENOSYS, 0x37, 0, \ "Function not implemented" ) /** The socket is not connected */ #define ENOTCONN __einfo_error ( EINFO_ENOTCONN ) -#define EINFO_ENOTCONN __einfo ( PXENV_STATUS_FAILURE, 0x38, 0, \ +#define EINFO_ENOTCONN __einfo ( PLATFORM_ENOTCONN, 0x38, 0, \ "The socket is not connected" ) /** Not a directory */ #define ENOTDIR __einfo_error ( EINFO_ENOTDIR ) -#define EINFO_ENOTDIR __einfo ( PXENV_STATUS_FAILURE, 0x39, 0, \ +#define EINFO_ENOTDIR __einfo ( PLATFORM_ENOTDIR, 0x39, 0, \ "Not a directory" ) /** Directory not empty */ #define ENOTEMPTY __einfo_error ( EINFO_ENOTEMPTY ) -#define EINFO_ENOTEMPTY __einfo ( PXENV_STATUS_FAILURE, 0x3a, 0, \ +#define EINFO_ENOTEMPTY __einfo ( PLATFORM_ENOTEMPTY, 0x3a, 0, \ "Directory not empty" ) /** Not a socket */ #define ENOTSOCK __einfo_error ( EINFO_ENOTSOCK ) -#define EINFO_ENOTSOCK __einfo ( PXENV_STATUS_FAILURE, 0x3b, 0, \ +#define EINFO_ENOTSOCK __einfo ( PLATFORM_ENOTSOCK, 0x3b, 0, \ "Not a socket" ) /** Operation not supported */ #define ENOTSUP __einfo_error ( EINFO_ENOTSUP ) -#define EINFO_ENOTSUP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3c, 0, \ +#define EINFO_ENOTSUP __einfo ( PLATFORM_ENOTSUP, 0x3c, 0, \ "Operation not supported" ) /** Inappropriate I/O control operation */ #define ENOTTY __einfo_error ( EINFO_ENOTTY ) -#define EINFO_ENOTTY __einfo ( PXENV_STATUS_FAILURE, 0x3d, 0, \ +#define EINFO_ENOTTY __einfo ( PLATFORM_ENOTTY, 0x3d, 0, \ "Inappropriate I/O control operation" ) /** No such device or address */ #define ENXIO __einfo_error ( EINFO_ENXIO ) -#define EINFO_ENXIO __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x3e, 0, \ +#define EINFO_ENXIO __einfo ( PLATFORM_ENXIO, 0x3e, 0, \ "No such device or address" ) /** Operation not supported on socket */ #define EOPNOTSUPP __einfo_error ( EINFO_EOPNOTSUPP ) -#define EINFO_EOPNOTSUPP __einfo ( PXENV_STATUS_UNSUPPORTED, 0x3f, 0, \ +#define EINFO_EOPNOTSUPP __einfo ( PLATFORM_EOPNOTSUPP, 0x3f, 0, \ "Operation not supported on socket" ) /** Value too large to be stored in data type */ #define EOVERFLOW __einfo_error ( EINFO_EOVERFLOW ) -#define EINFO_EOVERFLOW __einfo ( PXENV_STATUS_FAILURE, 0x40, 0, \ +#define EINFO_EOVERFLOW __einfo ( PLATFORM_EOVERFLOW, 0x40, 0, \ "Value too large to be stored in data type" ) /** Operation not permitted */ #define EPERM __einfo_error ( EINFO_EPERM ) -#define EINFO_EPERM __einfo ( PXENV_STATUS_TFTP_ACCESS_VIOLATION, 0x41, 0, \ +#define EINFO_EPERM __einfo ( PLATFORM_EPERM, 0x41, 0, \ "Operation not permitted" ) /** Broken pipe */ #define EPIPE __einfo_error ( EINFO_EPIPE ) -#define EINFO_EPIPE __einfo ( PXENV_STATUS_FAILURE, 0x42, 0, \ +#define EINFO_EPIPE __einfo ( PLATFORM_EPIPE, 0x42, 0, \ "Broken pipe" ) /** Protocol error */ #define EPROTO __einfo_error ( EINFO_EPROTO ) -#define EINFO_EPROTO __einfo ( PXENV_STATUS_FAILURE, 0x43, 0, \ +#define EINFO_EPROTO __einfo ( PLATFORM_EPROTO, 0x43, 0, \ "Protocol error" ) /** Protocol not supported */ #define EPROTONOSUPPORT __einfo_error ( EINFO_EPROTONOSUPPORT ) -#define EINFO_EPROTONOSUPPORT __einfo ( PXENV_STATUS_UNSUPPORTED, 0x44, 0, \ +#define EINFO_EPROTONOSUPPORT __einfo ( PLATFORM_EPROTONOSUPPORT, 0x44, 0, \ "Protocol not supported" ) /** Protocol wrong type for socket */ #define EPROTOTYPE __einfo_error ( EINFO_EPROTOTYPE ) -#define EINFO_EPROTOTYPE __einfo ( PXENV_STATUS_FAILURE, 0x45, 0, \ +#define EINFO_EPROTOTYPE __einfo ( PLATFORM_EPROTOTYPE, 0x45, 0, \ "Protocol wrong type for socket" ) /** Result too large */ #define ERANGE __einfo_error ( EINFO_ERANGE ) -#define EINFO_ERANGE __einfo ( PXENV_STATUS_FAILURE, 0x46, 0, \ +#define EINFO_ERANGE __einfo ( PLATFORM_ERANGE, 0x46, 0, \ "Result too large" ) /** Read-only file system */ #define EROFS __einfo_error ( EINFO_EROFS ) -#define EINFO_EROFS __einfo ( PXENV_STATUS_FAILURE, 0x47, 0, \ +#define EINFO_EROFS __einfo ( PLATFORM_EROFS, 0x47, 0, \ "Read-only file system" ) /** Invalid seek */ #define ESPIPE __einfo_error ( EINFO_ESPIPE ) -#define EINFO_ESPIPE __einfo ( PXENV_STATUS_FAILURE, 0x48, 0, \ +#define EINFO_ESPIPE __einfo ( PLATFORM_ESPIPE, 0x48, 0, \ "Invalid seek" ) /** No such process */ #define ESRCH __einfo_error ( EINFO_ESRCH ) -#define EINFO_ESRCH __einfo ( PXENV_STATUS_TFTP_FILE_NOT_FOUND, 0x49, 0, \ +#define EINFO_ESRCH __einfo ( PLATFORM_ESRCH, 0x49, 0, \ "No such process" ) /** Stale file handle */ #define ESTALE __einfo_error ( EINFO_ESTALE ) -#define EINFO_ESTALE __einfo ( PXENV_STATUS_FAILURE, 0x4a, 0, \ +#define EINFO_ESTALE __einfo ( PLATFORM_ESTALE, 0x4a, 0, \ "Stale file handle" ) /** Timer expired */ #define ETIME __einfo_error ( EINFO_ETIME ) -#define EINFO_ETIME __einfo ( PXENV_STATUS_FAILURE, 0x4b, 0, \ +#define EINFO_ETIME __einfo ( PLATFORM_ETIME, 0x4b, 0, \ "Timer expired" ) /** Connection timed out */ #define ETIMEDOUT __einfo_error ( EINFO_ETIMEDOUT ) -#define EINFO_ETIMEDOUT __einfo ( PXENV_STATUS_TFTP_READ_TIMEOUT, 0x4c, 0, \ +#define EINFO_ETIMEDOUT __einfo ( PLATFORM_ETIMEDOUT, 0x4c, 0, \ "Connection timed out" ) /** Text file busy */ #define ETXTBSY __einfo_error ( EINFO_ETXTBSY ) -#define EINFO_ETXTBSY __einfo ( PXENV_STATUS_FAILURE, 0x4d, 0, \ +#define EINFO_ETXTBSY __einfo ( PLATFORM_ETXTBSY, 0x4d, 0, \ "Text file busy" ) /** Operation would block */ #define EWOULDBLOCK __einfo_error ( EINFO_EWOULDBLOCK ) -#define EINFO_EWOULDBLOCK __einfo ( PXENV_STATUS_TFTP_OPEN, 0x4e, 0, \ +#define EINFO_EWOULDBLOCK __einfo ( PLATFORM_EWOULDBLOCK, 0x4e, 0, \ "Operation would block" ) /** Improper link */ #define EXDEV __einfo_error ( EINFO_EXDEV ) -#define EINFO_EXDEV __einfo ( PXENV_STATUS_FAILURE, 0x4f, 0, \ +#define EINFO_EXDEV __einfo ( PLATFORM_EXDEV, 0x4f, 0, \ "Improper link" ) /** @} */ +/** Platform-generated base error */ +#define EINFO_EPLATFORM __einfo ( 0, 0x7f, 0, "Platform-generated error" ) + extern int errno; #endif /* ERRNO_H */ diff --git a/src/include/ipxe/efi/Protocol/CpuIo.h b/src/include/ipxe/efi/Protocol/CpuIo.h deleted file mode 100644 index 39b82b3b..00000000 --- a/src/include/ipxe/efi/Protocol/CpuIo.h +++ /dev/null @@ -1,48 +0,0 @@ -/** @file - This code abstracts the CPU IO Protocol which installed by some platform or chipset-specific - PEIM that abstracts the processor-visible I/O operations. - - Note: This is a runtime protocol and can be used by runtime drivers after ExitBootServices(). - It is different from the PI 1.2 CPU I/O 2 Protocol, which is a boot services only protocol - and may not be used by runtime drivers after ExitBootServices(). - -Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
-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. - - @par Revision Reference: - CPU IO Protocol is defined in Framework of EFI CPU IO Protocol Spec - Version 0.9. - -**/ - -#ifndef _CPUIO_H_ -#define _CPUIO_H_ - -FILE_LICENCE ( BSD3 ); - -#include - -#define EFI_CPU_IO_PROTOCOL_GUID \ - { \ - 0xB0732526, 0x38C8, 0x4b40, {0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 } \ - } - -// -// Framework CPU IO protocol structure is the same as CPU IO 2 protocol defined in PI 1.2 spec. -// However, there is a significant different between the Framework CPU I/O -// Protocol and the PI 1.2 CPU I/O 2 Protocol. The Framework one is a runtime -// protocol, which means it can be used by runtime drivers after ExitBootServices(). -// The PI one is not runtime safe, so it is a boot services only protocol and may -// not be used by runtime drivers after ExitBootServices(). -// -typedef EFI_CPU_IO2_PROTOCOL EFI_CPU_IO_PROTOCOL; - -extern EFI_GUID gEfiCpuIoProtocolGuid; - -#endif diff --git a/src/include/ipxe/efi/Protocol/CpuIo2.h b/src/include/ipxe/efi/Protocol/CpuIo2.h deleted file mode 100644 index aef8157d..00000000 --- a/src/include/ipxe/efi/Protocol/CpuIo2.h +++ /dev/null @@ -1,144 +0,0 @@ -/** @file - This files describes the CPU I/O 2 Protocol. - - This protocol provides an I/O abstraction for a system processor. This protocol - is used by a PCI root bridge I/O driver to perform memory-mapped I/O and I/O transactions. - The I/O or memory primitives can be used by the consumer of the protocol to materialize - bus-specific configuration cycles, such as the transitional configuration address and data - ports for PCI. Only drivers that require direct access to the entire system should use this - protocol. - - Note: This is a boot-services only protocol and it may not be used by runtime drivers after - ExitBootServices(). It is different from the Framework CPU I/O Protocol, which is a runtime - protocol and can be used by runtime drivers after ExitBootServices(). - - Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
- 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. - - @par Revision Reference: - This Protocol is defined in UEFI Platform Initialization Specification 1.2 - Volume 5: Standards - -**/ - -#ifndef __CPU_IO2_H__ -#define __CPU_IO2_H__ - -FILE_LICENCE ( BSD3 ); - -#define EFI_CPU_IO2_PROTOCOL_GUID \ - { \ - 0xad61f191, 0xae5f, 0x4c0e, {0xb9, 0xfa, 0xe8, 0x69, 0xd2, 0x88, 0xc6, 0x4f} \ - } - -typedef struct _EFI_CPU_IO2_PROTOCOL EFI_CPU_IO2_PROTOCOL; - -/// -/// Enumeration that defines the width of the I/O operation. -/// -typedef enum { - EfiCpuIoWidthUint8, - EfiCpuIoWidthUint16, - EfiCpuIoWidthUint32, - EfiCpuIoWidthUint64, - EfiCpuIoWidthFifoUint8, - EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, - EfiCpuIoWidthFifoUint64, - EfiCpuIoWidthFillUint8, - EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, - EfiCpuIoWidthFillUint64, - EfiCpuIoWidthMaximum -} EFI_CPU_IO_PROTOCOL_WIDTH; - -/** - Enables a driver to access registers in the PI CPU I/O space. - - The Io.Read() and Io.Write() functions enable a driver to access PCI controller - registers in the PI CPU I/O space. - - The I/O operations are carried out exactly as requested. The caller is responsible - for satisfying any alignment and I/O width restrictions that a PI System on a - platform might require. For example on some platforms, width requests of - EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will - be handled by the driver. - - If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, - or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for - each of the Count operations that is performed. - - If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, - EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times on the same Address. - - If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, - EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is - incremented for each of the Count operations that is performed. The read or - write operation is performed Count times from the first element of Buffer. - - @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. - @param[in] Width Signifies the width of the I/O or Memory operation. - @param[in] Address The base address of the I/O operation. - @param[in] Count The number of I/O operations to perform. The number - of bytes moved is Width size * Count, starting at Address. - @param[in, out] Buffer For read operations, the destination buffer to store the results. - For write operations, the source buffer from which to write data. - - @retval EFI_SUCCESS The data was read from or written to the PI system. - @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. - @retval EFI_INVALID_PARAMETER Buffer is NULL. - @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. - @retval EFI_UNSUPPORTED The address range specified by Address, Width, - and Count is not valid for this PI system. - -**/ -typedef -EFI_STATUS -(EFIAPI *EFI_CPU_IO_PROTOCOL_IO_MEM)( - IN EFI_CPU_IO2_PROTOCOL *This, - IN EFI_CPU_IO_PROTOCOL_WIDTH Width, - IN UINT64 Address, - IN UINTN Count, - IN OUT VOID *Buffer - ); - -/// -/// Service for read and write accesses. -/// -typedef struct { - /// - /// This service provides the various modalities of memory and I/O read. - /// - EFI_CPU_IO_PROTOCOL_IO_MEM Read; - /// - /// This service provides the various modalities of memory and I/O write. - /// - EFI_CPU_IO_PROTOCOL_IO_MEM Write; -} EFI_CPU_IO_PROTOCOL_ACCESS; - -/// -/// Provides the basic memory and I/O interfaces that are used to abstract -/// accesses to devices in a system. -/// -struct _EFI_CPU_IO2_PROTOCOL { - /// - /// Enables a driver to access memory-mapped registers in the EFI system memory space. - /// - EFI_CPU_IO_PROTOCOL_ACCESS Mem; - /// - /// Enables a driver to access registers in the EFI CPU I/O space. - /// - EFI_CPU_IO_PROTOCOL_ACCESS Io; -}; - -extern EFI_GUID gEfiCpuIo2ProtocolGuid; - -#endif diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index 3aaac60e..0a21c6e7 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -108,29 +108,27 @@ struct efi_config_table { .required = (_required), \ } -/** Convert a iPXE status code to an EFI status code +/** + * Convert an iPXE status code to an EFI status code * - * FIXME: actually perform some kind of conversion. iPXE error codes - * will be detected as EFI error codes; both have the top bit set, and - * the success return code is zero for both. Anything that just - * reports a numerical error will be OK, anything attempting to - * interpret the value or to display a text equivalent will be - * screwed. + * @v rc iPXE status code + * @ret efirc EFI status code */ -#define RC_TO_EFIRC( rc ) (rc) +#define EFIRC( rc ) ERRNO_TO_PLATFORM ( -(rc) ) -/** Convert an EFI status code to a iPXE status code +/** + * Convert an EFI status code to an iPXE status code * - * FIXME: as above + * @v efirc EFI status code + * @ret rc iPXE status code (before negation) */ -#define EFIRC_TO_RC( efirc ) (efirc) +#define EEFI( efirc ) EPLATFORM ( EINFO_EPLATFORM, efirc ) extern EFI_HANDLE efi_image_handle; extern EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; extern EFI_DEVICE_PATH_PROTOCOL *efi_loaded_image_path; extern EFI_SYSTEM_TABLE *efi_systab; -extern const char * efi_strerror ( EFI_STATUS efirc ); extern const char * efi_guid_ntoa ( EFI_GUID *guid ); extern void dbg_efi_protocols ( EFI_HANDLE handle ); diff --git a/src/include/ipxe/efi/efi_driver.h b/src/include/ipxe/efi/efi_driver.h index e5872ced..d7eec964 100644 --- a/src/include/ipxe/efi/efi_driver.h +++ b/src/include/ipxe/efi/efi_driver.h @@ -44,6 +44,6 @@ struct efi_driver { extern EFI_DEVICE_PATH_PROTOCOL * efi_devpath_end ( EFI_DEVICE_PATH_PROTOCOL *path ); -extern EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ); +extern int efi_driver_install ( struct efi_driver *efidrv ); #endif /* _IPXE_EFI_DRIVER_H */ diff --git a/src/include/ipxe/efi/efi_io.h b/src/include/ipxe/efi/efi_io.h deleted file mode 100644 index 2ed96e10..00000000 --- a/src/include/ipxe/efi/efi_io.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef _IPXE_EFI_IO_H -#define _IPXE_EFI_IO_H - -/** @file - * - * iPXE I/O API for EFI - * - * EFI runs with flat physical addressing, so the various mappings - * between virtual addresses, I/O addresses and bus addresses are all - * no-ops. I/O is handled using the EFI_CPU_IO_PROTOCOL. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#ifdef IOAPI_EFI -#define IOAPI_PREFIX_efi -#else -#define IOAPI_PREFIX_efi __efi_ -#endif - -extern unsigned long long efi_ioread ( volatile void *io_addr, - size_t size ); -extern void efi_iowrite ( unsigned long long data, volatile void *io_addr, - size_t size ); -extern void efi_ioreads ( volatile void *io_addr, void *data, - size_t size, unsigned int count ); -extern void efi_iowrites ( volatile void *io_addr, const void *data, - size_t size, unsigned int count ); - -/* - * Physical<->Bus and Bus<->I/O address mappings - * - * EFI runs with flat physical addressing, so these are all no-ops. - * - */ - -static inline __always_inline unsigned long -IOAPI_INLINE ( efi, phys_to_bus ) ( unsigned long phys_addr ) { - return phys_addr; -} - -static inline __always_inline unsigned long -IOAPI_INLINE ( efi, bus_to_phys ) ( unsigned long bus_addr ) { - return bus_addr; -} - -static inline __always_inline void * -IOAPI_INLINE ( efi, ioremap ) ( unsigned long bus_addr, size_t len __unused ) { - return ( ( void * ) bus_addr ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, iounmap ) ( volatile const void *io_addr __unused ) { - /* Nothing to do */ -} - -static inline __always_inline unsigned long -IOAPI_INLINE ( efi, io_to_bus ) ( volatile const void *io_addr ) { - return ( ( unsigned long ) io_addr ); -} - -/* - * I/O functions - * - */ - -static inline __always_inline uint8_t -IOAPI_INLINE ( efi, readb ) ( volatile uint8_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint16_t -IOAPI_INLINE ( efi, readw ) ( volatile uint16_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint32_t -IOAPI_INLINE ( efi, readl ) ( volatile uint32_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint64_t -IOAPI_INLINE ( efi, readq ) ( volatile uint64_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writeb ) ( uint8_t data, volatile uint8_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writew ) ( uint16_t data, volatile uint16_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writel ) ( uint32_t data, volatile uint32_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, writeq ) ( uint64_t data, volatile uint64_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint8_t -IOAPI_INLINE ( efi, inb ) ( volatile uint8_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint16_t -IOAPI_INLINE ( efi, inw ) ( volatile uint16_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline uint32_t -IOAPI_INLINE ( efi, inl ) ( volatile uint32_t *io_addr ) { - return efi_ioread ( io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outb ) ( uint8_t data, volatile uint8_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outw ) ( uint16_t data, volatile uint16_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outl ) ( uint32_t data, volatile uint32_t *io_addr ) { - efi_iowrite ( data, io_addr, sizeof ( *io_addr ) ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, insb ) ( volatile uint8_t *io_addr, uint8_t *data, - unsigned int count ) { - efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, insw ) ( volatile uint16_t *io_addr, uint16_t *data, - unsigned int count ) { - efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, insl ) ( volatile uint32_t *io_addr, uint32_t *data, - unsigned int count ) { - efi_ioreads ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outsb ) ( volatile uint8_t *io_addr, const uint8_t *data, - unsigned int count ) { - efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outsw ) ( volatile uint16_t *io_addr, const uint16_t *data, - unsigned int count ) { - efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, outsl ) ( volatile uint32_t *io_addr, const uint32_t *data, - unsigned int count ) { - efi_iowrites ( io_addr, data, sizeof ( *io_addr ), count ); -} - -static inline __always_inline void -IOAPI_INLINE ( efi, mb ) ( void ) { - /* Do nothing; EFI readl()/writel() calls already act as - * memory barriers. - */ -} - -#endif /* _IPXE_EFI_IO_H */ diff --git a/src/include/ipxe/efi/efi_pci.h b/src/include/ipxe/efi/efi_pci.h index 6429f210..e6b31970 100644 --- a/src/include/ipxe/efi/efi_pci.h +++ b/src/include/ipxe/efi/efi_pci.h @@ -38,11 +38,11 @@ struct efi_pci_device { extern struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, EFI_HANDLE device ); -extern EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ); +extern int efipci_enable ( struct efi_pci_device *efipci ); extern struct efi_pci_device * efipci_find_efi ( EFI_HANDLE device ); extern struct efi_pci_device * efipci_find ( struct device *dev ); -extern EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, - EFI_HANDLE device ); +extern int efipci_child_add ( struct efi_pci_device *efipci, + EFI_HANDLE device ); extern void efipci_child_del ( struct efi_pci_device *efipci, EFI_HANDLE device ); extern void efipci_destroy ( struct efi_driver *efidrv, diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 514e1f8a..67edcc93 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -148,6 +148,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_skeleton ( ERRFILE_DRIVER | 0x00640000 ) #define ERRFILE_intel ( ERRFILE_DRIVER | 0x00650000 ) #define ERRFILE_myson ( ERRFILE_DRIVER | 0x00660000 ) +#define ERRFILE_intelx ( ERRFILE_DRIVER | 0x00670000 ) #define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 ) #define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 ) @@ -265,6 +266,15 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_nslookup ( ERRFILE_OTHER | 0x00300000 ) #define ERRFILE_efi_snp_hii ( ERRFILE_OTHER | 0x00310000 ) #define ERRFILE_readline ( ERRFILE_OTHER | 0x00320000 ) +#define ERRFILE_efi_bofm ( ERRFILE_OTHER | 0x00330000 ) +#define ERRFILE_efi_console ( ERRFILE_OTHER | 0x00340000 ) +#define ERRFILE_efi_debug ( ERRFILE_OTHER | 0x00350000 ) +#define ERRFILE_efi_download ( ERRFILE_OTHER | 0x00360000 ) +#define ERRFILE_efi_driver ( ERRFILE_OTHER | 0x00370000 ) +#define ERRFILE_efi_file ( ERRFILE_OTHER | 0x00380000 ) +#define ERRFILE_efi_init ( ERRFILE_OTHER | 0x00390000 ) +#define ERRFILE_efi_timer ( ERRFILE_OTHER | 0x003a0000 ) +#define ERRFILE_efi_umalloc ( ERRFILE_OTHER | 0x003b0000 ) /** @} */ diff --git a/src/include/ipxe/errno/efi.h b/src/include/ipxe/errno/efi.h new file mode 100644 index 00000000..e4f9e5fe --- /dev/null +++ b/src/include/ipxe/errno/efi.h @@ -0,0 +1,129 @@ +#ifndef _IPXE_ERRNO_EFI_H +#define _IPXE_ERRNO_EFI_H + +/** + * @file + * + * EFI platform error codes + * + * We derive our platform error codes from the possible values for + * EFI_STATUS defined in the UEFI specification. + * + * EFI_STATUS codes are 32-bit values consisting of a top bit which is + * set for errors and clear for warnings, and a mildly undefined + * code of low bits indicating the precise error/warning code. + * Errors and warnings have completely separate namespaces. + * + * We assume that no EFI_STATUS code will ever be defined which uses + * more than bits 0-6 of the low bits. We then choose to encode our + * platform-specific error by mapping bit 31 of the EFI_STATUS to bit + * 7 of the platform-specific error code, and preserving bits 0-6 + * as-is. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +/** + * Convert platform error code to platform component of iPXE error code + * + * @v platform Platform error code + * @ret errno Platform component of iPXE error code + */ +#define PLATFORM_TO_ERRNO( platform ) \ + ( ( (platform) | ( (platform) >> 24 ) ) & 0xff ) + +/** + * Convert iPXE error code to platform error code + * + * @v errno iPXE error code + * @ret platform Platform error code + */ +#define ERRNO_TO_PLATFORM( errno ) \ + ( ( ( (errno) << 24 ) | (errno) ) & 0x8000007f ) + +/* Platform-specific error codes */ +#define PLATFORM_ENOERR EFI_SUCCESS +#define PLATFORM_E2BIG EFI_BUFFER_TOO_SMALL +#define PLATFORM_EACCES EFI_ACCESS_DENIED +#define PLATFORM_EADDRINUSE EFI_ALREADY_STARTED +#define PLATFORM_EADDRNOTAVAIL EFI_NOT_READY +#define PLATFORM_EAFNOSUPPORT EFI_UNSUPPORTED +#define PLATFORM_EAGAIN EFI_NOT_READY +#define PLATFORM_EALREADY EFI_ALREADY_STARTED +#define PLATFORM_EBADF EFI_INVALID_PARAMETER +#define PLATFORM_EBADMSG EFI_PROTOCOL_ERROR +#define PLATFORM_EBUSY EFI_NO_RESPONSE +#define PLATFORM_ECANCELED EFI_ABORTED +#define PLATFORM_ECHILD EFI_NOT_FOUND +#define PLATFORM_ECONNABORTED EFI_ABORTED +#define PLATFORM_ECONNREFUSED EFI_NO_RESPONSE +#define PLATFORM_ECONNRESET EFI_ABORTED +#define PLATFORM_EDEADLK EFI_NOT_READY +#define PLATFORM_EDESTADDRREQ EFI_PROTOCOL_ERROR +#define PLATFORM_EDOM EFI_INVALID_PARAMETER +#define PLATFORM_EDQUOT EFI_VOLUME_FULL +#define PLATFORM_EEXIST EFI_WRITE_PROTECTED +#define PLATFORM_EFAULT EFI_INVALID_PARAMETER +#define PLATFORM_EFBIG EFI_END_OF_MEDIA +#define PLATFORM_EHOSTUNREACH EFI_NO_RESPONSE +#define PLATFORM_EIDRM EFI_INVALID_PARAMETER +#define PLATFORM_EILSEQ EFI_INVALID_PARAMETER +#define PLATFORM_EINPROGRESS EFI_ALREADY_STARTED +#define PLATFORM_EINTR EFI_NOT_READY +#define PLATFORM_EINVAL EFI_INVALID_PARAMETER +#define PLATFORM_EIO EFI_PROTOCOL_ERROR +#define PLATFORM_EISCONN EFI_ALREADY_STARTED +#define PLATFORM_EISDIR EFI_PROTOCOL_ERROR +#define PLATFORM_ELOOP EFI_VOLUME_CORRUPTED +#define PLATFORM_EMFILE EFI_OUT_OF_RESOURCES +#define PLATFORM_EMLINK EFI_OUT_OF_RESOURCES +#define PLATFORM_EMSGSIZE EFI_BAD_BUFFER_SIZE +#define PLATFORM_EMULTIHOP EFI_INVALID_PARAMETER +#define PLATFORM_ENAMETOOLONG EFI_INVALID_PARAMETER +#define PLATFORM_ENETDOWN EFI_NO_RESPONSE +#define PLATFORM_ENETRESET EFI_ABORTED +#define PLATFORM_ENETUNREACH EFI_NO_RESPONSE +#define PLATFORM_ENFILE EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOBUFS EFI_OUT_OF_RESOURCES +#define PLATFORM_ENODATA EFI_NO_RESPONSE +#define PLATFORM_ENODEV EFI_DEVICE_ERROR +#define PLATFORM_ENOENT EFI_NOT_FOUND +#define PLATFORM_ENOEXEC EFI_LOAD_ERROR +#define PLATFORM_ENOLCK EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOLINK EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOMEM EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOMSG EFI_PROTOCOL_ERROR +#define PLATFORM_ENOPROTOOPT EFI_UNSUPPORTED +#define PLATFORM_ENOSPC EFI_VOLUME_FULL +#define PLATFORM_ENOSR EFI_OUT_OF_RESOURCES +#define PLATFORM_ENOSTR EFI_PROTOCOL_ERROR +#define PLATFORM_ENOSYS EFI_UNSUPPORTED +#define PLATFORM_ENOTCONN EFI_NOT_STARTED +#define PLATFORM_ENOTDIR EFI_VOLUME_CORRUPTED +#define PLATFORM_ENOTEMPTY EFI_VOLUME_CORRUPTED +#define PLATFORM_ENOTSOCK EFI_INVALID_PARAMETER +#define PLATFORM_ENOTSUP EFI_UNSUPPORTED +#define PLATFORM_ENOTTY EFI_UNSUPPORTED +#define PLATFORM_ENXIO EFI_NOT_FOUND +#define PLATFORM_EOPNOTSUPP EFI_UNSUPPORTED +#define PLATFORM_EOVERFLOW EFI_BUFFER_TOO_SMALL +#define PLATFORM_EPERM EFI_ACCESS_DENIED +#define PLATFORM_EPIPE EFI_ABORTED +#define PLATFORM_EPROTO EFI_PROTOCOL_ERROR +#define PLATFORM_EPROTONOSUPPORT EFI_UNSUPPORTED +#define PLATFORM_EPROTOTYPE EFI_INVALID_PARAMETER +#define PLATFORM_ERANGE EFI_BUFFER_TOO_SMALL +#define PLATFORM_EROFS EFI_WRITE_PROTECTED +#define PLATFORM_ESPIPE EFI_END_OF_FILE +#define PLATFORM_ESRCH EFI_NOT_STARTED +#define PLATFORM_ESTALE EFI_PROTOCOL_ERROR +#define PLATFORM_ETIME EFI_TIMEOUT +#define PLATFORM_ETIMEDOUT EFI_TIMEOUT +#define PLATFORM_ETXTBSY EFI_MEDIA_CHANGED +#define PLATFORM_EWOULDBLOCK EFI_NOT_READY +#define PLATFORM_EXDEV EFI_VOLUME_CORRUPTED + +#endif /* _IPXE_ERRNO_EFI_H */ diff --git a/src/include/ipxe/errno/linux.h b/src/include/ipxe/errno/linux.h new file mode 100644 index 00000000..11309b4a --- /dev/null +++ b/src/include/ipxe/errno/linux.h @@ -0,0 +1,113 @@ +#ifndef _IPXE_ERRNO_LINUX_H +#define _IPXE_ERRNO_LINUX_H + +/** + * @file + * + * Linux platform error codes + * + * Linux error codes all fit inside 8 bits, so we just use them + * directly as our platform error codes. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * Convert platform error code to platform component of iPXE error code + * + * @v platform Platform error code + * @ret errno Platform component of iPXE error code + */ +#define PLATFORM_TO_ERRNO( platform ) ( (platform) & 0xff ) + +/** + * Convert iPXE error code to platform error code + * + * @v errno iPXE error code + * @ret platform Platform error code + */ +#define ERRNO_TO_PLATFORM( errno ) ( (errno) & 0xff ) + +/* Platform-specific error codes */ +#define PLATFORM_ENOERR 0 +#define PLATFORM_E2BIG 7 +#define PLATFORM_EACCES 13 +#define PLATFORM_EADDRINUSE 98 +#define PLATFORM_EADDRNOTAVAIL 99 +#define PLATFORM_EAFNOSUPPORT 97 +#define PLATFORM_EAGAIN 11 +#define PLATFORM_EALREADY 114 +#define PLATFORM_EBADF 9 +#define PLATFORM_EBADMSG 74 +#define PLATFORM_EBUSY 16 +#define PLATFORM_ECANCELED 125 +#define PLATFORM_ECHILD 10 +#define PLATFORM_ECONNABORTED 103 +#define PLATFORM_ECONNREFUSED 111 +#define PLATFORM_ECONNRESET 104 +#define PLATFORM_EDEADLK 35 +#define PLATFORM_EDESTADDRREQ 89 +#define PLATFORM_EDOM 33 +#define PLATFORM_EDQUOT 122 +#define PLATFORM_EEXIST 17 +#define PLATFORM_EFAULT 14 +#define PLATFORM_EFBIG 27 +#define PLATFORM_EHOSTUNREACH 113 +#define PLATFORM_EIDRM 43 +#define PLATFORM_EILSEQ 84 +#define PLATFORM_EINPROGRESS 115 +#define PLATFORM_EINTR 4 +#define PLATFORM_EINVAL 22 +#define PLATFORM_EIO 5 +#define PLATFORM_EISCONN 106 +#define PLATFORM_EISDIR 21 +#define PLATFORM_ELOOP 40 +#define PLATFORM_EMFILE 24 +#define PLATFORM_EMLINK 31 +#define PLATFORM_EMSGSIZE 90 +#define PLATFORM_EMULTIHOP 72 +#define PLATFORM_ENAMETOOLONG 36 +#define PLATFORM_ENETDOWN 100 +#define PLATFORM_ENETRESET 102 +#define PLATFORM_ENETUNREACH 101 +#define PLATFORM_ENFILE 23 +#define PLATFORM_ENOBUFS 105 +#define PLATFORM_ENODATA 61 +#define PLATFORM_ENODEV 19 +#define PLATFORM_ENOENT 2 +#define PLATFORM_ENOEXEC 8 +#define PLATFORM_ENOLCK 37 +#define PLATFORM_ENOLINK 67 +#define PLATFORM_ENOMEM 12 +#define PLATFORM_ENOMSG 42 +#define PLATFORM_ENOPROTOOPT 92 +#define PLATFORM_ENOSPC 28 +#define PLATFORM_ENOSR 63 +#define PLATFORM_ENOSTR 60 +#define PLATFORM_ENOSYS 38 +#define PLATFORM_ENOTCONN 107 +#define PLATFORM_ENOTDIR 20 +#define PLATFORM_ENOTEMPTY 39 +#define PLATFORM_ENOTSOCK 88 +#define PLATFORM_ENOTSUP PLATFORM_EOPNOTSUPP +#define PLATFORM_ENOTTY 25 +#define PLATFORM_ENXIO 6 +#define PLATFORM_EOPNOTSUPP 95 +#define PLATFORM_EOVERFLOW 75 +#define PLATFORM_EPERM 1 +#define PLATFORM_EPIPE 32 +#define PLATFORM_EPROTO 71 +#define PLATFORM_EPROTONOSUPPORT 93 +#define PLATFORM_EPROTOTYPE 91 +#define PLATFORM_ERANGE 34 +#define PLATFORM_EROFS 30 +#define PLATFORM_ESPIPE 29 +#define PLATFORM_ESRCH 3 +#define PLATFORM_ESTALE 116 +#define PLATFORM_ETIME 62 +#define PLATFORM_ETIMEDOUT 110 +#define PLATFORM_ETXTBSY 26 +#define PLATFORM_EWOULDBLOCK PLATFORM_EAGAIN +#define PLATFORM_EXDEV 18 + +#endif /* _IPXE_ERRNO_LINUX_H */ diff --git a/src/include/ipxe/io.h b/src/include/ipxe/io.h index b4d88fe8..b8b8aa31 100644 --- a/src/include/ipxe/io.h +++ b/src/include/ipxe/io.h @@ -53,7 +53,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); PROVIDE_SINGLE_API_INLINE ( IOAPI_PREFIX_ ## _subsys, _api_func ) /* Include all architecture-independent I/O API headers */ -#include /* Include all architecture-dependent I/O API headers */ #include diff --git a/src/include/ipxe/net80211.h b/src/include/ipxe/net80211.h index 771872c8..dd8bd228 100644 --- a/src/include/ipxe/net80211.h +++ b/src/include/ipxe/net80211.h @@ -1183,25 +1183,4 @@ static inline u16 net80211_cts_duration ( struct net80211_device *dev, net80211_duration ( dev, size, dev->rates[dev->rate] ) ); } -/** 802.11 device setting tag magic */ -#define NET80211_SETTING_TAG_MAGIC 0x8211 - -/** - * Construct 802.11 setting tag - * - * @v id Unique identifier - * @ret tag Setting tag - */ -#define NET80211_SETTING_TAG( id ) \ - NETDEV_SETTING_TAG ( ( NET80211_SETTING_TAG_MAGIC << 8 ) | (id) ) - -/** SSID setting tag */ -#define NET80211_SETTING_TAG_SSID NET80211_SETTING_TAG ( 0x01 ) - -/** Active scanning setting tag */ -#define NET80211_SETTING_TAG_ACTIVE_SCAN NET80211_SETTING_TAG ( 0x02 ) - -/** Wireless key setting tag */ -#define NET80211_SETTING_TAG_KEY NET80211_SETTING_TAG ( 0x03 ) - #endif diff --git a/src/include/ipxe/net80211_err.h b/src/include/ipxe/net80211_err.h index 2175b143..7df3d0d8 100644 --- a/src/include/ipxe/net80211_err.h +++ b/src/include/ipxe/net80211_err.h @@ -553,81 +553,83 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** Make return status code from 802.11 status code */ #define E80211_STATUS( stat ) \ - EUNIQ ( ( ( stat & 0x20 ) ? EHOSTUNREACH : ECONNREFUSED ), \ - ( stat &0x1f ), \ - ECONNREFUSED_FAILURE, \ - ECONNREFUSED_CAPAB_UNSUPP, \ - ECONNREFUSED_REASSOC_INVALID, \ - ECONNREFUSED_ASSOC_DENIED, \ - ECONNREFUSED_AUTH_ALGO_UNSUPP, \ - ECONNREFUSED_AUTH_SEQ_INVALID, \ - ECONNREFUSED_AUTH_CHALL_INVALID, \ - ECONNREFUSED_AUTH_TIMEOUT, \ - ECONNREFUSED_ASSOC_NO_ROOM, \ - ECONNREFUSED_ASSOC_NEED_RATE, \ - ECONNREFUSED_ASSOC_NEED_SHORT_PMBL, \ - ECONNREFUSED_ASSOC_NEED_PBCC, \ - ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY, \ - ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT, \ - ECONNREFUSED_ASSOC_BAD_POWER, \ - ECONNREFUSED_ASSOC_BAD_CHANNELS, \ - ECONNREFUSED_ASSOC_NEED_SHORT_SLOT, \ - ECONNREFUSED_ASSOC_NEED_DSSS_OFDM, \ - EHOSTUNREACH_QOS_FAILURE, \ - EHOSTUNREACH_QOS_NO_ROOM, \ - EHOSTUNREACH_LINK_IS_HORRIBLE, \ - EHOSTUNREACH_ASSOC_NEED_QOS, \ - EHOSTUNREACH_REQUEST_DECLINED, \ - EHOSTUNREACH_REQUEST_INVALID, \ - EHOSTUNREACH_TS_NOT_CREATED_AGAIN, \ - EHOSTUNREACH_INVALID_IE, \ - EHOSTUNREACH_GROUP_CIPHER_INVALID, \ - EHOSTUNREACH_PAIR_CIPHER_INVALID, \ - EHOSTUNREACH_AKMP_INVALID, \ - EHOSTUNREACH_RSN_VERSION_UNSUPP, \ - EHOSTUNREACH_RSN_CAPAB_INVALID, \ - EHOSTUNREACH_CIPHER_REJECTED, \ - EHOSTUNREACH_TS_NOT_CREATED_WAIT, \ - EHOSTUNREACH_DIRECT_LINK_FORBIDDEN, \ - EHOSTUNREACH_DEST_NOT_PRESENT, \ - EHOSTUNREACH_DEST_NOT_QOS, \ - EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH ) + ( ( (stat) & 0x20 ) ? \ + EUNIQ ( EINFO_EHOSTUNREACH, ( (stat) & 0x1f ), \ + EHOSTUNREACH_QOS_FAILURE, \ + EHOSTUNREACH_QOS_NO_ROOM, \ + EHOSTUNREACH_LINK_IS_HORRIBLE, \ + EHOSTUNREACH_ASSOC_NEED_QOS, \ + EHOSTUNREACH_REQUEST_DECLINED, \ + EHOSTUNREACH_REQUEST_INVALID, \ + EHOSTUNREACH_TS_NOT_CREATED_AGAIN, \ + EHOSTUNREACH_INVALID_IE, \ + EHOSTUNREACH_GROUP_CIPHER_INVALID, \ + EHOSTUNREACH_PAIR_CIPHER_INVALID, \ + EHOSTUNREACH_AKMP_INVALID, \ + EHOSTUNREACH_RSN_VERSION_UNSUPP, \ + EHOSTUNREACH_RSN_CAPAB_INVALID, \ + EHOSTUNREACH_CIPHER_REJECTED, \ + EHOSTUNREACH_TS_NOT_CREATED_WAIT, \ + EHOSTUNREACH_DIRECT_LINK_FORBIDDEN, \ + EHOSTUNREACH_DEST_NOT_PRESENT, \ + EHOSTUNREACH_DEST_NOT_QOS, \ + EHOSTUNREACH_ASSOC_LISTEN_TOO_HIGH ) : \ + EUNIQ ( EINFO_ECONNREFUSED, ( (stat) & 0x1f ), \ + ECONNREFUSED_FAILURE, \ + ECONNREFUSED_CAPAB_UNSUPP, \ + ECONNREFUSED_REASSOC_INVALID, \ + ECONNREFUSED_ASSOC_DENIED, \ + ECONNREFUSED_AUTH_ALGO_UNSUPP, \ + ECONNREFUSED_AUTH_SEQ_INVALID, \ + ECONNREFUSED_AUTH_CHALL_INVALID, \ + ECONNREFUSED_AUTH_TIMEOUT, \ + ECONNREFUSED_ASSOC_NO_ROOM, \ + ECONNREFUSED_ASSOC_NEED_RATE, \ + ECONNREFUSED_ASSOC_NEED_SHORT_PMBL, \ + ECONNREFUSED_ASSOC_NEED_PBCC, \ + ECONNREFUSED_ASSOC_NEED_CHAN_AGILITY, \ + ECONNREFUSED_ASSOC_NEED_SPECTRUM_MGMT, \ + ECONNREFUSED_ASSOC_BAD_POWER, \ + ECONNREFUSED_ASSOC_BAD_CHANNELS, \ + ECONNREFUSED_ASSOC_NEED_SHORT_SLOT, \ + ECONNREFUSED_ASSOC_NEED_DSSS_OFDM ) ) /** Make return status code from 802.11 reason code */ #define E80211_REASON( reas ) \ - EUNIQ ( ( ( reas & 0x20 ) ? ENETRESET : ECONNRESET ), \ - ( reas & 0x1f ), \ - ECONNRESET_UNSPECIFIED, \ - ECONNRESET_AUTH_NO_LONGER_VALID, \ - ECONNRESET_LEAVING, \ - ECONNRESET_INACTIVITY, \ - ECONNRESET_OUT_OF_RESOURCES, \ - ECONNRESET_NEED_AUTH, \ - ECONNRESET_NEED_ASSOC, \ - ECONNRESET_LEAVING_TO_ROAM, \ - ECONNRESET_REASSOC_INVALID, \ - ECONNRESET_BAD_POWER, \ - ECONNRESET_BAD_CHANNELS, \ - ECONNRESET_INVALID_IE, \ - ECONNRESET_MIC_FAILURE, \ - ECONNRESET_4WAY_TIMEOUT, \ - ECONNRESET_GROUPKEY_TIMEOUT, \ - ECONNRESET_4WAY_INVALID, \ - ECONNRESET_GROUP_CIPHER_INVALID, \ - ECONNRESET_PAIR_CIPHER_INVALID, \ - ECONNRESET_AKMP_INVALID, \ - ECONNRESET_RSN_VERSION_INVALID, \ - ECONNRESET_RSN_CAPAB_INVALID, \ - ECONNRESET_8021X_FAILURE, \ - ECONNRESET_CIPHER_REJECTED, \ - ENETRESET_QOS_UNSPECIFIED, \ - ENETRESET_QOS_OUT_OF_RESOURCES, \ - ENETRESET_LINK_IS_HORRIBLE, \ - ENETRESET_INVALID_TXOP, \ - ENETRESET_REQUESTED_LEAVING, \ - ENETRESET_REQUESTED_NO_USE, \ - ENETRESET_REQUESTED_NEED_SETUP, \ - ENETRESET_REQUESTED_TIMEOUT, \ - ENETRESET_CIPHER_UNSUPPORTED ) + ( ( (reas) & 0x20 ) ? \ + EUNIQ ( EINFO_ENETRESET, ( (reas) & 0x1f ), \ + ENETRESET_QOS_UNSPECIFIED, \ + ENETRESET_QOS_OUT_OF_RESOURCES, \ + ENETRESET_LINK_IS_HORRIBLE, \ + ENETRESET_INVALID_TXOP, \ + ENETRESET_REQUESTED_LEAVING, \ + ENETRESET_REQUESTED_NO_USE, \ + ENETRESET_REQUESTED_NEED_SETUP, \ + ENETRESET_REQUESTED_TIMEOUT, \ + ENETRESET_CIPHER_UNSUPPORTED ) : \ + EUNIQ ( EINFO_ECONNRESET, ( (reas) & 0x1f ), \ + ECONNRESET_UNSPECIFIED, \ + ECONNRESET_AUTH_NO_LONGER_VALID, \ + ECONNRESET_LEAVING, \ + ECONNRESET_INACTIVITY, \ + ECONNRESET_OUT_OF_RESOURCES, \ + ECONNRESET_NEED_AUTH, \ + ECONNRESET_NEED_ASSOC, \ + ECONNRESET_LEAVING_TO_ROAM, \ + ECONNRESET_REASSOC_INVALID, \ + ECONNRESET_BAD_POWER, \ + ECONNRESET_BAD_CHANNELS, \ + ECONNRESET_INVALID_IE, \ + ECONNRESET_MIC_FAILURE, \ + ECONNRESET_4WAY_TIMEOUT, \ + ECONNRESET_GROUPKEY_TIMEOUT, \ + ECONNRESET_4WAY_INVALID, \ + ECONNRESET_GROUP_CIPHER_INVALID, \ + ECONNRESET_PAIR_CIPHER_INVALID, \ + ECONNRESET_AKMP_INVALID, \ + ECONNRESET_RSN_VERSION_INVALID, \ + ECONNRESET_RSN_CAPAB_INVALID, \ + ECONNRESET_8021X_FAILURE, \ + ECONNRESET_CIPHER_REJECTED ) ) #endif /* _IPXE_NET80211_ERR_H */ diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index dad4d871..0daa1d62 100644 --- a/src/include/ipxe/netdevice.h +++ b/src/include/ipxe/netdevice.h @@ -346,6 +346,8 @@ struct net_device { size_t max_pkt_len; /** TX packet queue */ struct list_head tx_queue; + /** Deferred TX packet queue */ + struct list_head tx_deferred; /** RX packet queue */ struct list_head rx_queue; /** TX statistics */ @@ -409,41 +411,6 @@ struct net_driver { /** Declare a network driver */ #define __net_driver __table_entry ( NET_DRIVERS, 01 ) -/** Network device setting tag magic - * - * All DHCP option settings are deemed to be valid as network device - * settings. There are also some extra non-DHCP settings (such as - * "mac"), which are marked as being valid network device settings by - * using a magic tag value. - */ -#define NETDEV_SETTING_TAG_MAGIC 0xeb - -/** - * Construct network device setting tag - * - * @v id Unique identifier - * @ret tag Setting tag - */ -#define NETDEV_SETTING_TAG( id ) ( ( NETDEV_SETTING_TAG_MAGIC << 24 ) | (id) ) - -/** - * Check if tag is a network device setting tag - * - * @v tag Setting tag - * @ret is_ours Tag is a network device setting tag - */ -#define IS_NETDEV_SETTING_TAG( tag ) \ - ( ( (tag) >> 24 ) == NETDEV_SETTING_TAG_MAGIC ) - -/** MAC address setting tag */ -#define NETDEV_SETTING_TAG_MAC NETDEV_SETTING_TAG ( 0x01 ) - -/** Bus ID setting tag */ -#define NETDEV_SETTING_TAG_BUS_ID NETDEV_SETTING_TAG ( 0x02 ) - -/** MAC address setting tag */ -#define NETDEV_SETTING_TAG_MACHYP NETDEV_SETTING_TAG ( 0x03 ) - extern struct list_head net_devices; extern struct net_device_operations null_netdev_operations; extern struct settings_operations netdev_settings_operations; @@ -608,6 +575,8 @@ netdev_rx_frozen ( struct net_device *netdev ) { extern void netdev_link_err ( struct net_device *netdev, int rc ); extern void netdev_link_down ( struct net_device *netdev ); extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); +extern void netdev_tx_defer ( struct net_device *netdev, + struct io_buffer *iobuf ); extern void netdev_tx_err ( struct net_device *netdev, struct io_buffer *iobuf, int rc ); extern void netdev_tx_complete_err ( struct net_device *netdev, diff --git a/src/include/ipxe/ocsp.h b/src/include/ipxe/ocsp.h index fe825fd0..387e28f8 100644 --- a/src/include/ipxe/ocsp.h +++ b/src/include/ipxe/ocsp.h @@ -28,6 +28,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define OCSP_STATUS_SIG_REQUIRED 0x05 #define OCSP_STATUS_UNAUTHORIZED 0x06 +struct ocsp_check; + /** An OCSP request */ struct ocsp_request { /** Request builder */ @@ -36,12 +38,29 @@ struct ocsp_request { struct asn1_cursor cert_id; }; +/** An OCSP responder */ +struct ocsp_responder { + /** + * Check if certificate is the responder's certificate + * + * @v ocsp OCSP check + * @v cert Certificate + * @ret difference Difference as returned by memcmp() + */ + int ( * compare ) ( struct ocsp_check *ocsp, + struct x509_certificate *cert ); + /** Responder ID */ + struct asn1_cursor id; +}; + /** An OCSP response */ struct ocsp_response { /** Raw response */ void *data; /** Raw tbsResponseData */ struct asn1_cursor tbs; + /** Responder */ + struct ocsp_responder responder; /** Time at which status is known to be correct */ time_t this_update; /** Time at which newer status information will be available */ diff --git a/src/include/ipxe/process.h b/src/include/ipxe/process.h index 9b757981..2c76ff26 100644 --- a/src/include/ipxe/process.h +++ b/src/include/ipxe/process.h @@ -174,7 +174,7 @@ process_running ( struct process *process ) { * */ #define PERMANENT_PROCESS( name, step ) \ -struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \ +static struct process_descriptor name ## _desc = PROC_DESC_PURE ( step ); \ struct process name __permanent_process = { \ .list = LIST_HEAD_INIT ( name.list ), \ .desc = & name ## _desc, \ diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index 3f887602..9b7404ac 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -38,27 +38,14 @@ struct setting { * The setting tag is a numerical description of the setting * (such as a DHCP option number, or an SMBIOS structure and * field number). - * - * Users can construct tags for settings that are not - * explicitly known to iPXE using the generic syntax for - * numerical settings. For example, the setting name "60" - * will be interpreted as referring to DHCP option 60 (the - * vendor class identifier). - * - * This creates a potential for namespace collisions, since - * the interpretation of the numerical description will vary - * according to the settings block. When a user attempts to - * fetch a generic numerical setting, we need to ensure that - * only the intended settings block interprets the numerical - * description. (For example, we do not want to attempt to - * retrieve the subnet mask from SMBIOS, or the system UUID - * from DHCP.) - * - * This potential problem is resolved by allowing the setting - * tag to include a "magic" value indicating the - * interpretation to be placed upon the numerical description. */ unsigned int tag; + /** Setting scope (or NULL) + * + * For historic reasons, a NULL scope with a non-zero tag + * indicates a DHCPv4 option setting. + */ + struct settings_scope *scope; }; /** Configuration setting table */ @@ -134,12 +121,6 @@ struct settings { struct refcnt *refcnt; /** Name */ const char *name; - /** Tag magic - * - * This value will be ORed in to any numerical tags - * constructed by parse_setting_name(). - */ - unsigned int tag_magic; /** Parent settings block */ struct settings *parent; /** Sibling settings blocks */ @@ -148,8 +129,44 @@ struct settings { struct list_head children; /** Settings block operations */ struct settings_operations *op; + /** Default scope for numerical settings constructed for this block */ + struct settings_scope *default_scope; }; +/** + * A setting scope + * + * Users can construct tags for settings that are not explicitly known + * to iPXE using the generic syntax for numerical settings. For + * example, the setting name "60" will be interpreted as referring to + * DHCP option 60 (the vendor class identifier). + * + * This creates a potential for namespace collisions, since the + * interpretation of the numerical description will vary according to + * the settings block. When a user attempts to fetch a generic + * numerical setting, we need to ensure that only the intended + * settings blocks interpret this numerical description. (For + * example, we do not want to attempt to retrieve the subnet mask from + * SMBIOS, or the system UUID from DHCP.) + * + * This potential problem is resolved by including a user-invisible + * "scope" within the definition of each setting. Settings blocks may + * use this to determine whether or not the setting is applicable. + * Any settings constructed from a numerical description + * (e.g. "smbios/1.4.0") will be assigned the default scope of the + * settings block specified in the description (e.g. "smbios"); this + * provides behaviour matching the user's expectations in most + * circumstances. + */ +struct settings_scope { + /** Dummy field + * + * This is included only to ensure that pointers to different + * scopes always compare differently. + */ + uint8_t dummy; +} __attribute__ (( packed )); + /** * A setting type * @@ -329,17 +346,17 @@ extern struct setting busid_setting __setting ( SETTING_NETDEV ); * @v settings Settings block * @v op Settings block operations * @v refcnt Containing object reference counter, or NULL - * @v tag_magic Tag magic + * @v default_scope Default scope */ static inline void settings_init ( struct settings *settings, struct settings_operations *op, struct refcnt *refcnt, - unsigned int tag_magic ) { + struct settings_scope *default_scope ) { INIT_LIST_HEAD ( &settings->siblings ); INIT_LIST_HEAD ( &settings->children ); settings->op = op; settings->refcnt = refcnt; - settings->tag_magic = tag_magic; + settings->default_scope = default_scope; } /** @@ -351,7 +368,7 @@ static inline void settings_init ( struct settings *settings, static inline void generic_settings_init ( struct generic_settings *generics, struct refcnt *refcnt ) { settings_init ( &generics->settings, &generic_settings_operations, - refcnt, 0 ); + refcnt, NULL ); INIT_LIST_HEAD ( &generics->list ); } diff --git a/src/include/ipxe/smbios.h b/src/include/ipxe/smbios.h index 0765c4e4..aaba6cb1 100644 --- a/src/include/ipxe/smbios.h +++ b/src/include/ipxe/smbios.h @@ -162,7 +162,7 @@ struct smbios { #define SMBIOS_VERSION( major, minor ) ( ( (major) << 8 ) | (minor) ) extern int find_smbios ( struct smbios *smbios ); -extern int find_smbios_structure ( unsigned int type, +extern int find_smbios_structure ( unsigned int type, unsigned int instance, struct smbios_structure *structure ); extern int read_smbios_structure ( struct smbios_structure *structure, void *data, size_t len ); diff --git a/src/include/stddef.h b/src/include/stddef.h index 83a0f0ed..bf792771 100644 --- a/src/include/stddef.h +++ b/src/include/stddef.h @@ -23,7 +23,10 @@ FILE_LICENCE ( GPL2_ONLY ); /* __WCHAR_TYPE__ is defined by gcc and will change if -fshort-wchar is used */ #ifndef __WCHAR_TYPE__ -#define __WCHAR_TYPE__ long int +#define __WCHAR_TYPE__ uint16_t +#endif +#ifndef __WINT_TYPE__ +#define __WINT_TYPE__ int #endif typedef __WCHAR_TYPE__ wchar_t; typedef __WINT_TYPE__ wint_t; diff --git a/src/interface/efi/efi_bofm.c b/src/interface/efi/efi_bofm.c index c313d2e9..8a8489bd 100644 --- a/src/interface/efi/efi_bofm.c +++ b/src/interface/efi/efi_bofm.c @@ -181,7 +181,7 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, /* Create corresponding PCI device, if any */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { - efirc = EFI_UNSUPPORTED; + rc = -ENOTSUP; goto err_not_pci; } @@ -189,16 +189,15 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, if ( ( rc = bofm_find_driver ( &efipci->pci ) ) != 0 ) { DBGCP ( efidrv, "EFIBOFM " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); - efirc = EFI_UNSUPPORTED; goto err_no_driver; } /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM " "protocol\n", PCI_ARGS ( &efipci->pci ) ); - efirc = EFI_UNSUPPORTED; goto err_not_bofm; } @@ -207,9 +206,10 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, 0x04 /* Can change MAC */, 0x00 /* No iSCSI */, 0x02 /* Version */ ))!=0){ + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not register " "support: %s\n", PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); + strerror ( rc ) ); goto err_cannot_register; } @@ -226,7 +226,7 @@ efi_bofm_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, err_no_driver: efipci_destroy ( efidrv, efipci ); err_not_pci: - return efirc; + return EFIRC ( rc ); } /** @@ -254,25 +254,27 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, struct efi_pci_device *efipci; IBM_BOFM_TABLE *bofmtab; IBM_BOFM_TABLE *bofmtab2; - EFI_STATUS efirc; int bofmrc; + EFI_STATUS efirc; + int rc; DBGCP ( efidrv, "EFIBOFM DRIVER_START %p (%p)\n", device, child ); /* Create corresponding PCI device */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { - efirc = EFI_OUT_OF_RESOURCES; + rc = -ENOMEM; goto err_create; } /* Enable PCI device */ - if ( ( efirc = efipci_enable ( efipci ) ) != 0 ) + if ( ( rc = efipci_enable ( efipci ) ) != 0 ) goto err_enable; /* Locate BOFM protocol */ if ( ( efirc = bs->LocateProtocol ( &bofm1_protocol_guid, NULL, &bofm1.interface ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " cannot find BOFM " "protocol\n", PCI_ARGS ( &efipci->pci ) ); goto err_locate_bofm; @@ -324,17 +326,19 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, if ( bofmtab2 ) { if ( ( efirc = bofm2.bofm2->SetStatus ( bofm2.bofm2, device, FALSE, bofmrc ) ) != 0){ + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set " "BOFM2 status: %s\n", PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); + strerror ( rc ) ); goto err_set_status; } } else { if ( ( efirc = bofm1.bofm1->SetStatus ( bofm1.bofm1, device, FALSE, bofmrc ) ) != 0){ + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIBOFM " PCI_FMT " could not set " "BOFM status: %s\n", PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); + strerror ( rc ) ); goto err_set_status; } } @@ -350,7 +354,7 @@ static EFI_STATUS EFIAPI efi_bofm_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, err_enable: efipci_destroy ( efidrv, efipci ); err_create: - return efirc; + return EFIRC ( rc ); } /** @@ -385,12 +389,12 @@ static struct efi_driver efi_bofm_driver = */ static void efi_bofm_driver_init ( void ) { struct efi_driver *efidrv = &efi_bofm_driver; - EFI_STATUS efirc; + int rc; /* Install driver */ - if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) { + if ( ( rc = efi_driver_install ( efidrv ) ) != 0 ) { DBGC ( efidrv, "EFIBOFM could not install driver: %s\n", - efi_strerror ( efirc ) ); + strerror ( rc ) ); return; } diff --git a/src/interface/efi/efi_console.c b/src/interface/efi/efi_console.c index a30ca301..d86d30c9 100644 --- a/src/interface/efi/efi_console.c +++ b/src/interface/efi/efi_console.c @@ -20,6 +20,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include +#include #include #include #include @@ -227,6 +229,7 @@ static int efi_getchar ( void ) { const char *ansi_seq; EFI_INPUT_KEY key; EFI_STATUS efirc; + int rc; /* If we are mid-sequence, pass out the next byte */ if ( *ansi_input ) @@ -234,8 +237,8 @@ static int efi_getchar ( void ) { /* Read key from real EFI console */ if ( ( efirc = conin->ReadKeyStroke ( conin, &key ) ) != 0 ) { - DBG ( "EFI could not read keystroke: %s\n", - efi_strerror ( efirc ) ); + rc = -EEFI ( efirc ); + DBG ( "EFI could not read keystroke: %s\n", strerror ( rc ) ); return 0; } DBG2 ( "EFI read key stroke with unicode %04x scancode %04x\n", diff --git a/src/interface/efi/efi_debug.c b/src/interface/efi/efi_debug.c index a7ba7e2e..4ed66607 100644 --- a/src/interface/efi/efi_debug.c +++ b/src/interface/efi/efi_debug.c @@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -67,12 +68,14 @@ void dbg_efi_protocols ( EFI_HANDLE handle ) { UINTN count; unsigned int i; EFI_STATUS efirc; + int rc; /* Retrieve list of protocols */ if ( ( efirc = bs->ProtocolsPerHandle ( handle, &protocols, &count ) ) != 0 ) { + rc = -EEFI ( efirc ); printf ( "EFI could not retrieve protocols for %p: %s\n", - handle, efi_strerror ( efirc ) ); + handle, strerror ( rc ) ); return; } diff --git a/src/interface/efi/efi_download.c b/src/interface/efi/efi_download.c index 7b19ad3a..80279f7f 100644 --- a/src/interface/efi/efi_download.c +++ b/src/interface/efi/efi_download.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -59,7 +60,7 @@ struct efi_download_file { */ static void efi_download_close ( struct efi_download_file *file, int rc ) { - file->finish_callback ( file->context, RC_TO_EFIRC ( rc ) ); + file->finish_callback ( file->context, EFIRC ( rc ) ); intf_shutdown ( &file->xfer, rc ); } @@ -77,6 +78,7 @@ static int efi_download_deliver_iob ( struct efi_download_file *file, struct xfer_metadata *meta ) { EFI_STATUS efirc; size_t len = iob_len ( iobuf ); + int rc; /* Calculate new buffer position */ if ( meta->flags & XFER_FL_ABS_OFFSET ) @@ -84,14 +86,21 @@ static int efi_download_deliver_iob ( struct efi_download_file *file, file->pos += meta->offset; /* Call out to the data handler */ - efirc = file->data_callback ( file->context, iobuf->data, - len, file->pos ); + if ( ( efirc = file->data_callback ( file->context, iobuf->data, + len, file->pos ) ) != 0 ) { + rc = -EEFI ( efirc ); + goto err_callback; + } /* Update current buffer position */ file->pos += len; + /* Success */ + rc = 0; + + err_callback: free_iob ( iobuf ); - return EFIRC_TO_RC ( efirc ); + return rc; } /** Data transfer interface operations */ @@ -135,7 +144,7 @@ efi_download_start ( IPXE_DOWNLOAD_PROTOCOL *This __unused, rc = xfer_open ( &file->xfer, LOCATION_URI_STRING, Url ); if ( rc ) { free ( file ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } file->pos = 0; @@ -162,7 +171,7 @@ efi_download_abort ( IPXE_DOWNLOAD_PROTOCOL *This __unused, EFI_STATUS Status ) { struct efi_download_file *file = File; - efi_download_close ( file, EFIRC_TO_RC ( Status ) ); + efi_download_close ( file, -EEFI ( Status ) ); return EFI_SUCCESS; } @@ -195,6 +204,7 @@ static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface = { int efi_download_install ( EFI_HANDLE *handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; + int rc; efirc = bs->InstallMultipleProtocolInterfaces ( handle, @@ -202,9 +212,10 @@ int efi_download_install ( EFI_HANDLE *handle ) { &ipxe_download_protocol_interface, NULL ); if ( efirc ) { + rc = -EEFI ( efirc ); DBG ( "Could not install download protocol: %s\n", - efi_strerror ( efirc ) ); - return EFIRC_TO_RC ( efirc ); + strerror ( rc ) ); + return rc; } return 0; diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c index deb3cf2c..13ed1f50 100644 --- a/src/interface/efi/efi_driver.c +++ b/src/interface/efi/efi_driver.c @@ -21,6 +21,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include +#include #include #include #include @@ -122,11 +124,12 @@ efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, * @v efidrv EFI driver * @ret efirc EFI status code */ -EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ) { +int efi_driver_install ( struct efi_driver *efidrv ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_DRIVER_BINDING_PROTOCOL *driver = &efidrv->driver; EFI_COMPONENT_NAME2_PROTOCOL *wtf = &efidrv->wtf; EFI_STATUS efirc; + int rc; /* Configure driver binding protocol */ driver->ImageHandle = efi_image_handle; @@ -148,9 +151,10 @@ EFI_STATUS efi_driver_install ( struct efi_driver *efidrv ) { &efi_driver_binding_protocol_guid, driver, &efi_component_name2_protocol_guid, wtf, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efidrv, "EFIDRV %s could not install protocol: %s\n", - efidrv->name, efi_strerror ( efirc ) ); - return efirc; + efidrv->name, strerror ( rc ) ); + return rc; } DBGC ( efidrv, "EFIDRV %s installed\n", efidrv->name ); diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c index 6f9d44f8..4c482d2e 100644 --- a/src/interface/efi/efi_file.c +++ b/src/interface/efi/efi_file.c @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -549,6 +550,7 @@ static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol = { int efi_file_install ( EFI_HANDLE *handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; + int rc; /* Install the simple file system protocol and the block I/O * protocol. We don't have a block device, but large parts of @@ -563,9 +565,10 @@ int efi_file_install ( EFI_HANDLE *handle ) { &efi_block_io_protocol, &efi_simple_file_system_protocol_guid, &efi_simple_file_system_protocol, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( handle, "Could not install simple file system protocol: " - "%s\n", efi_strerror ( efirc ) ); - return EFIRC_TO_RC ( efirc ); + "%s\n", strerror ( rc ) ); + return rc; } return 0; diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index e40de4dd..2f6ca89c 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include @@ -94,6 +95,7 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, void *loaded_image; void *loaded_image_path; EFI_STATUS efirc; + int rc; /* Store image handle and system table pointer for future use */ efi_image_handle = image_handle; @@ -149,8 +151,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, &efi_loaded_image_protocol_guid, &loaded_image, image_handle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( systab, "EFI could not get loaded image protocol: %s", - efi_strerror ( efirc ) ); + strerror ( rc ) ); return efirc; } efi_loaded_image = loaded_image; @@ -162,8 +165,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, &efi_loaded_image_device_path_protocol_guid, &loaded_image_path, image_handle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( systab, "EFI could not get loaded image device path " - "protocol: %s", efi_strerror ( efirc ) ); + "protocol: %s", strerror ( rc ) ); return efirc; } efi_loaded_image_path = loaded_image_path; @@ -179,8 +183,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, if ( ( efirc = bs->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, efi_shutdown_hook, NULL, &efi_shutdown_event ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( systab, "EFI could not create ExitBootServices event: " - "%s\n", efi_strerror ( efirc ) ); + "%s\n", strerror ( rc ) ); return efirc; } diff --git a/src/interface/efi/efi_io.c b/src/interface/efi/efi_io.c deleted file mode 100644 index a620d6e4..00000000 --- a/src/interface/efi/efi_io.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown . - * - * 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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include -#include -#include -#include - -/** @file - * - * iPXE I/O API for EFI - * - */ - -/** CPU I/O protocol */ -static EFI_CPU_IO_PROTOCOL *cpu_io; -EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io ); - -/** Maximum address that can be used for port I/O */ -#define MAX_PORT_ADDRESS 0xffff - -/** - * Determine whether or not address is a port I/O address - * - * @v io_addr I/O address - * @v is_port I/O address is a port I/O address - */ -#define IS_PORT_ADDRESS(io_addr) \ - ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS ) - -/** - * Determine EFI CPU I/O width code - * - * @v size Size of value - * @ret width EFI width code - * - * Someone at Intel clearly gets paid by the number of lines of code - * they write. No-one should ever be able to make I/O this - * convoluted. The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite - * idiocy. - */ -static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) { - switch ( size ) { - case 1 : return EfiCpuIoWidthFifoUint8; - case 2 : return EfiCpuIoWidthFifoUint16; - case 4 : return EfiCpuIoWidthFifoUint32; - case 8 : return EfiCpuIoWidthFifoUint64; - default : - assert ( 0 ); - /* I wonder what this will actually do... */ - return EfiCpuIoWidthMaximum; - } -} - -/** - * Read from device - * - * @v io_addr I/O address - * @v size Size of value - * @ret data Value read - */ -unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) { - EFI_CPU_IO_PROTOCOL_IO_MEM read; - unsigned long long data = 0; - EFI_STATUS efirc; - - read = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Read : cpu_io->Mem.Read ); - - if ( ( efirc = read ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, 1, - ( void * ) &data ) ) != 0 ) { - DBG ( "EFI I/O read at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - return -1ULL; - } - - return data; -} - -/** - * Write to device - * - * @v data Value to write - * @v io_addr I/O address - * @v size Size of value - */ -void efi_iowrite ( unsigned long long data, volatile void *io_addr, - size_t size ) { - EFI_CPU_IO_PROTOCOL_IO_MEM write; - EFI_STATUS efirc; - - write = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Write : cpu_io->Mem.Write ); - - if ( ( efirc = write ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, 1, - ( void * ) &data ) ) != 0 ) { - DBG ( "EFI I/O write at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - } -} - -/** - * String read from device - * - * @v io_addr I/O address - * @v data Data buffer - * @v size Size of values - * @v count Number of values to read - */ -void efi_ioreads ( volatile void *io_addr, void *data, - size_t size, unsigned int count ) { - EFI_CPU_IO_PROTOCOL_IO_MEM read; - EFI_STATUS efirc; - - read = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Read : cpu_io->Mem.Read ); - - if ( ( efirc = read ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, count, - ( void * ) data ) ) != 0 ) { - DBG ( "EFI I/O string read at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - } -} - -/** - * String write to device - * - * @v io_addr I/O address - * @v data Data buffer - * @v size Size of values - * @v count Number of values to write - */ -void efi_iowrites ( volatile void *io_addr, const void *data, - size_t size, unsigned int count ) { - EFI_CPU_IO_PROTOCOL_IO_MEM write; - EFI_STATUS efirc; - - write = ( IS_PORT_ADDRESS ( io_addr ) ? - cpu_io->Io.Write : cpu_io->Mem.Write ); - - if ( ( efirc = write ( cpu_io, efi_width ( size ), - ( intptr_t ) io_addr, count, - ( void * ) data ) ) != 0 ) { - DBG ( "EFI I/O write at %p failed: %s\n", - io_addr, efi_strerror ( efirc ) ); - } -} - -/** - * Wait for I/O-mapped operation to complete - * - */ -static void efi_iodelay ( void ) { - /* Write to non-existent port. Probably x86-only. */ - outb ( 0, 0x80 ); -} - -/** - * Get memory map - * - * Can't be done on EFI so return an empty map - * - * @v memmap Memory map to fill in - */ -static void efi_get_memmap ( struct memory_map *memmap ) { - memmap->count = 0; -} - -PROVIDE_IOAPI_INLINE ( efi, phys_to_bus ); -PROVIDE_IOAPI_INLINE ( efi, bus_to_phys ); -PROVIDE_IOAPI_INLINE ( efi, ioremap ); -PROVIDE_IOAPI_INLINE ( efi, iounmap ); -PROVIDE_IOAPI_INLINE ( efi, io_to_bus ); -PROVIDE_IOAPI_INLINE ( efi, readb ); -PROVIDE_IOAPI_INLINE ( efi, readw ); -PROVIDE_IOAPI_INLINE ( efi, readl ); -PROVIDE_IOAPI_INLINE ( efi, readq ); -PROVIDE_IOAPI_INLINE ( efi, writeb ); -PROVIDE_IOAPI_INLINE ( efi, writew ); -PROVIDE_IOAPI_INLINE ( efi, writel ); -PROVIDE_IOAPI_INLINE ( efi, writeq ); -PROVIDE_IOAPI_INLINE ( efi, inb ); -PROVIDE_IOAPI_INLINE ( efi, inw ); -PROVIDE_IOAPI_INLINE ( efi, inl ); -PROVIDE_IOAPI_INLINE ( efi, outb ); -PROVIDE_IOAPI_INLINE ( efi, outw ); -PROVIDE_IOAPI_INLINE ( efi, outl ); -PROVIDE_IOAPI_INLINE ( efi, insb ); -PROVIDE_IOAPI_INLINE ( efi, insw ); -PROVIDE_IOAPI_INLINE ( efi, insl ); -PROVIDE_IOAPI_INLINE ( efi, outsb ); -PROVIDE_IOAPI_INLINE ( efi, outsw ); -PROVIDE_IOAPI_INLINE ( efi, outsl ); -PROVIDE_IOAPI ( efi, iodelay, efi_iodelay ); -PROVIDE_IOAPI_INLINE ( efi, mb ); -PROVIDE_IOAPI ( efi, get_memmap, efi_get_memmap ); diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c index 0288cf32..d6095d3e 100644 --- a/src/interface/efi/efi_pci.c +++ b/src/interface/efi/efi_pci.c @@ -57,13 +57,15 @@ static unsigned long efipci_address ( struct pci_device *pci, int efipci_read ( struct pci_device *pci, unsigned long location, void *value ) { EFI_STATUS efirc; + int rc; if ( ( efirc = efipci->Pci.Read ( efipci, EFIPCI_WIDTH ( location ), efipci_address ( pci, location ), 1, value ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFIPCI config read from " PCI_FMT " offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), - EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) ); + EFIPCI_OFFSET ( location ), strerror ( rc ) ); return -EIO; } @@ -73,13 +75,15 @@ int efipci_read ( struct pci_device *pci, unsigned long location, int efipci_write ( struct pci_device *pci, unsigned long location, unsigned long value ) { EFI_STATUS efirc; + int rc; if ( ( efirc = efipci->Pci.Write ( efipci, EFIPCI_WIDTH ( location ), efipci_address ( pci, location ), 1, &value ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFIPCI config write to " PCI_FMT " offset %02lx " "failed: %s\n", PCI_ARGS ( pci ), - EFIPCI_OFFSET ( location ), efi_strerror ( efirc ) ); + EFIPCI_OFFSET ( location ), strerror ( rc ) ); return -EIO; } @@ -149,6 +153,7 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, efidrv->driver.DriverBindingHandle, device, EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){ + rc = -EEFI ( efirc ); DBGCP ( efipci, "EFIPCI device %p is not a PCI device\n", device ); goto err_open_protocol; @@ -160,8 +165,9 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, &pci_segment, &pci_bus, &pci_dev, &pci_fn ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efipci, "EFIPCI device %p could not get PCI " - "location: %s\n", device, efi_strerror ( efirc ) ); + "location: %s\n", device, strerror ( rc ) ); goto err_get_location; } DBGC2 ( efipci, "EFIPCI device %p is PCI %04lx:%02lx:%02lx.%lx\n", @@ -185,6 +191,7 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, efidrv->driver.DriverBindingHandle, device, EFI_OPEN_PROTOCOL_BY_DRIVER )) !=0 ){ + rc = -EEFI ( efirc ); DBGC ( efipci, "EFIPCI " PCI_FMT " has no device path\n", PCI_ARGS ( &efipci->pci ) ); goto err_no_device_path; @@ -213,9 +220,9 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, * Enable EFI PCI device * * @v efipci EFI PCI device - * @ret efirc EFI status code + * @ret rc Return status code */ -EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) { +int efipci_enable ( struct efi_pci_device *efipci ) { EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io; /* Try to enable I/O cycles, memory cycles, and bus mastering. @@ -273,8 +280,7 @@ struct efi_pci_device * efipci_find ( struct device *dev ) { * @v device EFI child device * @ret efirc EFI status code */ -EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, - EFI_HANDLE device ) { +int efipci_child_add ( struct efi_pci_device *efipci, EFI_HANDLE device ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; struct efi_driver *efidrv = efipci->efidrv; union { @@ -282,6 +288,7 @@ EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, void *interface; } pci_io; EFI_STATUS efirc; + int rc; /* Re-open the PCI_IO_PROTOCOL */ if ( ( efirc = bs->OpenProtocol ( efipci->device, @@ -291,9 +298,10 @@ EFI_STATUS efipci_child_add ( struct efi_pci_device *efipci, device, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( efipci, "EFIPCI " PCI_FMT " could not add child: %s\n", - PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); - return efirc; + PCI_ARGS ( &efipci->pci ), strerror ( rc ) ); + return rc; } return 0; @@ -355,7 +363,6 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); struct efi_pci_device *efipci; - EFI_STATUS efirc; int rc; DBGCP ( efidrv, "EFIPCI DRIVER_SUPPORTED %p (%p)\n", device, child ); @@ -364,7 +371,7 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { /* Non-PCI devices are simply unsupported */ - efirc = EFI_UNSUPPORTED; + rc = -ENOTSUP; goto err_not_pci; } @@ -372,7 +379,6 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) { DBGCP ( efipci, "EFIPCI " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); - efirc = EFI_UNSUPPORTED; goto err_no_driver; } @@ -387,7 +393,7 @@ efipci_supported ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, err_no_driver: efipci_destroy ( efidrv, efipci ); err_not_pci: - return efirc; + return EFIRC ( rc ); } /** @@ -404,7 +410,6 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, struct efi_driver *efidrv = container_of ( driver, struct efi_driver, driver ); struct efi_pci_device *efipci; - EFI_STATUS efirc; int rc; DBGC ( efidrv, "EFIPCI DRIVER_START %p (%p)\n", device, child ); @@ -412,7 +417,7 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, /* Create corresponding PCI device */ efipci = efipci_create ( efidrv, device ); if ( ! efipci ) { - efirc = EFI_OUT_OF_RESOURCES; + rc = -ENOMEM; goto err_create; } @@ -420,12 +425,11 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, if ( ( rc = pci_find_driver ( &efipci->pci ) ) != 0 ) { DBGC ( efipci, "EFIPCI " PCI_FMT " has no driver\n", PCI_ARGS ( &efipci->pci ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_find_driver; } /* Enable PCI device */ - if ( ( efirc = efipci_enable ( efipci ) ) != 0 ) + if ( ( rc = efipci_enable ( efipci ) ) != 0 ) goto err_enable; /* Probe driver */ @@ -433,7 +437,6 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, DBGC ( efipci, "EFIPCI " PCI_FMT " could not probe driver " "\"%s\": %s\n", PCI_ARGS ( &efipci->pci ), efipci->pci.id->name, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_probe; } @@ -445,7 +448,7 @@ efipci_start ( EFI_DRIVER_BINDING_PROTOCOL *driver, EFI_HANDLE device, err_find_driver: efipci_destroy ( efidrv, efipci ); err_create: - return efirc; + return EFIRC ( rc ); } /** @@ -494,12 +497,12 @@ static struct efi_driver efipci_driver = */ static void efipci_driver_startup ( void ) { struct efi_driver *efidrv = &efipci_driver; - EFI_STATUS efirc; + int rc; /* Install driver */ - if ( ( efirc = efi_driver_install ( efidrv ) ) != 0 ) { + if ( ( rc = efi_driver_install ( efidrv ) ) != 0 ) { DBGC ( efidrv, "EFIPCI could not install driver: %s\n", - efi_strerror ( efirc ) ); + strerror ( rc ) ); return; } diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 95e39b7d..adeb38de 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -177,7 +177,7 @@ efi_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not open %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } snpdev->mode.State = EfiSimpleNetworkInitialized; @@ -206,7 +206,7 @@ efi_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ext_verify ) { if ( ( rc = netdev_open ( snpdev->netdev ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not reopen %s: %s\n", snpdev, snpdev->netdev->name, strerror ( rc ) ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } snpdev->mode.State = EfiSimpleNetworkInitialized; @@ -366,7 +366,7 @@ efi_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, BOOLEAN ipv6, ip, mac ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not hash %s: %s\n", snpdev, ip_str, strerror ( rc ) ); - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } return 0; @@ -490,7 +490,6 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, struct io_buffer *iobuf; size_t payload_len; int rc; - EFI_STATUS efirc; DBGC2 ( snpdev, "SNPDEV %p TRANSMIT %p+%lx", snpdev, data, ( ( unsigned long ) len ) ); @@ -515,25 +514,25 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, DBGC ( snpdev, "SNPDEV %p TX invalid header length " "%ld\n", snpdev, ( ( unsigned long ) ll_header_len ) ); - efirc = EFI_INVALID_PARAMETER; + rc = -EINVAL; goto err_sanity; } if ( len < ll_header_len ) { DBGC ( snpdev, "SNPDEV %p invalid packet length %ld\n", snpdev, ( ( unsigned long ) len ) ); - efirc = EFI_BUFFER_TOO_SMALL; + rc = -EINVAL; goto err_sanity; } if ( ! ll_dest ) { DBGC ( snpdev, "SNPDEV %p TX missing destination " "address\n", snpdev ); - efirc = EFI_INVALID_PARAMETER; + rc = -EINVAL; goto err_sanity; } if ( ! net_proto ) { DBGC ( snpdev, "SNPDEV %p TX missing network " "protocol\n", snpdev ); - efirc = EFI_INVALID_PARAMETER; + rc = -EINVAL; goto err_sanity; } if ( ! ll_src ) @@ -547,7 +546,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( ! iobuf ) { DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte " "buffer\n", snpdev, ( ( unsigned long ) len ) ); - efirc = EFI_DEVICE_ERROR; + rc = -ENOMEM; goto err_alloc_iob; } iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN - @@ -562,7 +561,6 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, htons ( *net_proto ) )) != 0 ){ DBGC ( snpdev, "SNPDEV %p TX could not construct " "header: %s\n", snpdev, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_ll_push; } } @@ -571,7 +569,6 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( ( rc = netdev_tx ( snpdev->netdev, iob_disown ( iobuf ) ) ) != 0){ DBGC ( snpdev, "SNPDEV %p TX could not transmit: %s\n", snpdev, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto err_tx; } @@ -586,7 +583,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, free_iob ( iobuf ); err_alloc_iob: err_sanity: - return efirc; + return EFIRC ( rc ); } /** @@ -615,7 +612,6 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, uint16_t iob_net_proto; unsigned int iob_flags; int rc; - EFI_STATUS efirc; DBGC2 ( snpdev, "SNPDEV %p RECEIVE %p(+%lx)", snpdev, data, ( ( unsigned long ) *len ) ); @@ -627,7 +623,7 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, iobuf = netdev_rx_dequeue ( snpdev->netdev ); if ( ! iobuf ) { DBGC2 ( snpdev, "\n" ); - efirc = EFI_NOT_READY; + rc = -EAGAIN; goto out_no_packet; } DBGC2 ( snpdev, "+%zx\n", iob_len ( iobuf ) ); @@ -642,7 +638,6 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, &iob_flags ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not parse header: %s\n", snpdev, strerror ( rc ) ); - efirc = RC_TO_EFIRC ( rc ); goto out_bad_ll_header; } @@ -656,12 +651,12 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, if ( net_proto ) *net_proto = ntohs ( iob_net_proto ); - efirc = 0; + rc = 0; out_bad_ll_header: free_iob ( iobuf ); out_no_packet: - return efirc; + return EFIRC ( rc ); } /** @@ -879,9 +874,9 @@ static int efi_snp_probe ( struct net_device *netdev ) { if ( ( efirc = bs->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, efi_snp_wait_for_packet, snpdev, &snpdev->snp.WaitForPacket ) ) != 0 ){ + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not create event: %s\n", - snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + snpdev, strerror ( rc ) ); goto err_create_event; } @@ -944,18 +939,17 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_component_name2_protocol_guid, &snpdev->name2, &efi_load_file_protocol_guid, &snpdev->load_file, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not install protocols: " - "%s\n", snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + "%s\n", snpdev, strerror ( rc ) ); goto err_install_protocol_interface; } /* Add as child of PCI device */ - if ( ( efirc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) { + if ( ( rc = efipci_child_add ( efipci, snpdev->handle ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not become child of " PCI_FMT ": %s\n", snpdev, PCI_ARGS ( &efipci->pci ), - efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + strerror ( rc ) ); goto err_efipci_child_add; } diff --git a/src/interface/efi/efi_snp_hii.c b/src/interface/efi/efi_snp_hii.c index 3a1193a3..9ea15a62 100644 --- a/src/interface/efi/efi_snp_hii.c +++ b/src/interface/efi/efi_snp_hii.c @@ -544,7 +544,7 @@ efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, results, &have_setting, efi_snp_hii_fetch ) ) != 0 ) { - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } } @@ -558,7 +558,7 @@ efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name, NULL, results, NULL ) ) != 0 ) { - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } } } @@ -592,7 +592,7 @@ efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, NULL, NULL, efi_snp_hii_store ) ) != 0 ) { - return RC_TO_EFIRC ( rc ); + return EFIRC ( rc ); } } @@ -657,9 +657,9 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list, snpdev->handle, &snpdev->hii_handle ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n", - snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + snpdev, strerror ( rc ) ); goto err_new_package_list; } @@ -668,9 +668,9 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { &snpdev->handle, &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ) ) != 0 ) { + rc = -EEFI ( efirc ); DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n", - snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); + snpdev, strerror ( rc ) ); goto err_install_protocol; } diff --git a/src/interface/efi/efi_strerror.c b/src/interface/efi/efi_strerror.c deleted file mode 100644 index 46bfbbb5..00000000 --- a/src/interface/efi/efi_strerror.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008 Michael Brown . - * - * 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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include -#include - -/** @file - * - * iPXE error message formatting for EFI - * - */ - -/** - * Format EFI status code - * - * @v efirc EFI status code - * @v efi_strerror EFI status code string - */ -const char * efi_strerror ( EFI_STATUS efirc ) { - static char errbuf[32]; - - if ( ! efirc ) - return "No error"; - - snprintf ( errbuf, sizeof ( errbuf ), "Error %lld", - ( unsigned long long ) ( efirc ^ MAX_BIT ) ); - return errbuf; -} diff --git a/src/interface/efi/efi_timer.c b/src/interface/efi/efi_timer.c index b110cae2..7a1ff786 100644 --- a/src/interface/efi/efi_timer.c +++ b/src/interface/efi/efi_timer.c @@ -19,6 +19,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include +#include #include #include #include @@ -54,10 +56,12 @@ EFI_REQUIRE_PROTOCOL ( EFI_CPU_ARCH_PROTOCOL, &cpu_arch ); static void efi_udelay ( unsigned long usecs ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; + int rc; if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFI could not delay for %ldus: %s\n", - usecs, efi_strerror ( efirc ) ); + usecs, strerror ( rc ) ); /* Probably screwed */ } } @@ -70,12 +74,13 @@ static void efi_udelay ( unsigned long usecs ) { static unsigned long efi_currticks ( void ) { UINT64 time; EFI_STATUS efirc; + int rc; /* Read CPU timer 0 (TSC) */ if ( ( efirc = cpu_arch->GetTimerValue ( cpu_arch, 0, &time, NULL ) ) != 0 ) { - DBG ( "EFI could not read CPU timer: %s\n", - efi_strerror ( efirc ) ); + rc = -EEFI ( efirc ); + DBG ( "EFI could not read CPU timer: %s\n", strerror ( rc ) ); /* Probably screwed */ return -1UL; } diff --git a/src/interface/efi/efi_umalloc.c b/src/interface/efi/efi_umalloc.c index b4994932..356efaa6 100644 --- a/src/interface/efi/efi_umalloc.c +++ b/src/interface/efi/efi_umalloc.c @@ -19,6 +19,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include +#include #include #include #include @@ -49,6 +51,7 @@ static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { userptr_t new_ptr = UNOWHERE; size_t old_size; EFI_STATUS efirc; + int rc; /* Allocate new memory if necessary. If allocation fails, * return without touching the old block. @@ -59,8 +62,9 @@ static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { EfiBootServicesData, new_pages, &phys_addr ) ) != 0 ) { + rc = -EEFI ( efirc ); DBG ( "EFI could not allocate %d pages: %s\n", - new_pages, efi_strerror ( efirc ) ); + new_pages, strerror ( rc ) ); return UNULL; } assert ( phys_addr != 0 ); @@ -84,8 +88,9 @@ static userptr_t efi_urealloc ( userptr_t old_ptr, size_t new_size ) { old_pages = ( EFI_SIZE_TO_PAGES ( old_size ) + 1 ); phys_addr = user_to_phys ( old_ptr, -EFI_PAGE_SIZE ); if ( ( efirc = bs->FreePages ( phys_addr, old_pages ) ) != 0 ){ + rc = -EEFI ( efirc ); DBG ( "EFI could not free %d pages at %llx: %s\n", - old_pages, phys_addr, efi_strerror ( efirc ) ); + old_pages, phys_addr, strerror ( rc ) ); /* Not fatal; we have leaked memory but successfully * allocated (if asked to do so). */ diff --git a/src/interface/smbios/smbios.c b/src/interface/smbios/smbios.c index 2adaa53d..90907e18 100644 --- a/src/interface/smbios/smbios.c +++ b/src/interface/smbios/smbios.c @@ -59,10 +59,11 @@ static size_t find_strings_terminator ( size_t offset ) { * Find specific structure type within SMBIOS * * @v type Structure type to search for + * @v instance Instance of this type of structure * @v structure SMBIOS structure descriptor to fill in * @ret rc Return status code */ -int find_smbios_structure ( unsigned int type, +int find_smbios_structure ( unsigned int type, unsigned int instance, struct smbios_structure *structure ) { unsigned int count = 0; size_t offset = 0; @@ -105,7 +106,8 @@ int find_smbios_structure ( unsigned int type, structure->header.len, structure->strings_len ); /* If this is the structure we want, return */ - if ( structure->header.type == type ) { + if ( ( structure->header.type == type ) && + ( instance-- == 0 ) ) { structure->offset = offset; return 0; } diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 663da968..d2975df4 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -27,15 +27,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include -/** SMBIOS settings tag magic number */ -#define SMBIOS_TAG_MAGIC 0x5B /* "SmBios" */ - -/** - * Construct SMBIOS empty tag - * - * @ret tag SMBIOS setting tag - */ -#define SMBIOS_EMPTY_TAG ( SMBIOS_TAG_MAGIC << 24 ) +/** SMBIOS settings scope */ +static struct settings_scope smbios_settings_scope; /** * Construct SMBIOS raw-data tag @@ -46,8 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @ret tag SMBIOS setting tag */ #define SMBIOS_RAW_TAG( _type, _structure, _field ) \ - ( ( SMBIOS_TAG_MAGIC << 24 ) | \ - ( (_type) << 16 ) | \ + ( ( (_type) << 16 ) | \ ( offsetof ( _structure, _field ) << 8 ) | \ ( sizeof ( ( ( _structure * ) 0 )->_field ) ) ) @@ -60,8 +52,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @ret tag SMBIOS setting tag */ #define SMBIOS_STRING_TAG( _type, _structure, _field ) \ - ( ( SMBIOS_TAG_MAGIC << 24 ) | \ - ( (_type) << 16 ) | \ + ( ( (_type) << 16 ) | \ ( offsetof ( _structure, _field ) << 8 ) ) /** @@ -73,11 +64,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ static int smbios_applies ( struct settings *settings __unused, struct setting *setting ) { - unsigned int tag_magic; - /* Check tag magic */ - tag_magic = ( setting->tag >> 24 ); - return ( tag_magic == SMBIOS_TAG_MAGIC ); + return ( setting->scope == &smbios_settings_scope ); } /** @@ -93,37 +81,43 @@ static int smbios_fetch ( struct settings *settings __unused, struct setting *setting, void *data, size_t len ) { struct smbios_structure structure; - unsigned int tag_magic; + unsigned int tag_instance; unsigned int tag_type; unsigned int tag_offset; unsigned int tag_len; int rc; - /* Split tag into type, offset and length */ - tag_magic = ( setting->tag >> 24 ); + /* Split tag into instance, type, offset and length */ + tag_instance = ( ( setting->tag >> 24 ) & 0xff ); tag_type = ( ( setting->tag >> 16 ) & 0xff ); tag_offset = ( ( setting->tag >> 8 ) & 0xff ); tag_len = ( setting->tag & 0xff ); - assert ( tag_magic == SMBIOS_TAG_MAGIC ); /* Find SMBIOS structure */ - if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 ) + if ( ( rc = find_smbios_structure ( tag_type, tag_instance, + &structure ) ) != 0 ) return rc; { uint8_t buf[structure.header.len]; const void *raw; union uuid uuid; + unsigned int index; /* Read SMBIOS structure */ if ( ( rc = read_smbios_structure ( &structure, buf, sizeof ( buf ) ) ) != 0 ) return rc; - /* A tag length of zero indicates a string */ - if ( tag_len == 0 ) { - if ( ( rc = read_smbios_string ( &structure, - buf[tag_offset], + /* A of zero indicates that the byte at + * contains a string index. An of + * zero indicates that the contains a literal + * string index. + */ + if ( ( tag_len == 0 ) || ( tag_offset == 0 ) ) { + index = ( ( tag_offset == 0 ) ? + tag_len : buf[tag_offset] ); + if ( ( rc = read_smbios_string ( &structure, index, data, len ) ) < 0 ) { return rc; } @@ -170,10 +164,10 @@ static struct settings_operations smbios_settings_operations = { /** SMBIOS settings */ static struct settings smbios_settings = { .refcnt = NULL, - .tag_magic = SMBIOS_EMPTY_TAG, .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ), .children = LIST_HEAD_INIT ( smbios_settings.children ), .op = &smbios_settings_operations, + .default_scope = &smbios_settings_scope, }; /** Initialise SMBIOS settings */ @@ -200,6 +194,7 @@ struct setting uuid_setting __setting ( SETTING_HOST ) = { .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, struct smbios_system_information, uuid ), .type = &setting_type_uuid, + .scope = &smbios_settings_scope, }; /** Other SMBIOS named settings */ @@ -211,6 +206,7 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_system_information, manufacturer ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, { .name = "product", @@ -219,6 +215,7 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_system_information, product ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, { .name = "serial", @@ -227,6 +224,7 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_system_information, serial ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, { .name = "asset", @@ -235,5 +233,6 @@ struct setting smbios_named_settings[] __setting ( SETTING_HOST_EXTRA ) = { struct smbios_enclosure_information, asset_tag ), .type = &setting_type_string, + .scope = &smbios_settings_scope, }, }; diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c index 2181fc4a..54df7905 100644 --- a/src/net/80211/net80211.c +++ b/src/net/80211/net80211.c @@ -208,7 +208,6 @@ struct setting net80211_ssid_setting __setting ( SETTING_NETDEV_EXTRA ) = { .name = "ssid", .description = "Wireless SSID", .type = &setting_type_string, - .tag = NET80211_SETTING_TAG_SSID, }; /** Whether to use active scanning @@ -221,7 +220,6 @@ struct setting net80211_active_setting __setting ( SETTING_NETDEV_EXTRA ) = { .name = "active-scan", .description = "Actively scan for wireless networks", .type = &setting_type_int8, - .tag = NET80211_SETTING_TAG_ACTIVE_SCAN, }; /** The cryptographic key to use @@ -234,7 +232,6 @@ struct setting net80211_key_setting __setting ( SETTING_NETDEV_EXTRA ) = { .name = "key", .description = "Wireless encryption key", .type = &setting_type_string, - .tag = NET80211_SETTING_TAG_KEY, }; /** @} */ diff --git a/src/net/80211/sec80211.c b/src/net/80211/sec80211.c index d159edbd..d1bc75e9 100644 --- a/src/net/80211/sec80211.c +++ b/src/net/80211/sec80211.c @@ -45,8 +45,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ENOTSUP_CCMP __einfo_error ( EINFO_ENOTSUP_CCMP ) #define EINFO_ENOTSUP_CCMP __einfo_uniqify ( EINFO_ENOTSUP, \ ( 0x10 | NET80211_CRYPT_CCMP ), "CCMP not supported" ) -#define ENOTSUP_CRYPT( crypt ) \ - EUNIQ ( ENOTSUP, ( 0x10 | (crypt) ), \ +#define ENOTSUP_CRYPT( crypt ) \ + EUNIQ ( EINFO_ENOTSUP, ( 0x10 | (crypt) ), \ ENOTSUP_WEP, ENOTSUP_TKIP, ENOTSUP_CCMP ) /** Mapping from net80211 crypto/secprot types to RSN OUI descriptors */ diff --git a/src/net/dhcppkt.c b/src/net/dhcppkt.c index 528f9003..3722c09e 100644 --- a/src/net/dhcppkt.c +++ b/src/net/dhcppkt.c @@ -230,7 +230,8 @@ static int dhcppkt_settings_applies ( struct settings *settings, struct dhcp_packet *dhcppkt = container_of ( settings, struct dhcp_packet, settings ); - return dhcppkt_applies ( dhcppkt, setting->tag ); + return ( ( setting->scope == NULL ) && + dhcppkt_applies ( dhcppkt, setting->tag ) ); } /** @@ -299,6 +300,6 @@ void dhcppkt_init ( struct dhcp_packet *dhcppkt, struct dhcphdr *data, dhcpopt_init ( &dhcppkt->options, &dhcppkt->dhcphdr->options, ( len - offsetof ( struct dhcphdr, options ) ), dhcpopt_no_realloc ); - settings_init ( &dhcppkt->settings, - &dhcppkt_settings_operations, &dhcppkt->refcnt, 0 ); + settings_init ( &dhcppkt->settings, &dhcppkt_settings_operations, + &dhcppkt->refcnt, NULL ); } diff --git a/src/net/fcoe.c b/src/net/fcoe.c index d1130425..e9e404ec 100644 --- a/src/net/fcoe.c +++ b/src/net/fcoe.c @@ -1011,7 +1011,7 @@ static void fcoe_expired ( struct retry_timer *timer, int over __unused ) { /* Increment the timeout counter */ fcoe->timeouts++; - if ( vlan_can_be_trunk ( fcoe->netdev ) & + if ( vlan_can_be_trunk ( fcoe->netdev ) && ! ( fcoe->flags & FCOE_VLAN_TIMED_OUT ) ) { /* If we have already found a VLAN, send infrequent diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index a05aaa95..d87a3c0f 100644 --- a/src/net/netdev_settings.c +++ b/src/net/netdev_settings.c @@ -39,35 +39,133 @@ struct setting mac_setting __setting ( SETTING_NETDEV ) = { .name = "mac", .description = "MAC address", .type = &setting_type_hex, - .tag = NETDEV_SETTING_TAG_MAC, }; struct setting machyp_setting __setting ( SETTING_NETDEV ) = { .name = "machyp", .description = "MAC address", .type = &setting_type_hexhyp, - .tag = NETDEV_SETTING_TAG_MACHYP, }; struct setting busid_setting __setting ( SETTING_NETDEV ) = { .name = "busid", .description = "Bus ID", .type = &setting_type_hex, - .tag = NETDEV_SETTING_TAG_BUS_ID, +}; +struct setting chip_setting __setting ( SETTING_NETDEV ) = { + .name = "chip", + .description = "Chip", + .type = &setting_type_string, }; /** - * Check applicability of network device setting + * Store MAC address setting * - * @v settings Settings block - * @v setting Setting - * @ret applies Setting applies within this settings block + * @v netdev Network device + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code */ -static int netdev_applies ( struct settings *settings __unused, - struct setting *setting ) { +static int netdev_store_mac ( struct net_device *netdev, + const void *data, size_t len ) { + struct ll_protocol *ll_protocol = netdev->ll_protocol; - return ( IS_NETDEV_SETTING_TAG ( setting->tag ) || - dhcpopt_applies ( setting->tag ) ); + /* Record new MAC address */ + if ( data ) { + if ( len != netdev->ll_protocol->ll_addr_len ) + return -EINVAL; + memcpy ( netdev->ll_addr, data, len ); + } else { + /* Reset MAC address if clearing setting */ + ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr ); + } + + return 0; } +/** + * Fetch MAC address setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_mac ( struct net_device *netdev, void *data, + size_t len ) { + + if ( len > netdev->ll_protocol->ll_addr_len ) + len = netdev->ll_protocol->ll_addr_len; + memcpy ( data, netdev->ll_addr, len ); + return netdev->ll_protocol->ll_addr_len; +} + +/** + * Fetch bus ID setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_busid ( struct net_device *netdev, void *data, + size_t len ) { + struct device_description *desc = &netdev->dev->desc; + struct dhcp_netdev_desc dhcp_desc; + + dhcp_desc.type = desc->bus_type; + dhcp_desc.vendor = htons ( desc->vendor ); + dhcp_desc.device = htons ( desc->device ); + if ( len > sizeof ( dhcp_desc ) ) + len = sizeof ( dhcp_desc ); + memcpy ( data, &dhcp_desc, len ); + return sizeof ( dhcp_desc ); +} + +/** + * Fetch chip setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int netdev_fetch_chip ( struct net_device *netdev, void *data, + size_t len ) { + const char *chip = netdev->dev->driver_name; + + strncpy ( data, chip, len ); + return strlen ( chip ); +} + +/** A network device setting operation */ +struct netdev_setting_operation { + /** Setting */ + struct setting *setting; + /** Store setting (or NULL if not supported) + * + * @v netdev Network device + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ + int ( * store ) ( struct net_device *netdev, const void *data, + size_t len ); + /** Fetch setting + * + * @v netdev Network device + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ + int ( * fetch ) ( struct net_device *netdev, void *data, size_t len ); +}; + +/** Network device settings */ +static struct netdev_setting_operation netdev_setting_operations[] = { + { &mac_setting, netdev_store_mac, netdev_fetch_mac }, + { &busid_setting, NULL, netdev_fetch_busid }, + { &chip_setting, NULL, netdev_fetch_chip }, +}; + /** * Store value of network device setting * @@ -81,15 +179,21 @@ static int netdev_store ( struct settings *settings, struct setting *setting, const void *data, size_t len ) { struct net_device *netdev = container_of ( settings, struct net_device, settings.settings ); + struct netdev_setting_operation *op; + unsigned int i; - if (( setting_cmp ( setting, &mac_setting ) == 0 ) || ( setting_cmp ( setting, &machyp_setting ) == 0 )) { - if ( len != netdev->ll_protocol->ll_addr_len ) - return -EINVAL; - memcpy ( netdev->ll_addr, data, len ); - return 0; + /* Handle network device-specific settings */ + for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) / + sizeof ( netdev_setting_operations[0] ) ) ; i++ ) { + op = &netdev_setting_operations[i]; + if ( setting_cmp ( setting, op->setting ) == 0 ) { + if ( op->store ) { + return op->store ( netdev, data, len ); + } else { + return -ENOTSUP; + } + } } - if ( setting_cmp ( setting, &busid_setting ) == 0 ) - return -ENOTSUP; return generic_settings_store ( settings, setting, data, len ); } @@ -99,31 +203,23 @@ static int netdev_store ( struct settings *settings, struct setting *setting, * * @v settings Settings block * @v setting Setting to fetch - * @v data Setting data, or NULL to clear setting - * @v len Length of setting data - * @ret rc Return status code + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error */ static int netdev_fetch ( struct settings *settings, struct setting *setting, void *data, size_t len ) { struct net_device *netdev = container_of ( settings, struct net_device, settings.settings ); - struct device_description *desc = &netdev->dev->desc; - struct dhcp_netdev_desc dhcp_desc; + struct netdev_setting_operation *op; + unsigned int i; - if (( setting_cmp ( setting, &mac_setting ) == 0 ) || ( setting_cmp ( setting, &machyp_setting ) == 0 )) { - if ( len > netdev->ll_protocol->ll_addr_len ) - len = netdev->ll_protocol->ll_addr_len; - memcpy ( data, netdev->ll_addr, len ); - return netdev->ll_protocol->ll_addr_len; - } - if ( setting_cmp ( setting, &busid_setting ) == 0 ) { - dhcp_desc.type = desc->bus_type; - dhcp_desc.vendor = htons ( desc->vendor ); - dhcp_desc.device = htons ( desc->device ); - if ( len > sizeof ( dhcp_desc ) ) - len = sizeof ( dhcp_desc ); - memcpy ( data, &dhcp_desc, len ); - return sizeof ( dhcp_desc ); + /* Handle network device-specific settings */ + for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) / + sizeof ( netdev_setting_operations[0] ) ) ; i++ ) { + op = &netdev_setting_operations[i]; + if ( setting_cmp ( setting, op->setting ) == 0 ) + return op->fetch ( netdev, data, len ); } return generic_settings_fetch ( settings, setting, data, len ); @@ -140,7 +236,6 @@ static void netdev_clear ( struct settings *settings ) { /** Network device configuration settings operations */ struct settings_operations netdev_settings_operations = { - .applies = netdev_applies, .store = netdev_store, .fetch = netdev_fetch, .clear = netdev_clear, diff --git a/src/net/netdevice.c b/src/net/netdevice.c index e9cbb9e9..1191ebc1 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -212,6 +213,43 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) { return rc; } +/** + * Defer transmitted packet + * + * @v netdev Network device + * @v iobuf I/O buffer + * + * Drivers may call netdev_tx_defer() if there is insufficient space + * in the transmit descriptor ring. Any packets deferred in this way + * will be automatically retransmitted as soon as space becomes + * available (i.e. as soon as the driver calls netdev_tx_complete()). + * + * The packet must currently be in the network device's TX queue. + * + * Drivers utilising netdev_tx_defer() must ensure that space in the + * transmit descriptor ring is freed up @b before calling + * netdev_tx_complete(). For example, if the ring is modelled using a + * producer counter and a consumer counter, then the consumer counter + * must be incremented before the call to netdev_tx_complete(). + * Failure to do this will cause the retransmitted packet to be + * immediately redeferred (which will result in out-of-order + * transmissions and other nastiness). + */ +void netdev_tx_defer ( struct net_device *netdev, struct io_buffer *iobuf ) { + + /* Catch data corruption as early as possible */ + list_check_contains_entry ( iobuf, &netdev->tx_queue, list ); + + /* Remove from transmit queue */ + list_del ( &iobuf->list ); + + /* Add to deferred transmit queue */ + list_add_tail ( &iobuf->list, &netdev->tx_deferred ); + + /* Record "out of space" statistic */ + netdev_tx_err ( netdev, NULL, -ENOBUFS ); +} + /** * Discard transmitted packet * @@ -257,6 +295,13 @@ void netdev_tx_complete_err ( struct net_device *netdev, /* Dequeue and free I/O buffer */ list_del ( &iobuf->list ); netdev_tx_err ( netdev, iobuf, rc ); + + /* Transmit first pending packet, if any */ + if ( ( iobuf = list_first_entry ( &netdev->tx_deferred, + struct io_buffer, list ) ) != NULL ) { + list_del ( &iobuf->list ); + netdev_tx ( netdev, iobuf ); + } } /** @@ -270,9 +315,9 @@ void netdev_tx_complete_err ( struct net_device *netdev, void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) { struct io_buffer *iobuf; - list_for_each_entry ( iobuf, &netdev->tx_queue, list ) { + if ( ( iobuf = list_first_entry ( &netdev->tx_queue, struct io_buffer, + list ) ) != NULL ) { netdev_tx_complete_err ( netdev, iobuf, rc ); - return; } } @@ -283,10 +328,15 @@ void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) { */ static void netdev_tx_flush ( struct net_device *netdev ) { - /* Discard any packets in the TX queue */ + /* Discard any packets in the TX queue. This will also cause + * any packets in the deferred TX queue to be discarded + * automatically. + */ while ( ! list_empty ( &netdev->tx_queue ) ) { netdev_tx_complete_next_err ( netdev, -ECANCELED ); } + assert ( list_empty ( &netdev->tx_queue ) ); + assert ( list_empty ( &netdev->tx_deferred ) ); } /** @@ -424,6 +474,7 @@ struct net_device * alloc_netdev ( size_t priv_size ) { ref_init ( &netdev->refcnt, free_netdev ); netdev->link_rc = -EUNKNOWN_LINK_STATUS; INIT_LIST_HEAD ( &netdev->tx_queue ); + INIT_LIST_HEAD ( &netdev->tx_deferred ); INIT_LIST_HEAD ( &netdev->rx_queue ); netdev_settings_init ( netdev ); netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) ); @@ -442,7 +493,9 @@ struct net_device * alloc_netdev ( size_t priv_size ) { */ int register_netdev ( struct net_device *netdev ) { static unsigned int ifindex = 0; + struct ll_protocol *ll_protocol = netdev->ll_protocol; struct net_driver *driver; + uint32_t seed; int rc; /* Create device name */ @@ -453,10 +506,17 @@ int register_netdev ( struct net_device *netdev ) { /* Set initial link-layer address, if not already set */ if ( ! netdev_has_ll_addr ( netdev ) ) { - netdev->ll_protocol->init_addr ( netdev->hw_addr, - netdev->ll_addr ); + ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr ); } + /* Use least significant bits of the link-layer address to + * improve the randomness of the (non-cryptographic) random + * number generator. + */ + memcpy ( &seed, ( netdev->ll_addr + ll_protocol->ll_addr_len + - sizeof ( seed ) ), sizeof ( seed ) ); + srand ( rand() ^ seed ); + /* Add to device list */ netdev_get ( netdev ); list_add_tail ( &netdev->list, &net_devices ); @@ -808,3 +868,36 @@ __weak struct net_device * vlan_find ( struct net_device *trunk __unused, /** Networking stack process */ PERMANENT_PROCESS ( net_process, net_step ); + +/** + * Discard some cached network device data + * + * @ret discarded Number of cached items discarded + */ +static unsigned int net_discard ( void ) { + struct net_device *netdev; + struct io_buffer *iobuf; + unsigned int discarded = 0; + + /* Try to drop one deferred TX packet from each network device */ + for_each_netdev ( netdev ) { + if ( ( iobuf = list_first_entry ( &netdev->tx_deferred, + struct io_buffer, + list ) ) != NULL ) { + + /* Discard first deferred packet */ + list_del ( &iobuf->list ); + free ( iobuf ); + + /* Report discard */ + discarded++; + } + } + + return discarded; +} + +/** Network device cache discarder */ +struct cache_discarder net_discarder __cache_discarder ( CACHE_NORMAL ) = { + .discard = net_discard, +}; diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index 613541f5..45f0f07c 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -205,7 +205,7 @@ static char * dns_qualify_name ( const char *string ) { char *fqdn; /* Leave unchanged if already fully-qualified or no local domain */ - if ( ( ! localdomain ) || ( strchr ( string, '.' ) != 0 ) ) + if ( ( ! localdomain ) || ( strchr ( string, '.' ) != NULL ) ) return strdup ( string ); /* Append local domain to name */ diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index b2d288ea..70f883a5 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -251,31 +251,42 @@ static void close_all_netdevs ( void ) { * @ret uri URI, or NULL on failure */ struct uri * fetch_next_server_and_filename ( struct settings *settings ) { - struct in_addr next_server; - char buf[256]; + struct in_addr next_server = { 0 }; + char *raw_filename = NULL; + struct uri *uri = NULL; char *filename; - struct uri *uri; - /* Fetch next-server setting */ - fetch_ipv4_setting ( settings, &next_server_setting, &next_server ); - if ( next_server.s_addr ) - printf ( "Next server: %s\n", inet_ntoa ( next_server ) ); + /* Determine settings block containing the filename, if any */ + settings = fetch_setting_origin ( settings, &filename_setting ); - /* Fetch filename setting */ - fetch_string_setting ( settings, &filename_setting, - buf, sizeof ( buf ) ); - if ( buf[0] ) - printf ( "Filename: %s\n", buf ); + /* If we have a filename, fetch it along with next-server */ + if ( settings ) { + fetch_ipv4_setting ( settings, &next_server_setting, + &next_server ); + if ( fetch_string_setting_copy ( settings, &filename_setting, + &raw_filename ) < 0 ) + goto err_fetch; + } /* Expand filename setting */ - filename = expand_settings ( buf ); + filename = expand_settings ( raw_filename ? raw_filename : "" ); if ( ! filename ) - return NULL; + goto err_expand; /* Parse next server and filename */ + if ( next_server.s_addr ) + printf ( "Next server: %s\n", inet_ntoa ( next_server ) ); + if ( filename[0] ) + printf ( "Filename: %s\n", filename ); uri = parse_next_server_and_filename ( next_server, filename ); + if ( ! uri ) + goto err_parse; + err_parse: free ( filename ); + err_expand: + free ( raw_filename ); + err_fetch: return uri; } diff --git a/src/util/einfo.c b/src/util/einfo.c index 354d475f..d2155898 100644 --- a/src/util/einfo.c +++ b/src/util/einfo.c @@ -38,10 +38,15 @@ struct options { /** Error usage information */ struct einfo { + /** Size of error information record */ uint32_t size; + /** Error number */ uint32_t error; + /** Offset to error description (NUL-terminated) */ uint32_t desc; + /** Offset to file name (NUL-terminated) */ uint32_t file; + /** Line number */ uint32_t line; } __attribute__ (( packed ));