summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--0001-build-customize-configuration.patch6
-rw-r--r--0002-Use-spec-compliant-timeouts.patch98
-rw-r--r--0003-librm-Use-explicit-operand-size-when-pushing-a-label.patch62
-rw-r--r--backport-allow-for-relative-uris-that-include-colons-within-the-path.patch90
-rw-r--r--backport-avoid-infinite-loop-on-allocation-failure-in.patch69
-rw-r--r--backport-do-not-clear-current-working-url-when-executing-embedded-image.patch56
-rw-r--r--backport-ensure-that-pci_read_config-initialises-all-fields.patch45
-rw-r--r--backport-retain-original-encodings-for-path-query-and-fragment-fields.patch629
-rw-r--r--ipxe.spec259
-rw-r--r--sources1
11 files changed, 1316 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..aa284d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/v1.21.1.tar.gz
diff --git a/0001-build-customize-configuration.patch b/0001-build-customize-configuration.patch
new file mode 100644
index 0000000..045561a
--- /dev/null
+++ b/0001-build-customize-configuration.patch
@@ -0,0 +1,6 @@
+diff -rupN ipxe-20190125-git36a4c85f/src/config/local/general.h ipxe-20190125-git36a4c85f.new/src/config/local/general.h
+--- ipxe-20190125-git36a4c85f/src/config/local/general.h 1970-01-01 01:00:00.000000000 +0100
++++ ipxe-20190125-git36a4c85f.new/src/config/local/general.h 2019-02-01 16:40:42.725293033 +0000
+@@ -0,0 +1,2 @@
++/* Enable IPv6. */
++#define NET_PROTO_IPV6
diff --git a/0002-Use-spec-compliant-timeouts.patch b/0002-Use-spec-compliant-timeouts.patch
new file mode 100644
index 0000000..f1a4d50
--- /dev/null
+++ b/0002-Use-spec-compliant-timeouts.patch
@@ -0,0 +1,98 @@
+From bc252caa54fcfb2e9fd0ddb01ebaa50192e85c38 Mon Sep 17 00:00:00 2001
+From: Alex Williamson <alex.williamson@redhat.com>
+Date: Wed, 21 Oct 2015 11:18:40 +0200
+Subject: Use spec compliant timeouts
+
+Message-id: <20150428212403.31299.29391.stgit@gimli.home>
+Patchwork-id: 64951
+O-Subject: [RHEL7.2 ipxe PATCH 2/2] [dhcp][RHEL-only] Use spec compliant timeouts
+Bugzilla: 1196352
+RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
+RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
+RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
+
+Use local config to override iPXE's abbreviated DHCP timeouts using
+the recommended values for spec compliance. This matches the state
+of RHEL6 gPXE DHCP timeouts after bz968474 + bz1206042
+
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
+(cherry picked from commit 7038f41c0131d263de5165b416500009acdbf550)
+---
+ src/config/local/.gitignore | 1 -
+ src/config/local/dhcp.h | 62 +++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 62 insertions(+), 1 deletion(-)
+ delete mode 100644 src/config/local/.gitignore
+ create mode 100644 src/config/local/dhcp.h
+
+diff --git a/src/config/local/dhcp.h b/src/config/local/dhcp.h
+new file mode 100644
+index 0000000..83df5b8
+--- /dev/null
++++ b/src/config/local/dhcp.h
+@@ -0,0 +1,62 @@
++/*
++ * Downstream localization
++ *
++ * For RHEL, use spec compliant DHCP timeouts (bz1196352)
++ */
++
++/*
++ * PXE spec defines timeouts of 4, 8, 16, 32 seconds
++ */
++#undef DHCP_DISC_START_TIMEOUT_SEC
++#define DHCP_DISC_START_TIMEOUT_SEC 4
++#undef DHCP_DISC_END_TIMEOUT_SEC
++#define DHCP_DISC_END_TIMEOUT_SEC 32
++
++/*
++ * Elapsed time used for early break waiting for ProxyDHCP, this therefore
++ * needs to be less than the cumulative time for the first 2 timeouts.
++ */
++#undef DHCP_DISC_PROXY_TIMEOUT_SEC
++#define DHCP_DISC_PROXY_TIMEOUT_SEC 11
++
++/*
++ * Approximate PXE spec requirement using minimum timeout (0.25s) for
++ * timeouts of 0.25, 0.5, 1, 2, 4
++ */
++#undef DHCP_REQ_START_TIMEOUT_SEC
++#define DHCP_REQ_START_TIMEOUT_SEC 0
++#undef DHCP_REQ_END_TIMEOUT_SEC
++#define DHCP_REQ_END_TIMEOUT_SEC 4
++
++/*
++ * Same as normal request phase, except non-fatal, so we extend the timer
++ * to 8 and set the early timeout to an elapsed time value that causes a
++ * break after the 4 second timeout. At least that's what we'd like to do,
++ * but our timer operates at 18Hz and has a minimum resolution of 7 cycles.
++ * Therefore the above quarter-second starting timeout looks more like
++ * 0.39s, 0.78s, 1.56s, 3.11s, 6.22s. If we had an ideal timer, we could
++ * set the timeout to 7s (0.25 + 0.5 + 1 + 2 + 4 = 7.75s) and exit without
++ * failure when the timer rolls over to 8s. With our timer, we get 0.39 +
++ * 0.78 + 1.56 + 3.11 = 5.84s. The next timeout would take us to 12.06s
++ * (+6.22). That seems like a long time to wait for an optional reply, so
++ * we reduce the early timeout to 5s to exit before the timer exceeds the
++ * max and causes a failure. This still adds one extra cycle vs the
++ * upstream defaults.
++ */
++#undef DHCP_PROXY_START_TIMEOUT_SEC
++#define DHCP_PROXY_START_TIMEOUT_SEC 0
++#undef DHCP_PROXY_END_TIMEOUT_SEC
++#define DHCP_PROXY_END_TIMEOUT_SEC 8
++#undef DHCP_REQ_PROXY_TIMEOUT_SEC
++#define DHCP_REQ_PROXY_TIMEOUT_SEC 5
++
++/*
++ * Same as above, retry each server using our approximation of standard
++ * timeouts and exit before timer induced failure.
++ */
++#undef PXEBS_START_TIMEOUT_SEC
++#define PXEBS_START_TIMEOUT_SEC 0
++#undef PXEBS_END_TIMEOUT_SEC
++#define PXEBS_END_TIMEOUT_SEC 8
++#undef PXEBS_MAX_TIMEOUT_SEC
++#define PXEBS_MAX_TIMEOUT_SEC 5
+--
+1.8.3.1
+
diff --git a/0003-librm-Use-explicit-operand-size-when-pushing-a-label.patch b/0003-librm-Use-explicit-operand-size-when-pushing-a-label.patch
new file mode 100644
index 0000000..6aa5107
--- /dev/null
+++ b/0003-librm-Use-explicit-operand-size-when-pushing-a-label.patch
@@ -0,0 +1,62 @@
+From 0aa2e4ec963597794dd8f8b36f77f4d0cf4e03c8 Mon Sep 17 00:00:00 2001
+From: Michael Brown <mcb30@ipxe.org>
+Date: Tue, 5 Sep 2023 19:47:38 +0800
+Subject: [PATCH] [librm] Use explicit operand size when pushing a label
+ address
+
+We currently use "push $1f" within inline assembly to push the address
+of the real-mode code fragment, relying on the assembler to treat this
+as "pushl" for 32-bit code or "pushq" for 64-bit code.
+
+As of binutils commit 5cc0077 ("x86: further adjust extend-to-32bit-
+address conditions"), first included in binutils-2.41, this implicit
+operand size is no longer calculated as expected and 64-bit builds
+will fail with
+
+ Error: operand size mismatch for `push'
+
+Fix by adding an explicit operand size to the "push" instruction.
+
+Originally-fixed-by: Justin Cano <jstncno@gmail.com>
+Signed-off-by: Michael Brown <mcb30@ipxe.org>
+
+---
+ src/arch/x86/include/librm.h | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/arch/x86/include/librm.h b/src/arch/x86/include/librm.h
+index 5196d39..40f0754 100644
+--- a/src/arch/x86/include/librm.h
++++ b/src/arch/x86/include/librm.h
+@@ -250,8 +250,10 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
+ /* CODE_DEFAULT: restore default .code32/.code64 directive */
+ #ifdef __x86_64__
+ #define CODE_DEFAULT ".code64"
++#define STACK_DEFAULT "q"
+ #else
+ #define CODE_DEFAULT ".code32"
++#define STACK_DEFAULT "l"
+ #endif
+
+ /* LINE_SYMBOL: declare a symbol for the current source code line */
+@@ -268,7 +270,7 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
+
+ /* REAL_CODE: declare a fragment of code that executes in real mode */
+ #define REAL_CODE( asm_code_str ) \
+- "push $1f\n\t" \
++ "push" STACK_DEFAULT " $1f\n\t" \
+ "call real_call\n\t" \
+ TEXT16_CODE ( "\n1:\n\t" \
+ asm_code_str \
+@@ -277,7 +279,7 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
+
+ /* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
+ #define PHYS_CODE( asm_code_str ) \
+- "push $1f\n\t" \
++ "push" STACK_DEFAULT " $1f\n\t" \
+ "call phys_call\n\t" \
+ ".section \".text.phys\", \"ax\", @progbits\n\t"\
+ "\n" LINE_SYMBOL "\n\t" \
+--
+2.44.0
+
diff --git a/backport-allow-for-relative-uris-that-include-colons-within-the-path.patch b/backport-allow-for-relative-uris-that-include-colons-within-the-path.patch
new file mode 100644
index 0000000..4bb1747
--- /dev/null
+++ b/backport-allow-for-relative-uris-that-include-colons-within-the-path.patch
@@ -0,0 +1,90 @@
+From e814d33900992e034a8c3ddec2c65463c5206090 Mon Sep 17 00:00:00 2001
+From: Michael Brown <mcb30@ipxe.org>
+Date: Thu, 13 Jan 2022 14:53:36 +0000
+Subject: [PATCH] [uri] Allow for relative URIs that include colons within the
+ path
+
+RFC3986 allows for colons to appear within the path component of a
+relative URI, but iPXE will currently parse such URIs incorrectly by
+interpreting the text before the colon as the URI scheme.
+
+Fix by checking for valid characters when identifying the URI scheme.
+Deliberately deviate from the RFC3986 definition of valid characters
+by accepting "_" (which was incorrectly used in the iPXE-specific
+"ib_srp" URI scheme and so must be accepted for compatibility with
+existing deployments), and by omitting the code to check for
+characters that are not used in any URI scheme supported by iPXE.
+
+Reported-by: Ignat Korchagin <ignat@cloudflare.com>
+Signed-off-by: Michael Brown <mcb30@ipxe.org>
+
+Conflict:NA
+Reference:https://github.com/ipxe/ipxe/commit/e814d33900992e034a8c3ddec2c65463c5206090
+---
+ src/core/uri.c | 15 ++++++++++-----
+ src/tests/uri_test.c | 10 ++++++++++
+ 2 files changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/src/core/uri.c b/src/core/uri.c
+index a0f79e9ec1..b82472ef03 100644
+--- a/src/core/uri.c
++++ b/src/core/uri.c
+@@ -334,8 +334,15 @@ struct uri * parse_uri ( const char *uri_string ) {
+ uri->efragment = tmp;
+ }
+
+- /* Identify absolute/relative URI */
+- if ( ( tmp = strchr ( raw, ':' ) ) ) {
++ /* Identify absolute URIs */
++ epath = raw;
++ for ( tmp = raw ; ; tmp++ ) {
++ /* Possible scheme character (for our URI schemes) */
++ if ( isalpha ( *tmp ) || ( *tmp == '-' ) || ( *tmp == '_' ) )
++ continue;
++ /* Invalid scheme character or NUL: is a relative URI */
++ if ( *tmp != ':' )
++ break;
+ /* Absolute URI: identify hierarchical/opaque */
+ uri->scheme = raw;
+ *(tmp++) = '\0';
+@@ -347,9 +354,7 @@ struct uri * parse_uri ( const char *uri_string ) {
+ uri->opaque = tmp;
+ epath = NULL;
+ }
+- } else {
+- /* Relative URI */
+- epath = raw;
++ break;
+ }
+
+ /* If we don't have a path (i.e. we have an absolute URI with
+diff --git a/src/tests/uri_test.c b/src/tests/uri_test.c
+index 929ab36325..338f479cd3 100644
+--- a/src/tests/uri_test.c
++++ b/src/tests/uri_test.c
+@@ -657,6 +657,15 @@ static struct uri_test uri_file_volume = {
+ },
+ };
+
++/** Relative URI with colons in path */
++static struct uri_test uri_colons = {
++ "/boot/52:54:00:12:34:56/boot.ipxe",
++ {
++ .path = "/boot/52:54:00:12:34:56/boot.ipxe",
++ .epath = "/boot/52:54:00:12:34:56/boot.ipxe",
++ },
++};
++
+ /** URI with port number */
+ static struct uri_port_test uri_explicit_port = {
+ "http://192.168.0.1:8080/boot.php",
+@@ -957,6 +966,7 @@ static void uri_test_exec ( void ) {
+ uri_parse_format_dup_ok ( &uri_file_relative );
+ uri_parse_format_dup_ok ( &uri_file_absolute );
+ uri_parse_format_dup_ok ( &uri_file_volume );
++ uri_parse_format_dup_ok ( &uri_colons );
+
+ /** URI port number tests */
+ uri_port_ok ( &uri_explicit_port );
+
+
diff --git a/backport-avoid-infinite-loop-on-allocation-failure-in.patch b/backport-avoid-infinite-loop-on-allocation-failure-in.patch
new file mode 100644
index 0000000..8dffce5
--- /dev/null
+++ b/backport-avoid-infinite-loop-on-allocation-failure-in.patch
@@ -0,0 +1,69 @@
+From 614d99eba149d0fafc64dfdddc7ef04970e0d86c Mon Sep 17 00:00:00 2001
+From: Michael Brown <mcb30@ipxe.org>
+Date: Tue, 20 Apr 2021 13:28:57 +0100
+Subject: [PATCH] [xen] Avoid infinite loop on allocation failure in
+ xenstore_response()
+Signed-off-by: Michael Brown <mcb30@ipxe.org>
+Conflict:NA
+Reference:https://github.com/ipxe/ipxe/commit/614d99eba149d0fafc64dfdddc7ef04970e0d86c
+---
+ src/interface/xen/xenstore.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+diff --git a/src/interface/xen/xenstore.c b/src/interface/xen/xenstore.c
+index a14881f..c2da532 100644
+--- a/src/interface/xen/xenstore.c
++++ b/src/interface/xen/xenstore.c
+@@ -68,14 +68,14 @@ static void xenstore_send ( struct xen_hypervisor *xen, const void *data,
+ XENSTORE_RING_IDX cons;
+ XENSTORE_RING_IDX idx;
+ const char *bytes = data;
+- size_t offset = 0;
++ size_t offset;
+ size_t fill;
+
+ DBGCP ( intf, "XENSTORE raw request:\n" );
+ DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len );
+
+ /* Write one byte at a time */
+- while ( offset < len ) {
++ for ( offset =0 ; offset < len ; offset++ ) {
+
+ /* Wait for space to become available */
+ while ( 1 ) {
+@@ -90,7 +90,7 @@ static void xenstore_send ( struct xen_hypervisor *xen, const void *data,
+
+ /* Write byte */
+ idx = MASK_XENSTORE_IDX ( prod++ );
+- writeb ( bytes[offset++], &intf->req[idx] );
++ writeb ( bytes[offset], &intf->req[idx] );
+ }
+
+ /* Update producer counter */
+@@ -125,13 +125,13 @@ static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
+ XENSTORE_RING_IDX prod;
+ XENSTORE_RING_IDX idx;
+ char *bytes = data;
+- size_t offset = 0;
++ size_t offset;
+ size_t fill;
+
+ DBGCP ( intf, "XENSTORE raw response:\n" );
+
+ /* Read one byte at a time */
+- while ( offset < len ) {
++ for ( offset = 0 ; offset < len ; offset++ ) {
+
+ /* Wait for data to be ready */
+ while ( 1 ) {
+@@ -147,7 +147,7 @@ static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
+ /* Read byte */
+ idx = MASK_XENSTORE_IDX ( cons++ );
+ if ( data )
+- bytes[offset++] = readb ( &intf->rsp[idx] );
++ bytes[offset] = readb ( &intf->rsp[idx] );
+ }
+ if ( data )
+ DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len );
+--
+2.23.0
+
diff --git a/backport-do-not-clear-current-working-url-when-executing-embedded-image.patch b/backport-do-not-clear-current-working-url-when-executing-embedded-image.patch
new file mode 100644
index 0000000..06b8081
--- /dev/null
+++ b/backport-do-not-clear-current-working-url-when-executing-embedded-image.patch
@@ -0,0 +1,56 @@
+From 5d22307c4161dde453d50e8dc7bef8b3a2f6c9b3 Mon Sep 17 00:00:00 2001
+From: Michael Brown <mcb30@ipxe.org>
+Date: Tue, 15 Feb 2022 14:28:01 +0000
+Subject: [PATCH] [image] Do not clear current working URI when executing
+ embedded image
+
+Embedded images do not have an associated URI. This currently causes
+the current working URI (cwuri) to be cleared when starting an
+embedded image.
+
+If the current working URI has been set via a ${next-server} setting
+from a cached DHCP packet then this will result in unexpected
+behaviour. An attempt by the embedded script to use a relative URI to
+download files from the TFTP server will fail with the error:
+
+ Could not start download: Operation not supported (ipxe.org/3c092083)
+
+Rerunning the "dhcp" command will not fix this error, since the TFTP
+settings applicator will not see any change to the ${next-server}
+setting and so will not reset the current working URI.
+
+Fix by setting the current working URI to the image's URI only if the
+image actually has an associated URI.
+
+Debugged-by: Ignat Korchagin <ignat@cloudflare.com>
+Originally-fixed-by: Ignat Korchagin <ignat@cloudflare.com>
+Tested-by: Ignat Korchagin <ignat@cloudflare.com>
+Signed-off-by: Michael Brown <mcb30@ipxe.org>
+
+Conflict:NA
+Reference:https://github.com/ipxe/ipxe/commit/5d22307c4161dde453d50e8dc7bef8b3a2f6c9b3
+---
+ src/core/image.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/core/image.c b/src/core/image.c
+index ce8cf868b0..3e236ca603 100644
+--- a/src/core/image.c
++++ b/src/core/image.c
+@@ -338,9 +338,12 @@ int image_exec ( struct image *image ) {
+ /* Sanity check */
+ assert ( image->flags & IMAGE_REGISTERED );
+
+- /* Switch current working directory to be that of the image itself */
++ /* Switch current working directory to be that of the image
++ * itself, if applicable
++ */
+ old_cwuri = uri_get ( cwuri );
+- churi ( image->uri );
++ if ( image->uri )
++ churi ( image->uri );
+
+ /* Preserve record of any currently-running image */
+ saved_current_image = current_image;
+
+
diff --git a/backport-ensure-that-pci_read_config-initialises-all-fields.patch b/backport-ensure-that-pci_read_config-initialises-all-fields.patch
new file mode 100644
index 0000000..a03b950
--- /dev/null
+++ b/backport-ensure-that-pci_read_config-initialises-all-fields.patch
@@ -0,0 +1,45 @@
+From 04288974f6d81019314cbf9cbd72ab1fae95496f Mon Sep 17 00:00:00 2001
+From: Michael Brown <mcb30@ipxe.org>
+Date: Wed, 16 Feb 2022 12:30:02 +0000
+Subject: [PATCH] [pci] Ensure that pci_read_config() initialises all fields
+
+As per the general pattern for initialisation functions in iPXE,
+pci_init() saves code size by assuming that the caller has already
+zeroed the underlying storage (e.g. as part of zeroing a larger
+containing structure). There are several places within the code where
+pci_init() is deliberately used to initialise a transient struct
+pci_device without zeroing the entire structure, because the calling
+code knows that only the PCI bus:dev.fn address is required to be
+initialised (e.g. when reading from PCI configuration space).
+
+Ensure that using pci_init() followed by pci_read_config() will fully
+initialise the struct pci_device even if the caller did not previously
+zero the underlying storage, since Coverity reports that there are
+several places in the code that rely upon this.
+
+Signed-off-by: Michael Brown <mcb30@ipxe.org>
+
+Conflict:NA
+Reference:https://github.com/ipxe/ipxe/commit/04288974f6d81019314cbf9cbd72ab1fae95496f
+---
+ src/drivers/bus/pci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c
+index 1b7350c8b8..5891e42ff4 100644
+--- a/src/drivers/bus/pci.c
++++ b/src/drivers/bus/pci.c
+@@ -121,6 +121,11 @@ static void pci_read_bases ( struct pci_device *pci ) {
+ unsigned long bar;
+ int reg;
+
++ /* Clear any existing base addresses */
++ pci->ioaddr = 0;
++ pci->membase = 0;
++
++ /* Get first memory and I/O BAR addresses */
+ for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4 ) {
+ bar = pci_bar ( pci, reg );
+ if ( bar & PCI_BASE_ADDRESS_SPACE_IO ) {
+
+
diff --git a/backport-retain-original-encodings-for-path-query-and-fragment-fields.patch b/backport-retain-original-encodings-for-path-query-and-fragment-fields.patch
new file mode 100644
index 0000000..0ba9b05
--- /dev/null
+++ b/backport-retain-original-encodings-for-path-query-and-fragment-fields.patch
@@ -0,0 +1,629 @@
+From 1844aacc837bf81cb1959fa65f2e52dcc70a0cae Mon Sep 17 00:00:00 2001
+From: Michael Brown <mcb30@ipxe.org>
+Date: Thu, 11 Nov 2021 23:31:23 +0000
+Subject: [PATCH] [uri] Retain original encodings for path, query, and fragment
+ fields
+
+iPXE decodes any percent-encoded characters during the URI parsing
+stage, thereby allowing protocol implementations to consume the raw
+field values directly without further decoding.
+
+When reconstructing a URI string for use in an HTTP request line, the
+percent-encoding is currently reapplied in a reversible way: we
+guarantee that our reconstructed URI string could be decoded to give
+the same raw field values.
+
+This technically violates RFC3986, which states that "URIs that differ
+in the replacement of a reserved character with its corresponding
+percent-encoded octet are not equivalent". Experiments show that
+several HTTP server applications will attach meaning to the choice of
+whether or not a particular character was percent-encoded, even when
+the percent-encoding is unnecessary from the perspective of parsing
+the URI into its component fields.
+
+Fix by storing the originally encoded substrings for the path, query,
+and fragment fields and using these original encoded versions when
+reconstructing a URI string. The path field is also stored as a
+decoded string, for use by protocols such as TFTP that communicate
+using raw strings rather than URI-encoded strings. All other fields
+(such as the username and password) continue to be stored only in
+their decoded versions since nothing ever needs to know the originally
+encoded versions of these fields.
+
+Signed-off-by: Michael Brown <mcb30@ipxe.org>
+
+Conflict:NA
+Reference:https://github.com/ipxe/ipxe/commit/1844aacc837bf81cb1959fa65f2e52dcc70a0cae
+---
+ src/core/uri.c | 131 +++++++++++++++++++++++++----------------
+ src/include/ipxe/uri.h | 31 +++++++---
+ src/net/tcp/httpcore.c | 4 +-
+ src/tests/uri_test.c | 53 +++++++++++++----
+ src/usr/imgmgmt.c | 4 +-
+ 5 files changed, 148 insertions(+), 75 deletions(-)
+
+diff --git a/src/core/uri.c b/src/core/uri.c
+index e9e512ab4a..a0f79e9ec1 100644
+--- a/src/core/uri.c
++++ b/src/core/uri.c
+@@ -79,12 +79,10 @@ size_t uri_decode ( const char *encoded, void *buf, size_t len ) {
+ /**
+ * Decode URI field in-place
+ *
+- * @v uri URI
+- * @v field URI field index
++ * @v encoded Encoded field, or NULL
+ */
+-static void uri_decode_inplace ( struct uri *uri, unsigned int field ) {
+- const char *encoded = uri_field ( uri, field );
+- char *decoded = ( ( char * ) encoded );
++static void uri_decode_inplace ( char *encoded ) {
++ char *decoded = encoded;
+ size_t len;
+
+ /* Do nothing if field is not present */
+@@ -150,7 +148,7 @@ static int uri_character_escaped ( char c, unsigned int field ) {
+ * parser but for any other URI parsers (e.g. HTTP query
+ * string parsers, which care about '=' and '&').
+ */
+- static const char *escaped[URI_FIELDS] = {
++ static const char *escaped[URI_EPATH] = {
+ /* Scheme or default: escape everything */
+ [URI_SCHEME] = "/#:@?=&",
+ /* Opaque part: escape characters which would affect
+@@ -172,20 +170,21 @@ static int uri_character_escaped ( char c, unsigned int field ) {
+ * appears within paths.
+ */
+ [URI_PATH] = "#:@?",
+- /* Query: escape everything except '/', which
+- * sometimes appears within queries.
+- */
+- [URI_QUERY] = "#:@?",
+- /* Fragment: escape everything */
+- [URI_FRAGMENT] = "/#:@?",
+ };
+
+- return ( /* Always escape non-printing characters and whitespace */
+- ( ! isprint ( c ) ) || ( c == ' ' ) ||
+- /* Always escape '%' */
+- ( c == '%' ) ||
+- /* Escape field-specific characters */
+- strchr ( escaped[field], c ) );
++ /* Always escape non-printing characters and whitespace */
++ if ( ( ! isprint ( c ) ) || ( c == ' ' ) )
++ return 1;
++
++ /* Escape nothing else in already-escaped fields */
++ if ( field >= URI_EPATH )
++ return 0;
++
++ /* Escape '%' and any field-specific characters */
++ if ( ( c == '%' ) || strchr ( escaped[field], c ) )
++ return 1;
++
++ return 0;
+ }
+
+ /**
+@@ -262,10 +261,12 @@ static void uri_dump ( const struct uri *uri ) {
+ DBGC ( uri, " port \"%s\"", uri->port );
+ if ( uri->path )
+ DBGC ( uri, " path \"%s\"", uri->path );
+- if ( uri->query )
+- DBGC ( uri, " query \"%s\"", uri->query );
+- if ( uri->fragment )
+- DBGC ( uri, " fragment \"%s\"", uri->fragment );
++ if ( uri->epath )
++ DBGC ( uri, " epath \"%s\"", uri->epath );
++ if ( uri->equery )
++ DBGC ( uri, " equery \"%s\"", uri->equery );
++ if ( uri->efragment )
++ DBGC ( uri, " efragment \"%s\"", uri->efragment );
+ if ( uri->params )
+ DBGC ( uri, " params \"%s\"", uri->params->name );
+ }
+@@ -298,17 +299,19 @@ struct uri * parse_uri ( const char *uri_string ) {
+ char *raw;
+ char *tmp;
+ char *path;
++ char *epath;
+ char *authority;
+ size_t raw_len;
+ unsigned int field;
+
+- /* Allocate space for URI struct and a copy of the string */
++ /* Allocate space for URI struct and two copies of the string */
+ raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
+- uri = zalloc ( sizeof ( *uri ) + raw_len );
++ uri = zalloc ( sizeof ( *uri ) + ( 2 * raw_len ) );
+ if ( ! uri )
+ return NULL;
+ ref_init ( &uri->refcnt, uri_free );
+ raw = ( ( ( void * ) uri ) + sizeof ( *uri ) );
++ path = ( raw + raw_len );
+
+ /* Copy in the raw string */
+ memcpy ( raw, uri_string, raw_len );
+@@ -328,7 +331,7 @@ struct uri * parse_uri ( const char *uri_string ) {
+ /* Chop off the fragment, if it exists */
+ if ( ( tmp = strchr ( raw, '#' ) ) ) {
+ *(tmp++) = '\0';
+- uri->fragment = tmp;
++ uri->efragment = tmp;
+ }
+
+ /* Identify absolute/relative URI */
+@@ -338,47 +341,47 @@ struct uri * parse_uri ( const char *uri_string ) {
+ *(tmp++) = '\0';
+ if ( *tmp == '/' ) {
+ /* Absolute URI with hierarchical part */
+- path = tmp;
++ epath = tmp;
+ } else {
+ /* Absolute URI with opaque part */
+ uri->opaque = tmp;
+- path = NULL;
++ epath = NULL;
+ }
+ } else {
+ /* Relative URI */
+- path = raw;
++ epath = raw;
+ }
+
+ /* If we don't have a path (i.e. we have an absolute URI with
+ * an opaque portion, we're already finished processing
+ */
+- if ( ! path )
++ if ( ! epath )
+ goto done;
+
+ /* Chop off the query, if it exists */
+- if ( ( tmp = strchr ( path, '?' ) ) ) {
++ if ( ( tmp = strchr ( epath, '?' ) ) ) {
+ *(tmp++) = '\0';
+- uri->query = tmp;
++ uri->equery = tmp;
+ }
+
+ /* If we have no path remaining, then we're already finished
+ * processing.
+ */
+- if ( ! path[0] )
++ if ( ! epath[0] )
+ goto done;
+
+ /* Identify net/absolute/relative path */
+- if ( uri->scheme && ( strncmp ( path, "//", 2 ) == 0 ) ) {
++ if ( uri->scheme && ( strncmp ( epath, "//", 2 ) == 0 ) ) {
+ /* Net path. If this is terminated by the first '/'
+ * of an absolute path, then we have no space for a
+ * terminator after the authority field, so shuffle
+ * the authority down by one byte, overwriting one of
+ * the two slashes.
+ */
+- authority = ( path + 2 );
++ authority = ( epath + 2 );
+ if ( ( tmp = strchr ( authority, '/' ) ) ) {
+ /* Shuffle down */
+- uri->path = tmp;
++ uri->epath = tmp;
+ memmove ( ( authority - 1 ), authority,
+ ( tmp - authority ) );
+ authority--;
+@@ -386,10 +389,16 @@ struct uri * parse_uri ( const char *uri_string ) {
+ }
+ } else {
+ /* Absolute/relative path */
+- uri->path = path;
++ uri->epath = epath;
+ authority = NULL;
+ }
+
++ /* Create copy of path for decoding */
++ if ( uri->epath ) {
++ strcpy ( path, uri->epath );
++ uri->path = path;
++ }
++
+ /* If we don't have an authority (i.e. we have a non-net
+ * path), we're already finished processing
+ */
+@@ -421,8 +430,8 @@ struct uri * parse_uri ( const char *uri_string ) {
+
+ done:
+ /* Decode fields in-place */
+- for ( field = 0 ; field < URI_FIELDS ; field++ )
+- uri_decode_inplace ( uri, field );
++ for ( field = 0 ; field < URI_EPATH ; field++ )
++ uri_decode_inplace ( ( char * ) uri_field ( uri, field ) );
+
+ DBGC ( uri, "URI parsed \"%s\" to", uri_string );
+ uri_dump ( uri );
+@@ -458,8 +467,8 @@ size_t format_uri ( const struct uri *uri, char *buf, size_t len ) {
+ static const char prefixes[URI_FIELDS] = {
+ [URI_PASSWORD] = ':',
+ [URI_PORT] = ':',
+- [URI_QUERY] = '?',
+- [URI_FRAGMENT] = '#',
++ [URI_EQUERY] = '?',
++ [URI_EFRAGMENT] = '#',
+ };
+ char prefix;
+ size_t used = 0;
+@@ -480,6 +489,10 @@ size_t format_uri ( const struct uri *uri, char *buf, size_t len ) {
+ if ( ! uri_field ( uri, field ) )
+ continue;
+
++ /* Skip path field if encoded path is present */
++ if ( ( field == URI_PATH ) && uri->epath )
++ continue;
++
+ /* Prefix this field, if applicable */
+ prefix = prefixes[field];
+ if ( ( field == URI_HOST ) && ( uri->user != NULL ) )
+@@ -676,6 +689,7 @@ char * resolve_path ( const char *base_path,
+ struct uri * resolve_uri ( const struct uri *base_uri,
+ struct uri *relative_uri ) {
+ struct uri tmp_uri;
++ char *tmp_epath = NULL;
+ char *tmp_path = NULL;
+ struct uri *new_uri;
+
+@@ -685,20 +699,27 @@ struct uri * resolve_uri ( const struct uri *base_uri,
+
+ /* Mangle URI */
+ memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
+- if ( relative_uri->path ) {
+- tmp_path = resolve_path ( ( base_uri->path ?
+- base_uri->path : "/" ),
+- relative_uri->path );
++ if ( relative_uri->epath ) {
++ tmp_epath = resolve_path ( ( base_uri->epath ?
++ base_uri->epath : "/" ),
++ relative_uri->epath );
++ if ( ! tmp_epath )
++ goto err_epath;
++ tmp_path = strdup ( tmp_epath );
++ if ( ! tmp_path )
++ goto err_path;
++ uri_decode_inplace ( tmp_path );
++ tmp_uri.epath = tmp_epath;
+ tmp_uri.path = tmp_path;
+- tmp_uri.query = relative_uri->query;
+- tmp_uri.fragment = relative_uri->fragment;
++ tmp_uri.equery = relative_uri->equery;
++ tmp_uri.efragment = relative_uri->efragment;
+ tmp_uri.params = relative_uri->params;
+- } else if ( relative_uri->query ) {
+- tmp_uri.query = relative_uri->query;
+- tmp_uri.fragment = relative_uri->fragment;
++ } else if ( relative_uri->equery ) {
++ tmp_uri.equery = relative_uri->equery;
++ tmp_uri.efragment = relative_uri->efragment;
+ tmp_uri.params = relative_uri->params;
+- } else if ( relative_uri->fragment ) {
+- tmp_uri.fragment = relative_uri->fragment;
++ } else if ( relative_uri->efragment ) {
++ tmp_uri.efragment = relative_uri->efragment;
+ tmp_uri.params = relative_uri->params;
+ } else if ( relative_uri->params ) {
+ tmp_uri.params = relative_uri->params;
+@@ -707,7 +728,14 @@ struct uri * resolve_uri ( const struct uri *base_uri,
+ /* Create demangled URI */
+ new_uri = uri_dup ( &tmp_uri );
+ free ( tmp_path );
++ free ( tmp_epath );
+ return new_uri;
++
++ free ( tmp_path );
++ err_path:
++ free ( tmp_epath );
++ err_epath:
++ return NULL;
+ }
+
+ /**
+@@ -746,6 +774,7 @@ static struct uri * tftp_uri ( struct sockaddr *sa_server,
+ if ( asprintf ( &path, "/%s", filename ) < 0 )
+ goto err_path;
+ tmp.path = path;
++ tmp.epath = path;
+
+ /* Demangle URI */
+ uri = uri_dup ( &tmp );
+diff --git a/src/include/ipxe/uri.h b/src/include/ipxe/uri.h
+index 3879a0e730..e5b7c8616b 100644
+--- a/src/include/ipxe/uri.h
++++ b/src/include/ipxe/uri.h
+@@ -46,6 +46,20 @@ struct parameters;
+ * scheme = "ftp", user = "joe", password = "secret",
+ * host = "insecure.org", port = "8081", path = "/hidden/path/to",
+ * query = "what=is", fragment = "this"
++ *
++ * The URI syntax includes a percent-encoding mechanism that can be
++ * used to represent characters that would otherwise not be possible,
++ * such as a '/' character within the password field. These encodings
++ * are decoded during the URI parsing stage, thereby allowing protocol
++ * implementations to consume the raw field values directly without
++ * further decoding.
++ *
++ * Some protocols (such as HTTP) communicate using URI-encoded values.
++ * For these protocols, the original encoded substring must be
++ * retained verbatim since the choice of whether or not to encode a
++ * particular character may have significance to the receiving
++ * application. We therefore retain the originally-encoded substrings
++ * for the path, query, and fragment fields.
+ */
+ struct uri {
+ /** Reference count */
+@@ -62,12 +76,14 @@ struct uri {
+ const char *host;
+ /** Port number */
+ const char *port;
+- /** Path */
++ /** Path (after URI decoding) */
+ const char *path;
+- /** Query */
+- const char *query;
+- /** Fragment */
+- const char *fragment;
++ /** Path (with original URI encoding) */
++ const char *epath;
++ /** Query (with original URI encoding) */
++ const char *equery;
++ /** Fragment (with original URI encoding) */
++ const char *efragment;
+ /** Form parameters */
+ struct parameters *params;
+ } __attribute__ (( packed ));
+@@ -100,8 +116,9 @@ enum uri_fields {
+ URI_HOST = URI_FIELD ( host ),
+ URI_PORT = URI_FIELD ( port ),
+ URI_PATH = URI_FIELD ( path ),
+- URI_QUERY = URI_FIELD ( query ),
+- URI_FRAGMENT = URI_FIELD ( fragment ),
++ URI_EPATH = URI_FIELD ( epath ),
++ URI_EQUERY = URI_FIELD ( equery ),
++ URI_EFRAGMENT = URI_FIELD ( efragment ),
+ URI_FIELDS
+ };
+
+diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c
+index 01bb496b21..fd94b5f083 100644
+--- a/src/net/tcp/httpcore.c
++++ b/src/net/tcp/httpcore.c
+@@ -614,8 +614,8 @@ int http_open ( struct interface *xfer, struct http_method *method,
+
+ /* Calculate request URI length */
+ memset ( &request_uri, 0, sizeof ( request_uri ) );
+- request_uri.path = ( uri->path ? uri->path : "/" );
+- request_uri.query = uri->query;
++ request_uri.epath = ( uri->epath ? uri->epath : "/" );
++ request_uri.equery = uri->equery;
+ request_uri_len =
+ ( format_uri ( &request_uri, NULL, 0 ) + 1 /* NUL */);
+
+diff --git a/src/tests/uri_test.c b/src/tests/uri_test.c
+index 92c2f90371..929ab36325 100644
+--- a/src/tests/uri_test.c
++++ b/src/tests/uri_test.c
+@@ -149,8 +149,10 @@ static void uri_okx ( struct uri *uri, struct uri *expected, const char *file,
+ okx ( uristrcmp ( uri->host, expected->host ) == 0, file, line );
+ okx ( uristrcmp ( uri->port, expected->port ) == 0, file, line );
+ okx ( uristrcmp ( uri->path, expected->path ) == 0, file, line );
+- okx ( uristrcmp ( uri->query, expected->query ) == 0, file, line );
+- okx ( uristrcmp ( uri->fragment, expected->fragment ) == 0, file, line);
++ okx ( uristrcmp ( uri->epath, expected->epath ) == 0, file, line );
++ okx ( uristrcmp ( uri->equery, expected->equery ) == 0, file, line );
++ okx ( uristrcmp ( uri->efragment, expected->efragment ) == 0,
++ file, line);
+ okx ( uri->params == expected->params, file, line );
+ }
+ #define uri_ok( uri, expected ) uri_okx ( uri, expected, __FILE__, __LINE__ )
+@@ -490,25 +492,33 @@ static struct uri_test uri_empty = {
+ /** Basic HTTP URI */
+ static struct uri_test uri_boot_ipxe_org = {
+ "http://boot.ipxe.org/demo/boot.php",
+- { .scheme = "http", .host = "boot.ipxe.org", .path = "/demo/boot.php" }
++ { .scheme = "http", .host = "boot.ipxe.org",
++ .path = "/demo/boot.php", .epath = "/demo/boot.php" },
+ };
+
+ /** Basic opaque URI */
+ static struct uri_test uri_mailto = {
+ "mailto:ipxe-devel@lists.ipxe.org",
+- { .scheme = "mailto", .opaque = "ipxe-devel@lists.ipxe.org" }
++ { .scheme = "mailto", .opaque = "ipxe-devel@lists.ipxe.org" },
++};
++
++/** Basic host-only URI */
++static struct uri_test uri_host = {
++ "http://boot.ipxe.org",
++ { .scheme = "http", .host = "boot.ipxe.org" },
+ };
+
+ /** Basic path-only URI */
+ static struct uri_test uri_path = {
+ "/var/lib/tftpboot/pxelinux.0",
+- { .path = "/var/lib/tftpboot/pxelinux.0" },
++ { .path = "/var/lib/tftpboot/pxelinux.0",
++ .epath ="/var/lib/tftpboot/pxelinux.0" },
+ };
+
+ /** Path-only URI with escaped characters */
+ static struct uri_test uri_path_escaped = {
+ "/hello%20world%3F",
+- { .path = "/hello world?" },
++ { .path = "/hello world?", .epath = "/hello%20world%3F" },
+ };
+
+ /** HTTP URI with all the trimmings */
+@@ -521,8 +531,9 @@ static struct uri_test uri_http_all = {
+ .host = "example.com",
+ .port = "3001",
+ .path = "/~foo/cgi-bin/foo.pl",
+- .query = "a=b&c=d",
+- .fragment = "bit",
++ .epath = "/~foo/cgi-bin/foo.pl",
++ .equery = "a=b&c=d",
++ .efragment = "bit",
+ },
+ };
+
+@@ -533,8 +544,9 @@ static struct uri_test uri_http_escaped = {
+ .scheme = "https",
+ .host = "test.ipxe.org",
+ .path = "/wtf?\n",
+- .query = "kind#of/uri is",
+- .fragment = "this?",
++ .epath = "/wtf%3F%0A",
++ .equery = "kind%23of/uri%20is",
++ .efragment = "this%3F",
+ },
+ };
+
+@@ -550,8 +562,9 @@ static struct uri_test uri_http_escaped_improper = {
+ .scheme = "https",
+ .host = "test.ipxe.org",
+ .path = "/wtf?\n",
+- .query = "kind#of/uri is",
+- .fragment = "this?",
++ .epath = "/wt%66%3f\n",
++ .equery = "kind%23of/uri is",
++ .efragment = "this?",
+ },
+ };
+
+@@ -562,6 +575,7 @@ static struct uri_test uri_ipv6 = {
+ .scheme = "http",
+ .host = "[2001:ba8:0:1d4::6950:5845]",
+ .path = "/",
++ .epath = "/",
+ },
+ };
+
+@@ -573,6 +587,7 @@ static struct uri_test uri_ipv6_port = {
+ .host = "[2001:ba8:0:1d4::6950:5845]",
+ .port = "8001",
+ .path = "/boot",
++ .epath = "/boot",
+ },
+ };
+
+@@ -583,6 +598,7 @@ static struct uri_test uri_ipv6_local = {
+ .scheme = "http",
+ .host = "[fe80::69ff:fe50:5845%net0]",
+ .path = "/ipxe",
++ .epath = "/ipxe",
+ },
+ };
+
+@@ -598,6 +614,7 @@ static struct uri_test uri_ipv6_local_non_conforming = {
+ .scheme = "http",
+ .host = "[fe80::69ff:fe50:5845%net0]",
+ .path = "/ipxe",
++ .epath = "/ipxe",
+ },
+ };
+
+@@ -625,6 +642,7 @@ static struct uri_test uri_file_absolute = {
+ {
+ .scheme = "file",
+ .path = "/boot/script.ipxe",
++ .epath = "/boot/script.ipxe",
+ },
+ };
+
+@@ -635,6 +653,7 @@ static struct uri_test uri_file_volume = {
+ .scheme = "file",
+ .host = "hpilo",
+ .path = "/boot/script.ipxe",
++ .epath = "/boot/script.ipxe",
+ },
+ };
+
+@@ -736,6 +755,7 @@ static struct uri_pxe_test uri_pxe_absolute = {
+ .scheme = "http",
+ .host = "not.a.tftp",
+ .path = "/uri",
++ .epath = "/uri",
+ },
+ "http://not.a.tftp/uri",
+ };
+@@ -754,6 +774,7 @@ static struct uri_pxe_test uri_pxe_absolute_path = {
+ .scheme = "tftp",
+ .host = "192.168.0.2",
+ .path = "//absolute/path",
++ .epath = "//absolute/path",
+ },
+ "tftp://192.168.0.2//absolute/path",
+ };
+@@ -772,6 +793,7 @@ static struct uri_pxe_test uri_pxe_relative_path = {
+ .scheme = "tftp",
+ .host = "192.168.0.3",
+ .path = "/relative/path",
++ .epath = "/relative/path",
+ },
+ "tftp://192.168.0.3/relative/path",
+ };
+@@ -790,8 +812,9 @@ static struct uri_pxe_test uri_pxe_icky = {
+ .scheme = "tftp",
+ .host = "10.0.0.6",
+ .path = "/C:\\tftpboot\\icky#path",
++ .epath = "/C:\\tftpboot\\icky#path",
+ },
+- "tftp://10.0.0.6/C%3A\\tftpboot\\icky%23path",
++ "tftp://10.0.0.6/C:\\tftpboot\\icky#path",
+ };
+
+ /** PXE URI with custom port */
+@@ -810,6 +833,7 @@ static struct uri_pxe_test uri_pxe_port = {
+ .host = "192.168.0.1",
+ .port = "4069",
+ .path = "//another/path",
++ .epath = "//another/path",
+ },
+ "tftp://192.168.0.1:4069//another/path",
+ };
+@@ -873,6 +897,7 @@ static struct uri_params_test uri_params = {
+ .scheme = "http",
+ .host = "boot.ipxe.org",
+ .path = "/demo/boot.php",
++ .epath = "/demo/boot.php",
+ },
+ NULL,
+ uri_params_list,
+@@ -902,6 +927,7 @@ static struct uri_params_test uri_named_params = {
+ .host = "192.168.100.4",
+ .port = "3001",
+ .path = "/register",
++ .epath = "/register",
+ },
+ "foo",
+ uri_named_params_list,
+@@ -917,6 +943,7 @@ static void uri_test_exec ( void ) {
+ uri_parse_format_dup_ok ( &uri_empty );
+ uri_parse_format_dup_ok ( &uri_boot_ipxe_org );
+ uri_parse_format_dup_ok ( &uri_mailto );
++ uri_parse_format_dup_ok ( &uri_host );
+ uri_parse_format_dup_ok ( &uri_path );
+ uri_parse_format_dup_ok ( &uri_path_escaped );
+ uri_parse_format_dup_ok ( &uri_http_all );
+diff --git a/src/usr/imgmgmt.c b/src/usr/imgmgmt.c
+index f8d149153a..b7fc8293d4 100644
+--- a/src/usr/imgmgmt.c
++++ b/src/usr/imgmgmt.c
+@@ -58,8 +58,8 @@ int imgdownload ( struct uri *uri, unsigned long timeout,
+ memcpy ( &uri_redacted, uri, sizeof ( uri_redacted ) );
+ uri_redacted.user = NULL;
+ uri_redacted.password = NULL;
+- uri_redacted.query = NULL;
+- uri_redacted.fragment = NULL;
++ uri_redacted.equery = NULL;
++ uri_redacted.efragment = NULL;
+ uri_string_redacted = format_uri_alloc ( &uri_redacted );
+ if ( ! uri_string_redacted ) {
+ rc = -ENOMEM;
+
+
diff --git a/ipxe.spec b/ipxe.spec
new file mode 100644
index 0000000..20956b3
--- /dev/null
+++ b/ipxe.spec
@@ -0,0 +1,259 @@
+%global formats rom
+%global qemuroms 10222000 10ec8029 8086100e 10ec8139 1af41000 80861209 808610d3 15ad07b0
+%global buildarches x86_64
+%global debug_package %{nil}
+%global enable_i386 0
+
+Name: ipxe
+Version: 1.21.1
+Release: 5
+Summary: A network boot loader
+Epoch: 1
+License: GPLv2 with additional permissions and BSD
+URL: http://ipxe.org/
+Source0: https://github.com/ipxe/ipxe/archive/v%{version}.tar.gz
+Patch0001: 0001-build-customize-configuration.patch
+Patch0002: 0002-Use-spec-compliant-timeouts.patch
+Patch0003: 0003-librm-Use-explicit-operand-size-when-pushing-a-label.patch
+
+Patch6000: backport-avoid-infinite-loop-on-allocation-failure-in.patch
+Patch6001: backport-ensure-that-pci_read_config-initialises-all-fields.patch
+Patch6002: backport-do-not-clear-current-working-url-when-executing-embedded-image.patch
+Patch6003: backport-retain-original-encodings-for-path-query-and-fragment-fields.patch
+Patch6004: backport-allow-for-relative-uris-that-include-colons-within-the-path.patch
+
+%ifarch %{buildarches}
+BuildRequires: perl-interpreter perl-Getopt-Long syslinux mtools genisoimage edk2-devel
+BuildRequires: xz-devel gcc binutils-devel
+Obsoletes: gpxe <= 1.0.1
+
+%package bootimgs
+Summary: Network boot loader images in bootable USB, CD, floppy and GRUB formats
+BuildArch: noarch
+Obsoletes: gpxe-bootimgs <= 1.0.1
+
+%package roms
+Summary: Network boot loader roms in .rom format
+Requires: %{name}-roms-qemu = %{epoch}:%{version}-%{release}
+BuildArch: noarch
+Obsoletes: gpxe-roms <= 1.0.1
+
+%package roms-qemu
+Summary: Network boot loader roms supported by QEMU, .rom format
+BuildArch: noarch
+Obsoletes: gpxe-roms-qemu <= 1.0.1
+
+%description bootimgs
+iPXE is an open source network bootloader. It provides a direct
+replacement for proprietary PXE ROMs, with many extra features such as
+DNS, HTTP, iSCSI, etc.
+
+This package contains the iPXE boot images in USB, CD, floppy, and PXE
+UNDI formats.
+
+%description roms
+iPXE is an open source network bootloader. It provides a direct
+replacement for proprietary PXE ROMs, with many extra features such as
+DNS, HTTP, iSCSI, etc.
+
+This package contains the iPXE roms in .rom format.
+
+
+%description roms-qemu
+iPXE is an open source network bootloader. It provides a direct
+replacement for proprietary PXE ROMs, with many extra features such as
+DNS, HTTP, iSCSI, etc.
+
+This package contains the iPXE ROMs for devices emulated by QEMU, in
+.rom format.
+%endif
+
+%description
+iPXE is an open source network bootloader. It provides a direct
+replacement for proprietary PXE ROMs, with many extra features such as
+DNS, HTTP, iSCSI, etc.
+
+%prep
+%setup -q -n %{name}-%{version}
+%autopatch -p1
+
+
+%build
+%ifarch %{buildarches}
+cd src
+
+rm -rf drivers/net/ath/ath9k
+
+make_ipxe() {
+ make %{?_smp_mflags} \
+ NO_WERROR=1 V=1 \
+ GITVERSION=%{hash} \
+ "$@"
+}
+
+make_ipxe bin-i386-efi/ipxe.efi bin-x86_64-efi/ipxe.efi bin-x86_64-linux/tests.linux \
+ %if 0%{?enable i386}
+ bin-i386-linux/tests.linux
+ %endif
+
+make_ipxe ISOLINUX_BIN=/usr/share/syslinux/isolinux.bin \
+ bin/undionly.kpxe bin/ipxe.{dsk,iso,usb,lkrn} \
+ allroms
+
+mkdir bin-combined
+for rom in %{qemuroms}; do
+ make_ipxe CONFIG=qemu bin/${rom}.rom
+%if 0%{?enable_i386}
+ make_ipxe CONFIG=qemu bin-i386-efi/${rom}.efidrv
+%endif
+ make_ipxe CONFIG=qemu bin-x86_64-efi/${rom}.efidrv
+ vid="0x${rom%%????}"
+ did="0x${rom#????}"
+ EfiRom -f "$vid" -i "$did" --pci23 \
+ -b bin/${rom}.rom \
+%if 0%{?enable_i386}
+ -ec bin-i386-efi/${rom}.efidrv \
+%endif
+ -ec bin-x86_64-efi/${rom}.efidrv \
+ -o bin-combined/${rom}.rom
+ EfiRom -d bin-combined/${rom}.rom
+ truncate -s \>256K bin-combined/${rom}.rom
+ test $(stat -c '%s' bin-combined/${rom}.rom) -le $((256 * 1024))
+done
+
+%endif
+
+%install
+%ifarch %{buildarches}
+mkdir -p %{buildroot}/%{_datadir}/%{name}/
+mkdir -p %{buildroot}/%{_datadir}/%{name}.efi/
+pushd src/bin/
+
+cp -a undionly.kpxe ipxe.{iso,usb,dsk,lkrn} %{buildroot}/%{_datadir}/%{name}/
+
+for fmt in %{formats};do
+ for img in *.${fmt};do
+ if [ -e $img ]; then
+ cp -a $img %{buildroot}/%{_datadir}/%{name}/
+ echo %{_datadir}/%{name}/$img >> ../../${fmt}.list
+ fi
+ done
+done
+popd
+
+cp -a src/bin-i386-efi/ipxe.efi %{buildroot}/%{_datadir}/%{name}/ipxe-i386.efi
+cp -a src/bin-x86_64-efi/ipxe.efi %{buildroot}/%{_datadir}/%{name}/ipxe-x86_64.efi
+
+for fmt in rom ;do
+ for rom in %{qemuroms} ; do
+ sed -i -e "/\/${rom}.${fmt}/d" ${fmt}.list
+ echo %{_datadir}/%{name}/${rom}.${fmt} >> qemu.${fmt}.list
+ done
+done
+for rom in %{qemuroms}; do
+ cp src/bin-combined/${rom}.rom %{buildroot}/%{_datadir}/%{name}.efi/
+ echo %{_datadir}/%{name}.efi/${rom}.rom >> qemu.rom.list
+done
+%endif
+
+%check
+%ifarch %{buildarches}
+cd ~/rpmbuild/BUILD/%{name}-%{version}/src/bin-x86_64-linux/
+./tests.linux
+%if 0%{?enable_i386}
+cd ~/rpmbuild/BUILD/%{name}-%{version}/src/bin-i386-linux/
+./tests.linux
+%endif
+%endif
+
+%ifarch %{buildarches}
+%files bootimgs
+%defattr(-,root,root)
+%license COPYING COPYING.GPLv2 COPYING.UBDL
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}/ipxe.iso
+%{_datadir}/%{name}/ipxe.usb
+%{_datadir}/%{name}/ipxe.dsk
+%{_datadir}/%{name}/ipxe.lkrn
+%{_datadir}/%{name}/ipxe-i386.efi
+%{_datadir}/%{name}/ipxe-x86_64.efi
+%{_datadir}/%{name}/undionly.kpxe
+
+%files roms -f rom.list
+%defattr(-,root,root)
+%license COPYING COPYING.GPLv2 COPYING.UBDL
+%dir %{_datadir}/%{name}
+
+%files roms-qemu -f qemu.rom.list
+%defattr(-,root,root)
+%license COPYING COPYING.GPLv2 COPYING.UBDL
+%dir %{_datadir}/%{name}
+%dir %{_datadir}/%{name}.efi
+%endif
+
+%changelog
+* Fri Mar 15 2024 herengui <herengui@kylinsec.com.cn> - 1:1.21.1-5
+- Type:bugfix
+- CVE:NA
+- SUG:NA
+- DESC: fix errors when compiling with binutils-2.41
+
+* Wed Nov 23 2022 zhangqiumiao <zhangqiumiao1@huawei.com> - 1:1.21.1-4
+- Type:bugfix
+- CVE:NA
+- SUG:NA
+- DESC:[pci] Ensure that pci_read_config() initialises all fields
+ [image] Do not clear current working URI when executing embedded image
+ [uri] Retain original encodings for path, query, and fragment fields
+ [uri] Allow for relative URIs that include colons within the path
+
+* Sat Mar 26 2022 wangkerong <wangkerong@h-partners.com> - 1.21.1-3
+- enable test
+
+* Wed Jun 09 2021 wangkerong <wangkerong@huawei.com> - 1.21.1-2
+- Type:bugfix
+- Id:NA
+- SUG:NA
+- DESC: round commmunity patch fix Avoid infinite loop on allocation failure
+
+* Wed Feb 03 2021 gaihuiying <gaihuiying1@huawei.com> - 1.21.1-1
+- Type:requirement
+- Id:NA
+- SUG:NA
+- DESC: update ipxe to 1.21.1
+
+* Thu Sep 03 2020 zhouyihang <zhouyihang3@huawei.com> - 1.20.1-2
+- Type:bugfix
+- Id:NA
+- SUG:NA
+- DESC: add epoch for roms-qemu when required by roms
+
+* Tue Jun 23 2020 zhujunhao <zhujunhao8@huawei.com> - 1.20.1-1
+- update to 1.20.1
+
+* Mon Jan 13 2020 openEuler Buildteam <buildteam@openeuler.org> - 20190125-5
+- Type:bugfix
+- Id:NA
+- SUG:NA
+- DESC: add bootimgs roms roms-qemu subpackages
+
+* Fri Nov 29 2019 openEuler Buildteam <buildteam@openeuler.org> - 20190125-4
+- Type:bugfix
+- Id:NA
+- SUG:NA
+- DESC: fix build error on x86_64
+
+* Sat Oct 19 2019 openEuler Buildteam <buildteam@openeuler.org> - 20190125-3
+- Type:bugfix
+- Id:NA
+- SUG:NA
+- DESC:change the directory of the license files
+
+* Thu Oct 10 2019 openEuler Buildteam <buildteam@openeuler.org> - 20190125-2
+- Type:enhancement
+- ID:NA
+- SUG:NA
+- DESC:add requires
+
+* Thu Sep 19 2019 openEuler Buildteam <buildteam@openeuler.org> - 20190125-1
+- Package init
diff --git a/sources b/sources
new file mode 100644
index 0000000..c8fe097
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+ad39d9bd2d6d77f3702c4015203426ae v1.21.1.tar.gz