Compare commits

..

28 Commits

Author SHA1 Message Date
c1834f323f [dhcp] Request NTP server option
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-19 11:13:52 +01:00
d5c08f78bd [ntp] Define NTP server setting
Define the IPv4 NTP server setting to simplify the use of a
DHCP-provided NTP server in scripts, using e.g.

  #!ipxe
  dhcp
  ntp ${ntp}

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-19 11:10:15 +01:00
c30b71ee9c [console] Restore compatibility with "--key" values in existing scripts
Commit 3ef4f7e ("[console] Avoid overlap between special keys and
Unicode characters") renumbered the special key encoding to avoid
collisions with Unicode key values outside the ASCII range.  This
change broke backwards compatibility with existing scripts that
specify key values using e.g. "prompt --key" or "menu --key".

Restore compatibility with existing scripts by tweaking the special
key encoding so that the relative key value (i.e. the delta from
KEY_MIN) is numerically equal to the old pre-Unicode key value, and by
modifying parse_key() to accept a relative key value.

Reported-by: Sven Dreyer <sven@dreyer-net.de>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-07 15:14:00 +01:00
f3036fc213 [linux] Set a default MAC address for tap devices
Avoid the need to always specify a local MAC address on the command
line by setting a default hardware MAC address (using the same default
address as for slirp devices).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-05 15:24:32 +01:00
59d065c9ac [linux] Fix error control flow in af_packet_nic_probe()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-05 15:17:58 +01:00
48ae5d5361 [linux] Fix error control flow in tap_probe()
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-05 14:47:13 +01:00
6701d91c50 [netdevice] Stop link block timer when device is closed
A running link block timer holds a reference to the network device and
will prevent it from being freed until the timer expires.  It is
impossible for free_netdev() to be called while the timer is still
running: the call to stop_timer() therein is therefore a no-op.

Stop the link block timer when the device is closed, to allow a
link-blocked device to be freed immediately upon unregistration of the
device.  (Since link block state is updated in response to received
packets, the state is effectively undefined for a closed device: there
is therefore no reason to leave the timer running.)

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-05 14:30:54 +01:00
b5b60ea33d [interface] Fix debug message values for temporary interfaces
The interface debug message values constructed by INTF_DBG() et al
rely on the interface being embedded within a containing object.  This
assumption is not valid for the temporary outbound-only interfaces
constructed on the stack by intf_shutdown() and xfer_vredirect().

Formalise the notion of a temporary outbound-only interface as having
a NULL interface descriptor, and overload the "original interface
descriptor" field to contain a pointer to the original interface that
the temporary interface is shadowing.

Originally-fixed-by: Vincent Fazio <vfazio@gmail.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-04 16:54:39 +01:00
8244410690 [build] Inhibit more linker warnings about an implied executable stack
Add .note.GNU-stack section declarations to the autogenerated PCI
device ID list objects.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-04 15:12:49 +01:00
daa9e54ab8 [build] Silence the "creating blib.a" message
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-04 15:03:31 +01:00
3ef4f7e2ef [console] Avoid overlap between special keys and Unicode characters
The special key range (from KEY_MIN upwards) currently overlaps with
the valid range for Unicode characters, and therefore prohibits the
use of Unicode key values outside the ASCII range.

Create space for Unicode key values by moving the special keys to the
range immediately above the maximum valid Unicode character.  This
allows the existing encoding of special keys as an efficiently packed
representation of the equivalent ANSI escape sequence to be maintained
almost as-is.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-04 14:33:43 +01:00
cc07ed7c7e [console] Avoid overlap between remapping flags and character values
The keyboard remapping flags currently occupy bits 8 and upwards of
the to-be-mapped character value.  This overlaps the range used for
special keys (KEY_MIN and upwards) and also overlaps the valid Unicode
character range.

No conflict is created by this overlap, since by design only ASCII
character values (as generated by an ASCII-only keyboard driver) are
subject to remapping, and so the to-be-remapped character values exist
in a conceptually separate namespace from either special keys or
non-ASCII Unicode characters.  However, the overlap is potentially
confusing for readers of the code.

Minimise cognitive load by using bits 24 and upwards for the keyboard
remapping flags.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-04 14:17:48 +01:00
6f57d91935 [build] Use separate code segment if supported by linker
Some versions of ld will complain that the automatically created (and
unused by our build process) ELF program headers include a "LOAD
segment with RWX permissions".

Silence this warning by adding "-z separate-code" to the linker
options, where supported.

For BIOS builds, where the prefix will generally require writable
access to its own (tiny) code segment, simply inhibit the warning
completely via "--no-warn-rwx-segments".

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-07-03 13:31:31 +01:00
e17568ad06 [build] Inhibit linker warnings about an implied executable stack
Signed-off-by: Geert Stappers <stappers@stappers.it>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-30 11:05:37 +01:00
2524a60550 [build] Avoid using multiple target patterns in pattern rules
Multiple target patterns in pattern rules are treated as grouped
targets regardless of the separator character.  Newer verions of make
will generate "warning: pattern recipe did not update peer target" to
warn that the rule was expected to update all of the (implicitly)
grouped targets.

Fix by splitting all multiple target pattern rules into single target
pattern rules.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-30 10:31:52 +01:00
280942a92a [loong64] Add support for building EFI binaries
Signed-off-by: Xiaotian Wu <wuxiaotian@loongson.cn>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-29 15:53:57 +01:00
6d98e0ca47 [loong64] Add CPU sleeping API for EFI LoongArch64
Signed-off-by: Xiaotian Wu <wuxiaotian@loongson.cn>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-29 15:53:33 +01:00
0c67a3632d [loong64] Add I/O API for LoongArch64
Signed-off-by: Xiaotian Wu <wuxiaotian@loongson.cn>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-29 15:40:24 +01:00
c57887bfc8 [ioapi] Centralise definitions for dummy PIO
There is no common standard for I/O-space access for non-x86 CPU
families, and non-MMIO peripherals are vanishingly rare.

Generalise the existing ARM definitions for dummy PIO to allow for
reuse by other CPU architectures.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-29 15:40:24 +01:00
18af669701 [arm] Add missing arch/arm/core source directory
Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-29 15:40:24 +01:00
cfe65aa826 [arm] Remove redundant inclusion of io.h
The PCI I/O API (supporting accesses to PCI configuration space) is
not related to the general I/O API (supporting accesses to
memory-mapped I/O peripherals).

Remove the spurious inclusion of ipxe/io.h from the PCI I/O header.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-29 15:40:24 +01:00
ae435cb4cc [efi] Process veto objects in reverse order of enumeration
While not guaranteed by the UEFI specification, the enumeration of
handles, protocols, and openers will generally return results in order
of creation.  Processing these objects in reverse order (as is already
done when calling DisconnectController() on the list of all handles)
will generally therefore perform the forcible uninstallation
operations in reverse order of object creation, which minimises the
number of implicit operations performed (e.g. when disconnecting a
controller that itself still has existent child controllers).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-23 16:51:10 +01:00
f8a0d1c0b8 [efi] Check for protocols opened by vetoed driver and image handles
The UEFI specification states that the AgentHandle may be either the
driving binding protocol handle or the image handle.

Check for both handles when searching for stale handles to be forcibly
closed on behalf of a vetoed driver.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-23 16:51:10 +01:00
f0b1025503 [efi] Unload vetoed drivers by image handle rather than driver handle
In most cases, the driver handle will be the image handle itself.
However, this is not required by the UEFI specification, and some
images will install multiple driver binding handles.

Use the image handle (extracted from the driver binding protocol
instance) when attempting to unload the driver's image.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-23 16:51:10 +01:00
c832580f19 [efi] Pass more detailed driver information to veto methods
Pass the driver binding handle, the driver binding protocol instance,
the image handle, and the loaded image protocol instance to all veto
methods.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-23 16:22:27 +01:00
9a118322a0 [efi] Show manufacturer in veto debug output
Simplify the process of adding new entries to the veto list by
including the manufacturer name within the standard debug output.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-22 23:20:37 +01:00
2689a6e776 [efi] Always poll for TX completions
Polling for TX completions is arguably redundant when there are no
transmissions currently in progress.  Commit c6c7e78 ("[efi] Poll for
TX completions only when there is an outstanding TX buffer") switched
to setting the PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS flag only when
there is an in-progress transmission awaiting completion, in order to
reduce reported TX errors and debug message noise from buggy NII
implementations that report spurious TX completions whenever the
transmit queue is empty.

Some other NII implementations (observed with the Realtek driver in a
Dell Latitude 3440) seem to have a bug in the transmit datapath
handling which results in the transmit ring freezing after sending a
few hundred packets under heavy load.  The symptoms are that the
TPPoll register's NPQ bit remains set and the 256-entry transmit ring
contains a large number of uncompleted descriptors (with the OWN bit
set), the first two of which have identical data buffer addresses.

Though iPXE will submit at most one in-progress transmission via NII,
the Dell/Realtek driver seems to make a page-aligned copy of each
transmit data buffer and to report TX completions immediately without
waiting for the packet to actually be transmitted.  These synthetic TX
completions continue even after the hardware transmit ring freezes.

Setting PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS on every poll reduces the
probability of this Dell/Realtek driver bug being triggered by a
factor of around 500, which brings the failure rate down to the point
that it can sensibly be managed by external logic such as the
"--timeout" option for image downloads.  Closing and reopening the
interface (via "ifclose"/"ifopen") will clear the error condition and
allow transmissions to resume.

Revert to setting PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS on every poll,
and silently ignore situations in which the hardware reports a
completion when no transmission is in progress.  This approximately
matches the behaviour of the SnpDxe driver, which will also generally
set PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS on every poll.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-21 11:49:53 +01:00
4fa4052c7e [efi] Provide read-only access to EFI variables via settings mechanism
EFI variables do not map neatly to the iPXE settings mechanism, since
the EFI variable identifier includes a namespace GUID that cannot
cleanly be supplied as part of a setting name.  Creating a new EFI
variable requires the variable's attributes to be specified, which
does not fit within iPXE's settings concept.

However, EFI variable names are generally unique even without the
namespace GUID, and EFI does provide a mechanism to iterate over all
existent variables.  We can therefore provide read-only access to EFI
variables by comparing only the names and ignoring the namespace
GUIDs.

Provide an "efi" settings block that implements this mechanism using a
syntax such as:

  echo Platform language is ${efi/PlatformLang:string}

  show efi/SecureBoot:int8

Settings are returned as raw binary values by default since an EFI
variable may contain boolean flags, integer values, ASCII strings,
UCS-2 strings, EFI device paths, X.509 certificates, or any other
arbitrary blob of data.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
2023-06-09 14:37:44 +01:00
66 changed files with 641 additions and 169 deletions

View File

@ -50,6 +50,10 @@ $(BIN)/efidrv.cab : $(BIN)/alldrv.efis # $(ALL_drv.efi) is not yet defined
$(QM)$(ECHO) " [CAB] $@"
$(Q)$(LCAB) -n -q $(ALL_drv.efi) $@
$(BIN)/%.iso $(BIN)/%.usb : $(BIN)/%.efi util/genfsimg
$(BIN)/%.iso : $(BIN)/%.efi util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<
$(BIN)/%.usb : $(BIN)/%.efi util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<

View File

@ -502,6 +502,13 @@ LDFLAGS += --gc-sections
#
LDFLAGS += -static
# Use separate code segment if supported by linker
#
ZSC_TEST = $(LD) -z separate-code --version 2>&1 > /dev/null
ZSC_FLAGS := $(shell [ -z "`$(ZSC_TEST)`" ] && \
$(ECHO) '-z separate-code -z max-page-size=4096')
LDFLAGS += $(ZSC_FLAGS)
# compiler.h is needed for our linking and debugging system
#
CFLAGS += -include include/compiler.h
@ -1002,6 +1009,7 @@ endif
# Device ID tables (using IDs from ROM definition file)
#
define obj_pci_id_asm
.section ".note.GNU-stack", "", $(ASM_TCHAR)progbits
.section ".pci_devlist.$(1)", "a", $(ASM_TCHAR)progbits
.globl pci_devlist_$(1)
pci_devlist_$(1):
@ -1171,7 +1179,7 @@ BLIB = $(BIN)/blib.a
$(BLIB) : $(BLIB_OBJS) $(BLIB_LIST) $(MAKEDEPS)
$(Q)$(RM) $(BLIB)
$(QM)$(ECHO) " [AR] $@"
$(Q)$(AR) rD $@ $(sort $(BLIB_OBJS))
$(Q)$(AR) rcD $@ $(sort $(BLIB_OBJS))
$(Q)$(OBJCOPY) --enable-deterministic-archives \
--prefix-symbols=$(SYMBOL_PREFIX) $@
$(Q)$(RANLIB) -D $@

View File

@ -9,4 +9,5 @@ INCDIRS += arch/arm/include
# ARM-specific directories containing source files
#
SRCDIRS += arch/arm/core
SRCDIRS += arch/arm/interface/efi

View File

@ -46,7 +46,7 @@ union arm32_io_qword {
*
* This is not atomic for ARM32.
*/
static uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
static __unused uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
volatile union arm32_io_qword *ptr =
container_of ( io_addr, union arm32_io_qword, qword );
union arm32_io_qword tmp;
@ -64,7 +64,8 @@ static uint64_t arm32_readq ( volatile uint64_t *io_addr ) {
*
* This is not atomic for ARM32.
*/
static void arm32_writeq ( uint64_t data, volatile uint64_t *io_addr ) {
static __unused void arm32_writeq ( uint64_t data,
volatile uint64_t *io_addr ) {
volatile union arm32_io_qword *ptr =
container_of ( io_addr, union arm32_io_qword, qword );
union arm32_io_qword tmp;
@ -82,7 +83,6 @@ PROVIDE_IOAPI_INLINE ( arm, readl );
PROVIDE_IOAPI_INLINE ( arm, writeb );
PROVIDE_IOAPI_INLINE ( arm, writew );
PROVIDE_IOAPI_INLINE ( arm, writel );
PROVIDE_IOAPI_INLINE ( arm, iodelay );
PROVIDE_IOAPI_INLINE ( arm, mb );
#ifdef __aarch64__
PROVIDE_IOAPI_INLINE ( arm, readq );
@ -91,3 +91,4 @@ PROVIDE_IOAPI_INLINE ( arm, writeq );
PROVIDE_IOAPI ( arm, readq, arm32_readq );
PROVIDE_IOAPI ( arm, writeq, arm32_writeq );
#endif
PROVIDE_DUMMY_PIO ( arm );

View File

@ -9,6 +9,4 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/io.h>
#endif /* _BITS_PCI_IO_H */

View File

@ -15,6 +15,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IOAPI_PREFIX_arm __arm_
#endif
#include <ipxe/dummy_pio.h>
/*
* Memory space mappings
*
@ -77,55 +79,6 @@ ARM_WRITEX ( w, uint16_t, "h", "" );
ARM_WRITEX ( l, uint32_t, "", "" );
#endif
/*
* Dummy PIO reads and writes up to 32 bits
*
* There is no common standard for I/O-space access for ARM, and
* non-MMIO peripherals are vanishingly rare. Provide dummy
* implementations that will allow code to link and should cause
* drivers to simply fail to detect hardware at runtime.
*
*/
#define ARM_INX( _suffix, _type ) \
static inline __always_inline _type \
IOAPI_INLINE ( arm, in ## _suffix ) ( volatile _type *io_addr __unused) { \
return ~( (_type) 0 ); \
} \
static inline __always_inline void \
IOAPI_INLINE ( arm, ins ## _suffix ) ( volatile _type *io_addr __unused, \
_type *data, unsigned int count ) { \
memset ( data, 0xff, count * sizeof ( *data ) ); \
}
ARM_INX ( b, uint8_t );
ARM_INX ( w, uint16_t );
ARM_INX ( l, uint32_t );
#define ARM_OUTX( _suffix, _type ) \
static inline __always_inline void \
IOAPI_INLINE ( arm, out ## _suffix ) ( _type data __unused, \
volatile _type *io_addr __unused ) { \
/* Do nothing */ \
} \
static inline __always_inline void \
IOAPI_INLINE ( arm, outs ## _suffix ) ( volatile _type *io_addr __unused, \
const _type *data __unused, \
unsigned int count __unused ) { \
/* Do nothing */ \
}
ARM_OUTX ( b, uint8_t );
ARM_OUTX ( w, uint16_t );
ARM_OUTX ( l, uint32_t );
/*
* Slow down I/O
*
*/
static inline __always_inline void
IOAPI_INLINE ( arm, iodelay ) ( void ) {
/* Nothing to do */
}
/*
* Memory barrier
*
@ -140,4 +93,7 @@ IOAPI_INLINE ( arm, mb ) ( void ) {
#endif
}
/* Dummy PIO */
DUMMY_PIO ( arm );
#endif /* _IPXE_ARM_IO_H */

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", %progbits
.text
/* Must match jmp_buf structure layout */

View File

@ -9,6 +9,7 @@
* Interrupt handlers
****************************************************************************
*/
.section ".note.GNU-stack", "", @progbits
.section ".text", "ax", @progbits
.code32

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code32

View File

@ -1,3 +1,4 @@
.section ".note.GNU-stack", "", @progbits
.arch i386
.section ".data", "aw", @progbits

View File

@ -20,6 +20,7 @@ CFLAGS += -fshort-wchar
# LoongArch64-specific directories containing source files
SRCDIRS += arch/loong64/core
SRCDIRS += arch/loong64/interface/efi
# Include platform-specific Makefile
MAKEDEPS += arch/loong64/Makefile.$(PLATFORM)

View File

@ -0,0 +1,14 @@
# -*- makefile -*- : Force emacs to use Makefile mode
# Specify EFI image builder
#
ELF2EFI = $(ELF2EFI64)
# Specify EFI boot file
#
EFI_BOOT_FILE = bootloongarch64.efi
# Include generic EFI Makefile
#
MAKEDEPS += Makefile.efi
include Makefile.efi

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2023, Xiaotian Wu <wuxiaotian@loongson.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/io.h>
#include <ipxe/loong64_io.h>
/** @file
*
* iPXE I/O API for LoongArch64
*
*/
PROVIDE_IOAPI_INLINE ( loong64, phys_to_bus );
PROVIDE_IOAPI_INLINE ( loong64, bus_to_phys );
PROVIDE_IOAPI_INLINE ( loong64, readb );
PROVIDE_IOAPI_INLINE ( loong64, readw );
PROVIDE_IOAPI_INLINE ( loong64, readl );
PROVIDE_IOAPI_INLINE ( loong64, readq );
PROVIDE_IOAPI_INLINE ( loong64, writeb );
PROVIDE_IOAPI_INLINE ( loong64, writew );
PROVIDE_IOAPI_INLINE ( loong64, writel );
PROVIDE_IOAPI_INLINE ( loong64, writeq );
PROVIDE_IOAPI_INLINE ( loong64, mb );
PROVIDE_DUMMY_PIO ( loong64 );

View File

@ -12,4 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Page shift */
#define PAGE_SHIFT 12
#include <ipxe/loong64_io.h>
#endif /* _BITS_IO_H */

View File

@ -9,4 +9,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_MAP_H */
#include <ipxe/efi/efiloong64_nap.h>
#endif /* _BITS_NAP_H */

View File

@ -0,0 +1,18 @@
#ifndef _IPXE_EFILOONG64_NAP_H
#define _IPXE_EFILOONG64_NAP_H
/** @file
*
* EFI CPU sleeping
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef NAP_EFILOONG64
#define NAP_PREFIX_efiloong64
#else
#define NAP_PREFIX_efiloong64 __efiloong64_
#endif
#endif /* _IPXE_EFILOONG64_NAP_H */

View File

@ -0,0 +1,82 @@
#ifndef _IPXE_LOONG64_IO_H
#define _IPXE_LOONG64_IO_H
/** @file
*
* iPXE I/O API for LoongArch64
*
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef IOAPI_LOONG64
#define IOAPI_PREFIX_loong64
#else
#define IOAPI_PREFIX_loong64 __loong64_
#endif
#include <ipxe/dummy_pio.h>
/*
* Memory space mappings
*
*/
/*
* Physical<->Bus address mappings
*
*/
static inline __always_inline unsigned long
IOAPI_INLINE ( loong64, phys_to_bus ) ( unsigned long phys_addr ) {
return phys_addr;
}
static inline __always_inline unsigned long
IOAPI_INLINE ( loong64, bus_to_phys ) ( unsigned long bus_addr ) {
return bus_addr;
}
/*
* MMIO reads and writes up to native word size
*
*/
#define LOONG64_READX( _suffix, _type, _insn_suffix ) \
static inline __always_inline _type \
IOAPI_INLINE ( loong64, read ## _suffix ) ( volatile _type *io_addr ) { \
_type data; \
__asm__ __volatile__ ( "ld." _insn_suffix " %0, %1" \
: "=r" ( data ) : "m" ( *io_addr ) ); \
return data; \
}
LOONG64_READX ( b, uint8_t, "bu");
LOONG64_READX ( w, uint16_t, "hu");
LOONG64_READX ( l, uint32_t, "wu");
LOONG64_READX ( q, uint64_t, "d");
#define LOONG64_WRITEX( _suffix, _type, _insn_suffix ) \
static inline __always_inline void \
IOAPI_INLINE ( loong64, write ## _suffix ) ( _type data, \
volatile _type *io_addr ) { \
__asm__ __volatile__ ( "st." _insn_suffix " %0, %1" \
: : "r" ( data ), "m" ( *io_addr ) ); \
}
LOONG64_WRITEX ( b, uint8_t, "b");
LOONG64_WRITEX ( w, uint16_t, "h");
LOONG64_WRITEX ( l, uint32_t, "w" );
LOONG64_WRITEX ( q, uint64_t, "d");
/*
* Memory barrier
*
*/
static inline __always_inline void
IOAPI_INLINE ( loong64, mb ) ( void ) {
__asm__ __volatile__ ( "dbar 0" );
}
/* Dummy PIO */
DUMMY_PIO ( loong64 );
#endif /* _IPXE_LOONG64_IO_H */

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2023, Xiaotian Wu <wuxiaotian@loongson.cn>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* You can also choose to distribute this program under the terms of
* the Unmodified Binary Distribution Licence (as given in the file
* COPYING.UBDL), provided that you have satisfied its requirements.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/nap.h>
#include <ipxe/efi/efi.h>
/** @file
*
* iPXE CPU sleeping API for EFI
*
*/
/**
* Sleep until next interrupt
*
*/
static void efiloong64_cpu_nap ( void ) {
/*
* I can't find any EFI API that allows us to put the CPU to
* sleep. The CpuSleep() function is defined in CpuLib.h, but
* isn't part of any exposed protocol so we have no way to
* call it.
*
* The EFI shell doesn't seem to bother sleeping the CPU; it
* just sits there idly burning power.
*
*/
__asm__ __volatile__ ( "idle 0" );
}
PROVIDE_NAP ( efiloong64, cpu_nap, efiloong64_cpu_nap );

View File

@ -13,6 +13,13 @@ LDSCRIPT_PREFIX = arch/x86/scripts/prefixonly.lds
#
LDFLAGS += -N --no-check-sections
# Do not warn about RWX segments (required by most prefixes)
#
WRWX_TEST = $(LD) --warn-rwx-segments --version 2>&1 > /dev/null
WRWX_FLAGS := $(shell [ -z "`$(WRWX_TEST)`" ] && \
$(ECHO) '--no-warn-rwx-segments')
LDFLAGS += $(WRWX_FLAGS)
# Media types.
#
MEDIA += rom
@ -54,9 +61,15 @@ LIST_NAME_mrom := ROMS
LIST_NAME_pcirom := ROMS
LIST_NAME_isarom := ROMS
# ISO or FAT filesystem images
# ISO images
NON_AUTO_MEDIA += iso
$(BIN)/%.iso $(BIN)/%.sdsk: $(BIN)/%.lkrn util/genfsimg
$(BIN)/%.iso : $(BIN)/%.lkrn util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<
# FAT filesystem images (via syslinux)
NON_AUTO_MEDIA += sdsk
$(BIN)/%.sdsk : $(BIN)/%.lkrn util/genfsimg
$(QM)$(ECHO) " [GENFSIMG] $@"
$(Q)util/genfsimg -o $@ $<

View File

@ -22,6 +22,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.arch i386
#ifdef __x86_64__

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.arch i386
/****************************************************************************

View File

@ -10,6 +10,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
#define PIC1_ICR 0x20
#define PIC2_ICR 0xa0
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16

View File

@ -290,29 +290,38 @@ static const char *bios_ansi_input = "";
struct bios_key {
/** Scancode */
uint8_t scancode;
/** Key code */
uint16_t key;
/** Relative key value */
uint16_t rkey;
} __attribute__ (( packed ));
/**
* Define a BIOS key mapping
*
* @v scancode Scancode
* @v key iPXE key code
* @v bioskey BIOS key mapping
*/
#define BIOS_KEY( scancode, key ) { scancode, KEY_REL ( key ) }
/** Mapping from BIOS scan codes to iPXE key codes */
static const struct bios_key bios_keys[] = {
{ 0x53, KEY_DC },
{ 0x48, KEY_UP },
{ 0x50, KEY_DOWN },
{ 0x4b, KEY_LEFT },
{ 0x4d, KEY_RIGHT },
{ 0x47, KEY_HOME },
{ 0x4f, KEY_END },
{ 0x49, KEY_PPAGE },
{ 0x51, KEY_NPAGE },
{ 0x3f, KEY_F5 },
{ 0x40, KEY_F6 },
{ 0x41, KEY_F7 },
{ 0x42, KEY_F8 },
{ 0x43, KEY_F9 },
{ 0x44, KEY_F10 },
{ 0x85, KEY_F11 },
{ 0x86, KEY_F12 },
BIOS_KEY ( 0x53, KEY_DC ),
BIOS_KEY ( 0x48, KEY_UP ),
BIOS_KEY ( 0x50, KEY_DOWN ),
BIOS_KEY ( 0x4b, KEY_LEFT ),
BIOS_KEY ( 0x4d, KEY_RIGHT ),
BIOS_KEY ( 0x47, KEY_HOME ),
BIOS_KEY ( 0x4f, KEY_END ),
BIOS_KEY ( 0x49, KEY_PPAGE ),
BIOS_KEY ( 0x51, KEY_NPAGE ),
BIOS_KEY ( 0x3f, KEY_F5 ),
BIOS_KEY ( 0x40, KEY_F6 ),
BIOS_KEY ( 0x41, KEY_F7 ),
BIOS_KEY ( 0x42, KEY_F8 ),
BIOS_KEY ( 0x43, KEY_F9 ),
BIOS_KEY ( 0x44, KEY_F10 ),
BIOS_KEY ( 0x85, KEY_F11 ),
BIOS_KEY ( 0x86, KEY_F12 ),
};
/**
@ -323,7 +332,7 @@ static const struct bios_key bios_keys[] = {
*/
static const char * bios_ansi_seq ( unsigned int scancode ) {
static char buf[ 5 /* "[" + two digits + terminator + NUL */ ];
unsigned int key;
unsigned int rkey;
unsigned int terminator;
unsigned int n;
unsigned int i;
@ -338,9 +347,9 @@ static const char * bios_ansi_seq ( unsigned int scancode ) {
continue;
/* Construct escape sequence */
key = bios_keys[i].key;
n = KEY_ANSI_N ( key );
terminator = KEY_ANSI_TERMINATOR ( key );
rkey = bios_keys[i].rkey;
n = KEY_ANSI_N ( rkey );
terminator = KEY_ANSI_TERMINATOR ( rkey );
*(tmp++) = '[';
if ( n )
tmp += sprintf ( tmp, "%d", n );
@ -479,6 +488,7 @@ struct console_driver bios_console __console_driver = {
static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
unsigned int discard_a;
unsigned int scancode;
unsigned int rkey;
unsigned int i;
uint16_t keypress;
int key;
@ -521,9 +531,10 @@ static __asmcall __used void bios_inject ( struct i386_all_regs *ix86 ) {
/* Handle special keys */
if ( key >= KEY_MIN ) {
rkey = KEY_REL ( key );
for ( i = 0 ; i < ( sizeof ( bios_keys ) /
sizeof ( bios_keys[0] ) ) ; i++ ) {
if ( bios_keys[i].key == key ) {
if ( bios_keys[i].rkey == rkey ) {
scancode = bios_keys[i].scancode;
keypress = ( scancode << 8 );
break;

View File

@ -23,6 +23,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16

View File

@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.arch i386
/****************************************************************************

View File

@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER )
#include "librm.h"
.section ".note.GNU-stack", "", @progbits
.text
.code32

View File

@ -5,6 +5,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define STACK_SEG 0x0200
#define STACK_SIZE 0x2000
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits

View File

@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_ONLY )
.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
.section ".note.GNU-stack", "", @progbits
.org 0
.arch i386
.text

View File

@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PSP_CMDLINE_LEN 0x80
#define PSP_CMDLINE_START 0x81
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.org 0

View File

@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits

View File

@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.arch i386
/* Image compression enabled */

View File

@ -4,6 +4,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BZI_LOAD_HIGH_ADDR 0x100000
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits

View File

@ -41,6 +41,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define _pcirom_start _mrom_start
#include "pciromprefix.S"
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16

View File

@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.code16

View File

@ -1,5 +1,6 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.org 0
.text
.arch i386

View File

@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXE_HACK_EB54 0x0001
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.org 0

View File

@ -8,6 +8,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.org 0

View File

@ -54,6 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BUSTYPE "PCIR"
#endif
.section ".note.GNU-stack", "", @progbits
.text
.code16
.arch i386

View File

@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <librm.h>
.section ".note.GNU-stack", "", @progbits
.text
.code16
.arch i386

View File

@ -43,6 +43,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
****************************************************************************
*/
.section ".note.GNU-stack", "", @progbits
.text
.arch i486
.section ".prefix.lib", "ax", @progbits

View File

@ -2,6 +2,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <config/console.h>
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".prefix", "awx", @progbits

View File

@ -24,6 +24,7 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.section ".note.GNU-stack", "", @progbits
.arch i386
/****************************************************************************

View File

@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/* Breakpoint for when debugging under bochs */
#define BOCHSBP xchgw %bx, %bx
.section ".note.GNU-stack", "", @progbits
.text
.arch i386
.section ".text16", "awx", @progbits

View File

@ -83,6 +83,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define if64 if 0
#endif
.section ".note.GNU-stack", "", @progbits
/****************************************************************************
* Global descriptor table
*

View File

@ -38,6 +38,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define SIGFPE 8
#define SIGSTKFLT 16
.section ".note.GNU-stack", "", @progbits
.section ".text.gdbmach_interrupt", "ax", @progbits
.code64

View File

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

View File

@ -67,4 +67,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IMAGE_GZIP /* GZIP image support */
#endif
#if defined ( __loongarch__ )
#define IOAPI_LOONG64
#define NAP_EFILOONG64
#endif
#endif /* CONFIG_DEFAULTS_EFI_H */

View File

@ -285,6 +285,7 @@ void intf_shutdown ( struct interface *intf, int rc ) {
intf_nullify ( intf );
/* Transfer destination to temporary interface */
intf_temp_init ( &tmp, intf );
tmp.dest = intf->dest;
intf->dest = &null_intf;

View File

@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <ipxe/netdevice.h>
@ -35,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/settings.h>
#include <ipxe/params.h>
#include <ipxe/timer.h>
#include <ipxe/keys.h>
#include <ipxe/parseopt.h>
#include <config/branding.h>
@ -213,6 +215,7 @@ int parse_flag ( char *text __unused, int *flag ) {
* @ret rc Return status code
*/
int parse_key ( char *text, unsigned int *key ) {
int rc;
/* Interpret single characters as being a literal key character */
if ( text[0] && ! text[1] ) {
@ -221,7 +224,17 @@ int parse_key ( char *text, unsigned int *key ) {
}
/* Otherwise, interpret as an integer */
return parse_integer ( text, key );
if ( ( rc = parse_integer ( text, key ) ) < 0 )
return rc;
/* For backwards compatibility with existing scripts, treat
* integers between the ASCII range and special key range as
* being relative special key values.
*/
if ( ( ! isascii ( *key ) ) && ( *key < KEY_MIN ) )
*key += KEY_MIN;
return 0;
}
/**

View File

@ -60,7 +60,7 @@ static struct xfer_metadata dummy_metadata;
* @ret rc Return status code
*/
int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
struct interface tmp = INTF_INIT ( null_intf_desc );
struct interface tmp;
struct interface *dest;
xfer_vredirect_TYPE ( void * ) *op =
intf_get_dest_op_no_passthru ( intf, xfer_vredirect, &dest );
@ -85,6 +85,7 @@ int xfer_vredirect ( struct interface *intf, int type, va_list args ) {
* If redirection fails, then send intf_close() to the
* parent interface.
*/
intf_temp_init ( &tmp, intf );
intf_plug ( &tmp, dest );
rc = xfer_vreopen ( dest, type, args );
if ( rc == 0 ) {

View File

@ -300,9 +300,9 @@ static int af_packet_nic_probe ( struct linux_device *device,
return 0;
err_settings:
unregister_netdev(netdev);
err_register:
err_settings:
netdev_nullify(netdev);
netdev_put(netdev);
return rc;

View File

@ -56,6 +56,10 @@ struct tap_nic {
int fd;
};
/** Default MAC address */
static const uint8_t tap_default_mac[ETH_ALEN] =
{ 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
/** Open the TAP device */
static int tap_open(struct net_device * netdev)
{
@ -202,6 +206,7 @@ static int tap_probe(struct linux_device *device, struct linux_device_request *r
nic = netdev->priv;
linux_set_drvdata(device, netdev);
netdev->dev = &device->dev;
memcpy ( netdev->hw_addr, tap_default_mac, ETH_ALEN );
memset(nic, 0, sizeof(*nic));
/* Look for the mandatory if setting */
@ -231,9 +236,9 @@ static int tap_probe(struct linux_device *device, struct linux_device_request *r
return 0;
err_settings:
unregister_netdev(netdev);
err_register:
err_settings:
netdev_nullify(netdev);
netdev_put(netdev);
return rc;

View File

@ -1032,8 +1032,9 @@ static void nii_poll_tx ( struct net_device *netdev, unsigned int stat ) {
if ( stat & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN )
return;
/* Sanity check */
assert ( nii->txbuf != NULL );
/* Ignore spurious completions reported by some devices */
if ( ! nii->txbuf )
return;
/* Complete transmission */
iobuf = nii->txbuf;
@ -1131,7 +1132,7 @@ static void nii_poll ( struct net_device *netdev ) {
/* Get status */
op = NII_OP ( PXE_OPCODE_GET_STATUS,
( PXE_OPFLAGS_GET_INTERRUPT_STATUS |
( nii->txbuf ? PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS : 0)|
PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS |
( nii->media ? PXE_OPFLAGS_GET_MEDIA_STATUS : 0 ) ) );
if ( ( stat = nii_issue_db ( nii, op, &db, sizeof ( db ) ) ) < 0 ) {
rc = -EIO_STAT ( stat );
@ -1141,8 +1142,7 @@ static void nii_poll ( struct net_device *netdev ) {
}
/* Process any TX completions */
if ( nii->txbuf )
nii_poll_tx ( netdev, stat );
nii_poll_tx ( netdev, stat );
/* Process any RX completions */
nii_poll_rx ( netdev );

View File

@ -95,7 +95,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
}
} else if ( keycode <= USBKBD_KEY_UP ) {
/* Special keys */
static const uint16_t special[] = {
static const unsigned int special[] = {
0, 0, 0, 0, 0, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9,
KEY_F10, KEY_F11, KEY_F12, 0, 0, 0, KEY_IC, KEY_HOME,
KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
@ -110,7 +110,7 @@ static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
if ( leds & USBKBD_LED_NUM_LOCK ) {
key = "1234567890." [ keycode - USBKBD_KEY_PAD_1 ];
} else {
static const uint16_t keypad[] = {
static const unsigned int keypad[] = {
KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, 0,
KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PPAGE,
KEY_IC, KEY_DC

View File

@ -9,6 +9,17 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Check if character is ASCII
*
* @v character Character
* @ret is_ascii Character is an ASCII character
*/
static inline int isascii ( int character ) {
return ( character <= '\x7f' );
}
/**
* Check if character is a decimal digit
*

View File

@ -86,6 +86,9 @@ struct dhcp_packet;
/** Maximum transmission unit */
#define DHCP_MTU 26
/** NTP servers */
#define DHCP_NTP_SERVERS 42
/** Vendor encapsulated options */
#define DHCP_VENDOR_ENCAP 43

View File

@ -0,0 +1,64 @@
#ifndef _IPXE_DUMMY_PIO_H
#define _IPXE_DUMMY_PIO_H
/** @file
*
* Dummy PIO reads and writes up to 32 bits
*
* There is no common standard for I/O-space access for non-x86 CPU
* families, and non-MMIO peripherals are vanishingly rare. Provide
* dummy implementations that will allow code to link and should cause
* drivers to simply fail to detect hardware at runtime.
*/
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define DUMMY_INX( _prefix, _suffix, _type ) \
static inline __always_inline _type \
IOAPI_INLINE ( _prefix, in ## _suffix ) ( volatile _type *io_addr __unused) { \
return ~( (_type) 0 ); \
} \
static inline __always_inline void \
IOAPI_INLINE ( _prefix, ins ## _suffix ) ( volatile _type *io_addr __unused, \
_type *data, unsigned int count ) {\
memset ( data, 0xff, count * sizeof ( *data ) ); \
}
#define DUMMY_OUTX( _prefix, _suffix, _type ) \
static inline __always_inline void \
IOAPI_INLINE ( _prefix, out ## _suffix ) ( _type data __unused, \
volatile _type *io_addr __unused ){\
/* Do nothing */ \
} \
static inline __always_inline void \
IOAPI_INLINE ( _prefix, outs ## _suffix ) ( volatile _type *io_addr __unused, \
const _type *data __unused, \
unsigned int count __unused ) { \
/* Do nothing */ \
}
#define DUMMY_IODELAY( _prefix ) \
static inline __always_inline void \
IOAPI_INLINE ( _prefix, iodelay ) ( void ) { \
/* Nothing to do */ \
}
#define DUMMY_PIO( _prefix ) \
DUMMY_INX ( _prefix, b, uint8_t ); \
DUMMY_INX ( _prefix, w, uint16_t ); \
DUMMY_INX ( _prefix, l, uint32_t ); \
DUMMY_OUTX ( _prefix, b, uint8_t ); \
DUMMY_OUTX ( _prefix, w, uint16_t ); \
DUMMY_OUTX ( _prefix, l, uint32_t ); \
DUMMY_IODELAY ( _prefix );
#define PROVIDE_DUMMY_PIO( _prefix ) \
PROVIDE_IOAPI_INLINE ( _prefix, inb ); \
PROVIDE_IOAPI_INLINE ( _prefix, inw ); \
PROVIDE_IOAPI_INLINE ( _prefix, inl ); \
PROVIDE_IOAPI_INLINE ( _prefix, outb ); \
PROVIDE_IOAPI_INLINE ( _prefix, outw ); \
PROVIDE_IOAPI_INLINE ( _prefix, outl ); \
PROVIDE_IOAPI_INLINE ( _prefix, iodelay );
#endif /* _IPXE_DUMMY_PIO_H */

View File

@ -133,17 +133,30 @@ struct interface {
struct interface *dest;
/** Reference counter
*
* If this interface is not part of a reference-counted
* object, this field may be NULL.
* If this interface is not part of a reference-counted object
* then this field is NULL.
*/
struct refcnt *refcnt;
/** Interface descriptor */
struct interface_descriptor *desc;
/** Original interface descriptor
/** Interface descriptor
*
* Used by intf_reinit().
* If this is a temporary outbound-only interface created by
* intf_temp_init() then this field is NULL.
*/
struct interface_descriptor *original;
struct interface_descriptor *desc;
/** Original interface properties */
union {
/** Original interface descriptor
*
* Used by intf_reinit().
*/
struct interface_descriptor *desc;
/** Original interface
*
* Used for temporary outbound-only interfaces created
* by intf_temp_init().
*/
struct interface *intf;
} original;
};
extern void intf_plug ( struct interface *intf, struct interface *dest );
@ -193,7 +206,7 @@ static inline void intf_init ( struct interface *intf,
intf->dest = &null_intf;
intf->refcnt = refcnt;
intf->desc = desc;
intf->original = desc;
intf->original.desc = desc;
}
/**
@ -201,13 +214,38 @@ static inline void intf_init ( struct interface *intf,
*
* @v descriptor Object interface descriptor
*/
#define INTF_INIT( descriptor ) { \
.dest = &null_intf, \
.refcnt = NULL, \
.desc = &(descriptor), \
.original = &(descriptor), \
#define INTF_INIT( descriptor ) { \
.dest = &null_intf, \
.refcnt = NULL, \
.desc = &(descriptor), \
.original = { \
.desc = &(descriptor), \
}, \
}
/**
* Initialise a temporary outbound-only object interface
*
* @v intf Temporary outbound-only object interface
* @v original Original object interface
*/
static inline void intf_temp_init ( struct interface *intf,
struct interface *original ) {
intf->dest = &null_intf;
intf->desc = NULL;
intf->original.intf = original;
}
/**
* Get original interface
*
* @v intf Object interface (possibly a temporary interface)
* @ret intf Original object interface
*/
static inline struct interface * intf_origin ( struct interface *intf ) {
return ( intf->desc ? intf : intf->original.intf );
}
/**
* Get object interface destination and operation method (without pass-through)
*
@ -240,7 +278,7 @@ static inline void intf_init ( struct interface *intf,
*
* Use as the first argument to DBGC() or equivalent macro.
*/
#define INTF_COL( intf ) intf_object ( intf )
#define INTF_COL( intf ) intf_object ( intf_origin ( intf ) )
/** printf() format string for INTF_DBG() */
#define INTF_FMT "%p+%zx"
@ -251,7 +289,9 @@ static inline void intf_init ( struct interface *intf,
* @v intf Object interface
* @ret args printf() argument list corresponding to INTF_FMT
*/
#define INTF_DBG( intf ) intf_object ( intf ), (intf)->desc->offset
#define INTF_DBG( intf ) \
intf_object ( intf_origin ( intf ) ), \
intf_origin ( intf )->desc->offset
/** printf() format string for INTF_INTF_DBG() */
#define INTF_INTF_FMT INTF_FMT "->" INTF_FMT
@ -273,7 +313,7 @@ static inline void intf_init ( struct interface *intf,
static inline void intf_reinit ( struct interface *intf ) {
/* Restore original interface descriptor */
intf->desc = intf->original;
intf->desc = intf->original.desc;
}
#endif /* _IPXE_INTERFACE_H */

View File

@ -52,10 +52,10 @@ struct keymap {
#define KEYMAP_PSEUDO 0x80
/** Ctrl key flag */
#define KEYMAP_CTRL 0x0100
#define KEYMAP_CTRL 0x01000000
/** CapsLock key flag */
#define KEYMAP_CAPSLOCK 0x0200
#define KEYMAP_CAPSLOCK 0x02000000
/** Undo CapsLock key flag
*
@ -64,13 +64,13 @@ struct keymap {
* in order to correctly handle keyboard mappings that swap alphabetic
* and non-alphabetic keys.
*/
#define KEYMAP_CAPSLOCK_UNDO 0x0400
#define KEYMAP_CAPSLOCK_UNDO 0x04000000
/** Undo and redo CapsLock key flags */
#define KEYMAP_CAPSLOCK_REDO ( KEYMAP_CAPSLOCK | KEYMAP_CAPSLOCK_UNDO )
/** AltGr key flag */
#define KEYMAP_ALTGR 0x0800
#define KEYMAP_ALTGR 0x08000000
extern unsigned int key_remap ( unsigned int character );
extern struct keymap * keymap_find ( const char *name );

View File

@ -49,19 +49,58 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define ESC 0x1b
/*
* Special keys outside the normal ASCII range
*
* Special keys outside the normal Unicode range
*
* The names are chosen to match those used by curses. The values are
* chosen to facilitate easy conversion from a received ANSI escape
* sequence to a KEY_XXX constant.
*
* Note that the values are exposed to iPXE commands via parse_key()
* and therefore may not be changed without breaking existing scripts.
*/
#define KEY_ANSI( n, terminator ) ( 0x100 * ( (n) + 1 ) + (terminator) )
#define KEY_ANSI_N( key ) ( ( (key) / 0x100 ) - 1 )
/**
* Minimum value for special keypresses
*
* This value is chosen to lie above the maximum Unicode code point
* value 0x10ffff.
*/
#define KEY_MIN 0x110000
/**
* Construct relative key value for special key
*
* @v key Key value
* @ret rkey Relative key value
*/
#define KEY_REL( key ) ( (key) - KEY_MIN )
/**
* Construct ANSI escape sequence key value
*
* @v n ANSI escape sequence numeric portion, or 0 for none
* @v terminator ANSI escape sequence terminating character
* @ret key Key value
*/
#define KEY_ANSI( n, terminator ) \
( KEY_MIN + ( ( (n) + 1 ) << 8 ) + (terminator) )
/**
* Extract ANSI escape sequence numeric portion
*
* @v key Key value (or relative key value)
* @ret n ANSI escape sequence numeric portion, or 0 for none
*/
#define KEY_ANSI_N( key ) ( ( ( (key) >> 8 ) & 0xff ) - 1 )
/**
* Extract ANSI escape sequence terminating character
*
* @v key Key value (or relative key value)
* @ret terminator ANSI escape sequence terminating character
*/
#define KEY_ANSI_TERMINATOR( key ) ( (key) & 0xff )
#define KEY_MIN 0x101
#define KEY_UP KEY_ANSI ( 0, 'A' ) /**< Up arrow */
#define KEY_DOWN KEY_ANSI ( 0, 'B' ) /**< Down arrow */
#define KEY_RIGHT KEY_ANSI ( 0, 'C' ) /**< Right arrow */

View File

@ -37,8 +37,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
*
*/
/** A driver veto */
struct efi_veto {
/** A driver veto candidate */
struct efi_veto_candidate {
/** Veto name (for debugging) */
const char *name;
/**
@ -57,22 +57,38 @@ struct efi_veto {
const char *manufacturer, const CHAR16 *name );
};
/** A driver veto */
struct efi_veto {
/** Driver binding handle */
EFI_HANDLE driver;
/** Driving binding protocol */
EFI_DRIVER_BINDING_PROTOCOL *binding;
/** Image handle */
EFI_HANDLE image;
/** Loaded image protocol */
EFI_LOADED_IMAGE_PROTOCOL *loaded;
};
/**
* Unload an EFI driver
*
* @v driver Driver binding handle
* @v veto Driver veto
* @ret rc Return status code
*/
static int efi_veto_unload ( EFI_HANDLE driver ) {
static int efi_veto_unload ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE driver = veto->driver;
EFI_HANDLE image = veto->image;
EFI_STATUS efirc;
int rc;
/* Unload the driver */
if ( ( efirc = bs->UnloadImage ( driver ) ) != 0 ) {
if ( ( efirc = bs->UnloadImage ( image ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( driver, "EFIVETO %s could not unload: %s\n",
efi_handle_name ( driver ), strerror ( rc ) );
DBGC ( driver, "EFIVETO %s could not unload",
efi_handle_name ( driver ) );
DBGC ( driver, " %s: %s\n", efi_handle_name ( image ),
strerror ( rc ) );
return rc;
}
@ -82,11 +98,12 @@ static int efi_veto_unload ( EFI_HANDLE driver ) {
/**
* Disconnect an EFI driver from all handles
*
* @v driver Driver binding handle
* @v veto Driver veto
* @ret rc Return status code
*/
static int efi_veto_disconnect ( EFI_HANDLE driver ) {
static int efi_veto_disconnect ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE driver = veto->driver;
EFI_HANDLE *handles;
EFI_HANDLE handle;
UINTN count;
@ -131,11 +148,12 @@ static int efi_veto_disconnect ( EFI_HANDLE driver ) {
/**
* Uninstall an EFI driver binding protocol
*
* @v driver Driver binding handle
* @v veto Driver veto
* @ret rc Return status code
*/
static int efi_veto_uninstall ( EFI_HANDLE driver ) {
static int efi_veto_uninstall ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE driver = veto->driver;
union {
EFI_DRIVER_BINDING_PROTOCOL *binding;
void *interface;
@ -178,14 +196,16 @@ static int efi_veto_uninstall ( EFI_HANDLE driver ) {
/**
* Close protocol on handle potentially opened by an EFI driver
*
* @v driver Driver binding handle
* @v veto Driver veto
* @v handle Potentially opened handle
* @v protocol Opened protocol
* @ret rc Return status code
*/
static int efi_veto_close_protocol ( EFI_HANDLE driver, EFI_HANDLE handle,
static int efi_veto_close_protocol ( struct efi_veto *veto, EFI_HANDLE handle,
EFI_GUID *protocol ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE driver = veto->driver;
EFI_HANDLE image = veto->image;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *openers;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *opener;
EFI_HANDLE controller;
@ -207,9 +227,11 @@ static int efi_veto_close_protocol ( EFI_HANDLE driver, EFI_HANDLE handle,
/* Close anything opened by this driver */
for ( i = 0 ; i < count ; i++ ) {
opener = &openers[i];
if ( opener->AgentHandle != driver )
opener = &openers[ count - i - 1 ];
if ( ( opener->AgentHandle != driver ) &&
( opener->AgentHandle != image ) ) {
continue;
}
controller = opener->ControllerHandle;
DBGC_EFI_OPENER ( driver, handle, protocol, opener );
if ( ( efirc = bs->CloseProtocol ( handle, protocol, driver,
@ -235,13 +257,15 @@ static int efi_veto_close_protocol ( EFI_HANDLE driver, EFI_HANDLE handle,
/**
* Close handle potentially opened by an EFI driver
*
* @v driver Driver binding handle
* @v veto Driver veto
* @v handle Potentially opened handle
* @ret rc Return status code
*/
static int efi_veto_close_handle ( EFI_HANDLE driver, EFI_HANDLE handle ) {
static int efi_veto_close_handle ( struct efi_veto *veto, EFI_HANDLE handle ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE driver = veto->driver;
EFI_GUID **protocols;
EFI_GUID *protocol;
UINTN count;
unsigned int i;
EFI_STATUS efirc;
@ -260,8 +284,9 @@ static int efi_veto_close_handle ( EFI_HANDLE driver, EFI_HANDLE handle ) {
/* Close each protocol */
for ( i = 0 ; i < count ; i++ ) {
if ( ( rc = efi_veto_close_protocol ( driver, handle,
protocols[i] ) ) != 0 )
protocol = protocols[ count - i - 1];
if ( ( rc = efi_veto_close_protocol ( veto, handle,
protocol ) ) != 0 )
goto err_close;
}
@ -277,12 +302,14 @@ static int efi_veto_close_handle ( EFI_HANDLE driver, EFI_HANDLE handle ) {
/**
* Close all remaining handles opened by an EFI driver
*
* @v driver Driver binding handle
* @v veto Driver veto
* @ret rc Return status code
*/
static int efi_veto_close ( EFI_HANDLE driver ) {
static int efi_veto_close ( struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
EFI_HANDLE driver = veto->driver;
EFI_HANDLE *handles;
EFI_HANDLE handle;
UINTN count;
unsigned int i;
EFI_STATUS efirc;
@ -299,8 +326,8 @@ static int efi_veto_close ( EFI_HANDLE driver ) {
/* Close each handle */
for ( i = 0 ; i < count ; i++ ) {
if ( ( rc = efi_veto_close_handle ( driver,
handles[i] ) ) != 0 )
handle = handles[ count - i - 1 ];
if ( ( rc = efi_veto_close_handle ( veto, handle ) ) != 0 )
goto err_close;
}
@ -318,22 +345,23 @@ static int efi_veto_close ( EFI_HANDLE driver ) {
/**
* Terminate an EFI driver with extreme prejudice
*
* @v driver Driver binding handle
* @v veto Driver veto
* @ret rc Return status code
*/
static int efi_veto_destroy ( EFI_HANDLE driver ) {
static int efi_veto_destroy ( struct efi_veto *veto ) {
EFI_HANDLE driver = veto->driver;
int rc;
/* Disconnect driver from all handles */
if ( ( rc = efi_veto_disconnect ( driver ) ) != 0 )
if ( ( rc = efi_veto_disconnect ( veto ) ) != 0 )
return rc;
/* Uninstall driver binding protocol */
if ( ( rc = efi_veto_uninstall ( driver ) ) != 0 )
if ( ( rc = efi_veto_uninstall ( veto ) ) != 0 )
return rc;
/* Close any remaining opened handles */
if ( ( rc = efi_veto_close ( driver ) ) != 0 )
if ( ( rc = efi_veto_close ( veto ) ) != 0 )
return rc;
DBGC ( driver, "EFIVETO %s forcibly removed\n",
@ -344,18 +372,18 @@ static int efi_veto_destroy ( EFI_HANDLE driver ) {
/**
* Veto an EFI driver
*
* @v driver Driver binding handle
* @v veto Driver veto
* @ret rc Return status code
*/
static int efi_veto_driver ( EFI_HANDLE driver ) {
static int efi_veto_driver ( struct efi_veto *veto ) {
int rc;
/* Try gracefully unloading the driver */
if ( ( rc = efi_veto_unload ( driver ) ) == 0 )
if ( ( rc = efi_veto_unload ( veto ) ) == 0 )
return 0;
/* If that fails, use a hammer */
if ( ( rc = efi_veto_destroy ( driver ) ) == 0 )
if ( ( rc = efi_veto_destroy ( veto ) ) == 0 )
return 0;
return rc;
@ -467,7 +495,7 @@ efi_veto_vmware_uefipxebc ( EFI_DRIVER_BINDING_PROTOCOL *binding __unused,
}
/** Driver vetoes */
static struct efi_veto efi_vetoes[] = {
static struct efi_veto_candidate efi_vetoes[] = {
{
.name = "Ip4Config",
.veto = efi_veto_ip4config,
@ -487,11 +515,11 @@ static struct efi_veto efi_vetoes[] = {
*
* @v driver Driver binding handle
* @v manufacturer Manufacturer name, if present
* @ret veto Driver veto, or NULL
* @ret veto Driver veto to fill in
* @ret rc Return status code
*/
static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
struct efi_veto **veto ) {
struct efi_veto *veto ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
union {
EFI_DRIVER_BINDING_PROTOCOL *binding;
@ -515,7 +543,7 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
efi_handle_name ( driver ) );
/* Mark as not vetoed */
*veto = NULL;
memset ( veto, 0, sizeof ( *veto ) );
/* Open driver binding protocol */
if ( ( efirc = bs->OpenProtocol (
@ -567,7 +595,13 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
sizeof ( efi_vetoes[0] ) ) ; i++ ) {
if ( efi_vetoes[i].veto ( binding.binding, loaded.loaded,
wtf.wtf, manufacturer, name ) ) {
*veto = &efi_vetoes[i];
DBGC ( driver, "EFIVETO %s is vetoed (%s)\n",
efi_handle_name ( driver ),
efi_vetoes[i].name );
veto->driver = driver;
veto->binding = binding.binding;
veto->image = image;
veto->loaded = loaded.loaded;
break;
}
}
@ -595,10 +629,10 @@ static int efi_veto_find ( EFI_HANDLE driver, const char *manufacturer,
*/
void efi_veto ( void ) {
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
struct efi_veto *veto;
struct efi_veto veto;
EFI_HANDLE *drivers;
EFI_HANDLE driver;
UINTN num_drivers;
UINTN count;
unsigned int i;
char *manufacturer;
EFI_STATUS efirc;
@ -607,7 +641,7 @@ void efi_veto ( void ) {
/* Locate all driver binding protocol handles */
if ( ( efirc = bs->LocateHandleBuffer (
ByProtocol, &efi_driver_binding_protocol_guid,
NULL, &num_drivers, &drivers ) ) != 0 ) {
NULL, &count, &drivers ) ) != 0 ) {
rc = -EEFI ( efirc );
DBGC ( &efi_vetoes, "EFIVETO could not list all drivers: "
"%s\n", strerror ( rc ) );
@ -617,10 +651,11 @@ void efi_veto ( void ) {
/* Get manufacturer name */
fetch_string_setting_copy ( NULL, &manufacturer_setting,
&manufacturer );
DBGC ( &efi_vetoes, "EFIVETO manufacturer is \"%s\"\n", manufacturer );
/* Unload any vetoed drivers */
for ( i = 0 ; i < num_drivers ; i++ ) {
driver = drivers[i];
for ( i = 0 ; i < count ; i++ ) {
driver = drivers[ count - i - 1 ];
if ( ( rc = efi_veto_find ( driver, manufacturer,
&veto ) ) != 0 ) {
DBGC ( driver, "EFIVETO %s could not determine "
@ -628,11 +663,9 @@ void efi_veto ( void ) {
efi_handle_name ( driver ), strerror ( rc ) );
continue;
}
if ( ! veto )
if ( ! veto.driver )
continue;
DBGC ( driver, "EFIVETO %s is vetoed (%s)\n",
efi_handle_name ( driver ), veto->name );
if ( ( rc = efi_veto_driver ( driver ) ) != 0 ) {
if ( ( rc = efi_veto_driver ( &veto ) ) != 0 ) {
DBGC ( driver, "EFIVETO %s could not veto: %s\n",
efi_handle_name ( driver ), strerror ( rc ) );
}

View File

@ -656,7 +656,7 @@ static void free_netdev ( struct refcnt *refcnt ) {
struct net_device *netdev =
container_of ( refcnt, struct net_device, refcnt );
stop_timer ( &netdev->link_block );
assert ( ! timer_running ( &netdev->link_block ) );
netdev_tx_flush ( netdev );
netdev_rx_flush ( netdev );
clear_settings ( netdev_settings ( netdev ) );
@ -879,6 +879,9 @@ void netdev_close ( struct net_device *netdev ) {
/* Close the device */
netdev->op->close ( netdev );
/* Stop link block timer */
stop_timer ( &netdev->link_block );
/* Flush TX and RX queues */
netdev_tx_flush ( netdev );
netdev_rx_flush ( netdev );

View File

@ -91,9 +91,10 @@ static uint8_t dhcp_request_options_data[] = {
DHCP_PARAMETER_REQUEST_LIST,
DHCP_OPTION ( DHCP_SUBNET_MASK, DHCP_ROUTERS, DHCP_DNS_SERVERS,
DHCP_LOG_SERVERS, DHCP_HOST_NAME, DHCP_DOMAIN_NAME,
DHCP_ROOT_PATH, DHCP_MTU, DHCP_VENDOR_ENCAP,
DHCP_VENDOR_CLASS_ID, DHCP_TFTP_SERVER_NAME,
DHCP_BOOTFILE_NAME, DHCP_DOMAIN_SEARCH,
DHCP_ROOT_PATH, DHCP_MTU, DHCP_NTP_SERVERS,
DHCP_VENDOR_ENCAP, DHCP_VENDOR_CLASS_ID,
DHCP_TFTP_SERVER_NAME, DHCP_BOOTFILE_NAME,
DHCP_DOMAIN_SEARCH,
128, 129, 130, 131, 132, 133, 134, 135, /* for PXE */
DHCP_EB_ENCAP, DHCP_ISCSI_INITIATOR_IQN ),
DHCP_END

View File

@ -36,6 +36,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/timer.h>
#include <ipxe/time.h>
#include <ipxe/tcpip.h>
#include <ipxe/dhcp.h>
#include <ipxe/settings.h>
#include <ipxe/ntp.h>
/** @file
@ -273,3 +275,11 @@ int start_ntp ( struct interface *job, const char *hostname ) {
err_alloc:
return rc;
}
/** IPv4 NTP server setting */
const struct setting ntp_setting __setting ( SETTING_IP4_EXTRA, ntp ) = {
.name = "ntp",
.description = "NTP server",
.tag = DHCP_NTP_SERVERS,
.type = &setting_type_ipv4,
};