From e5858c1938147a052c72357aacfa01b0b6d67d0f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 12 May 2012 00:58:42 +0100 Subject: [PATCH 001/250] [crypto] Parse X.509 raw public key bit string OCSP requires direct access to the bit string portion of the subject public key information. Signed-off-by: Michael Brown --- src/crypto/x509.c | 10 ++++++++-- src/include/ipxe/x509.h | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 6e3cfead..cfecfde3 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -632,6 +632,7 @@ static int x509_parse_public_key ( struct x509_certificate *cert, const struct asn1_cursor *raw ) { struct x509_public_key *public_key = &cert->subject.public_key; struct asn1_algorithm **algorithm = &public_key->algorithm; + struct x509_bit_string *raw_bits = &public_key->raw_bits; struct asn1_cursor cursor; int rc; @@ -639,6 +640,8 @@ static int x509_parse_public_key ( struct x509_certificate *cert, memcpy ( &cursor, raw, sizeof ( cursor ) ); asn1_shrink_any ( &cursor ); memcpy ( &public_key->raw, &cursor, sizeof ( public_key->raw ) ); + DBGC2 ( cert, "X509 %p public key is:\n", cert ); + DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len ); /* Enter subjectPublicKeyInfo */ asn1_enter ( &cursor, ASN1_SEQUENCE ); @@ -649,8 +652,11 @@ static int x509_parse_public_key ( struct x509_certificate *cert, return rc; DBGC2 ( cert, "X509 %p public key algorithm is %s\n", cert, (*algorithm)->name ); - DBGC2 ( cert, "X509 %p public key is:\n", cert ); - DBGC2_HDA ( cert, 0, public_key->raw.data, public_key->raw.len ); + asn1_skip_any ( &cursor ); + + /* Parse bit string */ + if ( ( rc = x509_parse_bit_string ( cert, raw_bits, &cursor ) ) != 0 ) + return rc; return 0; } diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index 8753bb05..a55511b8 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -54,10 +54,12 @@ struct x509_validity { /** An X.509 certificate public key */ struct x509_public_key { - /** Raw public key */ + /** Raw public key information */ struct asn1_cursor raw; /** Public key algorithm */ struct asn1_algorithm *algorithm; + /** Raw public key bit string */ + struct x509_bit_string raw_bits; }; /** An X.509 certificate subject */ From 88c09b36cfefc037cca7c409423b14d8c556e3be Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 13 May 2012 23:38:56 +0100 Subject: [PATCH 002/250] [crypto] Generalise x509_parse_time() to asn1_generalized_time() Signed-off-by: Michael Brown --- src/crypto/asn1.c | 113 +++++++++++++++++++++++++++++++++++ src/crypto/x509.c | 126 ++++------------------------------------ src/include/ipxe/asn1.h | 3 + 3 files changed, 126 insertions(+), 116 deletions(-) diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 2eab3422..55860558 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -21,7 +21,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include +#include #include #include @@ -52,6 +54,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_EINVAL_ASN1_INTEGER ) #define EINFO_EINVAL_ASN1_INTEGER \ __einfo_uniqify ( EINFO_EINVAL, 0x04, "Invalid integer" ) +#define EINVAL_ASN1_TIME \ + __einfo_error ( EINFO_EINVAL_ASN1_TIME ) +#define EINFO_EINVAL_ASN1_TIME \ + __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" ) /** * Invalidate ASN.1 object cursor @@ -400,3 +406,110 @@ struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) { return algorithm; } + +/** + * Parse ASN.1 GeneralizedTime + * + * @v cursor ASN.1 cursor + * @v time Time to fill in + * @ret rc Return status code + * + * RFC 5280 section 4.1.2.5 places several restrictions on the allowed + * formats for UTCTime and GeneralizedTime, and mandates the + * interpretation of centuryless year values. + */ +int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) { + struct asn1_cursor contents; + unsigned int have_century; + unsigned int type; + union { + struct { + uint8_t century; + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + } __attribute__ (( packed )) named; + uint8_t raw[7]; + } pairs; + struct tm tm; + const uint8_t *data; + size_t remaining; + unsigned int tens; + unsigned int units; + unsigned int i; + int rc; + + /* Determine time format utcTime/generalizedTime */ + memcpy ( &contents, cursor, sizeof ( contents ) ); + type = asn1_type ( &contents ); + switch ( type ) { + case ASN1_UTC_TIME: + have_century = 0; + break; + case ASN1_GENERALIZED_TIME: + have_century = 1; + break; + default: + DBGC ( cursor, "ASN1 %p invalid time type %02x\n", + cursor, type ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -EINVAL_ASN1_TIME; + } + + /* Enter utcTime/generalizedTime */ + if ( ( rc = asn1_enter ( &contents, type ) ) != 0 ) { + DBGC ( cursor, "ASN1 %p cannot locate %s time:\n", cursor, + ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return rc; + } + + /* Parse digit string a pair at a time */ + data = contents.data; + remaining = contents.len; + for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) { + if ( remaining < 2 ) { + DBGC ( cursor, "ASN1 %p invalid time:\n", cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -EINVAL_ASN1_TIME; + } + tens = data[0]; + units = data[1]; + if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) { + DBGC ( cursor, "ASN1 %p invalid time:\n", cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -EINVAL_ASN1_TIME; + } + pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) ); + data += 2; + remaining -= 2; + } + + /* Determine century if applicable */ + if ( ! have_century ) + pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 ); + + /* Check for trailing "Z" */ + if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) { + DBGC ( cursor, "ASN1 %p invalid time:\n", cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -EINVAL_ASN1_TIME; + } + + /* Fill in time */ + tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) + + pairs.named.year ); + tm.tm_mon = ( pairs.named.month - 1 ); + tm.tm_mday = pairs.named.day; + tm.tm_hour = pairs.named.hour; + tm.tm_min = pairs.named.minute; + tm.tm_sec = pairs.named.second; + + /* Convert to seconds since the Epoch */ + *time = mktime ( &tm ); + + return 0; +} diff --git a/src/crypto/x509.c b/src/crypto/x509.c index cfecfde3..1cb46a1d 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -20,8 +20,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include -#include -#include #include #include #include @@ -60,10 +58,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_EINVAL_BIT_STRING ) #define EINFO_EINVAL_BIT_STRING \ __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid bit string" ) -#define EINVAL_TIME \ - __einfo_error ( EINFO_EINVAL_TIME ) -#define EINFO_EINVAL_TIME \ - __einfo_uniqify ( EINFO_EINVAL, 0x03, "Invalid time" ) #define EINVAL_ALGORITHM_MISMATCH \ __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH ) #define EINFO_EINVAL_ALGORITHM_MISMATCH \ @@ -301,114 +295,6 @@ static int x509_parse_integral_bit_string ( struct x509_certificate *cert, return 0; } -/** - * Parse X.509 certificate time - * - * @v cert X.509 certificate - * @v time Time to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - * - * RFC 5280 section 4.1.2.5 places several restrictions on the allowed - * formats for UTCTime and GeneralizedTime, and mandates the - * interpretation of centuryless year values. - */ -static int x509_parse_time ( struct x509_certificate *cert, - struct x509_time *time, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - unsigned int have_century; - unsigned int type; - union { - struct { - uint8_t century; - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - } __attribute__ (( packed )) named; - uint8_t raw[7]; - } pairs; - struct tm tm; - const uint8_t *data; - size_t remaining; - unsigned int tens; - unsigned int units; - unsigned int i; - int rc; - - /* Determine time format utcTime/generalizedTime */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - type = asn1_type ( &cursor ); - switch ( type ) { - case ASN1_UTC_TIME: - have_century = 0; - break; - case ASN1_GENERALIZED_TIME: - have_century = 1; - break; - default: - DBGC ( cert, "X509 %p invalid time type %02x\n", cert, type ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_TIME; - } - - /* Enter utcTime/generalizedTime */ - if ( ( rc = asn1_enter ( &cursor, type ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot locate %s time:\n", cert, - ( ( type == ASN1_UTC_TIME ) ? "UTC" : "generalized" ) ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - - /* Parse digit string a pair at a time */ - data = cursor.data; - remaining = cursor.len; - for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) { - if ( remaining < 2 ) { - DBGC ( cert, "X509 %p invalid time:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_TIME; - } - tens = data[0]; - units = data[1]; - if ( ! ( isdigit ( tens ) && isdigit ( units ) ) ) { - DBGC ( cert, "X509 %p invalid time:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_TIME; - } - pairs.raw[i] = ( ( 10 * ( tens - '0' ) ) + ( units - '0' ) ); - data += 2; - remaining -= 2; - } - - /* Determine century if applicable */ - if ( ! have_century ) - pairs.named.century = ( ( pairs.named.year >= 50 ) ? 19 : 20 ); - - /* Check for trailing "Z" */ - if ( ( remaining != 1 ) || ( data[0] != 'Z' ) ) { - DBGC ( cert, "X509 %p invalid time:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_TIME; - } - - /* Fill in time */ - tm.tm_year = ( ( ( pairs.named.century - 19 ) * 100 ) + - pairs.named.year ); - tm.tm_mon = ( pairs.named.month - 1 ); - tm.tm_mday = pairs.named.day; - tm.tm_hour = pairs.named.hour; - tm.tm_min = pairs.named.minute; - tm.tm_sec = pairs.named.second; - - /* Convert to seconds since the Epoch */ - time->time = mktime ( &tm ); - - return 0; -} /** * Parse X.509 certificate version @@ -520,15 +406,23 @@ static int x509_parse_validity ( struct x509_certificate *cert, asn1_enter ( &cursor, ASN1_SEQUENCE ); /* Parse notBefore */ - if ( ( rc = x509_parse_time ( cert, not_before, &cursor ) ) != 0 ) + if ( ( rc = asn1_generalized_time ( &cursor, + ¬_before->time ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot parse notBefore: %s\n", + cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p valid from time %lld\n", cert, not_before->time ); asn1_skip_any ( &cursor ); /* Parse notAfter */ - if ( ( rc = x509_parse_time ( cert, not_after, &cursor ) ) != 0 ) + if ( ( rc = asn1_generalized_time ( &cursor, + ¬_after->time ) ) != 0 ) { + DBGC ( cert, "X509 %p cannot parse notAfter: %s\n", + cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p valid until time %lld\n", cert, not_after->time ); diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 1c433c5e..38f0e5b0 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -10,6 +10,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include /** An ASN.1 object cursor */ @@ -239,5 +240,7 @@ extern int asn1_compare ( const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2 ); extern struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ); +extern int asn1_generalized_time ( const struct asn1_cursor *cursor, + time_t *time ); #endif /* _IPXE_ASN1_H */ From 7deb610881d36dd156edbf705f923cf43cc0fdf5 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 14 May 2012 00:13:00 +0100 Subject: [PATCH 003/250] [crypto] Generalise asn1_{digest,pubkey,signature}_algorithm() Signed-off-by: Michael Brown --- src/crypto/asn1.c | 115 +++++++++++++++++++++++++++++++++++++--- src/crypto/cms.c | 41 ++++---------- src/crypto/x509.c | 79 +++++---------------------- src/include/ipxe/asn1.h | 10 +++- 4 files changed, 137 insertions(+), 108 deletions(-) diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 55860558..47c735c5 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -58,6 +58,18 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_EINVAL_ASN1_TIME ) #define EINFO_EINVAL_ASN1_TIME \ __einfo_uniqify ( EINFO_EINVAL, 0x05, "Invalid time" ) +#define EINVAL_ASN1_ALGORITHM \ + __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM ) +#define EINFO_EINVAL_ASN1_ALGORITHM \ + __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" ) +#define ENOTSUP_ALGORITHM \ + __einfo_error ( EINFO_ENOTSUP_ALGORITHM ) +#define EINFO_ENOTSUP_ALGORITHM \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Unsupported algorithm" ) +#define ENOTTY_ALGORITHM \ + __einfo_error ( EINFO_ENOTTY_ALGORITHM ) +#define EINFO_ENOTTY_ALGORITHM \ + __einfo_uniqify ( EINFO_ENOTTY, 0x01, "Inappropriate algorithm" ) /** * Invalidate ASN.1 object cursor @@ -377,11 +389,12 @@ asn1_find_algorithm ( const struct asn1_cursor *cursor ) { * Parse ASN.1 OID-identified algorithm * * @v cursor ASN.1 object cursor - * @ret algorithm Algorithm, or NULL + * @ret algorithm Algorithm + * @ret rc Return status code */ -struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) { +int asn1_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { struct asn1_cursor contents; - struct asn1_algorithm *algorithm; int rc; /* Enter signatureAlgorithm */ @@ -393,18 +406,104 @@ struct asn1_algorithm * asn1_algorithm ( const struct asn1_cursor *cursor ) { DBGC ( cursor, "ASN1 %p cannot locate algorithm OID:\n", cursor ); DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return NULL; + return -EINVAL_ASN1_ALGORITHM; } /* Identify algorithm */ - algorithm = asn1_find_algorithm ( &contents ); - if ( ! algorithm ) { + *algorithm = asn1_find_algorithm ( &contents ); + if ( ! *algorithm ) { DBGC ( cursor, "ASN1 %p unrecognised algorithm:\n", cursor ); DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); - return NULL; + return -ENOTSUP_ALGORITHM; } - return algorithm; + return 0; +} + +/** + * Parse ASN.1 OID-identified public-key algorithm + * + * @v cursor ASN.1 object cursor + * @ret algorithm Algorithm + * @ret rc Return status code + */ +int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { + int rc; + + /* Parse algorithm */ + if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) + return rc; + + /* Check algorithm has a public key */ + if ( ! (*algorithm)->pubkey ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a public-key " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + return 0; +} + +/** + * Parse ASN.1 OID-identified digest algorithm + * + * @v cursor ASN.1 object cursor + * @ret algorithm Algorithm + * @ret rc Return status code + */ +int asn1_digest_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { + int rc; + + /* Parse algorithm */ + if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) + return rc; + + /* Check algorithm has a digest */ + if ( ! (*algorithm)->digest ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a digest " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + return 0; +} + +/** + * Parse ASN.1 OID-identified signature algorithm + * + * @v cursor ASN.1 object cursor + * @ret algorithm Algorithm + * @ret rc Return status code + */ +int asn1_signature_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ) { + int rc; + + /* Parse algorithm */ + if ( ( rc = asn1_algorithm ( cursor, algorithm ) ) != 0 ) + return rc; + + /* Check algorithm has a public key */ + if ( ! (*algorithm)->pubkey ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a signature " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + /* Check algorithm has a digest */ + if ( ! (*algorithm)->digest ) { + DBGC ( cursor, "ASN1 %p algorithm %s is not a signature " + "algorithm:\n", cursor, (*algorithm)->name ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -ENOTTY_ALGORITHM; + } + + return 0; } /** diff --git a/src/crypto/cms.c b/src/crypto/cms.c index 18e59bfb..2083433e 100644 --- a/src/crypto/cms.c +++ b/src/crypto/cms.c @@ -65,15 +65,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_ENOTSUP_SIGNEDDATA ) #define EINFO_ENOTSUP_SIGNEDDATA \ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Not a digital signature" ) -#define ENOTSUP_DIGEST \ - __einfo_error ( EINFO_ENOTSUP_DIGEST ) -#define EINFO_ENOTSUP_DIGEST \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x02, "Unsupported digest algorithm" ) -#define ENOTSUP_PUBKEY \ - __einfo_error ( EINFO_ENOTSUP_PUBKEY ) -#define EINFO_ENOTSUP_PUBKEY \ - __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \ - "Unsupported public-key algorithm" ) /** "pkcs7-signedData" object identifier */ static uint8_t oid_signeddata[] = { ASN1_OID_SIGNEDDATA }; @@ -257,21 +248,14 @@ static int cms_parse_digest_algorithm ( struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw ) { struct asn1_algorithm *algorithm; + int rc; /* Identify algorithm */ - algorithm = asn1_algorithm ( raw ); - if ( ! algorithm ) { - DBGC ( sig, "CMS %p/%p could not identify digest algorithm:\n", - sig, info ); + if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) { + DBGC ( sig, "CMS %p/%p could not identify digest algorithm: " + "%s\n", sig, info, strerror ( rc ) ); DBGC_HDA ( sig, 0, raw->data, raw->len ); - return -ENOTSUP_DIGEST; - } - - /* Check algorithm is a digest algorithm */ - if ( ! algorithm->digest ) { - DBGC ( sig, "CMS %p/%p algorithm %s is not a digest " - "algorithm\n", sig, info, algorithm->name ); - return -EINVAL_DIGEST; + return rc; } /* Record digest algorithm */ @@ -294,21 +278,14 @@ static int cms_parse_signature_algorithm ( struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw ) { struct asn1_algorithm *algorithm; + int rc; /* Identify algorithm */ - algorithm = asn1_algorithm ( raw ); - if ( ! algorithm ) { + if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) { DBGC ( sig, "CMS %p/%p could not identify public-key " - "algorithm:\n", sig, info ); + "algorithm: %s\n", sig, info, strerror ( rc ) ); DBGC_HDA ( sig, 0, raw->data, raw->len ); - return -ENOTSUP_PUBKEY; - } - - /* Check algorithm is a signature algorithm */ - if ( ! algorithm->pubkey ) { - DBGC ( sig, "CMS %p/%p algorithm %s is not a public-key " - "algorithm\n", sig, info, algorithm->name ); - return -EINVAL_PUBKEY; + return rc; } /* Record signature algorithm */ diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 1cb46a1d..f25424a1 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -154,66 +154,6 @@ static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME }; static struct asn1_cursor oid_common_name_cursor = ASN1_OID_CURSOR ( oid_common_name ); -/** - * Parse X.509 certificate algorithm - * - * @v cert X.509 certificate - * @v algorithm Algorithm to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_pubkey_algorithm ( struct x509_certificate *cert, - struct asn1_algorithm **algorithm, - const struct asn1_cursor *raw ) { - - /* Parse algorithm */ - *algorithm = asn1_algorithm ( raw ); - if ( ! (*algorithm) ) { - DBGC ( cert, "X509 %p unrecognised algorithm:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -ENOTSUP_ALGORITHM; - } - - /* Check algorithm has a public key */ - if ( ! (*algorithm)->pubkey ) { - DBGC ( cert, "X509 %p algorithm %s is not a public-key " - "algorithm:\n", cert, (*algorithm)->name ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_ALGORITHM; - } - - return 0; -} - -/** - * Parse X.509 certificate signature algorithm - * - * @v cert X.509 certificate - * @v algorithm Algorithm to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_signature_algorithm ( struct x509_certificate *cert, - struct asn1_algorithm **algorithm, - const struct asn1_cursor *raw ) { - int rc; - - /* Parse algorithm */ - if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm, - raw ) ) != 0 ) - return rc; - - /* Check algorithm is a signature algorithm */ - if ( ! (*algorithm)->digest ) { - DBGC ( cert, "X509 %p algorithm %s is not a signature " - "algorithm:\n", cert, (*algorithm)->name ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_ALGORITHM; - } - - return 0; -} - /** * Parse X.509 certificate bit string * @@ -541,9 +481,11 @@ static int x509_parse_public_key ( struct x509_certificate *cert, asn1_enter ( &cursor, ASN1_SEQUENCE ); /* Parse algorithm */ - if ( ( rc = x509_parse_pubkey_algorithm ( cert, algorithm, - &cursor ) ) != 0 ) + if ( ( rc = asn1_pubkey_algorithm ( &cursor, algorithm ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse public key algorithm: " + "%s\n", cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p public key algorithm is %s\n", cert, (*algorithm)->name ); asn1_skip_any ( &cursor ); @@ -1045,9 +987,11 @@ static int x509_parse_tbscertificate ( struct x509_certificate *cert, asn1_skip_any ( &cursor ); /* Parse signature */ - if ( ( rc = x509_parse_signature_algorithm ( cert, algorithm, - &cursor ) ) != 0 ) + if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse signature algorithm: " + "%s\n", cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p tbsCertificate signature algorithm is %s\n", cert, (*algorithm)->name ); asn1_skip_any ( &cursor ); @@ -1107,9 +1051,12 @@ static int x509_parse ( struct x509_certificate *cert, asn1_skip_any ( &cursor ); /* Parse signatureAlgorithm */ - if ( ( rc = x509_parse_signature_algorithm ( cert, signature_algorithm, - &cursor ) ) != 0 ) + if ( ( rc = asn1_signature_algorithm ( &cursor, + signature_algorithm ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse signature algorithm: " + "%s\n", cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p signatureAlgorithm is %s\n", cert, (*signature_algorithm)->name ); asn1_skip_any ( &cursor ); diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 38f0e5b0..cd0d5342 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -238,8 +238,14 @@ extern int asn1_boolean ( const struct asn1_cursor *cursor ); extern int asn1_integer ( const struct asn1_cursor *cursor, int *value ); extern int asn1_compare ( const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2 ); -extern struct asn1_algorithm * -asn1_algorithm ( const struct asn1_cursor *cursor ); +extern int asn1_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); +extern int asn1_pubkey_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); +extern int asn1_digest_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); +extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor, + struct asn1_algorithm **algorithm ); extern int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ); From 4aad46ac70933458f118f59506044de35eb9f7cf Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 14 May 2012 09:54:19 +0100 Subject: [PATCH 004/250] [crypto] Generalise x509_parse_bit_string() to asn1_bit_string() Signed-off-by: Michael Brown --- src/crypto/asn1.c | 89 +++++++++++++++++++++++++++++++- src/crypto/rsa.c | 15 ++---- src/crypto/x509.c | 109 ++++++---------------------------------- src/include/ipxe/asn1.h | 18 +++---- src/include/ipxe/x509.h | 14 +----- 5 files changed, 119 insertions(+), 126 deletions(-) diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 47c735c5..9b3864ed 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -62,6 +62,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_EINVAL_ASN1_ALGORITHM ) #define EINFO_EINVAL_ASN1_ALGORITHM \ __einfo_uniqify ( EINFO_EINVAL, 0x06, "Invalid algorithm" ) +#define EINVAL_BIT_STRING \ + __einfo_error ( EINFO_EINVAL_BIT_STRING ) +#define EINFO_EINVAL_BIT_STRING \ + __einfo_uniqify ( EINFO_EINVAL, 0x07, "Invalid bit string" ) #define ENOTSUP_ALGORITHM \ __einfo_error ( EINFO_ENOTSUP_ALGORITHM ) #define EINFO_ENOTSUP_ALGORITHM \ @@ -295,7 +299,9 @@ int asn1_shrink_any ( struct asn1_cursor *cursor ) { */ int asn1_boolean ( const struct asn1_cursor *cursor ) { struct asn1_cursor contents; - const struct asn1_boolean *boolean; + const struct { + uint8_t value; + } __attribute__ (( packed )) *boolean; /* Enter boolean */ memcpy ( &contents, cursor, sizeof ( contents ) ); @@ -347,6 +353,87 @@ int asn1_integer ( const struct asn1_cursor *cursor, int *value ) { return 0; } +/** + * Parse ASN.1 bit string + * + * @v cursor ASN.1 cursor + * @v bits Bit string to fill in + * @ret rc Return status code + */ +int asn1_bit_string ( const struct asn1_cursor *cursor, + struct asn1_bit_string *bits ) { + struct asn1_cursor contents; + const struct { + uint8_t unused; + uint8_t data[0]; + } __attribute__ (( packed )) *bit_string; + size_t len; + unsigned int unused; + uint8_t unused_mask; + const uint8_t *last; + int rc; + + /* Enter bit string */ + memcpy ( &contents, cursor, sizeof ( contents ) ); + if ( ( rc = asn1_enter ( &contents, ASN1_BIT_STRING ) ) != 0 ) { + DBGC ( cursor, "ASN1 %p cannot locate bit string:\n", cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return rc; + } + + /* Validity checks */ + if ( contents.len < sizeof ( *bit_string ) ) { + DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -EINVAL_BIT_STRING; + } + bit_string = contents.data; + len = ( contents.len - offsetof ( typeof ( *bit_string ), data ) ); + unused = bit_string->unused; + unused_mask = ( 0xff >> ( 8 - unused ) ); + last = ( bit_string->data + len - 1 ); + if ( ( unused >= 8 ) || + ( ( unused > 0 ) && ( len == 0 ) ) || + ( ( *last & unused_mask ) != 0 ) ) { + DBGC ( cursor, "ASN1 %p invalid bit string:\n", cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -EINVAL_BIT_STRING; + } + + /* Populate bit string */ + bits->data = &bit_string->data; + bits->len = len; + bits->unused = unused; + + return 0; +} + +/** + * Parse ASN.1 bit string that must be an integral number of bytes + * + * @v cursor ASN.1 cursor + * @v bits Bit string to fill in + * @ret rc Return status code + */ +int asn1_integral_bit_string ( const struct asn1_cursor *cursor, + struct asn1_bit_string *bits ) { + int rc; + + /* Parse bit string */ + if ( ( rc = asn1_bit_string ( cursor, bits ) ) != 0 ) + return rc; + + /* Check that there are no unused bits at end of string */ + if ( bits->unused ) { + DBGC ( cursor, "ASN1 %p invalid integral bit string:\n", + cursor ); + DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); + return -EINVAL_BIT_STRING; + } + + return 0; +} + /** * Compare two ASN.1 objects * diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c index be2696ba..563d6b9b 100644 --- a/src/crypto/rsa.c +++ b/src/crypto/rsa.c @@ -241,7 +241,7 @@ static int rsa_parse_integer ( struct rsa_context *context, */ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { struct rsa_context *context = ctx; - const struct asn1_bit_string *bit_string; + struct asn1_bit_string bits; struct asn1_cursor modulus; struct asn1_cursor exponent; struct asn1_cursor cursor; @@ -274,17 +274,10 @@ static int rsa_init ( void *ctx, const void *key, size_t key_len ) { asn1_skip ( &cursor, ASN1_SEQUENCE ); /* Enter subjectPublicKey */ - asn1_enter ( &cursor, ASN1_BIT_STRING ); - - /* Check and skip unused-bits byte of bit string */ - bit_string = cursor.data; - if ( ( cursor.len < sizeof ( *bit_string ) ) || - ( bit_string->unused != 0 ) ) { - rc = -EINVAL; + if ( ( rc = asn1_integral_bit_string ( &cursor, &bits ) ) != 0 ) goto err_parse; - } - cursor.data = &bit_string->data; - cursor.len -= offsetof ( typeof ( *bit_string ), data ); + cursor.data = bits.data; + cursor.len = bits.len; /* Enter RSAPublicKey */ asn1_enter ( &cursor, ASN1_SEQUENCE ); diff --git a/src/crypto/x509.c b/src/crypto/x509.c index f25424a1..dc8745dc 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -54,10 +54,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_EINVAL_ALGORITHM ) #define EINFO_EINVAL_ALGORITHM \ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid algorithm type" ) -#define EINVAL_BIT_STRING \ - __einfo_error ( EINFO_EINVAL_BIT_STRING ) -#define EINFO_EINVAL_BIT_STRING \ - __einfo_uniqify ( EINFO_EINVAL, 0x02, "Invalid bit string" ) #define EINVAL_ALGORITHM_MISMATCH \ __einfo_error ( EINFO_EINVAL_ALGORITHM_MISMATCH ) #define EINFO_EINVAL_ALGORITHM_MISMATCH \ @@ -154,88 +150,6 @@ static uint8_t oid_common_name[] = { ASN1_OID_COMMON_NAME }; static struct asn1_cursor oid_common_name_cursor = ASN1_OID_CURSOR ( oid_common_name ); -/** - * Parse X.509 certificate bit string - * - * @v cert X.509 certificate - * @v bits Bit string to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_bit_string ( struct x509_certificate *cert, - struct x509_bit_string *bits, - const struct asn1_cursor *raw ) { - struct asn1_cursor cursor; - const struct asn1_bit_string *bit_string; - size_t len; - unsigned int unused; - uint8_t unused_mask; - const uint8_t *last; - int rc; - - /* Enter bit string */ - memcpy ( &cursor, raw, sizeof ( cursor ) ); - if ( ( rc = asn1_enter ( &cursor, ASN1_BIT_STRING ) ) != 0 ) { - DBGC ( cert, "X509 %p cannot locate bit string:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return rc; - } - - /* Validity checks */ - if ( cursor.len < sizeof ( *bit_string ) ) { - DBGC ( cert, "X509 %p invalid bit string:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_BIT_STRING; - } - bit_string = cursor.data; - len = ( cursor.len - offsetof ( typeof ( *bit_string ), data ) ); - unused = bit_string->unused; - unused_mask = ( 0xff >> ( 8 - unused ) ); - last = ( bit_string->data + len - 1 ); - if ( ( unused >= 8 ) || - ( ( unused > 0 ) && ( len == 0 ) ) || - ( ( *last & unused_mask ) != 0 ) ) { - DBGC ( cert, "X509 %p invalid bit string:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_BIT_STRING; - } - - /* Populate bit string */ - bits->data = &bit_string->data; - bits->len = len; - bits->unused = unused; - - return 0; -} - -/** - * Parse X.509 certificate bit string that must be an integral number of bytes - * - * @v cert X.509 certificate - * @v bits Bit string to fill in - * @v raw ASN.1 cursor - * @ret rc Return status code - */ -static int x509_parse_integral_bit_string ( struct x509_certificate *cert, - struct x509_bit_string *bits, - const struct asn1_cursor *raw ) { - int rc; - - /* Parse bit string */ - if ( ( rc = x509_parse_bit_string ( cert, bits, raw ) ) != 0 ) - return rc; - - /* Check that there are no unused bits at end of string */ - if ( bits->unused ) { - DBGC ( cert, "X509 %p invalid integral bit string:\n", cert ); - DBGC_HDA ( cert, 0, raw->data, raw->len ); - return -EINVAL_BIT_STRING; - } - - return 0; -} - - /** * Parse X.509 certificate version * @@ -466,7 +380,7 @@ static int x509_parse_public_key ( struct x509_certificate *cert, const struct asn1_cursor *raw ) { struct x509_public_key *public_key = &cert->subject.public_key; struct asn1_algorithm **algorithm = &public_key->algorithm; - struct x509_bit_string *raw_bits = &public_key->raw_bits; + struct asn1_bit_string *raw_bits = &public_key->raw_bits; struct asn1_cursor cursor; int rc; @@ -491,8 +405,11 @@ static int x509_parse_public_key ( struct x509_certificate *cert, asn1_skip_any ( &cursor ); /* Parse bit string */ - if ( ( rc = x509_parse_bit_string ( cert, raw_bits, &cursor ) ) != 0 ) + if ( ( rc = asn1_bit_string ( &cursor, raw_bits ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse public key bits: %s\n", + cert, strerror ( rc ) ); return rc; + } return 0; } @@ -569,7 +486,7 @@ static int x509_parse_basic_constraints ( struct x509_certificate *cert, static int x509_parse_key_usage ( struct x509_certificate *cert, const struct asn1_cursor *raw ) { struct x509_key_usage *usage = &cert->extensions.usage; - struct x509_bit_string bit_string; + struct asn1_bit_string bit_string; const uint8_t *bytes; size_t len; unsigned int i; @@ -579,8 +496,11 @@ static int x509_parse_key_usage ( struct x509_certificate *cert, usage->present = 1; /* Parse bit string */ - if ( ( rc = x509_parse_bit_string ( cert, &bit_string, raw ) ) != 0 ) + if ( ( rc = asn1_bit_string ( raw, &bit_string ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse key usage: %s\n", + cert, strerror ( rc ) ); return rc; + } /* Parse key usage bits */ bytes = bit_string.data; @@ -1034,7 +954,7 @@ static int x509_parse ( struct x509_certificate *cert, const struct asn1_cursor *raw ) { struct x509_signature *signature = &cert->signature; struct asn1_algorithm **signature_algorithm = &signature->algorithm; - struct x509_bit_string *signature_value = &signature->value; + struct asn1_bit_string *signature_value = &signature->value; struct asn1_cursor cursor; int rc; @@ -1062,9 +982,12 @@ static int x509_parse ( struct x509_certificate *cert, asn1_skip_any ( &cursor ); /* Parse signatureValue */ - if ( ( rc = x509_parse_integral_bit_string ( cert, signature_value, - &cursor ) ) != 0 ) + if ( ( rc = asn1_integral_bit_string ( &cursor, + signature_value ) ) != 0 ) { + DBGC ( cert, "X509 %p could not parse signature value: %s\n", + cert, strerror ( rc ) ); return rc; + } DBGC2 ( cert, "X509 %p signatureValue is:\n", cert ); DBGC2_HDA ( cert, 0, signature_value->data, signature_value->len ); diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index cd0d5342..222e32ec 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -200,18 +200,14 @@ struct asn1_algorithm { /** Declare an ASN.1 OID-identified algorithm */ #define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 ) -/** An ASN.1 boolean */ -struct asn1_boolean { - /** Value */ - uint8_t value; -} __attribute__ (( packed )); - /** An ASN.1 bit string */ struct asn1_bit_string { - /** Number of unused bits */ - uint8_t unused; /** Data */ - uint8_t data[0]; + const void *data; + /** Length */ + size_t len; + /** Unused bits at end of data */ + unsigned int unused; } __attribute__ (( packed )); /** @@ -236,6 +232,10 @@ extern int asn1_skip_any ( struct asn1_cursor *cursor ); extern int asn1_shrink_any ( struct asn1_cursor *cursor ); extern int asn1_boolean ( const struct asn1_cursor *cursor ); extern int asn1_integer ( const struct asn1_cursor *cursor, int *value ); +extern int asn1_bit_string ( const struct asn1_cursor *cursor, + struct asn1_bit_string *bits ); +extern int asn1_integral_bit_string ( const struct asn1_cursor *cursor, + struct asn1_bit_string *bits ); extern int asn1_compare ( const struct asn1_cursor *cursor1, const struct asn1_cursor *cursor2 ); extern int asn1_algorithm ( const struct asn1_cursor *cursor, diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index a55511b8..8b1dda25 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -16,16 +16,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include -/** An X.509 bit string */ -struct x509_bit_string { - /** Data */ - const void *data; - /** Length */ - size_t len; - /** Unused bits at end of data */ - unsigned int unused; -}; - /** An X.509 serial number */ struct x509_serial { /** Raw serial number */ @@ -59,7 +49,7 @@ struct x509_public_key { /** Public key algorithm */ struct asn1_algorithm *algorithm; /** Raw public key bit string */ - struct x509_bit_string raw_bits; + struct asn1_bit_string raw_bits; }; /** An X.509 certificate subject */ @@ -77,7 +67,7 @@ struct x509_signature { /** Signature algorithm */ struct asn1_algorithm *algorithm; /** Signature value */ - struct x509_bit_string value; + struct asn1_bit_string value; }; /** An X.509 certificate basic constraints set */ From e01af7367dfb14a76767c7bfb8763e5a705822c1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 14 May 2012 14:09:52 +0100 Subject: [PATCH 005/250] [crypto] Parse OCSPSigning key purpose, if present Signed-off-by: Michael Brown --- src/crypto/x509.c | 8 ++++++++ src/include/ipxe/asn1.h | 7 +++++++ src/include/ipxe/x509.h | 1 + 3 files changed, 16 insertions(+) diff --git a/src/crypto/x509.c b/src/crypto/x509.c index dc8745dc..a8660934 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -518,6 +518,9 @@ static int x509_parse_key_usage ( struct x509_certificate *cert, /** "id-kp-codeSigning" object identifier */ static uint8_t oid_code_signing[] = { ASN1_OID_CODESIGNING }; +/** "id-kp-OCSPSigning" object identifier */ +static uint8_t oid_ocsp_signing[] = { ASN1_OID_OCSPSIGNING }; + /** Supported key purposes */ static struct x509_key_purpose x509_key_purposes[] = { { @@ -525,6 +528,11 @@ static struct x509_key_purpose x509_key_purposes[] = { .bits = X509_CODE_SIGNING, .oid = ASN1_OID_CURSOR ( oid_code_signing ), }, + { + .name = "ocspSigning", + .bits = X509_OCSP_SIGNING, + .oid = ASN1_OID_CURSOR ( oid_ocsp_signing ), + }, }; /** diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 222e32ec..cd5c3306 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -176,6 +176,13 @@ struct asn1_cursor { ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \ ASN1_OID_SINGLE ( 48 ), ASN1_OID_SINGLE ( 1 ) +/** ASN.1 OID for id-kp-OCSPSigning (1.3.6.1.5.5.7.3.9) */ +#define ASN1_OID_OCSPSIGNING \ + ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \ + ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \ + ASN1_OID_SINGLE ( 3 ), ASN1_OID_SINGLE ( 9 ) + /** Define an ASN.1 cursor containing an OID */ #define ASN1_OID_CURSOR( oid_value ) { \ .data = oid_value, \ diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index 8b1dda25..6dc31b45 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -119,6 +119,7 @@ struct x509_extended_key_usage { */ enum x509_extended_key_usage_bits { X509_CODE_SIGNING = 0x0001, + X509_OCSP_SIGNING = 0x0002, }; /** X.509 certificate OCSP responder */ From deac4ea1baa62ab554b57179e481c1b255716bb1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 11 May 2012 16:40:28 +0100 Subject: [PATCH 006/250] [crypto] Add functions for constructing ASN.1 objects Signed-off-by: Michael Brown --- src/crypto/asn1.c | 139 ++++++++++++++++++++++++++++++++++++++++ src/include/ipxe/asn1.h | 33 ++++++++++ 2 files changed, 172 insertions(+) diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 9b3864ed..5fc37849 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include @@ -699,3 +700,141 @@ int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) { return 0; } + +/** + * Construct ASN.1 header + * + * @v header ASN.1 builder header + * @v type Type + * @v len Content length + * @ret header_len Header length + */ +static size_t asn1_header ( struct asn1_builder_header *header, + unsigned int type, size_t len ) { + unsigned int header_len = 2; + unsigned int len_len = 0; + size_t temp; + + /* Construct header */ + header->type = type; + if ( len < 0x80 ) { + header->length[0] = len; + } else { + for ( temp = len ; temp ; temp >>= 8 ) + len_len++; + header->length[0] = ( 0x80 | len_len ); + header_len += len_len; + for ( temp = len ; temp ; temp >>= 8 ) + header->length[len_len--] = ( temp & 0xff ); + } + + return header_len; +} + +/** + * Grow ASN.1 builder + * + * @v builder ASN.1 builder + * @v extra Extra space to prepend + * @ret rc Return status code + */ +static int asn1_grow ( struct asn1_builder *builder, size_t extra ) { + size_t new_len; + void *new; + + /* As with the ASN1 parsing functions, make errors permanent */ + if ( builder->len && ! builder->data ) + return -ENOMEM; + + /* Reallocate data buffer */ + new_len = ( builder->len + extra ); + new = realloc ( builder->data, new_len ); + if ( ! new ) { + free ( builder->data ); + builder->data = NULL; + return -ENOMEM; + } + builder->data = new; + + /* Move existing data to end of buffer */ + memmove ( ( builder->data + extra ), builder->data, builder->len ); + builder->len = new_len; + + return 0; +} + +/** + * Prepend raw data to ASN.1 builder + * + * @v builder ASN.1 builder + * @v data Data to prepend + * @v len Length of data to prepend + * @ret rc Return status code + */ +int asn1_prepend_raw ( struct asn1_builder *builder, const void *data, + size_t len ) { + int rc; + + /* Grow buffer */ + if ( ( rc = asn1_grow ( builder, len ) ) != 0 ) + return rc; + + /* Populate data buffer */ + memcpy ( builder->data, data, len ); + + return 0; +} + +/** + * Prepend data to ASN.1 builder + * + * @v builder ASN.1 builder + * @v type Type + * @v data Data to prepend + * @v len Length of data to prepend + * @ret rc Return status code + */ +int asn1_prepend ( struct asn1_builder *builder, unsigned int type, + const void *data, size_t len ) { + struct asn1_builder_header header; + size_t header_len; + int rc; + + /* Construct header */ + header_len = asn1_header ( &header, type, len ); + + /* Grow buffer */ + if ( ( rc = asn1_grow ( builder, header_len + len ) ) != 0 ) + return rc; + + /* Populate data buffer */ + memcpy ( builder->data, &header, header_len ); + memcpy ( ( builder->data + header_len ), data, len ); + + return 0; +} + +/** + * Wrap ASN.1 builder + * + * @v builder ASN.1 builder + * @v type Type + * @ret rc Return status code + */ +int asn1_wrap ( struct asn1_builder *builder, unsigned int type ) { + struct asn1_builder_header header; + size_t header_len; + int rc; + + /* Construct header */ + header_len = asn1_header ( &header, type, builder->len ); + + /* Grow buffer */ + if ( ( rc = asn1_grow ( builder, header_len ) ) != 0 ) + return rc; + + /* Populate data buffer */ + memcpy ( builder->data, &header, header_len ); + + return 0; +} diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index cd5c3306..3fbd09f4 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -21,6 +21,34 @@ struct asn1_cursor { size_t len; }; +/** An ASN.1 object builder */ +struct asn1_builder { + /** Data + * + * This is always dynamically allocated. If @c data is NULL + * while @len is non-zero, this indicates that a memory + * allocation error has occurred during the building process. + */ + void *data; + /** Length of data */ + size_t len; +}; + +/** Maximum (viable) length of ASN.1 length + * + * While in theory unlimited, this length is sufficient to contain a + * size_t. + */ +#define ASN1_MAX_LEN_LEN ( 1 + sizeof ( size_t ) ) + +/** An ASN.1 header */ +struct asn1_builder_header { + /** Type */ + uint8_t type; + /** Length (encoded) */ + uint8_t length[ASN1_MAX_LEN_LEN]; +} __attribute__ (( packed )); + /** ASN.1 end */ #define ASN1_END 0x00 @@ -255,5 +283,10 @@ extern int asn1_signature_algorithm ( const struct asn1_cursor *cursor, struct asn1_algorithm **algorithm ); extern int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ); +extern int asn1_prepend_raw ( struct asn1_builder *builder, const void *data, + size_t len ); +extern int asn1_prepend ( struct asn1_builder *builder, unsigned int type, + const void *data, size_t len ); +extern int asn1_wrap ( struct asn1_builder *builder, unsigned int type ); #endif /* _IPXE_ASN1_H */ From 39ac285a8abced92b03842a8ce48957550d454ad Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 14 May 2012 18:22:38 +0100 Subject: [PATCH 007/250] [crypto] Add framework for OCSP Add support for constructing OCSP queries and parsing OCSP responses. (There is no support yet for actually issuing an OCSP query via an HTTP POST.) Signed-off-by: Michael Brown --- src/crypto/ocsp.c | 749 +++++++++++++++++++++++++++++++++++++ src/crypto/x509.c | 6 +- src/include/ipxe/asn1.h | 11 + src/include/ipxe/errfile.h | 1 + src/include/ipxe/ocsp.h | 108 ++++++ src/include/ipxe/x509.h | 5 + 6 files changed, 877 insertions(+), 3 deletions(-) create mode 100644 src/crypto/ocsp.c create mode 100644 src/include/ipxe/ocsp.h diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c new file mode 100644 index 00000000..7dca281f --- /dev/null +++ b/src/crypto/ocsp.c @@ -0,0 +1,749 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * Online Certificate Status Protocol + * + */ + +/* Disambiguate the various error causes */ +#define EACCES_CERT_STATUS \ + __einfo_error ( EINFO_EACCES_CERT_STATUS ) +#define EINFO_EACCES_CERT_STATUS \ + __einfo_uniqify ( EINFO_EACCES, 0x01, \ + "Certificate status not good" ) +#define EACCES_CERT_MISMATCH \ + __einfo_error ( EINFO_EACCES_CERT_MISMATCH ) +#define EINFO_EACCES_CERT_MISMATCH \ + __einfo_uniqify ( EINFO_EACCES, 0x02, \ + "Certificate ID mismatch" ) +#define EACCES_NON_OCSP_SIGNING \ + __einfo_error ( EINFO_EACCES_NON_OCSP_SIGNING ) +#define EINFO_EACCES_NON_OCSP_SIGNING \ + __einfo_uniqify ( EINFO_EACCES, 0x03, \ + "Not an OCSP signing certificate" ) +#define EACCES_STALE \ + __einfo_error ( EINFO_EACCES_STALE ) +#define EINFO_EACCES_STALE \ + __einfo_uniqify ( EINFO_EACCES, 0x04, \ + "Stale (or premature) OCSP repsonse" ) +#define EPROTO_MALFORMED_REQUEST \ + __einfo_error ( EINFO_EPROTO_MALFORMED_REQUEST ) +#define EINFO_EPROTO_MALFORMED_REQUEST \ + __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_MALFORMED_REQUEST, \ + "Illegal confirmation request" ) +#define EPROTO_INTERNAL_ERROR \ + __einfo_error ( EINFO_EPROTO_INTERNAL_ERROR ) +#define EINFO_EPROTO_INTERNAL_ERROR \ + __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_INTERNAL_ERROR, \ + "Internal error in issuer" ) +#define EPROTO_TRY_LATER \ + __einfo_error ( EINFO_EPROTO_TRY_LATER ) +#define EINFO_EPROTO_TRY_LATER \ + __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_TRY_LATER, \ + "Try again later" ) +#define EPROTO_SIG_REQUIRED \ + __einfo_error ( EINFO_EPROTO_SIG_REQUIRED ) +#define EINFO_EPROTO_SIG_REQUIRED \ + __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_SIG_REQUIRED, \ + "Must sign the request" ) +#define EPROTO_UNAUTHORIZED \ + __einfo_error ( EINFO_EPROTO_UNAUTHORIZED ) +#define EINFO_EPROTO_UNAUTHORIZED \ + __einfo_uniqify ( EINFO_EPROTO, OCSP_STATUS_UNAUTHORIZED, \ + "Request unauthorized" ) +#define EPROTO_STATUS( status ) \ + EUNIQ ( EPROTO, (status), EPROTO_MALFORMED_REQUEST, \ + EPROTO_INTERNAL_ERROR, EPROTO_TRY_LATER, \ + EPROTO_SIG_REQUIRED, EPROTO_UNAUTHORIZED ) + +/** OCSP digest algorithm */ +#define ocsp_digest_algorithm sha1_algorithm + +/** OCSP digest algorithm identifier */ +static const uint8_t ocsp_algorithm_id[] = + { OCSP_ALGORITHM_IDENTIFIER ( ASN1_OID_SHA1 ) }; + +/** OCSP basic response type */ +static const uint8_t oid_basic_response_type[] = { ASN1_OID_OCSP_BASIC }; + +/** OCSP basic response type cursor */ +static struct asn1_cursor oid_basic_response_type_cursor = + ASN1_OID_CURSOR ( oid_basic_response_type ); + +/** + * Free OCSP check + * + * @v refcnt Reference count + */ +static void ocsp_free ( struct refcnt *refcnt ) { + struct ocsp_check *ocsp = + container_of ( refcnt, struct ocsp_check, refcnt ); + + x509_put ( ocsp->cert ); + x509_put ( ocsp->issuer ); + free ( ocsp->request.builder.data ); + free ( ocsp->response.data ); + x509_put ( ocsp->response.signer ); + free ( ocsp ); +} + +/** + * Build OCSP request + * + * @v ocsp OCSP check + * @ret rc Return status code + */ +static int ocsp_request ( struct ocsp_check *ocsp ) { + struct digest_algorithm *digest = &ocsp_digest_algorithm; + struct asn1_builder *builder = &ocsp->request.builder; + struct asn1_cursor *cert_id = &ocsp->request.cert_id; + uint8_t digest_ctx[digest->ctxsize]; + uint8_t name_digest[digest->digestsize]; + uint8_t pubkey_digest[digest->digestsize]; + int rc; + + /* Generate digests */ + digest_init ( digest, digest_ctx ); + digest_update ( digest, digest_ctx, ocsp->cert->issuer.raw.data, + ocsp->cert->issuer.raw.len ); + digest_final ( digest, digest_ctx, name_digest ); + digest_init ( digest, digest_ctx ); + digest_update ( digest, digest_ctx, + ocsp->issuer->subject.public_key.raw_bits.data, + ocsp->issuer->subject.public_key.raw_bits.len ); + digest_final ( digest, digest_ctx, pubkey_digest ); + + /* Construct request */ + if ( ( rc = ( asn1_prepend_raw ( builder, ocsp->cert->serial.raw.data, + ocsp->cert->serial.raw.len ), + asn1_prepend ( builder, ASN1_OCTET_STRING, + pubkey_digest, sizeof ( pubkey_digest ) ), + asn1_prepend ( builder, ASN1_OCTET_STRING, + name_digest, sizeof ( name_digest ) ), + asn1_prepend ( builder, ASN1_SEQUENCE, + ocsp_algorithm_id, + sizeof ( ocsp_algorithm_id ) ), + asn1_wrap ( builder, ASN1_SEQUENCE ), + asn1_wrap ( builder, ASN1_SEQUENCE ), + asn1_wrap ( builder, ASN1_SEQUENCE ), + asn1_wrap ( builder, ASN1_SEQUENCE ), + asn1_wrap ( builder, ASN1_SEQUENCE ) ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not build request: %s\n", + ocsp, ocsp->cert->subject.name, strerror ( rc ) ); + return rc; + } + DBGC2 ( ocsp, "OCSP %p \"%s\" request is:\n", + ocsp, ocsp->cert->subject.name ); + DBGC2_HDA ( ocsp, 0, builder->data, builder->len ); + + /* Parse certificate ID for comparison with response */ + cert_id->data = builder->data; + cert_id->len = builder->len; + if ( ( rc = ( asn1_enter ( cert_id, ASN1_SEQUENCE ), + asn1_enter ( cert_id, ASN1_SEQUENCE ), + asn1_enter ( cert_id, ASN1_SEQUENCE ), + asn1_enter ( cert_id, ASN1_SEQUENCE ) ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not locate certID: %s\n", + ocsp, ocsp->cert->subject.name, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * Create OCSP check + * + * @v cert Certificate to check + * @v issuer Issuing certificate + * @ret ocsp OCSP check + * @ret rc Return status code + */ +int ocsp_check ( struct x509_certificate *cert, + struct x509_certificate *issuer, + struct ocsp_check **ocsp ) { + int rc; + + /* Sanity checks */ + assert ( cert != NULL ); + assert ( issuer != NULL ); + assert ( issuer->valid ); + + /* Allocate and initialise check */ + *ocsp = zalloc ( sizeof ( **ocsp ) ); + if ( ! *ocsp ) { + rc = -ENOMEM; + goto err_alloc; + } + ref_init ( &(*ocsp)->refcnt, ocsp_free ); + (*ocsp)->cert = x509_get ( cert ); + (*ocsp)->issuer = x509_get ( issuer ); + + /* Build request */ + if ( ( rc = ocsp_request ( *ocsp ) ) != 0 ) + goto err_request; + + return 0; + + err_request: + ocsp_put ( *ocsp ); + err_alloc: + return rc; +} + +/** + * Parse OCSP response status + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_response_status ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + uint8_t status; + int rc; + + /* Enter responseStatus */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + if ( ( rc = asn1_enter ( &cursor, ASN1_ENUMERATED ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not locate responseStatus: " + "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc )); + return rc; + } + + /* Extract response status */ + if ( cursor.len != sizeof ( status ) ) { + DBGC ( ocsp, "OCSP %p \"%s\" invalid status:\n", + ocsp, ocsp->cert->subject.name ); + DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); + return -EINVAL; + } + memcpy ( &status, cursor.data, sizeof ( status ) ); + + /* Check response status */ + if ( status != OCSP_STATUS_SUCCESSFUL ) { + DBGC ( ocsp, "OCSP %p \"%s\" response status %d\n", + ocsp, ocsp->cert->subject.name, status ); + return EPROTO_STATUS ( status ); + } + + return 0; +} + +/** + * Parse OCSP response type + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_response_type ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + + /* Enter responseType */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_OID ); + + /* Check responseType is "basic" */ + if ( asn1_compare ( &oid_basic_response_type_cursor, &cursor ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" response type not supported:\n", + ocsp, ocsp->cert->subject.name ); + DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); + return -ENOTSUP; + } + + return 0; +} + +/** + * Parse OCSP certificate ID + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_cert_id ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + + /* Check certID matches request */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_shrink_any ( &cursor ); + if ( asn1_compare ( &cursor, &ocsp->request.cert_id ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" certID mismatch:\n", + ocsp, ocsp->cert->subject.name ); + DBGC_HDA ( ocsp, 0, ocsp->request.cert_id.data, + ocsp->request.cert_id.len ); + DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); + return -EACCES_CERT_MISMATCH; + } + + return 0; +} + +/** + * Parse OCSP responses + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_responses ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct ocsp_response *response = &ocsp->response; + struct asn1_cursor cursor; + int rc; + + /* Enter responses */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Enter first singleResponse */ + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse certID */ + if ( ( rc = ocsp_parse_cert_id ( ocsp, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Check certStatus */ + if ( asn1_type ( &cursor ) != ASN1_IMPLICIT_TAG ( 0 ) ) { + DBGC ( ocsp, "OCSP %p \"%s\" non-good certStatus:\n", + ocsp, ocsp->cert->subject.name ); + DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); + return -EACCES_CERT_STATUS; + } + asn1_skip_any ( &cursor ); + + /* Parse thisUpdate */ + if ( ( rc = asn1_generalized_time ( &cursor, + &response->this_update ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not parse thisUpdate: %s\n", + ocsp, ocsp->cert->subject.name, strerror ( rc ) ); + return rc; + } + DBGC2 ( ocsp, "OCSP %p \"%s\" this update was at time %lld\n", + ocsp, ocsp->cert->subject.name, response->this_update ); + asn1_skip_any ( &cursor ); + + /* Parse nextUpdate, if present */ + if ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) { + asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); + if ( ( rc = asn1_generalized_time ( &cursor, + &response->next_update ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not parse " + "nextUpdate: %s\n", ocsp, + ocsp->cert->subject.name, strerror ( rc ) ); + return rc; + } + DBGC2 ( ocsp, "OCSP %p \"%s\" next update is at time %lld\n", + ocsp, ocsp->cert->subject.name, response->next_update ); + } else { + /* If no nextUpdate is present, this indicates that + * "newer revocation information is available all the + * time". Actually, this indicates that there is no + * point to performing the OCSP check, since an + * attacker could replay the response at any future + * time and it would still be valid. + */ + DBGC ( ocsp, "OCSP %p \"%s\" responder is a moron\n", + ocsp, ocsp->cert->subject.name ); + response->next_update = time ( NULL ); + } + + return 0; +} + +/** + * Parse OCSP response data + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_tbs_response_data ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct ocsp_response *response = &ocsp->response; + struct asn1_cursor cursor; + int rc; + + /* Record raw tbsResponseData */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_shrink_any ( &cursor ); + memcpy ( &response->tbs, &cursor, sizeof ( response->tbs ) ); + + /* Enter tbsResponseData */ + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Skip version, if present */ + asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); + + /* Skip responderID */ + asn1_skip_any ( &cursor ); + + /* Skip producedAt */ + asn1_skip_any ( &cursor ); + + /* Parse responses */ + if ( ( rc = ocsp_parse_responses ( ocsp, &cursor ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Parse OCSP certificates + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_certs ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct ocsp_response *response = &ocsp->response; + struct asn1_cursor cursor; + int rc; + + /* Enter certs */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse certificate, if present. The data structure permits + * multiple certificates, but the protocol requires that the + * OCSP signing certificate must either be the issuer itself, + * or must be directly issued by the issuer (see RFC2560 + * section 4.2.2.2 "Authorized Responders"). + */ + if ( ( cursor.len != 0 ) && + ( ( rc = x509_certificate ( cursor.data, cursor.len, + &response->signer ) ) != 0 ) ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not parse certificate: " + "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc )); + DBGC_HDA ( ocsp, 0, cursor.data, cursor.len ); + return rc; + } + DBGC2 ( ocsp, "OCSP %p \"%s\" response is signed by \"%s\"\n", ocsp, + ocsp->cert->subject.name, response->signer->subject.name ); + + return 0; +} + +/** + * Parse OCSP basic response + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_basic_response ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct ocsp_response *response = &ocsp->response; + struct asn1_algorithm **algorithm = &response->algorithm; + struct asn1_bit_string *signature = &response->signature; + struct asn1_cursor cursor; + int rc; + + /* Enter BasicOCSPResponse */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse tbsResponseData */ + if ( ( rc = ocsp_parse_tbs_response_data ( ocsp, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse signatureAlgorithm */ + if ( ( rc = asn1_signature_algorithm ( &cursor, algorithm ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature " + "algorithm: %s\n", + ocsp, ocsp->cert->subject.name, strerror ( rc ) ); + return rc; + } + DBGC2 ( ocsp, "OCSP %p \"%s\" signature algorithm is %s\n", + ocsp, ocsp->cert->subject.name, (*algorithm)->name ); + asn1_skip_any ( &cursor ); + + /* Parse signature */ + if ( ( rc = asn1_integral_bit_string ( &cursor, signature ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" cannot parse signature: %s\n", + ocsp, ocsp->cert->subject.name, strerror ( rc ) ); + return rc; + } + asn1_skip_any ( &cursor ); + + /* Parse certs, if present */ + if ( ( asn1_type ( &cursor ) == ASN1_EXPLICIT_TAG ( 0 ) ) && + ( ( rc = ocsp_parse_certs ( ocsp, &cursor ) ) != 0 ) ) + return rc; + + return 0; +} + +/** + * Parse OCSP response bytes + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_response_bytes ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + int rc; + + /* Enter responseBytes */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse responseType */ + if ( ( rc = ocsp_parse_response_type ( ocsp, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Enter response */ + asn1_enter ( &cursor, ASN1_OCTET_STRING ); + + /* Parse response */ + if ( ( rc = ocsp_parse_basic_response ( ocsp, &cursor ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Parse OCSP response + * + * @v ocsp OCSP check + * @v raw ASN.1 cursor + * @ret rc Return status code + */ +static int ocsp_parse_response ( struct ocsp_check *ocsp, + const struct asn1_cursor *raw ) { + struct asn1_cursor cursor; + int rc; + + /* Enter OCSPResponse */ + memcpy ( &cursor, raw, sizeof ( cursor ) ); + asn1_enter ( &cursor, ASN1_SEQUENCE ); + + /* Parse responseStatus */ + if ( ( rc = ocsp_parse_response_status ( ocsp, &cursor ) ) != 0 ) + return rc; + asn1_skip_any ( &cursor ); + + /* Parse responseBytes */ + if ( ( rc = ocsp_parse_response_bytes ( ocsp, &cursor ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Receive OCSP response + * + * @v ocsp OCSP check + * @v data Response data + * @v len Length of response data + * @ret rc Return status code + */ +int ocsp_response ( struct ocsp_check *ocsp, const void *data, size_t len ) { + struct ocsp_response *response = &ocsp->response; + struct asn1_cursor cursor; + int rc; + + /* Duplicate data */ + x509_put ( response->signer ); + response->signer = NULL; + free ( response->data ); + response->data = malloc ( len ); + if ( ! response->data ) + return -ENOMEM; + memcpy ( response->data, data, len ); + cursor.data = response->data; + cursor.len = len; + + /* Parse response */ + if ( ( rc = ocsp_parse_response ( ocsp, &cursor ) ) != 0 ) + return rc; + + return 0; +} + +/** + * OCSP dummy root certificate store + * + * OCSP validation uses no root certificates, since it takes place + * only when there already exists a validated issuer certificate. + */ +static struct x509_root ocsp_root = { + .digest = &ocsp_digest_algorithm, + .count = 0, + .fingerprints = NULL, +}; + +/** + * Check OCSP response signature + * + * @v ocsp OCSP check + * @v signer Signing certificate + * @ret rc Return status code + */ +static int ocsp_check_signature ( struct ocsp_check *ocsp, + struct x509_certificate *signer ) { + struct ocsp_response *response = &ocsp->response; + struct digest_algorithm *digest = response->algorithm->digest; + struct pubkey_algorithm *pubkey = response->algorithm->pubkey; + struct x509_public_key *public_key = &signer->subject.public_key; + uint8_t digest_ctx[ digest->ctxsize ]; + uint8_t digest_out[ digest->digestsize ]; + uint8_t pubkey_ctx[ pubkey->ctxsize ]; + int rc; + + /* Generate digest */ + digest_init ( digest, digest_ctx ); + digest_update ( digest, digest_ctx, response->tbs.data, + response->tbs.len ); + digest_final ( digest, digest_ctx, digest_out ); + + /* Initialise public-key algorithm */ + if ( ( rc = pubkey_init ( pubkey, pubkey_ctx, public_key->raw.data, + public_key->raw.len ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not initialise public key: " + "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc )); + goto err_init; + } + + /* Verify digest */ + if ( ( rc = pubkey_verify ( pubkey, pubkey_ctx, digest, digest_out, + response->signature.data, + response->signature.len ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" signature verification failed: " + "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc )); + goto err_verify; + } + + DBGC2 ( ocsp, "OCSP %p \"%s\" signature is correct\n", + ocsp, ocsp->cert->subject.name ); + + err_verify: + pubkey_final ( pubkey, pubkey_ctx ); + err_init: + return rc; +} + +/** + * Validate OCSP response + * + * @v ocsp OCSP check + * @v time Time at which to validate response + * @ret rc Return status code + */ +int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) { + struct ocsp_response *response = &ocsp->response; + struct x509_certificate *signer = response->signer; + int rc; + + /* Sanity checks */ + assert ( response->data != NULL ); + assert ( signer != NULL ); + + /* Validate signer, if applicable. If the signer is not the + * issuer, then it must be signed directly by the issuer. + */ + if ( signer != ocsp->issuer ) { + /* Forcibly invalidate the signer, since we need to + * ensure that it was signed by our issuer (and not + * some other issuer). This prevents a sub-CA's OCSP + * certificate from fraudulently signing OCSP + * responses from the parent CA. + */ + x509_invalidate ( signer ); + if ( ( rc = x509_validate ( signer, ocsp->issuer, time, + &ocsp_root ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not validate " + "signer \"%s\": %s\n", ocsp, + ocsp->cert->subject.name, signer->subject.name, + strerror ( rc ) ); + return rc; + } + + /* If signer is not the issuer, then it must have the + * extendedKeyUsage id-kp-OCSPSigning. + */ + if ( ! ( signer->extensions.ext_usage.bits & + X509_OCSP_SIGNING ) ) { + DBGC ( ocsp, "OCSP %p \"%s\" signer \"%s\" is " + "not an OCSP-signing certificate\n", ocsp, + ocsp->cert->subject.name, signer->subject.name ); + return -EACCES_NON_OCSP_SIGNING; + } + } + + /* Check OCSP response signature */ + if ( ( rc = ocsp_check_signature ( ocsp, signer ) ) != 0 ) + return rc; + + /* Check OCSP response is valid at the specified time + * (allowing for some margin of error). + */ + if ( response->this_update > ( time - OCSP_ERROR_MARGIN_TIME ) ) { + DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at " + "time %lld)\n", ocsp, ocsp->cert->subject.name, time ); + return -EACCES_STALE; + } + if ( response->next_update < ( time + OCSP_ERROR_MARGIN_TIME ) ) { + DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time " + "%lld)\n", ocsp, ocsp->cert->subject.name, time ); + return -EACCES_STALE; + } + DBGC2 ( ocsp, "OCSP %p \"%s\" response is valid (at time %lld)\n", + ocsp, ocsp->cert->subject.name, time ); + + /* Mark certificate as passing OCSP verification */ + ocsp->cert->extensions.auth_info.ocsp.good = 1; + + /* Validate certificate against issuer */ + if ( ( rc = x509_validate ( ocsp->cert, ocsp->issuer, time, + &ocsp_root ) ) != 0 ) { + DBGC ( ocsp, "OCSP %p \"%s\" could not validate certificate: " + "%s\n", ocsp, ocsp->cert->subject.name, strerror ( rc )); + return rc; + } + DBGC ( ocsp, "OCSP %p \"%s\" successfully validated using \"%s\"\n", + ocsp, ocsp->cert->subject.name, signer->subject.name ); + + return 0; +} diff --git a/src/crypto/x509.c b/src/crypto/x509.c index a8660934..18a8cebe 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -1290,9 +1290,9 @@ int x509_check_time ( struct x509_certificate *cert, time_t time ) { * successfully validated then @c issuer, @c time, and @c root will be * ignored. */ -static int x509_validate ( struct x509_certificate *cert, - struct x509_certificate *issuer, - time_t time, struct x509_root *root ) { +int x509_validate ( struct x509_certificate *cert, + struct x509_certificate *issuer, + time_t time, struct x509_root *root ) { unsigned int max_path_remaining; int rc; diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 3fbd09f4..3e73b59c 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -70,6 +70,9 @@ struct asn1_builder_header { /** ASN.1 object identifier */ #define ASN1_OID 0x06 +/** ASN.1 enumeration */ +#define ASN1_ENUMERATED 0x0a + /** ASN.1 UTC time */ #define ASN1_UTC_TIME 0x17 @@ -204,6 +207,14 @@ struct asn1_builder_header { ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \ ASN1_OID_SINGLE ( 48 ), ASN1_OID_SINGLE ( 1 ) +/** ASN.1 OID for id-pkix-ocsp-basic ( 1.3.6.1.5.5.7.48.1.1) */ +#define ASN1_OID_OCSP_BASIC \ + ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \ + ASN1_OID_SINGLE ( 1 ), ASN1_OID_SINGLE ( 5 ), \ + ASN1_OID_SINGLE ( 5 ), ASN1_OID_SINGLE ( 7 ), \ + ASN1_OID_SINGLE ( 48 ), ASN1_OID_SINGLE ( 1 ), \ + ASN1_OID_SINGLE ( 1 ) + /** ASN.1 OID for id-kp-OCSPSigning (1.3.6.1.5.5.7.3.9) */ #define ASN1_OID_OCSPSIGNING \ ASN1_OID_INITIAL ( 1, 3 ), ASN1_OID_SINGLE ( 6 ), \ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 2109cf2f..108efc7a 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -260,6 +260,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_menu_ui ( ERRFILE_OTHER | 0x002c0000 ) #define ERRFILE_menu_cmd ( ERRFILE_OTHER | 0x002d0000 ) #define ERRFILE_validator ( ERRFILE_OTHER | 0x002e0000 ) +#define ERRFILE_ocsp ( ERRFILE_OTHER | 0x002f0000 ) /** @} */ diff --git a/src/include/ipxe/ocsp.h b/src/include/ipxe/ocsp.h new file mode 100644 index 00000000..e8414923 --- /dev/null +++ b/src/include/ipxe/ocsp.h @@ -0,0 +1,108 @@ +#ifndef _IPXE_OCSP_H +#define _IPXE_OCSP_H + +/** @file + * + * Online Certificate Status Protocol + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include + +/** OCSP algorithm identifier */ +#define OCSP_ALGORITHM_IDENTIFIER( ... ) \ + ASN1_OID, VA_ARG_COUNT ( __VA_ARGS__ ), __VA_ARGS__, \ + ASN1_NULL, 0x00 + +/* OCSP response statuses */ +#define OCSP_STATUS_SUCCESSFUL 0x00 +#define OCSP_STATUS_MALFORMED_REQUEST 0x01 +#define OCSP_STATUS_INTERNAL_ERROR 0x02 +#define OCSP_STATUS_TRY_LATER 0x03 +#define OCSP_STATUS_SIG_REQUIRED 0x05 +#define OCSP_STATUS_UNAUTHORIZED 0x06 + +/** Margin of error allowed in OCSP response times + * + * We allow a generous margin of error: 12 hours to allow for the + * local time zone being non-GMT, plus 30 minutes to allow for general + * clock drift. + */ +#define OCSP_ERROR_MARGIN_TIME ( ( 12 * 60 + 30 ) * 60 ) + +/** An OCSP request */ +struct ocsp_request { + /** Request builder */ + struct asn1_builder builder; + /** Certificate ID */ + struct asn1_cursor cert_id; +}; + +/** An OCSP response */ +struct ocsp_response { + /** Raw response */ + void *data; + /** Raw tbsResponseData */ + struct asn1_cursor tbs; + /** Time at which status is known to be correct */ + time_t this_update; + /** Time at which newer status information will be available */ + time_t next_update; + /** Signature algorithm */ + struct asn1_algorithm *algorithm; + /** Signature value */ + struct asn1_bit_string signature; + /** Signing certificate */ + struct x509_certificate *signer; +}; + +/** An OCSP check */ +struct ocsp_check { + /** Reference count */ + struct refcnt refcnt; + /** Certificate being checked */ + struct x509_certificate *cert; + /** Issuing certificate */ + struct x509_certificate *issuer; + /** Request */ + struct ocsp_request request; + /** Response */ + struct ocsp_response response; +}; + +/** + * Get reference to OCSP check + * + * @v ocsp OCSP check + * @ret ocsp OCSP check + */ +static inline __attribute__ (( always_inline )) struct ocsp_check * +ocsp_get ( struct ocsp_check *ocsp ) { + ref_get ( &ocsp->refcnt ); + return ocsp; +} + +/** + * Drop reference to OCSP check + * + * @v ocsp OCSP check + */ +static inline __attribute__ (( always_inline )) void +ocsp_put ( struct ocsp_check *ocsp ) { + ref_put ( &ocsp->refcnt ); +} + +extern int ocsp_check ( struct x509_certificate *cert, + struct x509_certificate *issuer, + struct ocsp_check **ocsp ); +extern int ocsp_response ( struct ocsp_check *ocsp, const void *data, + size_t len ); +extern int ocsp_validate ( struct ocsp_check *check, time_t time ); + +#endif /* _IPXE_OCSP_H */ diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index 6dc31b45..a5626c8a 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -126,6 +126,8 @@ enum x509_extended_key_usage_bits { struct x509_ocsp_responder { /** URI */ char *uri; + /** OCSP status is good */ + int good; }; /** X.509 certificate authority information access */ @@ -322,6 +324,9 @@ struct x509_root { extern int x509_certificate ( const void *data, size_t len, struct x509_certificate **cert ); +extern int x509_validate ( struct x509_certificate *cert, + struct x509_certificate *issuer, + time_t time, struct x509_root *root ); extern struct x509_chain * x509_alloc_chain ( void ); extern int x509_append ( struct x509_chain *chain, From a33298dcda4f9b6037e1c21f3d6f056dba77ab18 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 14 May 2012 18:25:00 +0100 Subject: [PATCH 008/250] [test] Add self-tests for OCSP Add self-tests for OCSP using test vectors generated with the openssl tools. Signed-off-by: Michael Brown --- src/tests/ocsp_test.c | 1525 +++++++++++++++++++++++++++++++++++++++++ src/tests/tests.c | 1 + 2 files changed, 1526 insertions(+) create mode 100644 src/tests/ocsp_test.c diff --git a/src/tests/ocsp_test.c b/src/tests/ocsp_test.c new file mode 100644 index 00000000..863f4c26 --- /dev/null +++ b/src/tests/ocsp_test.c @@ -0,0 +1,1525 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * OCSP tests + * + * + * Test vectors generated using OpenSSL: + * + * openssl ocsp -no_nonce -issuer issuer.crt -cert cert.crt \ + * -url http://ocsp.server.address \ + * -reqout request.der -respout response.der + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include +#include +#include +#include +#include +#include + +/** An OCSP test certificate */ +struct ocsp_test_certificate { + /** Data */ + const void *data; + /** Length of data */ + size_t len; + /** Parsed certificate */ + struct x509_certificate *cert; +}; + +/** An OCSP test */ +struct ocsp_test { + /** Certificate */ + struct ocsp_test_certificate *cert; + /** Issuing certificate */ + struct ocsp_test_certificate *issuer; + /** Request */ + const void *request; + /** Length of request */ + size_t request_len; + /** Response */ + const void *response; + /** Length of response */ + size_t response_len; + /* OCSP check */ + struct ocsp_check *ocsp; +}; + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define a test certificate */ +#define CERTIFICATE( name, DATA, FINGERPRINT ) \ + static const uint8_t name ## _data[] = DATA; \ + static struct ocsp_test_certificate name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + } + +/** Define an OCSP test */ +#define OCSP( name, CERT, ISSUER, REQUEST, RESPONSE ) \ + static const uint8_t name ## _request[] = REQUEST; \ + static const uint8_t name ## _response[] = RESPONSE; \ + static struct ocsp_test name = { \ + .cert = CERT, \ + .issuer = ISSUER, \ + .request = name ## _request, \ + .request_len = sizeof ( name ## _request ), \ + .response = name ## _response, \ + .response_len = sizeof ( name ## _response ), \ + } + +/** + * Prepare an OCSP test + * + * @v test OCSP test + */ +static void ocsp_prepare_test ( struct ocsp_test *test ) { + struct x509_certificate *cert = test->cert->cert; + struct x509_certificate *issuer = test->issuer->cert; + + /* Invalidate certificate being checked */ + x509_invalidate ( cert ); + + /* Force-validate issuer certificate */ + issuer->valid = 1; + issuer->path_remaining = ( issuer->extensions.basic.path_len + 1 ); +} + +/* + * subject bank.barclays.co.uk + * issuer VeriSign Class 3 International Server CA - G3 + */ +CERTIFICATE ( barclays_crt, + DATA ( 0x30, 0x82, 0x05, 0x7b, 0x30, 0x82, 0x04, 0x63, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x49, 0x83, 0xfc, 0x05, 0x76, + 0xdf, 0x36, 0x91, 0x7c, 0x64, 0x2a, 0x27, 0xc1, 0xf1, 0x48, + 0xe3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xbc, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, + 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65, + 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, + 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74, + 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, + 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x31, + 0x30, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x2d, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, + 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x31, 0x31, 0x32, 0x30, 0x35, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x31, 0x32, + 0x30, 0x34, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, + 0x7f, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x47, 0x42, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x07, 0x45, 0x6e, 0x67, 0x6c, 0x61, + 0x6e, 0x64, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x14, 0x0a, 0x47, 0x6c, 0x6f, 0x75, 0x63, 0x65, 0x73, + 0x74, 0x65, 0x72, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x14, 0x11, 0x42, 0x61, 0x72, 0x63, 0x6c, 0x61, + 0x79, 0x73, 0x20, 0x42, 0x61, 0x6e, 0x6b, 0x20, 0x50, 0x6c, + 0x63, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x14, 0x06, 0x47, 0x4c, 0x4f, 0x2d, 0x4c, 0x32, 0x31, 0x1c, + 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x13, 0x62, + 0x61, 0x6e, 0x6b, 0x2e, 0x62, 0x61, 0x72, 0x63, 0x6c, 0x61, + 0x79, 0x73, 0x2e, 0x63, 0x6f, 0x2e, 0x75, 0x6b, 0x30, 0x82, + 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, + 0x00, 0x99, 0x4c, 0x2e, 0x00, 0xa0, 0xaf, 0xe2, 0xbc, 0x52, + 0x43, 0x83, 0x34, 0x03, 0x58, 0xdf, 0xd3, 0xea, 0x43, 0xa2, + 0xfd, 0x2c, 0x4c, 0x3c, 0x32, 0x9c, 0x60, 0x40, 0xe5, 0xa1, + 0x07, 0x8d, 0x32, 0x21, 0xc1, 0xbd, 0xf1, 0x04, 0x2e, 0x90, + 0xf3, 0x05, 0x30, 0xd4, 0x6f, 0x81, 0x3e, 0x08, 0xb6, 0xc3, + 0xc1, 0xcf, 0xc4, 0x59, 0x7c, 0x56, 0x27, 0xea, 0x74, 0xe7, + 0x8f, 0x50, 0xd1, 0xa9, 0x13, 0x57, 0x3a, 0x05, 0x5a, 0xd7, + 0x7f, 0xfc, 0xc5, 0xc6, 0x66, 0xec, 0xa4, 0x03, 0xec, 0x97, + 0x1a, 0x4b, 0x28, 0xf9, 0xc9, 0xf4, 0xea, 0xc6, 0x89, 0x68, + 0xc1, 0x42, 0xcd, 0x80, 0xfc, 0xeb, 0x86, 0x6d, 0x1c, 0xd6, + 0xa1, 0x05, 0x16, 0xa4, 0xcf, 0x82, 0x1d, 0x07, 0x67, 0x7c, + 0xeb, 0xa1, 0x69, 0xf3, 0xf2, 0x21, 0xa7, 0x79, 0xf5, 0xf2, + 0xdc, 0xb6, 0x0b, 0x6e, 0x19, 0xcc, 0x50, 0x53, 0xf3, 0xbd, + 0xb9, 0x71, 0xdc, 0x2b, 0x15, 0x78, 0x6d, 0xd4, 0xd3, 0x82, + 0xce, 0x37, 0x0c, 0xb5, 0x5e, 0x24, 0x8d, 0x80, 0x40, 0x71, + 0x4e, 0x7b, 0x0a, 0x6e, 0x30, 0x4b, 0xb6, 0x2c, 0x23, 0x9e, + 0xd5, 0x08, 0x7d, 0x8a, 0x72, 0x46, 0xf6, 0x52, 0x98, 0xcb, + 0x03, 0x79, 0x61, 0xfe, 0xc1, 0x97, 0x15, 0x4b, 0x05, 0x36, + 0x0c, 0x11, 0xe9, 0x95, 0x4b, 0xef, 0xf3, 0x2d, 0xf3, 0xef, + 0x33, 0x6c, 0xc6, 0x98, 0xb9, 0x65, 0xe3, 0x3c, 0x26, 0x86, + 0xb5, 0x87, 0x9e, 0x20, 0x92, 0x7b, 0x8f, 0x13, 0x66, 0x5e, + 0x26, 0x09, 0xd6, 0x83, 0xee, 0x56, 0x72, 0x08, 0x6c, 0x2a, + 0x4c, 0xf2, 0x5b, 0xf1, 0x08, 0x4b, 0x91, 0x9e, 0x67, 0x37, + 0x2f, 0xc5, 0xcf, 0x1a, 0xa8, 0xa1, 0x1c, 0xb6, 0x2d, 0xd0, + 0x81, 0xf4, 0xf7, 0x37, 0xb9, 0xa3, 0x37, 0x3f, 0x6b, 0x2f, + 0x62, 0x82, 0xa7, 0x17, 0xc1, 0x8c, 0x69, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0xaf, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, + 0x03, 0x02, 0x05, 0xa0, 0x30, 0x41, 0x06, 0x03, 0x55, 0x1d, + 0x1f, 0x04, 0x3a, 0x30, 0x38, 0x30, 0x36, 0xa0, 0x34, 0xa0, + 0x32, 0x86, 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x53, 0x56, 0x52, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x47, 0x33, + 0x2d, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, + 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x56, + 0x52, 0x49, 0x6e, 0x74, 0x6c, 0x47, 0x33, 0x2e, 0x63, 0x72, + 0x6c, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x3d, + 0x30, 0x3b, 0x30, 0x39, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, + 0x86, 0xf8, 0x45, 0x01, 0x07, 0x17, 0x03, 0x30, 0x2a, 0x30, + 0x28, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, + 0x01, 0x16, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, + 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x70, + 0x61, 0x30, 0x28, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, + 0x30, 0x1f, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x42, 0x04, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x02, 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, 0x30, + 0x24, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, + 0x01, 0x86, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, + 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3c, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, + 0x30, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x53, 0x56, + 0x52, 0x49, 0x6e, 0x74, 0x6c, 0x2d, 0x47, 0x33, 0x2d, 0x61, + 0x69, 0x61, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x56, 0x52, 0x49, + 0x6e, 0x74, 0x6c, 0x47, 0x33, 0x2e, 0x63, 0x65, 0x72, 0x30, + 0x6e, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, + 0x0c, 0x04, 0x62, 0x30, 0x60, 0xa1, 0x5e, 0xa0, 0x5c, 0x30, + 0x5a, 0x30, 0x58, 0x30, 0x56, 0x16, 0x09, 0x69, 0x6d, 0x61, + 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0x30, 0x21, 0x30, 0x1f, + 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, + 0x14, 0x4b, 0x6b, 0xb9, 0x28, 0x96, 0x06, 0x0c, 0xbb, 0xd0, + 0x52, 0x38, 0x9b, 0x29, 0xac, 0x4b, 0x07, 0x8b, 0x21, 0x05, + 0x18, 0x30, 0x26, 0x16, 0x24, 0x68, 0x74, 0x74, 0x70, 0x3a, + 0x2f, 0x2f, 0x6c, 0x6f, 0x67, 0x6f, 0x2e, 0x76, 0x65, 0x72, + 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x76, 0x73, 0x6c, 0x6f, 0x67, 0x6f, 0x31, 0x2e, 0x67, 0x69, + 0x66, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, + 0x00, 0x49, 0xf3, 0x7c, 0x15, 0xb0, 0x50, 0x97, 0xb7, 0xcd, + 0x87, 0x75, 0x85, 0xcc, 0x55, 0x7c, 0x62, 0x97, 0x97, 0x04, + 0xbd, 0xc2, 0x22, 0xfc, 0xf5, 0x2c, 0x75, 0xdc, 0x25, 0x6d, + 0xed, 0xcd, 0x22, 0x2e, 0xa4, 0xcd, 0x88, 0x95, 0xe8, 0x52, + 0x45, 0x7a, 0xa0, 0x85, 0xcc, 0x6d, 0x1c, 0xcb, 0xd8, 0xc3, + 0x26, 0x2c, 0xee, 0xb5, 0xe1, 0x38, 0x3f, 0xb6, 0x96, 0x10, + 0xa3, 0xb3, 0x1e, 0x2d, 0xdc, 0xe8, 0x07, 0x2f, 0xc2, 0xb7, + 0x50, 0xd5, 0x60, 0x73, 0x0d, 0x43, 0xb1, 0xaf, 0xd9, 0xcb, + 0x39, 0x00, 0xc7, 0x00, 0xb3, 0x1f, 0xa4, 0xaf, 0xf8, 0xed, + 0x9b, 0x6a, 0x7a, 0x10, 0xcc, 0x81, 0x92, 0xc2, 0x58, 0x7e, + 0x42, 0xe4, 0xbf, 0xcf, 0x8c, 0x91, 0x7f, 0xde, 0xe6, 0xac, + 0x37, 0x31, 0x58, 0x90, 0xee, 0x51, 0xf5, 0x0e, 0xe5, 0x84, + 0xd8, 0x51, 0x89, 0x50, 0xfe, 0xfa, 0xad, 0xc9, 0xbb, 0x19, + 0xb3, 0x4a, 0xc8, 0x6b, 0x26, 0x98, 0x4b, 0x63, 0x41, 0x81, + 0xe1, 0x12, 0xab, 0xcc, 0x89, 0xbe, 0xdf, 0xa8, 0x7e, 0xf5, + 0x0e, 0x07, 0xf6, 0x92, 0x89, 0x64, 0x3b, 0xc2, 0x64, 0xa2, + 0x4b, 0xd1, 0x6b, 0x9b, 0x4e, 0x6a, 0xf2, 0x63, 0xf7, 0xc3, + 0xe0, 0x9f, 0xc5, 0x4e, 0xb6, 0x77, 0x0a, 0xad, 0x6d, 0x0f, + 0x30, 0x87, 0x6b, 0xfb, 0x66, 0xb3, 0x90, 0x87, 0xa3, 0x48, + 0xbe, 0xa4, 0x34, 0x9c, 0x5a, 0x93, 0xa3, 0x74, 0x0e, 0x36, + 0x8e, 0xf6, 0x3b, 0x6c, 0xae, 0xa0, 0x6a, 0xa1, 0x1a, 0x12, + 0x78, 0x99, 0x75, 0x50, 0xb1, 0x72, 0xed, 0x22, 0x34, 0x0f, + 0xe1, 0x89, 0xfe, 0x81, 0x0a, 0xcc, 0x2a, 0xd0, 0xf3, 0x25, + 0xe6, 0xd9, 0x19, 0x06, 0x20, 0x2d, 0x29, 0x8b, 0xdd, 0xb5, + 0x60, 0xf4, 0x0d, 0x08, 0x97, 0x7b, 0x81, 0x4a, 0xfb, 0x20, + 0xfb, 0x83, 0xa3, 0xc8, 0x1d, 0x79, 0xb9 ), + FINGERPRINT ( 0x7e, 0x54, 0x41, 0x60, 0x21, 0xca, 0x3e, 0x63, + 0xce, 0x5a, 0x41, 0x6c, 0xbe, 0x52, 0x01, 0x88, + 0xcf, 0x41, 0x36, 0x48, 0xdb, 0xe3, 0xdf, 0x8e, + 0x79, 0x73, 0x5f, 0xcf, 0x8e, 0x8e, 0xac, 0xd8 ) ); + +/* + * subject www.google.com + * issuer Thawte SGC CA + */ +CERTIFICATE ( google_crt, + DATA ( 0x30, 0x82, 0x03, 0x21, 0x30, 0x82, 0x02, 0x8a, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x4f, 0x9d, 0x96, 0xd9, 0x66, + 0xb0, 0x99, 0x2b, 0x54, 0xc2, 0x95, 0x7c, 0xb4, 0x15, 0x7d, + 0x4d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4c, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, + 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x13, 0x1c, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, + 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e, + 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, + 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, + 0x31, 0x30, 0x32, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x39, 0x33, 0x30, 0x32, + 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x68, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, + 0x69, 0x61, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x14, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x14, 0x0a, 0x47, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x17, 0x30, + 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x14, 0x0e, 0x77, 0x77, + 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, + 0x6f, 0x6d, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, + 0x00, 0xde, 0xb7, 0x26, 0x43, 0xa6, 0x99, 0x85, 0xcd, 0x38, + 0xa7, 0x15, 0x09, 0xb9, 0xcf, 0x0f, 0xc9, 0xc3, 0x55, 0x8c, + 0x88, 0xee, 0x8c, 0x8d, 0x28, 0x27, 0x24, 0x4b, 0x2a, 0x5e, + 0xa0, 0xd8, 0x16, 0xfa, 0x61, 0x18, 0x4b, 0xcf, 0x6d, 0x60, + 0x80, 0xd3, 0x35, 0x40, 0x32, 0x72, 0xc0, 0x8f, 0x12, 0xd8, + 0xe5, 0x4e, 0x8f, 0xb9, 0xb2, 0xf6, 0xd9, 0x15, 0x5e, 0x5a, + 0x86, 0x31, 0xa3, 0xba, 0x86, 0xaa, 0x6b, 0xc8, 0xd9, 0x71, + 0x8c, 0xcc, 0xcd, 0x27, 0x13, 0x1e, 0x9d, 0x42, 0x5d, 0x38, + 0xf6, 0xa7, 0xac, 0xef, 0xfa, 0x62, 0xf3, 0x18, 0x81, 0xd4, + 0x24, 0x46, 0x7f, 0x01, 0x77, 0x7c, 0xc6, 0x2a, 0x89, 0x14, + 0x99, 0xbb, 0x98, 0x39, 0x1d, 0xa8, 0x19, 0xfb, 0x39, 0x00, + 0x44, 0x7d, 0x1b, 0x94, 0x6a, 0x78, 0x2d, 0x69, 0xad, 0xc0, + 0x7a, 0x2c, 0xfa, 0xd0, 0xda, 0x20, 0x12, 0x98, 0xd3, 0x02, + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xe7, 0x30, 0x81, 0xe4, + 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x02, 0x30, 0x00, 0x30, 0x36, 0x06, 0x03, 0x55, 0x1d, + 0x1f, 0x04, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0xa0, 0x29, 0xa0, + 0x27, 0x86, 0x25, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x63, 0x72, 0x6c, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, + 0x65, 0x53, 0x47, 0x43, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x6c, + 0x30, 0x28, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x21, 0x30, + 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, + 0x01, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, + 0x02, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, + 0x04, 0x01, 0x30, 0x72, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x01, 0x01, 0x04, 0x66, 0x30, 0x64, 0x30, 0x22, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, + 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, + 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x3e, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x32, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x74, + 0x68, 0x61, 0x77, 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, + 0x2f, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x5f, 0x53, 0x47, + 0x43, 0x5f, 0x43, 0x41, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x21, 0xac, 0xd5, + 0xae, 0xca, 0x34, 0x89, 0x5a, 0xc2, 0xab, 0x52, 0xd2, 0xb2, + 0x34, 0x66, 0x9d, 0x7a, 0xab, 0xee, 0xe6, 0x7c, 0xd5, 0x7e, + 0xc2, 0x5c, 0x28, 0xbb, 0x74, 0x00, 0xc9, 0x10, 0x1f, 0x42, + 0x13, 0xfc, 0x69, 0x8a, 0x1e, 0x24, 0xa0, 0x02, 0x00, 0xe9, + 0xba, 0x5b, 0xca, 0x19, 0x04, 0xb2, 0xd3, 0xaf, 0x01, 0xb2, + 0x7e, 0x5f, 0x14, 0xdb, 0xa6, 0xdb, 0x52, 0xb9, 0x9a, 0xf3, + 0x12, 0x7f, 0x7c, 0xa2, 0x9c, 0x3b, 0x6f, 0x99, 0x7d, 0xea, + 0x50, 0x0d, 0x76, 0x23, 0x12, 0xff, 0xf7, 0x66, 0x73, 0x29, + 0xb7, 0x95, 0x0a, 0xad, 0xd8, 0x8b, 0xb2, 0xde, 0x20, 0xe9, + 0x0a, 0x70, 0x64, 0x11, 0x08, 0xc8, 0x5a, 0xf1, 0x7d, 0x9e, + 0xec, 0x69, 0xa5, 0xa5, 0xd5, 0x82, 0xd7, 0x27, 0x1e, 0x9e, + 0x56, 0xcd, 0xd2, 0x76, 0xd5, 0x79, 0x2b, 0xf7, 0x25, 0x43, + 0x1c, 0x69, 0xf0, 0xb8, 0xf9 ), + FINGERPRINT ( 0xec, 0x6a, 0x6b, 0x15, 0x6b, 0x30, 0x62, 0xfa, + 0x99, 0x49, 0x9d, 0x1e, 0x15, 0x15, 0xcf, 0x6c, + 0x50, 0x48, 0xaf, 0x17, 0x94, 0x57, 0x48, 0x39, + 0x6b, 0xd2, 0xec, 0xf1, 0x2b, 0x8d, 0xe2, 0x2c ) ); + +/* + * subject boot.test.ipxe.org + * issuer iPXE self-test leaf CA + */ +CERTIFICATE ( server_crt, + DATA ( 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xe6, 0x02, 0x01, + 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, + 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, + 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, + 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, + 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, + 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, + 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, + 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, + 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, + 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, + 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x84, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, + 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, + 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, + 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, + 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, + 0x6f, 0x72, 0x67, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, + 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, + 0x00, 0xbd, 0x43, 0x97, 0x45, 0xa2, 0xe0, 0x1d, 0x38, 0x41, + 0xb0, 0xd9, 0x91, 0xf9, 0x77, 0xa9, 0xcb, 0x9c, 0x9c, 0x93, + 0xfe, 0x5a, 0xee, 0xbc, 0xd9, 0x0f, 0x39, 0xf6, 0x42, 0xe4, + 0x55, 0x21, 0xbb, 0x11, 0xfd, 0xfd, 0xba, 0x25, 0x58, 0xc8, + 0xc6, 0xa5, 0x3b, 0x6f, 0x80, 0xba, 0x5b, 0xbc, 0x89, 0xca, + 0x7a, 0xdf, 0x6e, 0xb9, 0x81, 0xb6, 0x25, 0x67, 0x0a, 0x38, + 0x10, 0xf8, 0x26, 0x43, 0x0c, 0x51, 0x02, 0x14, 0xd6, 0xf2, + 0x9d, 0x7c, 0xf5, 0x25, 0x1c, 0x78, 0x4d, 0x47, 0xaf, 0x87, + 0x2e, 0x38, 0x49, 0x87, 0xb5, 0x8a, 0xf3, 0xb5, 0xd4, 0x15, + 0x69, 0x2a, 0x52, 0xc9, 0x46, 0x97, 0x34, 0x8e, 0x50, 0x4b, + 0xc4, 0xf2, 0xfb, 0x39, 0xfd, 0x16, 0x68, 0xdb, 0xa8, 0x17, + 0xe2, 0x71, 0x4b, 0xe0, 0xdf, 0x3d, 0xfc, 0xc3, 0x9b, 0x9d, + 0x22, 0xc9, 0xd3, 0xf6, 0x02, 0xa6, 0x60, 0xef, 0xf7, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, + 0x81, 0x81, 0x00, 0x7d, 0xff, 0x73, 0xf3, 0x68, 0xe3, 0x75, + 0xf1, 0xcf, 0xac, 0x2e, 0x23, 0x73, 0xea, 0xd1, 0x26, 0x33, + 0xbf, 0xf9, 0x56, 0xdf, 0xbf, 0x98, 0x20, 0x84, 0x08, 0x78, + 0x6b, 0xe6, 0x71, 0x7e, 0x22, 0x68, 0x4d, 0x6c, 0xbb, 0xd5, + 0xcc, 0xb4, 0x28, 0x33, 0x5e, 0xbe, 0x4d, 0x10, 0x16, 0x9f, + 0x65, 0x3b, 0x68, 0x90, 0xa7, 0xf7, 0x9d, 0x57, 0x71, 0x45, + 0x39, 0x86, 0x4c, 0xc0, 0x97, 0x34, 0x03, 0x9c, 0x2b, 0x25, + 0x05, 0xb1, 0x5c, 0x0c, 0x4e, 0xf2, 0x14, 0xbf, 0xcf, 0xf0, + 0x9a, 0x2d, 0xcf, 0x02, 0x47, 0x60, 0xd2, 0xe9, 0xed, 0xbf, + 0x71, 0x5d, 0x07, 0x09, 0x01, 0x87, 0xeb, 0xf7, 0xa8, 0x26, + 0x86, 0x24, 0x59, 0xf0, 0x31, 0x3b, 0x42, 0xd1, 0xf1, 0xfd, + 0x7c, 0x49, 0x5f, 0x1a, 0xf0, 0x41, 0x67, 0xf0, 0x16, 0x3a, + 0xfd, 0xb6, 0xb5, 0xf6, 0x2e, 0x0c, 0x18, 0x1f, 0x09, 0x8e, + 0x4d ), + FINGERPRINT ( 0xe0, 0xdb, 0x60, 0x53, 0x7c, 0xf6, 0x25, 0x8f, + 0xa7, 0xba, 0xdf, 0xe2, 0x1a, 0xfc, 0x27, 0x49, + 0xf6, 0x83, 0x15, 0xbd, 0x1b, 0x4c, 0x3f, 0x36, + 0x6f, 0x33, 0xf2, 0x47, 0x8e, 0x8b, 0x38, 0xa8 ) ); + +/* + * subject VeriSign Class 3 International Server CA - G3 + * issuer VeriSign Class 3 Public Primary Certification Authority - G5 + */ +CERTIFICATE ( verisign_crt, + DATA ( 0x30, 0x82, 0x06, 0x29, 0x30, 0x82, 0x05, 0x11, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x64, 0x1b, 0xe8, 0x20, 0xce, + 0x02, 0x08, 0x13, 0xf3, 0x2d, 0x4d, 0x2d, 0x95, 0xd6, 0x7e, + 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xca, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, + 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65, + 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x31, 0x3a, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x31, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, + 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x20, 0x2d, 0x20, 0x46, 0x6f, 0x72, + 0x20, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, + 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, + 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x3c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, + 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, + 0x72, 0x79, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2d, 0x20, 0x47, + 0x35, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x32, 0x30, + 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, + 0x32, 0x30, 0x30, 0x32, 0x30, 0x37, 0x32, 0x33, 0x35, 0x39, + 0x35, 0x39, 0x5a, 0x30, 0x81, 0xbc, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, + 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65, 0x72, 0x69, 0x53, + 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x3b, 0x30, + 0x39, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x32, 0x54, 0x65, + 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x65, + 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, + 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, + 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, + 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x31, 0x30, 0x31, 0x36, + 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x56, + 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6c, + 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x20, + 0x2d, 0x20, 0x47, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, + 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x99, 0xd6, 0x9c, + 0x62, 0xf0, 0x15, 0xf4, 0x81, 0x9a, 0x41, 0x08, 0x59, 0x8f, + 0x13, 0x9d, 0x17, 0xc9, 0x9f, 0x51, 0xdc, 0xda, 0xb1, 0x52, + 0xef, 0xff, 0xe3, 0x41, 0xdd, 0xe0, 0xdf, 0xc4, 0x28, 0xc6, + 0xe3, 0xad, 0x79, 0x1f, 0x27, 0x10, 0x98, 0xb8, 0xbb, 0x20, + 0x97, 0xc1, 0x28, 0x44, 0x41, 0x0f, 0xea, 0xa9, 0xa8, 0x52, + 0xcf, 0x4d, 0x4e, 0x1b, 0x8b, 0xbb, 0xb5, 0xc4, 0x76, 0xd9, + 0xcc, 0x56, 0x06, 0xee, 0xb3, 0x55, 0x20, 0x2a, 0xde, 0x15, + 0x8d, 0x71, 0xcb, 0x54, 0xc8, 0x6f, 0x17, 0xcd, 0x89, 0x00, + 0xe4, 0xdc, 0xff, 0xe1, 0xc0, 0x1f, 0x68, 0x71, 0xe9, 0xc7, + 0x29, 0x2e, 0x7e, 0xbc, 0x3b, 0xfc, 0xe5, 0xbb, 0xab, 0x26, + 0x54, 0x8b, 0x66, 0x90, 0xcd, 0xf6, 0x92, 0xb9, 0x31, 0x24, + 0x80, 0xbc, 0x9e, 0x6c, 0xd5, 0xfc, 0x7e, 0xd2, 0xe1, 0x4b, + 0x8c, 0xdc, 0x42, 0xfa, 0x44, 0x4b, 0x5f, 0xf8, 0x18, 0xb5, + 0x2e, 0x30, 0xf4, 0x3d, 0x12, 0x98, 0xd3, 0x62, 0x05, 0x73, + 0x54, 0xa6, 0x9c, 0xa2, 0x1d, 0xbe, 0x52, 0x83, 0x3a, 0x07, + 0x46, 0xc4, 0x3b, 0x02, 0x56, 0x21, 0xbf, 0xf2, 0x51, 0x4f, + 0xd0, 0xa6, 0x99, 0x39, 0xe9, 0xae, 0xa5, 0x3f, 0x89, 0x9b, + 0x9c, 0x7d, 0xfe, 0x4d, 0x60, 0x07, 0x25, 0x20, 0xf7, 0xbb, + 0xd7, 0x69, 0x83, 0x2b, 0x82, 0x93, 0x43, 0x37, 0xd9, 0x83, + 0x41, 0x1b, 0x6b, 0x0b, 0xab, 0x4a, 0x66, 0x84, 0x4f, 0x4a, + 0x8e, 0xde, 0x7e, 0x34, 0x99, 0x8e, 0x68, 0xd6, 0xca, 0x39, + 0x06, 0x9b, 0x4c, 0xb3, 0x9a, 0x48, 0x4d, 0x13, 0x46, 0xb4, + 0x58, 0x21, 0x04, 0xc4, 0xfb, 0xa0, 0x4d, 0xac, 0x2e, 0x4b, + 0x62, 0x12, 0xe3, 0xfb, 0x4d, 0xf6, 0xc9, 0x51, 0x00, 0x01, + 0x1f, 0xfc, 0x1e, 0x6a, 0x81, 0x2a, 0x38, 0xe0, 0xb9, 0x4f, + 0xd6, 0x2d, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, + 0x02, 0x15, 0x30, 0x82, 0x02, 0x11, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, + 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x70, 0x06, 0x03, + 0x55, 0x1d, 0x20, 0x04, 0x69, 0x30, 0x67, 0x30, 0x65, 0x06, + 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x07, + 0x17, 0x03, 0x30, 0x56, 0x30, 0x28, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x1c, 0x68, 0x74, + 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, + 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x70, 0x73, 0x30, 0x2a, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x1e, + 0x1a, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, + 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, + 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x70, 0x61, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, + 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x6d, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0c, 0x04, 0x61, + 0x30, 0x5f, 0xa1, 0x5d, 0xa0, 0x5b, 0x30, 0x59, 0x30, 0x57, + 0x30, 0x55, 0x16, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, + 0x67, 0x69, 0x66, 0x30, 0x21, 0x30, 0x1f, 0x30, 0x07, 0x06, + 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14, 0x8f, 0xe5, + 0xd3, 0x1a, 0x86, 0xac, 0x8d, 0x8e, 0x6b, 0xc3, 0xcf, 0x80, + 0x6a, 0xd4, 0x48, 0x18, 0x2c, 0x7b, 0x19, 0x2e, 0x30, 0x25, + 0x16, 0x23, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, + 0x6f, 0x67, 0x6f, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, + 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x73, 0x6c, + 0x6f, 0x67, 0x6f, 0x2e, 0x67, 0x69, 0x66, 0x30, 0x34, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, + 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01, 0x06, + 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08, + 0x01, 0x30, 0x34, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x01, 0x01, 0x04, 0x28, 0x30, 0x26, 0x30, 0x24, 0x06, + 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, + 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, + 0x73, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x34, 0x06, 0x03, 0x55, + 0x1d, 0x1f, 0x04, 0x2d, 0x30, 0x2b, 0x30, 0x29, 0xa0, 0x27, + 0xa0, 0x25, 0x86, 0x23, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, + 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, + 0x61, 0x33, 0x2d, 0x67, 0x35, 0x2e, 0x63, 0x72, 0x6c, 0x30, + 0x28, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x21, 0x30, 0x1f, + 0xa4, 0x1d, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x10, 0x56, 0x65, 0x72, 0x69, 0x53, + 0x69, 0x67, 0x6e, 0x4d, 0x50, 0x4b, 0x49, 0x2d, 0x32, 0x2d, + 0x37, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, + 0x04, 0x14, 0xd7, 0x9b, 0x7c, 0xd8, 0x22, 0xa0, 0x15, 0xf7, + 0xdd, 0xad, 0x5f, 0xce, 0x29, 0x9b, 0x58, 0xc3, 0xbc, 0x46, + 0x00, 0xb5, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, + 0x18, 0x30, 0x16, 0x80, 0x14, 0x7f, 0xd3, 0x65, 0xa7, 0xc2, + 0xdd, 0xec, 0xbb, 0xf0, 0x30, 0x09, 0xf3, 0x43, 0x39, 0xfa, + 0x02, 0xaf, 0x33, 0x31, 0x33, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x71, 0xb5, 0x7d, 0x73, 0x52, + 0x4a, 0xdd, 0xd7, 0x4d, 0x34, 0x2b, 0x2e, 0xaf, 0x94, 0x46, + 0xa5, 0x49, 0x50, 0x02, 0x4f, 0xf8, 0x2f, 0x17, 0x70, 0xf2, + 0x13, 0xdc, 0x1f, 0x21, 0x86, 0xaa, 0xc2, 0x4f, 0x7c, 0x37, + 0x3c, 0xd4, 0x46, 0x78, 0xae, 0x5d, 0x78, 0x6f, 0xd1, 0xba, + 0x5a, 0xbc, 0x10, 0xab, 0x58, 0x36, 0xc5, 0x8c, 0x62, 0x15, + 0x45, 0x60, 0x17, 0x21, 0xe2, 0xd5, 0x42, 0xa8, 0x77, 0xa1, + 0x55, 0xd8, 0x43, 0x04, 0x51, 0xf6, 0x6e, 0xba, 0x48, 0xe6, + 0x5d, 0x4c, 0xb7, 0x44, 0xd3, 0x3e, 0xa4, 0xd5, 0xd6, 0x33, + 0x9a, 0x9f, 0x0d, 0xe6, 0xd7, 0x4e, 0x96, 0x44, 0x95, 0x5a, + 0x6c, 0xd6, 0xa3, 0x16, 0x53, 0x0e, 0x98, 0x43, 0xce, 0xa4, + 0xb8, 0xc3, 0x66, 0x7a, 0x05, 0x5c, 0x62, 0x10, 0xe8, 0x1b, + 0x12, 0xdb, 0x7d, 0x2e, 0x76, 0x50, 0xff, 0xdf, 0xd7, 0x6b, + 0x1b, 0xcc, 0x8a, 0xcc, 0x71, 0xfa, 0xb3, 0x40, 0x56, 0x7c, + 0x33, 0x7a, 0x77, 0x94, 0x5b, 0xf5, 0x0b, 0x53, 0xfb, 0x0e, + 0x5f, 0xbc, 0x68, 0xfb, 0xaf, 0x2a, 0xee, 0x30, 0x37, 0x79, + 0x16, 0x93, 0x25, 0x7f, 0x4d, 0x10, 0xff, 0x57, 0xfb, 0xbf, + 0x6e, 0x3b, 0x33, 0x21, 0xde, 0x79, 0xdc, 0x86, 0x17, 0x59, + 0x2d, 0x43, 0x64, 0xb7, 0xa6, 0x66, 0x87, 0xea, 0xbc, 0x96, + 0x46, 0x19, 0x1a, 0x86, 0x8b, 0x6f, 0xd7, 0xb7, 0x49, 0x00, + 0x5b, 0xdb, 0xa3, 0xbf, 0x29, 0x9a, 0xee, 0xf7, 0xd3, 0x33, + 0xae, 0xa3, 0xf4, 0x9e, 0x4c, 0xca, 0x5e, 0x69, 0xd4, 0x1b, + 0xad, 0xb7, 0x90, 0x77, 0x6a, 0xd8, 0x59, 0x6f, 0x79, 0xab, + 0x01, 0xfa, 0x55, 0xf0, 0x8a, 0x21, 0x66, 0xe5, 0x65, 0x6e, + 0xfd, 0x7c, 0xd3, 0xdf, 0x1e, 0xeb, 0x7e, 0x3f, 0x06, 0x90, + 0xfb, 0x19, 0x0b, 0xd3, 0x06, 0x02, 0x1b, 0x78, 0x43, 0x99, + 0xa8 ), + FINGERPRINT ( 0x6e, 0x21, 0x87, 0x6c, 0xf1, 0x63, 0x47, 0x20, + 0x1f, 0x63, 0x7a, 0x17, 0x8c, 0xb4, 0x2b, 0x17, + 0x1d, 0x52, 0x37, 0x9a, 0xf7, 0xe5, 0xf5, 0xb6, + 0xf6, 0x75, 0x5b, 0x3e, 0xe9, 0xbb, 0x2e, 0xd4 ) ); + +/* + * subject Thawte SGC CA +issuer= /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority + */ +CERTIFICATE ( thawte_crt, + DATA ( 0x30, 0x82, 0x03, 0x23, 0x30, 0x82, 0x02, 0x8c, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x04, 0x30, 0x00, 0x00, 0x02, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x05, 0x05, 0x00, 0x30, 0x5f, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, + 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, + 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, + 0x55, 0x04, 0x0b, 0x13, 0x2e, 0x43, 0x6c, 0x61, 0x73, 0x73, + 0x20, 0x33, 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, + 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x35, 0x31, + 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, + 0x31, 0x34, 0x30, 0x35, 0x31, 0x32, 0x32, 0x33, 0x35, 0x39, + 0x35, 0x39, 0x5a, 0x30, 0x4c, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, 0x41, 0x31, 0x25, + 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x54, + 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, + 0x79, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, + 0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0d, 0x54, 0x68, + 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, 0x43, 0x20, 0x43, + 0x41, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xd4, 0xd3, 0x67, 0xd0, 0x8d, 0x15, 0x7f, 0xae, 0xcd, 0x31, + 0xfe, 0x7d, 0x1d, 0x91, 0xa1, 0x3f, 0x0b, 0x71, 0x3c, 0xac, + 0xcc, 0xc8, 0x64, 0xfb, 0x63, 0xfc, 0x32, 0x4b, 0x07, 0x94, + 0xbd, 0x6f, 0x80, 0xba, 0x2f, 0xe1, 0x04, 0x93, 0xc0, 0x33, + 0xfc, 0x09, 0x33, 0x23, 0xe9, 0x0b, 0x74, 0x2b, 0x71, 0xc4, + 0x03, 0xc6, 0xd2, 0xcd, 0xe2, 0x2f, 0xf5, 0x09, 0x63, 0xcd, + 0xff, 0x48, 0xa5, 0x00, 0xbf, 0xe0, 0xe7, 0xf3, 0x88, 0xb7, + 0x2d, 0x32, 0xde, 0x98, 0x36, 0xe6, 0x0a, 0xad, 0x00, 0x7b, + 0xc4, 0x64, 0x4a, 0x3b, 0x84, 0x75, 0x03, 0xf2, 0x70, 0x92, + 0x7d, 0x0e, 0x62, 0xf5, 0x21, 0xab, 0x69, 0x36, 0x84, 0x31, + 0x75, 0x90, 0xf8, 0xbf, 0xc7, 0x6c, 0x88, 0x1b, 0x06, 0x95, + 0x7c, 0xc9, 0xe5, 0xa8, 0xde, 0x75, 0xa1, 0x2c, 0x7a, 0x68, + 0xdf, 0xd5, 0xca, 0x1c, 0x87, 0x58, 0x60, 0x19, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfe, 0x30, 0x81, 0xfb, 0x30, + 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, + 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, + 0x01, 0x06, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x86, 0xf8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x01, + 0x06, 0x30, 0x28, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x21, + 0x30, 0x1f, 0xa4, 0x1d, 0x30, 0x1b, 0x31, 0x19, 0x30, 0x17, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x50, 0x72, 0x69, + 0x76, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x33, + 0x2d, 0x31, 0x35, 0x30, 0x31, 0x06, 0x03, 0x55, 0x1d, 0x1f, + 0x04, 0x2a, 0x30, 0x28, 0x30, 0x26, 0xa0, 0x24, 0xa0, 0x22, + 0x86, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, + 0x72, 0x6c, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, + 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x63, 0x61, 0x33, + 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x32, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x26, 0x30, 0x24, + 0x30, 0x22, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x86, 0x16, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x74, 0x68, 0x61, 0x77, + 0x74, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x34, 0x06, 0x03, + 0x55, 0x1d, 0x25, 0x04, 0x2d, 0x30, 0x2b, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01, 0x06, 0x0a, + 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x45, 0x01, 0x08, 0x01, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x55, + 0xac, 0x63, 0xea, 0xde, 0xa1, 0xdd, 0xd2, 0x90, 0x5f, 0x9f, + 0x0b, 0xce, 0x76, 0xbe, 0x13, 0x51, 0x8f, 0x93, 0xd9, 0x05, + 0x2b, 0xc8, 0x1b, 0x77, 0x4b, 0xad, 0x69, 0x50, 0xa1, 0xee, + 0xde, 0xdc, 0xfd, 0xdb, 0x07, 0xe9, 0xe8, 0x39, 0x94, 0xdc, + 0xab, 0x72, 0x79, 0x2f, 0x06, 0xbf, 0xab, 0x81, 0x70, 0xc4, + 0xa8, 0xed, 0xea, 0x53, 0x34, 0xed, 0xef, 0x1e, 0x53, 0xd9, + 0x06, 0xc7, 0x56, 0x2b, 0xd1, 0x5c, 0xf4, 0xd1, 0x8a, 0x8e, + 0xb4, 0x2b, 0xb1, 0x37, 0x90, 0x48, 0x08, 0x42, 0x25, 0xc5, + 0x3e, 0x8a, 0xcb, 0x7f, 0xeb, 0x6f, 0x04, 0xd1, 0x6d, 0xc5, + 0x74, 0xa2, 0xf7, 0xa2, 0x7c, 0x7b, 0x60, 0x3c, 0x77, 0xcd, + 0x0e, 0xce, 0x48, 0x02, 0x7f, 0x01, 0x2f, 0xb6, 0x9b, 0x37, + 0xe0, 0x2a, 0x2a, 0x36, 0xdc, 0xd5, 0x85, 0xd6, 0xac, 0xe5, + 0x3f, 0x54, 0x6f, 0x96, 0x1e, 0x05, 0xaf ), + FINGERPRINT ( 0x10, 0x85, 0xa6, 0xf4, 0x54, 0xd0, 0xc9, 0x11, + 0x98, 0xfd, 0xda, 0xb1, 0x1a, 0x31, 0xc7, 0x16, + 0xd5, 0xdc, 0xd6, 0x8d, 0xf9, 0x1c, 0x03, 0x9c, + 0xe1, 0x8d, 0xca, 0x9b, 0xeb, 0x3c, 0xde, 0x3d ) ); + +/* + * subject StartCom Class 2 Primary Intermediate Server CA + * issuer StartCom Certification Authority + */ +CERTIFICATE ( startssl_crt, + DATA ( 0x30, 0x82, 0x07, 0xe3, 0x30, 0x82, 0x05, 0xcb, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x0b, 0x30, 0x0d, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, + 0x00, 0x30, 0x7d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x16, 0x30, 0x14, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e, + 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x29, 0x30, 0x27, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, + 0x17, 0x0d, 0x30, 0x37, 0x31, 0x30, 0x32, 0x34, 0x32, 0x30, + 0x35, 0x37, 0x30, 0x38, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x31, + 0x30, 0x32, 0x32, 0x32, 0x30, 0x35, 0x37, 0x30, 0x38, 0x5a, + 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x16, 0x30, 0x14, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e, + 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x38, 0x30, 0x36, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x2f, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, + 0x20, 0x32, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, + 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, + 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x4f, 0x39, 0x2f, + 0xa1, 0x8c, 0x9a, 0x85, 0xad, 0x08, 0x0e, 0x08, 0x3e, 0x57, + 0xf2, 0x88, 0x01, 0x21, 0x1b, 0x94, 0xa9, 0x6c, 0xe2, 0xb8, + 0xdb, 0xaa, 0x19, 0x18, 0x46, 0x3a, 0x52, 0xa1, 0xf5, 0x0f, + 0xf4, 0x6e, 0x8c, 0xea, 0x96, 0x8c, 0x96, 0x87, 0x79, 0x13, + 0x40, 0x51, 0x2f, 0x22, 0xf2, 0x0c, 0x8b, 0x87, 0x0f, 0x65, + 0xdf, 0x71, 0x74, 0x34, 0x43, 0x55, 0xb1, 0x35, 0x09, 0x9b, + 0xd9, 0xbc, 0x1f, 0xfa, 0xeb, 0x42, 0xd0, 0x97, 0x40, 0x72, + 0xb7, 0x43, 0x96, 0x3d, 0xba, 0x96, 0x9d, 0x5d, 0x50, 0x02, + 0x1c, 0x9b, 0x91, 0x8d, 0x9c, 0xc0, 0xac, 0xd7, 0xbb, 0x2f, + 0x17, 0xd7, 0xcb, 0x3e, 0x82, 0x9d, 0x73, 0xeb, 0x07, 0x42, + 0x92, 0xb2, 0xcd, 0x64, 0xb3, 0x74, 0x55, 0x1b, 0xb4, 0x4b, + 0x86, 0x21, 0x2c, 0xf7, 0x78, 0x87, 0x32, 0xe0, 0x16, 0xe4, + 0xda, 0xbd, 0x4c, 0x95, 0xea, 0xa4, 0x0a, 0x7e, 0xb6, 0x0a, + 0x0d, 0x2e, 0x8a, 0xcf, 0x55, 0xab, 0xc3, 0xe5, 0xdd, 0x41, + 0x8a, 0x4e, 0xe6, 0x6f, 0x65, 0x6c, 0xb2, 0x40, 0xcf, 0x17, + 0x5d, 0xb9, 0xc3, 0x6a, 0x0b, 0x27, 0x11, 0x84, 0x77, 0x61, + 0xf6, 0xc2, 0x7c, 0xed, 0xc0, 0x8d, 0x78, 0x14, 0x18, 0x99, + 0x81, 0x99, 0x75, 0x63, 0xb7, 0xe8, 0x53, 0xd3, 0xba, 0x61, + 0xe9, 0x0e, 0xfa, 0xa2, 0x30, 0xf3, 0x46, 0xa2, 0xb9, 0xc9, + 0x1f, 0x6c, 0x80, 0x5a, 0x40, 0xac, 0x27, 0xed, 0x48, 0x47, + 0x33, 0xb0, 0x54, 0xc6, 0x46, 0x1a, 0xf3, 0x35, 0x61, 0xc1, + 0x02, 0x29, 0x90, 0x54, 0x7e, 0x64, 0x4d, 0xc4, 0x30, 0x52, + 0x02, 0x82, 0xd7, 0xdf, 0xce, 0x21, 0x6e, 0x18, 0x91, 0xd7, + 0xb8, 0xab, 0x8c, 0x27, 0x17, 0xb5, 0xf0, 0xa3, 0x01, 0x2f, + 0x8e, 0xd2, 0x2e, 0x87, 0x3a, 0x3d, 0xb4, 0x29, 0x67, 0x8a, + 0xc4, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x03, + 0x5c, 0x30, 0x82, 0x03, 0x58, 0x30, 0x0c, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, + 0x01, 0xa6, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x11, 0xdb, 0x23, 0x45, 0xfd, 0x54, 0xcc, + 0x6a, 0x71, 0x6f, 0x84, 0x8a, 0x03, 0xd7, 0xbe, 0xf7, 0x01, + 0x2f, 0x26, 0x86, 0x30, 0x81, 0xa8, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x81, 0xa0, 0x30, 0x81, 0x9d, 0x80, 0x14, 0x4e, + 0x0b, 0xef, 0x1a, 0xa4, 0x40, 0x5b, 0xa5, 0x17, 0x69, 0x87, + 0x30, 0xca, 0x34, 0x68, 0x43, 0xd0, 0x41, 0xae, 0xf2, 0xa1, + 0x81, 0x81, 0xa4, 0x7f, 0x30, 0x7d, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, + 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c, + 0x74, 0x64, 0x2e, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x29, + 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x20, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x82, 0x01, 0x01, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, + 0x12, 0x04, 0x02, 0x30, 0x00, 0x30, 0x3d, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x31, 0x30, + 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x30, 0x02, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, + 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x73, 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, + 0x66, 0x73, 0x63, 0x61, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x60, + 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x59, 0x30, 0x57, 0x30, + 0x2c, 0xa0, 0x2a, 0xa0, 0x28, 0x86, 0x26, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x73, 0x66, 0x73, 0x63, 0x61, 0x2d, 0x63, 0x72, + 0x6c, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x27, 0xa0, 0x25, 0xa0, + 0x23, 0x86, 0x21, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, + 0x63, 0x72, 0x6c, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, + 0x73, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x66, 0x73, + 0x63, 0x61, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x82, 0x01, 0x5d, + 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x82, 0x01, 0x54, 0x30, + 0x82, 0x01, 0x50, 0x30, 0x82, 0x01, 0x4c, 0x06, 0x0b, 0x2b, + 0x06, 0x01, 0x04, 0x01, 0x81, 0xb5, 0x37, 0x01, 0x01, 0x04, + 0x30, 0x82, 0x01, 0x3b, 0x30, 0x2f, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x23, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, + 0x72, 0x67, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x70, 0x64, 0x66, 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x29, 0x68, 0x74, 0x74, + 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, + 0x69, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x64, 0x66, 0x30, 0x81, + 0xd0, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, + 0x02, 0x30, 0x81, 0xc3, 0x30, 0x27, 0x16, 0x20, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, + 0x63, 0x69, 0x61, 0x6c, 0x20, 0x28, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6d, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e, + 0x30, 0x03, 0x02, 0x01, 0x01, 0x1a, 0x81, 0x97, 0x4c, 0x69, + 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x4c, 0x69, 0x61, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x72, 0x65, 0x61, + 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x2a, 0x4c, 0x65, 0x67, 0x61, 0x6c, + 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2a, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x70, 0x64, 0x66, 0x30, + 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, + 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x51, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, + 0x0d, 0x04, 0x44, 0x16, 0x42, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, + 0x32, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x20, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, + 0x74, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20, 0x53, 0x53, + 0x4c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, + 0x00, 0x64, 0x82, 0x4c, 0x59, 0x5c, 0x0c, 0x6c, 0x16, 0xb6, + 0xa2, 0x39, 0x45, 0x11, 0x87, 0x98, 0xdf, 0x10, 0x33, 0xae, + 0x42, 0x9e, 0x25, 0xd1, 0xfd, 0x70, 0x53, 0x45, 0x5e, 0xf4, + 0x35, 0xc0, 0xe4, 0x30, 0x77, 0xe0, 0x9c, 0xf7, 0xef, 0x27, + 0xe5, 0x6e, 0x28, 0xef, 0xac, 0xd7, 0xf3, 0x16, 0xcc, 0xc1, + 0x6c, 0x53, 0x9c, 0x8f, 0x2d, 0x82, 0x6f, 0x94, 0xf7, 0x14, + 0x36, 0x17, 0xae, 0xb2, 0xe5, 0xa2, 0x3f, 0xa2, 0x83, 0x73, + 0xa4, 0xdf, 0xa8, 0xbb, 0xca, 0x01, 0x31, 0x6c, 0x9a, 0x43, + 0x08, 0xdd, 0x1a, 0x5d, 0xad, 0x4b, 0x6d, 0x7f, 0xf4, 0x7e, + 0xf0, 0x12, 0x3a, 0x05, 0xbf, 0xa7, 0x44, 0x10, 0x07, 0x17, + 0x44, 0x93, 0x50, 0xe3, 0x95, 0x29, 0xb3, 0xf4, 0x13, 0xd2, + 0x40, 0xe0, 0x3e, 0xdf, 0x3d, 0x3d, 0x39, 0x5e, 0x81, 0x48, + 0x0f, 0x32, 0xba, 0x48, 0xd5, 0x03, 0x1b, 0xf5, 0xf7, 0x4e, + 0x0a, 0x8e, 0x03, 0x8d, 0xfc, 0xca, 0x87, 0xe6, 0xc9, 0xdf, + 0x26, 0xdf, 0x84, 0x3a, 0x49, 0xb1, 0x99, 0x55, 0x3f, 0xd4, + 0x2c, 0xab, 0x78, 0x0d, 0x62, 0x03, 0x15, 0x9f, 0xb1, 0x45, + 0x4b, 0x23, 0x78, 0x62, 0x2a, 0xee, 0xeb, 0x7b, 0x60, 0x2d, + 0x77, 0x72, 0x1e, 0x61, 0x24, 0x69, 0x62, 0xe8, 0xe1, 0x35, + 0x3c, 0x82, 0x02, 0x40, 0x15, 0x32, 0x4b, 0x57, 0xcd, 0x97, + 0xb9, 0x29, 0x8f, 0xa4, 0xd7, 0x84, 0xdb, 0x09, 0xe5, 0x35, + 0x5b, 0x2f, 0x60, 0x59, 0x49, 0xe9, 0xd6, 0x59, 0xf5, 0xfa, + 0x5d, 0xc8, 0xcd, 0x4d, 0x94, 0x70, 0xc4, 0xe8, 0x3c, 0x35, + 0x01, 0x06, 0x75, 0xe8, 0x71, 0x9b, 0x7f, 0x2b, 0x10, 0xca, + 0x6b, 0x3f, 0xc0, 0xb3, 0x97, 0x72, 0xda, 0xff, 0x74, 0x16, + 0x8e, 0xfb, 0xfb, 0x9b, 0xe4, 0x05, 0xf0, 0x98, 0xe7, 0x15, + 0xac, 0xca, 0x24, 0xa2, 0xe7, 0x8a, 0xb4, 0xcf, 0x72, 0x31, + 0x2b, 0xe3, 0x31, 0x0e, 0x30, 0x5f, 0xd5, 0xcb, 0x94, 0xb3, + 0xee, 0x35, 0x04, 0xd3, 0x45, 0x07, 0x09, 0x14, 0x51, 0x8a, + 0xf5, 0x07, 0x31, 0x5e, 0x13, 0x2f, 0x5d, 0x0c, 0xd9, 0xd7, + 0x36, 0xa8, 0xb0, 0x52, 0x37, 0x94, 0xc2, 0x75, 0x9c, 0x5a, + 0x2e, 0xa8, 0xd1, 0xb0, 0x73, 0x6b, 0x69, 0xda, 0x0c, 0x3a, + 0xd6, 0x11, 0x6b, 0xac, 0x9d, 0xbc, 0x45, 0x32, 0x05, 0xe8, + 0x89, 0x77, 0xd5, 0xb7, 0xbe, 0xc0, 0xed, 0xcd, 0xcd, 0x4e, + 0x6d, 0x28, 0x58, 0x0a, 0xf0, 0xb4, 0x51, 0xc8, 0xcd, 0x86, + 0xd1, 0x89, 0x23, 0xc5, 0x23, 0xed, 0xcf, 0x10, 0xf9, 0x0e, + 0x6e, 0xd8, 0xc1, 0xd7, 0x3f, 0x80, 0xfa, 0xa6, 0x2a, 0x47, + 0xc4, 0xdb, 0x07, 0x16, 0xe7, 0x0b, 0x8b, 0x53, 0x97, 0x11, + 0x2e, 0xa3, 0x61, 0x27, 0xb3, 0xbb, 0x4a, 0xd7, 0x01, 0x6d, + 0xb1, 0x71, 0xa5, 0xe5, 0x23, 0xd6, 0xda, 0xa1, 0xa8, 0x55, + 0x26, 0xaf, 0xb7, 0xba, 0x5e, 0x56, 0x2d, 0x3d, 0x10, 0xa3, + 0x71, 0x4a, 0x93, 0x45, 0x1c, 0x7a, 0x3c, 0x92, 0x2a, 0x69, + 0x3f, 0x4f, 0x1e, 0x96, 0x99, 0x90, 0x09, 0xc8, 0x01, 0xbf, + 0x28, 0x34, 0xb2, 0x7d, 0x11, 0x50, 0x59, 0xd0, 0x9b, 0xe3, + 0x33, 0x56, 0x65, 0xee, 0x98, 0x97, 0x3f, 0x3e, 0x54, 0x69, + 0x2d, 0x26, 0x2e, 0x03, 0x2b, 0xa0, 0xbe, 0xab, 0x6b, 0x80, + 0x20, 0xe1, 0x3a, 0x4b, 0xbb, 0x26, 0xbe, 0xab, 0xab, 0xa5, + 0x39, 0xb1, 0x9a, 0x49, 0xa6, 0xb4, 0x5b, 0x96, 0x66, 0xe2, + 0x49, 0x0b, 0x70, 0x02, 0xaa, 0x49, 0x49, 0x61, 0x0e, 0xfe, + 0xae, 0xf5, 0xa5, 0x96, 0xe7, 0xf6, 0xba, 0x6c, 0x89, 0x9f, + 0x0e, 0x72, 0xec, 0xfb, 0x45, 0x00, 0x87, 0x8f, 0x2c, 0xe7, + 0x7f, 0xb2, 0xc5, 0xa5, 0x52, 0xbe, 0x03, 0xfa, 0x31, 0x2a, + 0x02, 0x6a, 0xf8 ), + FINGERPRINT ( 0x9f, 0xd1, 0x93, 0xd3, 0x8f, 0x95, 0x30, 0xab, + 0x55, 0xa5, 0xc1, 0xb3, 0x51, 0x4a, 0x1d, 0x64, + 0x1c, 0xec, 0xc2, 0x1c, 0xc5, 0xc2, 0xf5, 0x67, + 0x48, 0xa7, 0x11, 0x01, 0x69, 0x83, 0xfd, 0x8e ) ); + +OCSP ( barclays_ocsp, &barclays_crt, &verisign_crt, + DATA ( 0x30, 0x51, 0x30, 0x4f, 0x30, 0x4d, 0x30, 0x4b, 0x30, 0x49, + 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14, 0xd4, 0xb4, 0x3b, 0x8e, 0x3d, 0x02, 0x49, + 0x1a, 0x65, 0x50, 0x6f, 0x96, 0x73, 0x14, 0xdd, 0xe8, 0x59, + 0x44, 0x52, 0xe4, 0x04, 0x14, 0xd7, 0x9b, 0x7c, 0xd8, 0x22, + 0xa0, 0x15, 0xf7, 0xdd, 0xad, 0x5f, 0xce, 0x29, 0x9b, 0x58, + 0xc3, 0xbc, 0x46, 0x00, 0xb5, 0x02, 0x10, 0x49, 0x83, 0xfc, + 0x05, 0x76, 0xdf, 0x36, 0x91, 0x7c, 0x64, 0x2a, 0x27, 0xc1, + 0xf1, 0x48, 0xe3 ), + DATA ( 0x30, 0x82, 0x06, 0x4d, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x06, + 0x46, 0x30, 0x82, 0x06, 0x42, 0x06, 0x09, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x06, 0x33, + 0x30, 0x82, 0x06, 0x2f, 0x30, 0x82, 0x01, 0x1f, 0xa0, 0x03, + 0x02, 0x01, 0x00, 0xa1, 0x81, 0x91, 0x30, 0x81, 0x8e, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, + 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65, + 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x3c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, + 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, + 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x20, 0x4f, 0x43, 0x53, + 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, + 0x72, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31, + 0x34, 0x31, 0x34, 0x30, 0x31, 0x34, 0x31, 0x5a, 0x30, 0x73, + 0x30, 0x71, 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, + 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0xd4, 0xb4, 0x3b, + 0x8e, 0x3d, 0x02, 0x49, 0x1a, 0x65, 0x50, 0x6f, 0x96, 0x73, + 0x14, 0xdd, 0xe8, 0x59, 0x44, 0x52, 0xe4, 0x04, 0x14, 0xd7, + 0x9b, 0x7c, 0xd8, 0x22, 0xa0, 0x15, 0xf7, 0xdd, 0xad, 0x5f, + 0xce, 0x29, 0x9b, 0x58, 0xc3, 0xbc, 0x46, 0x00, 0xb5, 0x02, + 0x10, 0x49, 0x83, 0xfc, 0x05, 0x76, 0xdf, 0x36, 0x91, 0x7c, + 0x64, 0x2a, 0x27, 0xc1, 0xf1, 0x48, 0xe3, 0x80, 0x00, 0x18, + 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31, 0x34, 0x31, + 0x34, 0x30, 0x31, 0x34, 0x31, 0x5a, 0xa0, 0x11, 0x18, 0x0f, + 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x32, 0x31, 0x31, 0x34, + 0x30, 0x31, 0x34, 0x31, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x78, 0xa8, 0xe7, 0xdc, 0xaf, 0xf2, + 0x8b, 0xc2, 0x9f, 0x99, 0xf9, 0x44, 0x84, 0xa8, 0x8a, 0x2c, + 0x35, 0xd7, 0x91, 0xd8, 0x44, 0x3e, 0xd6, 0xe0, 0xc6, 0x3f, + 0xbf, 0xe3, 0x71, 0x22, 0x45, 0x5a, 0x73, 0xf4, 0x59, 0x1b, + 0x4c, 0xa5, 0x51, 0x21, 0x5c, 0xfa, 0xbe, 0x10, 0xcb, 0x5f, + 0xb0, 0x2f, 0xef, 0x22, 0x89, 0xf6, 0xc7, 0x0f, 0x7c, 0x6d, + 0x26, 0xbe, 0x83, 0x99, 0xe2, 0x02, 0xf5, 0x95, 0x6e, 0xca, + 0xd9, 0x6d, 0xdd, 0xc2, 0xf0, 0xf2, 0x4f, 0x99, 0x66, 0x93, + 0x6e, 0x2e, 0xcf, 0xc5, 0xab, 0x68, 0x5f, 0xde, 0x52, 0x3d, + 0xf2, 0x23, 0x9d, 0xe8, 0x99, 0xd5, 0xf4, 0x4f, 0x8a, 0xf3, + 0xfd, 0x99, 0xa3, 0xe3, 0x12, 0x56, 0xd1, 0x54, 0xf1, 0xe1, + 0x24, 0xa0, 0xce, 0xeb, 0x80, 0xb6, 0xde, 0x44, 0xa8, 0xef, + 0xb1, 0xfc, 0x9c, 0x76, 0xbb, 0x1f, 0x17, 0x40, 0xbe, 0x2a, + 0xc8, 0x12, 0xa0, 0x82, 0x04, 0x75, 0x30, 0x82, 0x04, 0x71, + 0x30, 0x82, 0x04, 0x6d, 0x30, 0x82, 0x03, 0x55, 0xa0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x68, 0x8e, 0x69, 0x1f, 0x05, + 0x02, 0x11, 0x40, 0x45, 0x8e, 0xf0, 0x39, 0x24, 0x07, 0xcf, + 0xd6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0xbc, 0x31, + 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, + 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1f, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x16, 0x56, 0x65, + 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x32, 0x54, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20, + 0x75, 0x73, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68, 0x74, 0x74, + 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, + 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x72, 0x70, 0x61, 0x20, 0x28, 0x63, 0x29, 0x31, + 0x30, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x2d, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, + 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x32, 0x30, 0x33, 0x31, 0x33, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, + 0x31, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, + 0x81, 0x8e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, + 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, + 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, + 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x16, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, + 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x31, 0x45, 0x30, 0x43, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x3c, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, + 0x67, 0x6e, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x33, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x47, 0x33, 0x20, + 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x64, 0x65, 0x72, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, + 0x81, 0x81, 0x00, 0xa4, 0x3c, 0x3c, 0x43, 0xd3, 0x33, 0x14, + 0x0a, 0xb4, 0x5e, 0x25, 0x03, 0x6d, 0x60, 0x6c, 0x2f, 0xc9, + 0x33, 0x11, 0xe6, 0x79, 0xd9, 0x8c, 0x4a, 0x05, 0x60, 0xad, + 0x16, 0x8b, 0x23, 0x67, 0x8b, 0x1a, 0xaf, 0x84, 0xc3, 0xbb, + 0x6b, 0xcf, 0x9e, 0xf7, 0x65, 0x6d, 0x04, 0x97, 0xca, 0x12, + 0x96, 0x0b, 0x30, 0x7f, 0x0d, 0x6e, 0x7f, 0x81, 0x49, 0x53, + 0xf3, 0xcb, 0x5c, 0x00, 0xd8, 0x6d, 0xf9, 0x03, 0xf4, 0x23, + 0xd6, 0xd2, 0x9e, 0x8c, 0xca, 0x41, 0xfd, 0xa1, 0x02, 0x20, + 0xc8, 0x70, 0xb0, 0xfb, 0xaa, 0x1b, 0x33, 0x1e, 0x64, 0x30, + 0x70, 0x36, 0xed, 0x7b, 0xac, 0xe8, 0x64, 0xd9, 0x79, 0xa8, + 0x48, 0x20, 0x02, 0xdd, 0x8c, 0x02, 0x6f, 0x87, 0x2f, 0xad, + 0x29, 0x99, 0x8e, 0x15, 0x2c, 0xd1, 0xe0, 0x64, 0x82, 0x24, + 0x77, 0x31, 0xee, 0xb8, 0x68, 0xd1, 0x02, 0x32, 0xfb, 0xf0, + 0xcd, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x19, + 0x30, 0x82, 0x01, 0x15, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x81, 0xac, 0x06, 0x03, + 0x55, 0x1d, 0x20, 0x04, 0x81, 0xa4, 0x30, 0x81, 0xa1, 0x30, + 0x81, 0x9e, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, + 0x45, 0x01, 0x07, 0x17, 0x03, 0x30, 0x81, 0x8e, 0x30, 0x28, + 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, + 0x16, 0x1c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, + 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, + 0x67, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, + 0x30, 0x62, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x02, 0x02, 0x30, 0x56, 0x30, 0x15, 0x16, 0x0e, 0x56, 0x65, + 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, + 0x63, 0x2e, 0x30, 0x03, 0x02, 0x01, 0x01, 0x1a, 0x3d, 0x56, + 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x27, 0x73, 0x20, + 0x43, 0x50, 0x53, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x61, 0x62, 0x2e, + 0x20, 0x6c, 0x74, 0x64, 0x2e, 0x20, 0x28, 0x63, 0x29, 0x39, + 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, + 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, + 0x09, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, + 0x03, 0x02, 0x07, 0x80, 0x30, 0x0f, 0x06, 0x09, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, + 0x00, 0x30, 0x26, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x1f, + 0x30, 0x1d, 0xa4, 0x1b, 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0e, 0x4f, 0x43, 0x53, + 0x50, 0x38, 0x2d, 0x54, 0x47, 0x56, 0x37, 0x2d, 0x32, 0x38, + 0x35, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, + 0x00, 0x3b, 0xce, 0xd6, 0xa6, 0x61, 0x41, 0x3d, 0xb2, 0xc4, + 0x75, 0x00, 0x45, 0xf9, 0x3c, 0x2f, 0x2e, 0x4a, 0x8b, 0xfb, + 0x9c, 0xff, 0x15, 0xcb, 0x28, 0x65, 0xde, 0xc6, 0x97, 0xd8, + 0x85, 0x32, 0xa2, 0xfe, 0x74, 0x2d, 0xed, 0x34, 0xf8, 0x3c, + 0x15, 0xac, 0xfe, 0x72, 0x7f, 0x8c, 0x0e, 0x24, 0xdd, 0xb2, + 0x80, 0x55, 0xbd, 0x10, 0x0d, 0xa8, 0xb6, 0xf3, 0xe0, 0x98, + 0x8f, 0x24, 0x0b, 0xa0, 0x9d, 0x2c, 0x05, 0x20, 0x13, 0x4d, + 0x0b, 0x15, 0x2d, 0x1a, 0x02, 0x76, 0x0a, 0x5a, 0xb2, 0xb9, + 0xce, 0x6f, 0xb8, 0xc1, 0xec, 0xc4, 0xde, 0x46, 0xe4, 0xec, + 0x32, 0x05, 0x2d, 0xca, 0xb1, 0x4c, 0x59, 0x41, 0x13, 0x47, + 0x44, 0x9a, 0x55, 0x20, 0x26, 0xcc, 0x0d, 0x66, 0xb2, 0xd1, + 0x76, 0x87, 0x74, 0x73, 0xea, 0x5e, 0xe9, 0x49, 0xaf, 0x57, + 0x9c, 0xa6, 0x3d, 0xe5, 0x2c, 0x28, 0x21, 0xe5, 0x0a, 0x80, + 0xae, 0x99, 0x44, 0xe9, 0x83, 0x78, 0x7e, 0x24, 0xb5, 0xfa, + 0x50, 0x9d, 0x32, 0x55, 0x70, 0x73, 0xaf, 0x10, 0x92, 0xd3, + 0x14, 0xd3, 0x69, 0xfa, 0xa6, 0x81, 0x5c, 0xba, 0x9d, 0x18, + 0x25, 0xda, 0x78, 0x47, 0x33, 0x83, 0xd1, 0xc3, 0x96, 0x12, + 0x6f, 0x8b, 0xc9, 0x98, 0x32, 0x79, 0x59, 0x76, 0xcb, 0x56, + 0x7f, 0x5e, 0x6d, 0x1e, 0x78, 0xb2, 0xd0, 0x39, 0x3c, 0x41, + 0xd7, 0xab, 0x77, 0x2a, 0x0e, 0xbb, 0xc8, 0x69, 0xae, 0xfd, + 0x9c, 0x20, 0x11, 0xba, 0x0a, 0x5d, 0x00, 0x58, 0xf8, 0x74, + 0xb0, 0x77, 0x36, 0x9b, 0x8e, 0xd5, 0x4d, 0x85, 0xb1, 0xbb, + 0xcd, 0xcb, 0x1d, 0xee, 0x08, 0xb9, 0x53, 0x9a, 0x5f, 0xe3, + 0x88, 0xb1, 0x1a, 0xc3, 0x41, 0x41, 0x3e, 0x06, 0xf7, 0x70, + 0x58, 0xe8, 0x22, 0x22, 0xd7, 0x0e, 0xbb, 0x88, 0xce, 0x73, + 0x0e, 0xd0, 0x04, 0x81, 0x50, 0xd2, 0x33 ) ); + +OCSP ( google_ocsp, &google_crt, &thawte_crt, + DATA ( 0x30, 0x51, 0x30, 0x4f, 0x30, 0x4d, 0x30, 0x4b, 0x30, 0x49, + 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14, 0x1e, 0x92, 0x09, 0xaa, 0x71, 0x3c, 0x79, + 0x4b, 0xca, 0x1e, 0x93, 0x1a, 0x0a, 0x61, 0xad, 0x3f, 0xd0, + 0xba, 0x60, 0x83, 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91, + 0x73, 0xb2, 0x8a, 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3, + 0x70, 0x32, 0x9e, 0x18, 0x54, 0x02, 0x10, 0x4f, 0x9d, 0x96, + 0xd9, 0x66, 0xb0, 0x99, 0x2b, 0x54, 0xc2, 0x95, 0x7c, 0xb4, + 0x15, 0x7d, 0x4d ), + DATA ( 0x30, 0x82, 0x04, 0x38, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x04, + 0x31, 0x30, 0x82, 0x04, 0x2d, 0x06, 0x09, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x04, 0x1e, + 0x30, 0x82, 0x04, 0x1a, 0x30, 0x81, 0xe7, 0xa0, 0x03, 0x02, + 0x01, 0x00, 0xa1, 0x5a, 0x30, 0x58, 0x31, 0x0b, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5a, 0x41, 0x31, + 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x1c, + 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x50, + 0x74, 0x79, 0x29, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x31, 0x22, + 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x54, + 0x68, 0x61, 0x77, 0x74, 0x65, 0x20, 0x53, 0x47, 0x43, 0x20, + 0x4f, 0x43, 0x53, 0x50, 0x20, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x64, 0x65, 0x72, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, + 0x30, 0x35, 0x31, 0x32, 0x31, 0x39, 0x33, 0x31, 0x34, 0x33, + 0x5a, 0x30, 0x73, 0x30, 0x71, 0x30, 0x49, 0x30, 0x09, 0x06, + 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, + 0x1e, 0x92, 0x09, 0xaa, 0x71, 0x3c, 0x79, 0x4b, 0xca, 0x1e, + 0x93, 0x1a, 0x0a, 0x61, 0xad, 0x3f, 0xd0, 0xba, 0x60, 0x83, + 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91, 0x73, 0xb2, 0x8a, + 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3, 0x70, 0x32, 0x9e, + 0x18, 0x54, 0x02, 0x10, 0x4f, 0x9d, 0x96, 0xd9, 0x66, 0xb0, + 0x99, 0x2b, 0x54, 0xc2, 0x95, 0x7c, 0xb4, 0x15, 0x7d, 0x4d, + 0x80, 0x00, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, + 0x31, 0x32, 0x31, 0x39, 0x33, 0x31, 0x34, 0x33, 0x5a, 0xa0, + 0x11, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31, + 0x39, 0x31, 0x39, 0x33, 0x31, 0x34, 0x33, 0x5a, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x05, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x57, 0xf9, 0xf8, + 0x26, 0x0f, 0xda, 0x0c, 0xc2, 0xf0, 0xe4, 0x80, 0xd0, 0x29, + 0xd6, 0x04, 0x77, 0xab, 0x0c, 0xf6, 0x7e, 0x77, 0xc9, 0xac, + 0x53, 0xa4, 0x4d, 0x6b, 0x75, 0x58, 0xb9, 0xc7, 0x7a, 0x9a, + 0x39, 0x5d, 0x4c, 0xfd, 0x15, 0x1b, 0x47, 0x55, 0x8e, 0x39, + 0x05, 0x2b, 0x06, 0x2f, 0x3e, 0x1d, 0x3a, 0x7c, 0x2c, 0xf4, + 0x4c, 0x70, 0x6a, 0x58, 0x7a, 0x4b, 0x8f, 0x77, 0xaf, 0x9e, + 0xcf, 0xc6, 0xb1, 0x66, 0x8d, 0xed, 0xbf, 0xc1, 0xd9, 0xe1, + 0x78, 0x5a, 0x18, 0x61, 0xca, 0xa8, 0xf5, 0x2b, 0xe3, 0x9b, + 0x50, 0x25, 0x60, 0x7d, 0x8d, 0xd1, 0xe0, 0x76, 0xbb, 0x5c, + 0x7b, 0xc1, 0x5d, 0xe1, 0x27, 0x3f, 0x7f, 0x9b, 0xb3, 0xb0, + 0xb2, 0x79, 0x37, 0xd4, 0x53, 0x29, 0x62, 0x46, 0x8f, 0xe6, + 0x34, 0x9e, 0xe5, 0x6e, 0x63, 0x5d, 0xcc, 0xb3, 0xb2, 0xe2, + 0x73, 0x7e, 0xa6, 0xad, 0xa0, 0xa0, 0x82, 0x02, 0x99, 0x30, + 0x82, 0x02, 0x95, 0x30, 0x82, 0x02, 0x91, 0x30, 0x82, 0x01, + 0xfa, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x67, 0x4d, + 0x9b, 0x61, 0x8f, 0x57, 0xcd, 0x51, 0xfb, 0x58, 0x07, 0x66, + 0x1d, 0x24, 0xf5, 0xa5, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, + 0x4c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x5a, 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x54, 0x68, 0x61, 0x77, 0x74, + 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69, + 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, 0x4c, + 0x74, 0x64, 0x2e, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0d, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x20, 0x53, 0x47, 0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, + 0x0d, 0x31, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, + 0x30, 0x32, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, + 0x58, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x5a, 0x41, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x1c, 0x54, 0x68, 0x61, 0x77, 0x74, + 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x74, 0x69, + 0x6e, 0x67, 0x20, 0x28, 0x50, 0x74, 0x79, 0x29, 0x20, 0x4c, + 0x74, 0x64, 0x2e, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x19, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, + 0x20, 0x53, 0x47, 0x43, 0x20, 0x4f, 0x43, 0x53, 0x50, 0x20, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x30, + 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, + 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc2, 0x21, + 0x52, 0xe2, 0x10, 0x44, 0xe3, 0xc7, 0xe3, 0x72, 0x19, 0x01, + 0xa8, 0x0c, 0x5a, 0x8b, 0x63, 0x0b, 0x30, 0x4c, 0x4f, 0xa2, + 0xe2, 0xdf, 0x62, 0x2e, 0xdf, 0xe2, 0x77, 0xb9, 0x27, 0x3b, + 0x8d, 0x45, 0xe2, 0xa1, 0x21, 0x95, 0x13, 0x5a, 0xf2, 0x7d, + 0x58, 0x2c, 0x6d, 0x53, 0xb2, 0x42, 0x52, 0x8f, 0x8e, 0xf4, + 0x17, 0xc5, 0xcb, 0xfa, 0x2f, 0x2d, 0x9b, 0x02, 0xd0, 0x1a, + 0xf1, 0x32, 0xc5, 0xb9, 0xd3, 0x5a, 0xc0, 0xd6, 0x20, 0xb8, + 0x3f, 0xa3, 0x93, 0x8b, 0xe5, 0x22, 0x91, 0x1a, 0x7e, 0x7c, + 0x8b, 0x35, 0xeb, 0x94, 0xee, 0xe6, 0xcc, 0x58, 0xe4, 0x3c, + 0xcd, 0x00, 0x86, 0xaa, 0xc3, 0x2e, 0x8b, 0xb4, 0x3c, 0x29, + 0x11, 0x21, 0x5d, 0x71, 0x4a, 0xb6, 0x7a, 0x22, 0xa9, 0xf2, + 0xf8, 0x90, 0xed, 0x5c, 0x73, 0x8c, 0xe0, 0x70, 0x56, 0xde, + 0x70, 0xc5, 0x0d, 0x81, 0xb4, 0x5b, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x68, 0x30, 0x66, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, + 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09, 0x30, 0x0b, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, + 0x30, 0x0f, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x05, 0x04, 0x02, 0x05, 0x00, 0x30, 0x26, 0x06, + 0x03, 0x55, 0x1d, 0x11, 0x04, 0x1f, 0x30, 0x1d, 0xa4, 0x1b, + 0x30, 0x19, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x0e, 0x4f, 0x43, 0x53, 0x50, 0x38, 0x2d, 0x54, + 0x47, 0x56, 0x37, 0x2d, 0x32, 0x37, 0x35, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, + 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x98, 0x50, 0x14, 0xbe, + 0x31, 0x44, 0x01, 0x97, 0xee, 0x21, 0xf9, 0xcf, 0xa4, 0x32, + 0xc2, 0x91, 0x6a, 0x4b, 0x02, 0x61, 0x62, 0xa9, 0xe4, 0xad, + 0x8a, 0xac, 0xe4, 0x12, 0x12, 0xbe, 0x9b, 0xba, 0x4c, 0xe2, + 0x92, 0xdb, 0x8b, 0x92, 0x11, 0xe6, 0x9e, 0x25, 0x2e, 0xd5, + 0x4b, 0xe8, 0x5d, 0xc8, 0x63, 0xd2, 0xff, 0xfa, 0x80, 0x89, + 0x83, 0x0f, 0xe4, 0xe2, 0x91, 0xcc, 0x0a, 0x85, 0x74, 0x38, + 0xb7, 0xdf, 0xb9, 0x1c, 0xf6, 0x35, 0xfe, 0x6f, 0xf3, 0x29, + 0xc0, 0xc5, 0x0a, 0x2c, 0x04, 0xd7, 0x69, 0xff, 0x02, 0x45, + 0x1c, 0x29, 0x7a, 0x27, 0xf8, 0xb2, 0xe3, 0x58, 0x09, 0x34, + 0xc4, 0xd7, 0x77, 0x74, 0xbd, 0xe4, 0x7c, 0xda, 0x99, 0x09, + 0x83, 0x03, 0x6c, 0x36, 0x0d, 0xb2, 0x91, 0x71, 0x40, 0xc7, + 0x97, 0x85, 0xfb, 0x2a, 0xa3, 0x92, 0x65, 0x0b, 0x02, 0x58, + 0x14, 0x89, 0x8f, 0x3b ) ); + +OCSP ( unauthorized_ocsp, &server_crt, &thawte_crt, + DATA ( 0x30, 0x42, 0x30, 0x40, 0x30, 0x3e, 0x30, 0x3c, 0x30, 0x3a, + 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14, 0x68, 0x7a, 0xcf, 0x39, 0x5d, 0xdf, 0x7c, + 0x2c, 0x91, 0x6d, 0xdb, 0xcb, 0x9d, 0x0c, 0x27, 0x5b, 0x30, + 0x64, 0x28, 0xf2, 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91, + 0x73, 0xb2, 0x8a, 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3, + 0x70, 0x32, 0x9e, 0x18, 0x54, 0x02, 0x01, 0x03 ), + DATA ( 0x30, 0x03, 0x0a, 0x01, 0x06 ) ); + +OCSP ( unknown_ocsp, &thawte_crt, &startssl_crt, + DATA ( 0x30, 0x45, 0x30, 0x43, 0x30, 0x41, 0x30, 0x3f, 0x30, 0x3d, + 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, + 0x00, 0x04, 0x14, 0x48, 0xb7, 0x64, 0x49, 0xf3, 0xd5, 0xfe, + 0xfa, 0x11, 0x33, 0xaa, 0x80, 0x5e, 0x42, 0x0f, 0x0f, 0xca, + 0x64, 0x36, 0x51, 0x04, 0x14, 0x11, 0xdb, 0x23, 0x45, 0xfd, + 0x54, 0xcc, 0x6a, 0x71, 0x6f, 0x84, 0x8a, 0x03, 0xd7, 0xbe, + 0xf7, 0x01, 0x2f, 0x26, 0x86, 0x02, 0x04, 0x30, 0x00, 0x00, + 0x02 ), + DATA ( 0x30, 0x82, 0x06, 0x46, 0x0a, 0x01, 0x00, 0xa0, 0x82, 0x06, + 0x3f, 0x30, 0x82, 0x06, 0x3b, 0x06, 0x09, 0x2b, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x30, 0x01, 0x01, 0x04, 0x82, 0x06, 0x2c, + 0x30, 0x82, 0x06, 0x28, 0x30, 0x81, 0xec, 0xa1, 0x70, 0x30, + 0x6e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x49, 0x4c, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x13, 0x28, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e, 0x20, 0x28, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, + 0x65, 0x72, 0x63, 0x69, 0x61, 0x6c, 0x20, 0x4c, 0x69, 0x6d, + 0x69, 0x74, 0x65, 0x64, 0x29, 0x31, 0x2c, 0x30, 0x2a, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x23, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, + 0x20, 0x32, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x4f, 0x43, 0x53, 0x50, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, + 0x72, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x35, 0x31, + 0x35, 0x31, 0x31, 0x35, 0x34, 0x30, 0x38, 0x5a, 0x30, 0x67, + 0x30, 0x65, 0x30, 0x3d, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, + 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x48, 0xb7, 0x64, + 0x49, 0xf3, 0xd5, 0xfe, 0xfa, 0x11, 0x33, 0xaa, 0x80, 0x5e, + 0x42, 0x0f, 0x0f, 0xca, 0x64, 0x36, 0x51, 0x04, 0x14, 0x11, + 0xdb, 0x23, 0x45, 0xfd, 0x54, 0xcc, 0x6a, 0x71, 0x6f, 0x84, + 0x8a, 0x03, 0xd7, 0xbe, 0xf7, 0x01, 0x2f, 0x26, 0x86, 0x02, + 0x04, 0x30, 0x00, 0x00, 0x02, 0x82, 0x00, 0x18, 0x0f, 0x32, + 0x30, 0x31, 0x32, 0x30, 0x35, 0x31, 0x35, 0x31, 0x31, 0x35, + 0x34, 0x30, 0x38, 0x5a, 0xa0, 0x11, 0x18, 0x0f, 0x32, 0x30, + 0x31, 0x32, 0x30, 0x35, 0x31, 0x36, 0x31, 0x31, 0x35, 0x34, + 0x30, 0x38, 0x5a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x01, 0x00, 0xbe, 0x1b, 0xa7, 0xa7, 0xba, 0x17, 0xd9, + 0x94, 0x16, 0xdf, 0xd2, 0x86, 0x1e, 0x39, 0x38, 0x2f, 0x0e, + 0x0e, 0xb0, 0x19, 0x74, 0x9d, 0x64, 0x61, 0xfb, 0x34, 0x15, + 0x64, 0xe6, 0x7a, 0x44, 0xfc, 0x24, 0xaf, 0x63, 0xe3, 0xe5, + 0x01, 0x3f, 0xeb, 0x62, 0xc4, 0x2f, 0xd7, 0x56, 0xac, 0x9e, + 0x39, 0x8c, 0x54, 0x20, 0x24, 0x9f, 0xe0, 0x9a, 0x2c, 0x9a, + 0xfb, 0xbe, 0x13, 0x8d, 0x18, 0xf1, 0x95, 0x37, 0xf7, 0x6a, + 0x93, 0x28, 0x2a, 0xf6, 0x10, 0xc0, 0x5e, 0xa0, 0xfc, 0xf7, + 0x66, 0x97, 0xe4, 0x76, 0x04, 0x90, 0xd3, 0x45, 0x59, 0x26, + 0xfd, 0xe9, 0xb4, 0xe5, 0xd6, 0x30, 0x2f, 0xe0, 0xfb, 0xda, + 0xcc, 0x4b, 0xc4, 0x11, 0xbf, 0x20, 0x50, 0x18, 0xd5, 0x18, + 0xfc, 0xe7, 0x86, 0xb8, 0x80, 0x2b, 0x2e, 0x35, 0x50, 0xcd, + 0x73, 0x0d, 0x70, 0xbe, 0x55, 0xa2, 0xef, 0x2c, 0x62, 0x96, + 0xe3, 0x6a, 0xec, 0x69, 0xa6, 0x8f, 0x9d, 0x37, 0xb6, 0xbe, + 0x6b, 0x72, 0x02, 0x99, 0x02, 0xea, 0x0b, 0x18, 0x01, 0x26, + 0x82, 0x3b, 0x7b, 0x44, 0x8a, 0x84, 0xe4, 0x78, 0x6c, 0xb3, + 0x5b, 0x83, 0x87, 0x7c, 0xab, 0x80, 0x17, 0xfd, 0x00, 0xfd, + 0x56, 0x87, 0x85, 0x2b, 0x49, 0x42, 0xa2, 0x63, 0x84, 0x4f, + 0x4a, 0xaa, 0x5e, 0x7d, 0x64, 0x29, 0x09, 0x81, 0xac, 0xea, + 0x53, 0x00, 0x36, 0xbf, 0x19, 0x33, 0x5c, 0x0e, 0xee, 0xa9, + 0x6a, 0x9e, 0x2e, 0x44, 0x9b, 0x3e, 0xc9, 0x27, 0xb7, 0x49, + 0x15, 0x76, 0xa8, 0x42, 0x79, 0x2d, 0x4a, 0x42, 0x1f, 0xf1, + 0x32, 0x35, 0x31, 0x4c, 0xcb, 0xa2, 0xee, 0x50, 0xae, 0x1f, + 0x5e, 0x4d, 0x5d, 0xc1, 0x9e, 0x28, 0x17, 0x59, 0x6d, 0x1d, + 0x2a, 0x0a, 0x3d, 0xeb, 0x88, 0x10, 0xb5, 0xe6, 0x3b, 0xa7, + 0x81, 0x1f, 0xc7, 0xa0, 0xc8, 0x4a, 0xfe, 0x6c, 0x8f, 0xa0, + 0x82, 0x04, 0x21, 0x30, 0x82, 0x04, 0x1d, 0x30, 0x82, 0x04, + 0x19, 0x30, 0x82, 0x03, 0x01, 0xa0, 0x03, 0x02, 0x01, 0x02, + 0x02, 0x03, 0x00, 0xca, 0x67, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x30, 0x81, 0x8c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x16, 0x30, 0x14, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x4c, 0x74, 0x64, 0x2e, + 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, + 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x44, 0x69, + 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x31, 0x38, 0x30, 0x36, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x2f, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, + 0x20, 0x32, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, + 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x30, + 0x34, 0x32, 0x32, 0x30, 0x35, 0x33, 0x30, 0x35, 0x39, 0x5a, + 0x17, 0x0d, 0x31, 0x32, 0x30, 0x36, 0x30, 0x32, 0x30, 0x36, + 0x32, 0x39, 0x32, 0x37, 0x5a, 0x30, 0x6e, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, + 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, + 0x28, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, 0x20, + 0x4c, 0x74, 0x64, 0x2e, 0x20, 0x28, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 0x63, 0x69, + 0x61, 0x6c, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, + 0x29, 0x31, 0x2c, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x23, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6d, + 0x20, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x4f, 0x43, 0x53, 0x50, + 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x82, 0x01, + 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, + 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xd0, 0xd5, 0xf5, 0x70, 0x9a, 0x2b, 0x41, 0x35, 0xf7, 0xf8, + 0xcf, 0xb5, 0x6b, 0xb3, 0xdf, 0xe0, 0xb9, 0x12, 0x0d, 0x3d, + 0xd3, 0x99, 0x9f, 0x32, 0x73, 0x01, 0x1f, 0xbc, 0x7d, 0x4f, + 0x3e, 0x66, 0xf7, 0xfd, 0x60, 0x57, 0x92, 0x30, 0xb4, 0xdb, + 0x9a, 0xf5, 0xd3, 0x49, 0x19, 0xd6, 0xad, 0x37, 0x43, 0x78, + 0x69, 0x8c, 0x0d, 0x23, 0x0e, 0x7a, 0xd1, 0x65, 0x08, 0xeb, + 0x71, 0x8c, 0x37, 0x36, 0xd3, 0x4d, 0xa6, 0xcb, 0x11, 0xb2, + 0xfa, 0xb4, 0x38, 0x3e, 0x2b, 0x70, 0x8c, 0xf7, 0xf1, 0xd9, + 0x64, 0x62, 0x26, 0xf4, 0xa7, 0x2c, 0x24, 0x25, 0x4e, 0x4d, + 0x3e, 0x7a, 0x54, 0x57, 0x0f, 0xc1, 0x89, 0x9e, 0xb6, 0x55, + 0x0b, 0x7c, 0xbe, 0x38, 0xda, 0x8b, 0x62, 0xe9, 0xf1, 0xfa, + 0x8c, 0xd9, 0x32, 0x1f, 0xbe, 0x6d, 0x2e, 0x3d, 0x48, 0xa7, + 0x4f, 0x48, 0xd4, 0xff, 0x6b, 0xf6, 0x17, 0xf8, 0x31, 0xb2, + 0x37, 0xeb, 0x89, 0x71, 0x19, 0x0f, 0xe7, 0x86, 0x06, 0x66, + 0xfb, 0xc5, 0xad, 0x7b, 0x75, 0x0b, 0xcc, 0x2e, 0x3c, 0x4d, + 0x1c, 0x99, 0x40, 0x32, 0x72, 0xd4, 0x5c, 0xc9, 0x06, 0xaa, + 0x98, 0xe9, 0x01, 0x92, 0xdb, 0x25, 0x48, 0x1a, 0xae, 0x3f, + 0x01, 0x4d, 0x8a, 0xb0, 0x78, 0xb1, 0x28, 0xe0, 0x09, 0x9b, + 0x23, 0xe2, 0x28, 0x46, 0x6f, 0x50, 0x52, 0x71, 0x1c, 0xf1, + 0x09, 0xa0, 0x87, 0x3b, 0xdb, 0x84, 0xa3, 0xb1, 0x57, 0x6f, + 0xbf, 0x52, 0xd2, 0x30, 0x83, 0x30, 0x26, 0xc0, 0x27, 0x8e, + 0x6d, 0x03, 0x43, 0x14, 0x42, 0x31, 0x29, 0xf2, 0x7e, 0x52, + 0xcb, 0x84, 0x20, 0x2e, 0x87, 0x19, 0xe5, 0x48, 0xad, 0x06, + 0xce, 0x2e, 0x0f, 0xed, 0x78, 0x2a, 0x3d, 0x79, 0xc4, 0xb0, + 0xdb, 0xfa, 0x4e, 0x95, 0x88, 0x46, 0x75, 0x12, 0xb0, 0x7a, + 0x55, 0x6a, 0x38, 0xae, 0xea, 0x59, 0x02, 0x03, 0x01, 0x00, + 0x01, 0xa3, 0x81, 0xa0, 0x30, 0x81, 0x9d, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, + 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x03, + 0xa8, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x17, + 0x30, 0x15, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x03, 0x09, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x05, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, + 0x04, 0x16, 0x04, 0x14, 0xbd, 0x4c, 0xef, 0x0e, 0xf7, 0x08, + 0xac, 0xc9, 0xbd, 0x39, 0x0f, 0xd9, 0xa0, 0xd3, 0xce, 0xcf, + 0x26, 0x48, 0xb8, 0x19, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x11, 0xdb, 0x23, + 0x45, 0xfd, 0x54, 0xcc, 0x6a, 0x71, 0x6f, 0x84, 0x8a, 0x03, + 0xd7, 0xbe, 0xf7, 0x01, 0x2f, 0x26, 0x86, 0x30, 0x23, 0x06, + 0x03, 0x55, 0x1d, 0x12, 0x04, 0x1c, 0x30, 0x1a, 0x86, 0x18, + 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, + 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x73, 0x6c, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x56, 0x1f, 0xef, 0xa5, 0x1a, 0x07, + 0xbe, 0xb1, 0xd1, 0xd0, 0x17, 0xeb, 0x72, 0x5b, 0x17, 0x11, + 0xe5, 0x96, 0xc3, 0x96, 0xe7, 0x9a, 0xdb, 0xbf, 0x64, 0x1c, + 0x99, 0x11, 0x2f, 0x18, 0x07, 0xb2, 0x45, 0x48, 0xf3, 0x58, + 0xcd, 0x38, 0x69, 0x33, 0xf4, 0x58, 0x5b, 0x16, 0xed, 0xfb, + 0xce, 0xb3, 0xc3, 0x14, 0x27, 0xa6, 0x16, 0xff, 0xd0, 0x70, + 0x9e, 0xe1, 0x9d, 0x4b, 0xd1, 0x26, 0x6c, 0x61, 0x25, 0xf1, + 0x39, 0x9c, 0xbe, 0x69, 0x75, 0x58, 0xcd, 0xbd, 0x8e, 0x36, + 0xfd, 0x46, 0xd1, 0xe3, 0xb9, 0x1a, 0x8a, 0xc1, 0xd7, 0x3e, + 0x6e, 0x82, 0xb8, 0xb0, 0x3f, 0xcf, 0x14, 0x3f, 0xc6, 0xf6, + 0x3a, 0x86, 0xce, 0x03, 0x76, 0x1f, 0xdb, 0x0b, 0x12, 0xac, + 0x99, 0x79, 0x53, 0xf0, 0x3d, 0x70, 0xd3, 0x5a, 0x05, 0xf6, + 0xba, 0x6e, 0x35, 0x31, 0x1e, 0x08, 0x30, 0xc1, 0xa4, 0xd4, + 0x45, 0x43, 0x5a, 0x01, 0xd9, 0x3d, 0xa5, 0xdb, 0xd2, 0xd7, + 0x73, 0x97, 0xe9, 0xab, 0xe4, 0x60, 0xf1, 0xfc, 0xf0, 0x9b, + 0xe2, 0x5a, 0x1e, 0x31, 0xe0, 0x1b, 0x47, 0x3f, 0x5a, 0x78, + 0xf3, 0x6e, 0xf0, 0x94, 0x6c, 0x2c, 0xfb, 0x67, 0x6e, 0xcb, + 0x8c, 0xb6, 0x8d, 0xcc, 0xcf, 0x1e, 0x9f, 0xd2, 0x10, 0x52, + 0xc2, 0xe7, 0xc8, 0x05, 0x2c, 0xa0, 0x18, 0xf5, 0x53, 0x4a, + 0xd2, 0xb0, 0x57, 0x5e, 0x5f, 0x63, 0xd7, 0x7b, 0x8e, 0xfa, + 0x22, 0xa0, 0x69, 0x17, 0xd2, 0xa0, 0xc7, 0x70, 0x01, 0x79, + 0x8b, 0x69, 0x1f, 0x0f, 0xdb, 0xe5, 0xf9, 0x83, 0x2b, 0x26, + 0x05, 0x05, 0x87, 0x80, 0x0d, 0xf9, 0x20, 0x0e, 0x16, 0x39, + 0xc5, 0x9b, 0x14, 0x2e, 0xf2, 0x06, 0x57, 0x46, 0x3d, 0x0b, + 0x8c, 0x3e, 0xb4, 0x66, 0x76, 0x67, 0x34, 0x70, 0x00, 0x63, + 0xcf, 0x9e, 0xc8, 0xc5, 0x5f, 0x48, 0x06, 0x53, 0x26, 0x55 ) ); + +/** Time at which OCSP responses are valid */ +static time_t test_time = 1337062083ULL; /* Tue 15 May 2012 06:08:03 */ + +/** Time at which OCSP responses are not valid */ +static time_t test_stale = 1375573111ULL; /* Sat Aug 3 23:38:31 2013 */ + +/** + * Report certificate parsing test result + * + * @v crt Test certificate + */ +#define ocsp_certificate_ok( crt ) do { \ + ok ( x509_certificate ( (crt)->data, (crt)->len, \ + &(crt)->cert ) == 0 ); \ + } while ( 0 ) + +/** + * Report OCSP check creation test result + * + * @v test OCSP test + */ +#define ocsp_check_ok( test ) do { \ + ocsp_prepare_test ( (test) ); \ + ok ( ocsp_check ( (test)->cert->cert, (test)->issuer->cert, \ + &(test)->ocsp ) == 0 ); \ + } while ( 0 ) + +/** + * Report OCSP request construction test result + * + * @v test OCSP test + */ +#define ocsp_request_ok( test ) do { \ + DBGC ( (test), "OCSPTEST %p expected request:\n", (test) ); \ + DBGC_HDA ( (test), 0, (test)->request, (test)->request_len ); \ + ok ( (test)->ocsp->request.builder.len == (test)->request_len );\ + ok ( memcmp ( (test)->ocsp->request.builder.data, \ + (test)->request, (test)->request_len ) == 0 ); \ + DBGC ( (test), "OCSPTEST %p generated request:\n", (test) ); \ + DBGC_HDA ( (test), 0, (test)->ocsp->request.builder.data, \ + (test)->ocsp->request.builder.len ); \ + } while ( 0 ) + +/** + * Report OCSP response test result + * + * @v test OCSP test + */ +#define ocsp_response_ok( test ) do { \ + ok ( ocsp_response ( (test)->ocsp, (test)->response, \ + (test)->response_len ) == 0 ); \ + } while ( 0 ) + +/** + * Report OCSP response failure test result + * + * @v test OCSP test + */ +#define ocsp_response_fail_ok( test ) do { \ + ok ( ocsp_response ( (test)->ocsp, (test)->response, \ + (test)->response_len ) != 0 ); \ + } while ( 0 ) + +/** + * Report OCSP validation test result + * + * @v test OCSP test + * @v time Test time + */ +#define ocsp_validate_ok( test, time ) do { \ + ocsp_prepare_test ( (test) ); \ + ok ( ocsp_validate ( (test)->ocsp, time ) == 0 ); \ + } while ( 0 ) + +/** + * Report OCSP validation failure test result + * + * @v test OCSP test + * @v time Test time + */ +#define ocsp_validate_fail_ok( test, time ) do { \ + ocsp_prepare_test ( (test) ); \ + ok ( ocsp_validate ( (test)->ocsp, time ) != 0 ); \ + } while ( 0 ) + +/** + * Perform OCSP self-tests + * + */ +static void ocsp_test_exec ( void ) { + + /* Parse certificates */ + ocsp_certificate_ok ( &barclays_crt ); + ocsp_certificate_ok ( &google_crt ); + ocsp_certificate_ok ( &server_crt ); + ocsp_certificate_ok ( &verisign_crt ); + ocsp_certificate_ok ( &thawte_crt ); + ocsp_certificate_ok ( &startssl_crt ); + + /* Parse OCSP checks */ + ocsp_check_ok ( &barclays_ocsp ); + ocsp_check_ok ( &google_ocsp ); + ocsp_check_ok ( &unauthorized_ocsp ); + ocsp_check_ok ( &unknown_ocsp ); + + /* "barclays" test */ + ocsp_request_ok ( &barclays_ocsp ); + ocsp_response_ok ( &barclays_ocsp ); + ocsp_validate_ok ( &barclays_ocsp, test_time ); + ocsp_validate_fail_ok ( &barclays_ocsp, test_stale ); + + /* "google" test */ + ocsp_request_ok ( &google_ocsp ); + ocsp_response_ok ( &google_ocsp ); + ocsp_validate_ok ( &google_ocsp, test_time ); + ocsp_validate_fail_ok ( &google_ocsp, test_stale ); + + /* "unauthorized" test */ + ocsp_request_ok ( &unauthorized_ocsp ); + ocsp_response_fail_ok ( &unauthorized_ocsp ); + + /* "unknown" test */ + ocsp_request_ok ( &unknown_ocsp ); + ocsp_response_fail_ok ( &unknown_ocsp ); + + /* Drop OCSP check references */ + ocsp_put ( unknown_ocsp.ocsp ); + ocsp_put ( unauthorized_ocsp.ocsp ); + ocsp_put ( google_ocsp.ocsp ); + ocsp_put ( barclays_ocsp.ocsp ); + + /* Drop certificate references */ + x509_put ( startssl_crt.cert ); + x509_put ( thawte_crt.cert ); + x509_put ( verisign_crt.cert ); + x509_put ( server_crt.cert ); + x509_put ( google_crt.cert ); + x509_put ( barclays_crt.cert ); +} + +/** OCSP self-test */ +struct self_test ocsp_test __self_test = { + .name = "ocsp", + .exec = ocsp_test_exec, +}; + +/* Drag in algorithms required for tests */ +REQUIRE_OBJECT ( rsa ); +REQUIRE_OBJECT ( sha1 ); diff --git a/src/tests/tests.c b/src/tests/tests.c index cfecff6e..1bf40418 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -39,4 +39,5 @@ REQUIRE_OBJECT ( hash_df_test ); REQUIRE_OBJECT ( bigint_test ); REQUIRE_OBJECT ( rsa_test ); REQUIRE_OBJECT ( x509_test ); +REQUIRE_OBJECT ( ocsp_test ); REQUIRE_OBJECT ( cms_test ); From 73b21174b228add00e49de2a01b94a2fbaa8b130 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 16 May 2012 10:50:56 +0100 Subject: [PATCH 009/250] [iscsi] Report SCSI response only when applicable iSCSI generally includes a full SCSI response only when an error occurs. iscsi_scsi_done() currently passes the NULL response through to scsi_response(), which ends up causing scsicmd_response() to dereference a NULL pointer. Fix by calling scsi_response() only if we have a non-NULL response. Reported-by: Brendon Walsh Tested-by: Brendon Walsh Signed-off-by: Michael Brown --- src/net/tcp/iscsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index 9eaf3cc5..457ea731 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -337,7 +337,8 @@ static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc, iscsi->command = NULL; /* Send SCSI response, if any */ - scsi_response ( &iscsi->data, rsp ); + if ( rsp ) + scsi_response ( &iscsi->data, rsp ); /* Close SCSI command, if this is still the same command. (It * is possible that the command interface has already been From 1af9284225993de505c89d128d5bcf77c636637a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 16 May 2012 19:04:33 +0100 Subject: [PATCH 010/250] [efi] Work around platforms which choke on EFI_PCI_DEVICE_ENABLE EFI_PCI_DEVICE_ENABLE is a list of the standard attributes that must be enabled for a PCI device to function: I/O cycles, memory cycles, and bus-mastering. We currently call EFI_PCI_IO_PROTOCOL::Attribute() with the parameter EFI_PCI_DEVICE_ENABLE to enable a PCI device. This should translate to a single write to PCI configuration space. Simplicity is not a virtue within the UEFI world. Some platforms will 'helpfully' report an error if EFI_PCI_DEVICE_ENABLE is used on a device that doesn't actually support all three of the relevant attributes. For example, if a PCI device provides only memory-mapped accesses (and so hardwires the I/O enable bit to zero), then using EFI_PCI_DEVICE_ENABLE on such a platform will result in an EFI_UNSUPPORTED error. There is no plausible use case in which it is useful for the platform to return an error in this way, and doing so makes it impossible to distinguish genuine errors from noise. Work around this broken behaviour by attempting to enable the three attributes individually, and ignoring any errors. Signed-off-by: Michael Brown --- src/interface/efi/efi_pci.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c index fa71e7d8..0a2da2e4 100644 --- a/src/interface/efi/efi_pci.c +++ b/src/interface/efi/efi_pci.c @@ -216,17 +216,19 @@ struct efi_pci_device * efipci_create ( struct efi_driver *efidrv, */ EFI_STATUS efipci_enable ( struct efi_pci_device *efipci ) { EFI_PCI_IO_PROTOCOL *pci_io = efipci->pci_io; - EFI_STATUS efirc; - /* Enable device */ - if ( ( efirc = pci_io->Attributes ( pci_io, - EfiPciIoAttributeOperationSet, - EFI_PCI_DEVICE_ENABLE, - NULL ) ) != 0 ) { - DBGC ( efipci, "EFIPCI " PCI_FMT " could not be enabled: %s\n", - PCI_ARGS ( &efipci->pci ), efi_strerror ( efirc ) ); - return efirc; - } + /* Try to enable I/O cycles, memory cycles, and bus mastering. + * Some platforms will 'helpfully' report errors if these bits + * can't be enabled (for example, if the card doesn't actually + * support I/O cycles). Work around any such platforms by + * enabling bits individually and simply ignoring any errors. + */ + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IO, NULL ); + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_MEMORY, NULL ); + pci_io->Attributes ( pci_io, EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, NULL ); return 0; } From 40e68e1119ed45ed27c586836d4cb9400a96db1c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 20 May 2012 16:38:57 +0100 Subject: [PATCH 011/250] [base64] Avoid overrunning input data buffer Signed-off-by: Michael Brown --- src/core/base64.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/base64.c b/src/core/base64.c index 7514c1fa..761b42f2 100644 --- a/src/core/base64.c +++ b/src/core/base64.c @@ -54,11 +54,16 @@ void base64_encode ( const uint8_t *raw, size_t len, char *encoded ) { uint8_t *encoded_bytes = ( ( uint8_t * ) encoded ); size_t raw_bit_len = ( 8 * len ); unsigned int bit; + unsigned int byte; + unsigned int shift; unsigned int tmp; for ( bit = 0 ; bit < raw_bit_len ; bit += 6 ) { - tmp = ( ( raw_bytes[ bit / 8 ] << ( bit % 8 ) ) | - ( raw_bytes[ bit / 8 + 1 ] >> ( 8 - ( bit % 8 ) ) ) ); + byte = ( bit / 8 ); + shift = ( bit % 8 ); + tmp = ( raw_bytes[byte] << shift ); + if ( ( byte + 1 ) < len ) + tmp |= ( raw_bytes[ byte + 1 ] >> ( 8 - shift ) ); tmp = ( ( tmp >> 2 ) & 0x3f ); *(encoded_bytes++) = base64[tmp]; } From f4c88d55bd4330a688f2d18fc53019291d073240 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 20 May 2012 17:10:23 +0100 Subject: [PATCH 012/250] [test] Add self-tests for base64 Signed-off-by: Michael Brown --- src/tests/base64_test.c | 124 ++++++++++++++++++++++++++++++++++++++++ src/tests/tests.c | 1 + 2 files changed, 125 insertions(+) create mode 100644 src/tests/base64_test.c diff --git a/src/tests/base64_test.c b/src/tests/base64_test.c new file mode 100644 index 00000000..c088298c --- /dev/null +++ b/src/tests/base64_test.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Base64 tests + * + * Test vectors generated using "base64 -w 0" + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include +#include +#include +#include + +/** A Base64 test */ +struct base64_test { + /** Raw data */ + const void *data; + /** Length of raw data */ + size_t len; + /** Base64-encoded data */ + const char *encoded; +}; + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define a base64 test */ +#define BASE64( name, DATA, ENCODED ) \ + static const uint8_t name ## _data[] = DATA; \ + static struct base64_test name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + .encoded = ENCODED, \ + } + +/** Empty data test */ +BASE64 ( empty_test, DATA(), "" ); + +/** "Hello world" test */ +BASE64 ( hw_test, + DATA ( 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' ), + "SGVsbG8gd29ybGQ=" ); + +/** Random data test */ +BASE64 ( random_test, + DATA ( 0x36, 0x03, 0x84, 0xdc, 0x4e, 0x03, 0x46, 0xa0, 0xb5, 0x2d, + 0x03, 0x6e, 0xd0, 0x56, 0xed, 0xa0, 0x37, 0x02, 0xac, 0xc6, + 0x65, 0xd1 ), + "NgOE3E4DRqC1LQNu0FbtoDcCrMZl0Q==" ); + +/** + * Report a base64 encoding test result + * + * @v test Base64 test + */ +#define base64_encode_ok( test ) do { \ + size_t len = base64_encoded_len ( (test)->len ); \ + char buf[ len + 1 /* NUL */ ]; \ + ok ( len == strlen ( (test)->encoded ) ); \ + base64_encode ( (test)->data, (test)->len, buf ); \ + ok ( strcmp ( (test)->encoded, buf ) == 0 ); \ + } while ( 0 ) + +/** + * Report a base64 decoding test result + * + * @v test Base64 test + */ +#define base64_decode_ok( test ) do { \ + size_t max_len = base64_decoded_max_len ( (test)->encoded ); \ + uint8_t buf[max_len]; \ + int len; \ + len = base64_decode ( (test)->encoded, buf ); \ + ok ( len >= 0 ); \ + ok ( ( size_t ) len <= max_len ); \ + ok ( ( size_t ) len == (test)->len ); \ + ok ( memcmp ( (test)->data, buf, len ) == 0 ); \ + } while ( 0 ) + +/** + * Perform Base64 self-tests + * + */ +static void base64_test_exec ( void ) { + + base64_encode_ok ( &empty_test ); + base64_decode_ok ( &empty_test ); + + base64_encode_ok ( &hw_test ); + base64_decode_ok ( &hw_test ); + + base64_encode_ok ( &random_test ); + base64_decode_ok ( &random_test ); +} + +/** Base64 self-test */ +struct self_test base64_test __self_test = { + .name = "base64", + .exec = base64_test_exec, +}; diff --git a/src/tests/tests.c b/src/tests/tests.c index 1bf40418..95a3c4ba 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); /* Drag in all applicable self-tests */ REQUIRE_OBJECT ( list_test ); REQUIRE_OBJECT ( byteswap_test ); +REQUIRE_OBJECT ( base64_test ); REQUIRE_OBJECT ( settings_test ); REQUIRE_OBJECT ( time_test ); REQUIRE_OBJECT ( crc32_test ); From f20c3742e713092ee04cdfd1aa65d5d640be6a77 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 21 May 2012 23:20:03 +0100 Subject: [PATCH 013/250] [crypto] Accept UTCTime/GeneralizedTime with no "seconds" field Signed-off-by: Michael Brown --- src/crypto/asn1.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 5fc37849..462885f3 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -655,10 +655,16 @@ int asn1_generalized_time ( const struct asn1_cursor *cursor, time_t *time ) { } /* Parse digit string a pair at a time */ + memset ( &pairs, 0, sizeof ( pairs ) ); data = contents.data; remaining = contents.len; for ( i = ( have_century ? 0 : 1 ) ; i < sizeof ( pairs.raw ) ; i++ ) { if ( remaining < 2 ) { + /* Some certificates violate the X.509 RFC by + * omitting the "seconds" value. + */ + if ( i == ( sizeof ( pairs.raw ) - 1 ) ) + break; DBGC ( cursor, "ASN1 %p invalid time:\n", cursor ); DBGC_HDA ( cursor, 0, cursor->data, cursor->len ); return -EINVAL_ASN1_TIME; From c923d57663183da3b738dbc9f999d3e2e620305b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 21 May 2012 23:00:08 +0100 Subject: [PATCH 014/250] [crypto] Return a NULL X.509 certificate if construction fails Signed-off-by: Michael Brown --- src/crypto/x509.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 18a8cebe..2180173b 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -1068,6 +1068,7 @@ int x509_certificate ( const void *data, size_t len, /* Parse certificate */ if ( ( rc = x509_parse ( *cert, &cursor ) ) != 0 ) { x509_put ( *cert ); + *cert = NULL; return rc; } From b27809490207e02647add54288ec2c3ce2e4da50 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 21 May 2012 23:01:29 +0100 Subject: [PATCH 015/250] [crypto] Return a NULL OCSP check if construction fails Signed-off-by: Michael Brown --- src/crypto/ocsp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c index 7dca281f..58b987d4 100644 --- a/src/crypto/ocsp.c +++ b/src/crypto/ocsp.c @@ -217,6 +217,7 @@ int ocsp_check ( struct x509_certificate *cert, err_request: ocsp_put ( *ocsp ); err_alloc: + *ocsp = NULL; return rc; } From 57de8b6272c38e92d48b815997c81e103fc172ee Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 21 May 2012 23:00:46 +0100 Subject: [PATCH 016/250] [crypto] Fix margin of error for OCSP checks Signed-off-by: Michael Brown --- src/crypto/ocsp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c index 58b987d4..02edd9d3 100644 --- a/src/crypto/ocsp.c +++ b/src/crypto/ocsp.c @@ -720,12 +720,12 @@ int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) { /* Check OCSP response is valid at the specified time * (allowing for some margin of error). */ - if ( response->this_update > ( time - OCSP_ERROR_MARGIN_TIME ) ) { + if ( response->this_update > ( time + OCSP_ERROR_MARGIN_TIME ) ) { DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at " "time %lld)\n", ocsp, ocsp->cert->subject.name, time ); return -EACCES_STALE; } - if ( response->next_update < ( time + OCSP_ERROR_MARGIN_TIME ) ) { + if ( response->next_update < ( time - OCSP_ERROR_MARGIN_TIME ) ) { DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time " "%lld)\n", ocsp, ocsp->cert->subject.name, time ); return -EACCES_STALE; From 944e023def7da2e1e84621803f4bb62855ff99c7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 20 May 2012 15:54:03 +0100 Subject: [PATCH 017/250] [crypto] Construct OCSP check URI Signed-off-by: Michael Brown --- src/crypto/ocsp.c | 74 +++++++++++++++++++++++++++++++++ src/include/ipxe/ocsp.h | 2 + src/tests/ocsp_test.c | 91 ++++------------------------------------- 3 files changed, 84 insertions(+), 83 deletions(-) diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c index 02edd9d3..f5d03dc6 100644 --- a/src/crypto/ocsp.c +++ b/src/crypto/ocsp.c @@ -21,11 +21,14 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include #include #include #include #include +#include +#include #include /** @file @@ -110,6 +113,7 @@ static void ocsp_free ( struct refcnt *refcnt ) { x509_put ( ocsp->cert ); x509_put ( ocsp->issuer ); + free ( ocsp->uri_string ); free ( ocsp->request.builder.data ); free ( ocsp->response.data ); x509_put ( ocsp->response.signer ); @@ -180,6 +184,71 @@ static int ocsp_request ( struct ocsp_check *ocsp ) { return 0; } +/** + * Build OCSP URI string + * + * @v ocsp OCSP check + * @ret rc Return status code + */ +static int ocsp_uri_string ( struct ocsp_check *ocsp ) { + char *base_uri_string; + char *base64_request; + size_t base64_request_len; + size_t uri_string_len; + size_t prefix_len; + int rc; + + /* Sanity check */ + base_uri_string = ocsp->cert->extensions.auth_info.ocsp.uri; + if ( ! base_uri_string ) { + DBGC ( ocsp, "OCSP %p \"%s\" has no OCSP URI\n", + ocsp, ocsp->cert->subject.name ); + rc = -ENOTTY; + goto err_no_uri; + } + + /* Base64-encode the request */ + base64_request_len = ( base64_encoded_len ( ocsp->request.builder.len ) + + 1 /* NUL */ ); + base64_request = malloc ( base64_request_len ); + if ( ! base64_request ) { + rc = -ENOMEM; + goto err_alloc_base64; + } + base64_encode ( ocsp->request.builder.data, ocsp->request.builder.len, + base64_request ); + + /* Allocate URI string */ + uri_string_len = ( strlen ( base_uri_string ) + 1 /* "/" */ + + uri_encode ( base64_request, NULL, 0, URI_FRAGMENT ) + + 1 /* NUL */ ); + ocsp->uri_string = malloc ( uri_string_len ); + if ( ! ocsp->uri_string ) { + rc = -ENOMEM; + goto err_alloc_uri; + } + + /* Construct URI string */ + prefix_len = snprintf ( ocsp->uri_string, uri_string_len, + "%s/", base_uri_string ); + uri_encode ( base64_request, ( ocsp->uri_string + prefix_len ), + ( uri_string_len - prefix_len ), URI_FRAGMENT ); + DBGC2 ( ocsp, "OCSP %p \"%s\" URI is %s\n", + ocsp, ocsp->cert->subject.name, ocsp->uri_string ); + + /* Free base64-encoded request */ + free ( base64_request ); + base64_request = NULL; + + return 0; + + err_alloc_uri: + free ( base64_request ); + err_alloc_base64: + err_no_uri: + return rc; +} + /** * Create OCSP check * @@ -212,8 +281,13 @@ int ocsp_check ( struct x509_certificate *cert, if ( ( rc = ocsp_request ( *ocsp ) ) != 0 ) goto err_request; + /* Build URI string */ + if ( ( rc = ocsp_uri_string ( *ocsp ) ) != 0 ) + goto err_uri_string; + return 0; + err_uri_string: err_request: ocsp_put ( *ocsp ); err_alloc: diff --git a/src/include/ipxe/ocsp.h b/src/include/ipxe/ocsp.h index e8414923..2521681c 100644 --- a/src/include/ipxe/ocsp.h +++ b/src/include/ipxe/ocsp.h @@ -70,6 +70,8 @@ struct ocsp_check { struct x509_certificate *cert; /** Issuing certificate */ struct x509_certificate *issuer; + /** URI string */ + char *uri_string; /** Request */ struct ocsp_request request; /** Response */ diff --git a/src/tests/ocsp_test.c b/src/tests/ocsp_test.c index 863f4c26..24405db8 100644 --- a/src/tests/ocsp_test.c +++ b/src/tests/ocsp_test.c @@ -352,81 +352,6 @@ CERTIFICATE ( google_crt, 0x50, 0x48, 0xaf, 0x17, 0x94, 0x57, 0x48, 0x39, 0x6b, 0xd2, 0xec, 0xf1, 0x2b, 0x8d, 0xe2, 0x2c ) ); -/* - * subject boot.test.ipxe.org - * issuer iPXE self-test leaf CA - */ -CERTIFICATE ( server_crt, - DATA ( 0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xe6, 0x02, 0x01, - 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x88, 0x31, - 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, - 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, - 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, 0x30, - 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, 0x61, - 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, 0x30, - 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, 0x65, - 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, - 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, - 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, - 0x72, 0x67, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, - 0x03, 0x0c, 0x16, 0x69, 0x50, 0x58, 0x45, 0x20, 0x73, 0x65, - 0x6c, 0x66, 0x2d, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x65, - 0x61, 0x66, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, - 0x32, 0x30, 0x33, 0x32, 0x32, 0x30, 0x30, 0x30, 0x31, 0x33, - 0x34, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x33, 0x32, 0x32, - 0x30, 0x30, 0x30, 0x31, 0x33, 0x34, 0x5a, 0x30, 0x81, 0x84, - 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x47, 0x42, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, - 0x04, 0x08, 0x0c, 0x0e, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, - 0x64, 0x67, 0x65, 0x73, 0x68, 0x69, 0x72, 0x65, 0x31, 0x12, - 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x09, 0x43, - 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x31, 0x18, - 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0f, 0x46, - 0x65, 0x6e, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, - 0x20, 0x4c, 0x74, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, - 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x69, 0x70, 0x78, 0x65, 0x2e, - 0x6f, 0x72, 0x67, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, - 0x04, 0x03, 0x0c, 0x12, 0x62, 0x6f, 0x6f, 0x74, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x2e, 0x69, 0x70, 0x78, 0x65, 0x2e, 0x6f, - 0x72, 0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, - 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, - 0x00, 0xbd, 0x43, 0x97, 0x45, 0xa2, 0xe0, 0x1d, 0x38, 0x41, - 0xb0, 0xd9, 0x91, 0xf9, 0x77, 0xa9, 0xcb, 0x9c, 0x9c, 0x93, - 0xfe, 0x5a, 0xee, 0xbc, 0xd9, 0x0f, 0x39, 0xf6, 0x42, 0xe4, - 0x55, 0x21, 0xbb, 0x11, 0xfd, 0xfd, 0xba, 0x25, 0x58, 0xc8, - 0xc6, 0xa5, 0x3b, 0x6f, 0x80, 0xba, 0x5b, 0xbc, 0x89, 0xca, - 0x7a, 0xdf, 0x6e, 0xb9, 0x81, 0xb6, 0x25, 0x67, 0x0a, 0x38, - 0x10, 0xf8, 0x26, 0x43, 0x0c, 0x51, 0x02, 0x14, 0xd6, 0xf2, - 0x9d, 0x7c, 0xf5, 0x25, 0x1c, 0x78, 0x4d, 0x47, 0xaf, 0x87, - 0x2e, 0x38, 0x49, 0x87, 0xb5, 0x8a, 0xf3, 0xb5, 0xd4, 0x15, - 0x69, 0x2a, 0x52, 0xc9, 0x46, 0x97, 0x34, 0x8e, 0x50, 0x4b, - 0xc4, 0xf2, 0xfb, 0x39, 0xfd, 0x16, 0x68, 0xdb, 0xa8, 0x17, - 0xe2, 0x71, 0x4b, 0xe0, 0xdf, 0x3d, 0xfc, 0xc3, 0x9b, 0x9d, - 0x22, 0xc9, 0xd3, 0xf6, 0x02, 0xa6, 0x60, 0xef, 0xf7, 0x02, - 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, - 0x81, 0x81, 0x00, 0x7d, 0xff, 0x73, 0xf3, 0x68, 0xe3, 0x75, - 0xf1, 0xcf, 0xac, 0x2e, 0x23, 0x73, 0xea, 0xd1, 0x26, 0x33, - 0xbf, 0xf9, 0x56, 0xdf, 0xbf, 0x98, 0x20, 0x84, 0x08, 0x78, - 0x6b, 0xe6, 0x71, 0x7e, 0x22, 0x68, 0x4d, 0x6c, 0xbb, 0xd5, - 0xcc, 0xb4, 0x28, 0x33, 0x5e, 0xbe, 0x4d, 0x10, 0x16, 0x9f, - 0x65, 0x3b, 0x68, 0x90, 0xa7, 0xf7, 0x9d, 0x57, 0x71, 0x45, - 0x39, 0x86, 0x4c, 0xc0, 0x97, 0x34, 0x03, 0x9c, 0x2b, 0x25, - 0x05, 0xb1, 0x5c, 0x0c, 0x4e, 0xf2, 0x14, 0xbf, 0xcf, 0xf0, - 0x9a, 0x2d, 0xcf, 0x02, 0x47, 0x60, 0xd2, 0xe9, 0xed, 0xbf, - 0x71, 0x5d, 0x07, 0x09, 0x01, 0x87, 0xeb, 0xf7, 0xa8, 0x26, - 0x86, 0x24, 0x59, 0xf0, 0x31, 0x3b, 0x42, 0xd1, 0xf1, 0xfd, - 0x7c, 0x49, 0x5f, 0x1a, 0xf0, 0x41, 0x67, 0xf0, 0x16, 0x3a, - 0xfd, 0xb6, 0xb5, 0xf6, 0x2e, 0x0c, 0x18, 0x1f, 0x09, 0x8e, - 0x4d ), - FINGERPRINT ( 0xe0, 0xdb, 0x60, 0x53, 0x7c, 0xf6, 0x25, 0x8f, - 0xa7, 0xba, 0xdf, 0xe2, 0x1a, 0xfc, 0x27, 0x49, - 0xf6, 0x83, 0x15, 0xbd, 0x1b, 0x4c, 0x3f, 0x36, - 0x6f, 0x33, 0xf2, 0x47, 0x8e, 0x8b, 0x38, 0xa8 ) ); - /* * subject VeriSign Class 3 International Server CA - G3 * issuer VeriSign Class 3 Public Primary Certification Authority - G5 @@ -1193,14 +1118,16 @@ OCSP ( google_ocsp, &google_crt, &thawte_crt, 0x97, 0x85, 0xfb, 0x2a, 0xa3, 0x92, 0x65, 0x0b, 0x02, 0x58, 0x14, 0x89, 0x8f, 0x3b ) ); -OCSP ( unauthorized_ocsp, &server_crt, &thawte_crt, - DATA ( 0x30, 0x42, 0x30, 0x40, 0x30, 0x3e, 0x30, 0x3c, 0x30, 0x3a, +OCSP ( unauthorized_ocsp, &barclays_crt, &thawte_crt, + DATA ( 0x30, 0x51, 0x30, 0x4f, 0x30, 0x4d, 0x30, 0x4b, 0x30, 0x49, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, - 0x00, 0x04, 0x14, 0x68, 0x7a, 0xcf, 0x39, 0x5d, 0xdf, 0x7c, - 0x2c, 0x91, 0x6d, 0xdb, 0xcb, 0x9d, 0x0c, 0x27, 0x5b, 0x30, - 0x64, 0x28, 0xf2, 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91, + 0x00, 0x04, 0x14, 0xd4, 0xb4, 0x3b, 0x8e, 0x3d, 0x02, 0x49, + 0x1a, 0x65, 0x50, 0x6f, 0x96, 0x73, 0x14, 0xdd, 0xe8, 0x59, + 0x44, 0x52, 0xe4, 0x04, 0x14, 0x3b, 0x34, 0x9a, 0x70, 0x91, 0x73, 0xb2, 0x8a, 0x1b, 0x0c, 0xf4, 0xe9, 0x37, 0xcd, 0xb3, - 0x70, 0x32, 0x9e, 0x18, 0x54, 0x02, 0x01, 0x03 ), + 0x70, 0x32, 0x9e, 0x18, 0x54, 0x02, 0x10, 0x49, 0x83, 0xfc, + 0x05, 0x76, 0xdf, 0x36, 0x91, 0x7c, 0x64, 0x2a, 0x27, 0xc1, + 0xf1, 0x48, 0xe3 ), DATA ( 0x30, 0x03, 0x0a, 0x01, 0x06 ) ); OCSP ( unknown_ocsp, &thawte_crt, &startssl_crt, @@ -1468,7 +1395,6 @@ static void ocsp_test_exec ( void ) { /* Parse certificates */ ocsp_certificate_ok ( &barclays_crt ); ocsp_certificate_ok ( &google_crt ); - ocsp_certificate_ok ( &server_crt ); ocsp_certificate_ok ( &verisign_crt ); ocsp_certificate_ok ( &thawte_crt ); ocsp_certificate_ok ( &startssl_crt ); @@ -1509,7 +1435,6 @@ static void ocsp_test_exec ( void ) { x509_put ( startssl_crt.cert ); x509_put ( thawte_crt.cert ); x509_put ( verisign_crt.cert ); - x509_put ( server_crt.cert ); x509_put ( google_crt.cert ); x509_put ( barclays_crt.cert ); } From 89a354d55339fbf03d4b880b30111f9cba68ffff Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 00:44:49 +0100 Subject: [PATCH 018/250] [monojob] Allow monojob to be completely silent Signed-off-by: Michael Brown --- src/core/monojob.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/core/monojob.c b/src/core/monojob.c index 7431f88a..7917b427 100644 --- a/src/core/monojob.c +++ b/src/core/monojob.c @@ -53,7 +53,7 @@ struct interface monojob = INTF_INIT ( monojob_intf_desc ); /** * Wait for single foreground job to complete * - * @v string Job description to display + * @v string Job description to display, or NULL to be silent * @ret rc Job final status code */ int monojob_wait ( const char *string ) { @@ -67,7 +67,8 @@ int monojob_wait ( const char *string ) { unsigned int percentage; int shown_percentage = 0; - printf ( "%s...", string ); + if ( string ) + printf ( "%s...", string ); monojob_rc = -EINPROGRESS; last_progress = currticks(); while ( monojob_rc == -EINPROGRESS ) { @@ -83,7 +84,7 @@ int monojob_wait ( const char *string ) { } } elapsed = ( currticks() - last_progress ); - if ( elapsed >= TICKS_PER_SEC ) { + if ( string && ( elapsed >= TICKS_PER_SEC ) ) { if ( shown_percentage ) printf ( "\b\b\b\b \b\b\b\b" ); job_progress ( &monojob, &progress ); @@ -106,10 +107,13 @@ int monojob_wait ( const char *string ) { if ( shown_percentage ) printf ( "\b\b\b\b \b\b\b\b" ); - if ( rc ) { - printf ( " %s\n", strerror ( rc ) ); - } else { - printf ( " ok\n" ); + if ( string ) { + if ( rc ) { + printf ( " %s\n", strerror ( rc ) ); + } else { + printf ( " ok\n" ); + } } + return rc; } From 071171e807b26d6f16c880674b52a553f26ccd08 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 00:45:31 +0100 Subject: [PATCH 019/250] [image] Allow "imgtrust" to automatically download cross-signed certificates Signed-off-by: Michael Brown --- src/usr/imgtrust.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/usr/imgtrust.c b/src/usr/imgtrust.c index 651f0493..be0ca6ee 100644 --- a/src/usr/imgtrust.c +++ b/src/usr/imgtrust.c @@ -25,6 +25,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include /** @file @@ -46,6 +48,7 @@ int imgverify ( struct image *image, struct image *signature, size_t len; void *data; struct cms_signature *sig; + struct cms_signer_info *info; time_t now; int rc; @@ -69,6 +72,14 @@ int imgverify ( struct image *image, struct image *signature, free ( data ); data = NULL; + /* Complete all certificate chains */ + list_for_each_entry ( info, &sig->info, list ) { + if ( ( rc = create_validator ( &monojob, info->chain ) ) != 0 ) + goto err_create_validator; + if ( ( rc = monojob_wait ( NULL ) ) != 0 ) + goto err_validator_wait; + } + /* Use signature to verify image */ now = time ( NULL ); if ( ( rc = cms_verify ( sig, image->data, image->len, @@ -86,6 +97,8 @@ int imgverify ( struct image *image, struct image *signature, return 0; err_verify: + err_validator_wait: + err_create_validator: cms_put ( sig ); err_parse: free ( data ); From 073331c2ee7cf332c5df32bf9c74819cada848b9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 20 May 2012 16:46:00 +0100 Subject: [PATCH 020/250] [crypto] Automatically perform OCSP checks when applicable Signed-off-by: Michael Brown --- src/net/validator.c | 273 ++++++++++++++++++++++++++++++++------------ 1 file changed, 200 insertions(+), 73 deletions(-) diff --git a/src/net/validator.c b/src/net/validator.c index 80fecea8..c4051d48 100644 --- a/src/net/validator.c +++ b/src/net/validator.c @@ -35,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -51,12 +52,19 @@ struct validator { struct interface job; /** Data transfer interface */ struct interface xfer; + /** Process */ struct process process; + /** X.509 certificate chain */ struct x509_chain *chain; + /** OCSP check */ + struct ocsp_check *ocsp; /** Data buffer */ struct xfer_buffer buffer; + /** Action to take upon completed transfer */ + int ( * done ) ( struct validator *validator, const void *data, + size_t len ); }; /** @@ -70,6 +78,7 @@ static void validator_free ( struct refcnt *refcnt ) { DBGC2 ( validator, "VALIDATOR %p freed\n", validator ); x509_chain_put ( validator->chain ); + ocsp_put ( validator->ocsp ); xferbuf_done ( &validator->buffer ); free ( validator ); } @@ -122,72 +131,6 @@ struct setting crosscert_setting __setting ( SETTING_CRYPTO ) = { /** Default cross-signed certificate source */ static const char crosscert_default[] = "http://ca.ipxe.org/auto"; -/** - * Start download of cross-signing certificate - * - * @v validator Certificate validator - * @v issuer Required issuer - * @ret rc Return status code - */ -static int validator_start_download ( struct validator *validator, - const struct asn1_cursor *issuer ) { - const char *crosscert; - char *crosscert_copy; - char *uri_string; - size_t uri_string_len; - uint32_t crc; - int len; - int rc; - - /* Determine cross-signed certificate source */ - len = fetch_string_setting_copy ( NULL, &crosscert_setting, - &crosscert_copy ); - if ( len < 0 ) { - rc = len; - DBGC ( validator, "VALIDATOR %p could not fetch crosscert " - "setting: %s\n", validator, strerror ( rc ) ); - goto err_fetch_crosscert; - } - crosscert = ( crosscert_copy ? crosscert_copy : crosscert_default ); - - /* Allocate URI string */ - uri_string_len = ( strlen ( crosscert ) + 22 /* "/%08x.der?subject=" */ - + base64_encoded_len ( issuer->len ) + 1 /* NUL */ ); - uri_string = zalloc ( uri_string_len ); - if ( ! uri_string ) { - rc = -ENOMEM; - goto err_alloc_uri_string; - } - - /* Generate CRC32 */ - crc = crc32_le ( 0xffffffffUL, issuer->data, issuer->len ); - - /* Generate URI string */ - len = snprintf ( uri_string, uri_string_len, "%s/%08x.der?subject=", - crosscert, crc ); - base64_encode ( issuer->data, issuer->len, ( uri_string + len ) ); - DBGC ( validator, "VALIDATOR %p downloading cross-signed certificate " - "from %s\n", validator, uri_string ); - - /* Open URI */ - if ( ( rc = xfer_open_uri_string ( &validator->xfer, - uri_string ) ) != 0 ) { - DBGC ( validator, "VALIDATOR %p could not open %s: %s\n", - validator, uri_string, strerror ( rc ) ); - goto err_open_uri_string; - } - - /* Success */ - rc = 0; - - err_open_uri_string: - free ( uri_string ); - err_alloc_uri_string: - free ( crosscert_copy ); - err_fetch_crosscert: - return rc; -} - /** * Append cross-signing certificates to certificate chain * @@ -271,6 +214,155 @@ static int validator_append ( struct validator *validator, return rc; } +/** + * Start download of cross-signing certificate + * + * @v validator Certificate validator + * @v issuer Required issuer + * @ret rc Return status code + */ +static int validator_start_download ( struct validator *validator, + const struct asn1_cursor *issuer ) { + const char *crosscert; + char *crosscert_copy; + char *uri_string; + size_t uri_string_len; + uint32_t crc; + int len; + int rc; + + /* Determine cross-signed certificate source */ + len = fetch_string_setting_copy ( NULL, &crosscert_setting, + &crosscert_copy ); + if ( len < 0 ) { + rc = len; + DBGC ( validator, "VALIDATOR %p could not fetch crosscert " + "setting: %s\n", validator, strerror ( rc ) ); + goto err_fetch_crosscert; + } + crosscert = ( crosscert_copy ? crosscert_copy : crosscert_default ); + + /* Allocate URI string */ + uri_string_len = ( strlen ( crosscert ) + 22 /* "/%08x.der?subject=" */ + + base64_encoded_len ( issuer->len ) + 1 /* NUL */ ); + uri_string = zalloc ( uri_string_len ); + if ( ! uri_string ) { + rc = -ENOMEM; + goto err_alloc_uri_string; + } + + /* Generate CRC32 */ + crc = crc32_le ( 0xffffffffUL, issuer->data, issuer->len ); + + /* Generate URI string */ + len = snprintf ( uri_string, uri_string_len, "%s/%08x.der?subject=", + crosscert, crc ); + base64_encode ( issuer->data, issuer->len, ( uri_string + len ) ); + DBGC ( validator, "VALIDATOR %p downloading cross-signed certificate " + "from %s\n", validator, uri_string ); + + /* Set completion handler */ + validator->done = validator_append; + + /* Open URI */ + if ( ( rc = xfer_open_uri_string ( &validator->xfer, + uri_string ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not open %s: %s\n", + validator, uri_string, strerror ( rc ) ); + goto err_open_uri_string; + } + + /* Success */ + rc = 0; + + err_open_uri_string: + free ( uri_string ); + err_alloc_uri_string: + free ( crosscert_copy ); + err_fetch_crosscert: + return rc; +} + +/**************************************************************************** + * + * OCSP checks + * + */ + +/** + * Validate OCSP response + * + * @v validator Certificate validator + * @v data Raw OCSP response + * @v len Length of raw data + * @ret rc Return status code + */ +static int validator_ocsp_validate ( struct validator *validator, + const void *data, size_t len ) { + time_t now; + int rc; + + /* Record OCSP response */ + if ( ( rc = ocsp_response ( validator->ocsp, data, len ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not record OCSP " + "response: %s\n", validator, strerror ( rc ) ); + return rc; + } + + /* Validate OCSP response */ + now = time ( NULL ); + if ( ( rc = ocsp_validate ( validator->ocsp, now ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not validate OCSP " + "response: %s\n", validator, strerror ( rc ) ); + return rc; + } + + /* Drop reference to OCSP check */ + ocsp_put ( validator->ocsp ); + validator->ocsp = NULL; + + return 0; +} + +/** + * Start OCSP check + * + * @v validator Certificate validator + * @v cert Certificate to check + * @v issuer Issuing certificate + * @ret rc Return status code + */ +static int validator_start_ocsp ( struct validator *validator, + struct x509_certificate *cert, + struct x509_certificate *issuer ) { + const char *uri_string; + int rc; + + /* Create OCSP check */ + assert ( validator->ocsp == NULL ); + if ( ( rc = ocsp_check ( cert, issuer, &validator->ocsp ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not create OCSP check: " + "%s\n", validator, strerror ( rc ) ); + return rc; + } + + /* Set completion handler */ + validator->done = validator_ocsp_validate; + + /* Open URI */ + uri_string = validator->ocsp->uri_string; + DBGC ( validator, "VALIDATOR %p performing OCSP check at %s\n", + validator, uri_string ); + if ( ( rc = xfer_open_uri_string ( &validator->xfer, + uri_string ) ) != 0 ) { + DBGC ( validator, "VALIDATOR %p could not open %s: %s\n", + validator, uri_string, strerror ( rc ) ); + return rc; + } + + return 0; +} + /**************************************************************************** * * Data transfer interface @@ -290,14 +382,15 @@ static void validator_xfer_close ( struct validator *validator, int rc ) { /* Check for errors */ if ( rc != 0 ) { - DBGC ( validator, "VALIDATOR %p download failed: %s\n", + DBGC ( validator, "VALIDATOR %p transfer failed: %s\n", validator, strerror ( rc ) ); - goto err_download; + goto err_transfer; } - DBGC2 ( validator, "VALIDATOR %p download complete\n", validator ); + DBGC2 ( validator, "VALIDATOR %p transfer complete\n", validator ); - /* Append downloaded certificates */ - if ( ( rc = validator_append ( validator, validator->buffer.data, + /* Process completed download */ + assert ( validator->done != NULL ); + if ( ( rc = validator->done ( validator, validator->buffer.data, validator->buffer.len ) ) != 0 ) goto err_append; @@ -310,7 +403,7 @@ static void validator_xfer_close ( struct validator *validator, int rc ) { return; err_append: - err_download: + err_transfer: validator_finished ( validator, rc ); } @@ -361,7 +454,11 @@ static struct interface_descriptor validator_xfer_desc = * @v validator Certificate validator */ static void validator_step ( struct validator *validator ) { - struct x509_certificate *last = x509_last ( validator->chain ); + struct x509_link *link; + struct x509_link *previous; + struct x509_certificate *cert; + struct x509_certificate *issuer = NULL; + struct x509_certificate *last; time_t now; int rc; @@ -376,9 +473,39 @@ static void validator_step ( struct validator *validator ) { return; } + /* If there is a certificate that could be validated using + * OCSP, try it. + */ + list_for_each_entry ( link, &validator->chain->links, list ) { + cert = issuer; + issuer = link->cert; + previous = link; + if ( ! cert ) + continue; + if ( ! issuer->valid ) + continue; + /* The issuer is valid, but this certificate is not + * yet valid. If OCSP is applicable, start it. + */ + if ( cert->extensions.auth_info.ocsp.uri && + ( ! cert->extensions.auth_info.ocsp.good ) ) { + /* Start OCSP */ + if ( ( rc = validator_start_ocsp ( validator, cert, + issuer ) ) != 0 ) { + validator_finished ( validator, rc ); + return; + } + return; + } + /* Otherwise, this is a permanent failure */ + validator_finished ( validator, rc ); + return; + } + /* If chain ends with a self-issued certificate, then there is * nothing more to do. */ + last = x509_last ( validator->chain ); if ( asn1_compare ( &last->issuer.raw, &last->subject.raw ) == 0 ) { validator_finished ( validator, rc ); return; From 7fa1f41f7d3522349399fe1d1523a644b59f59de Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 00:53:44 +0100 Subject: [PATCH 021/250] [crypto] Require OCSP check if certificate provides an OCSP URI Signed-off-by: Michael Brown --- src/crypto/x509.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 2180173b..1a27eb24 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -98,6 +98,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); __einfo_error ( EINFO_EACCES_EMPTY ) #define EINFO_EACCES_EMPTY \ __einfo_uniqify ( EINFO_EACCES, 0x08, "Empty certificate chain" ) +#define EACCES_OCSP_REQUIRED \ + __einfo_error ( EINFO_EACCES_OCSP_REQUIRED ) +#define EINFO_EACCES_OCSP_REQUIRED \ + __einfo_uniqify ( EINFO_EACCES, 0x09, "OCSP check required" ) /** Certificate cache */ static LIST_HEAD ( x509_cache ); @@ -1343,6 +1347,14 @@ int x509_validate ( struct x509_certificate *cert, return -EACCES_PATH_LEN; } + /* Fail if OCSP is required */ + if ( cert->extensions.auth_info.ocsp.uri && + ( ! cert->extensions.auth_info.ocsp.good ) ) { + DBGC ( cert, "X509 %p \"%s\" requires an OCSP check\n", + cert, cert->subject.name ); + return -EACCES_OCSP_REQUIRED; + } + /* Calculate effective path length */ cert->path_remaining = ( issuer->path_remaining - 1 ); max_path_remaining = ( cert->extensions.basic.path_len + 1 ); From 4fa1a2b4fe7f49b46c44fb3985984efd7dec212d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 01:09:34 +0100 Subject: [PATCH 022/250] [crypto] Rename KEY= to PRIVKEY= and "key" to "privkey" The setting name "key" conflicts with the setting name "key" already in use by the 802.11 code. Resolve the conflict by renaming the newer setting to "privkey". Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 33 ++++++++++++++++++--------------- src/crypto/clientcert.c | 6 +++--- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index d2b4ee38..9cfb8a3e 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -608,36 +608,39 @@ CFLAGS_clientcert += $(if $(CERT),-DCERTIFICATE="\"$(CERT_INC)\"") # (Single-element) list of client private keys # -KEY_LIST := $(BIN)/.private_key.list -ifeq ($(wildcard $(KEY_LIST)),) -KEY_OLD := +ifdef KEY +PRIVKEY := $(KEY) # Maintain backwards compatibility +endif +PRIVKEY_LIST := $(BIN)/.private_key.list +ifeq ($(wildcard $(PRIVKEY_LIST)),) +PRIVKEY_OLD := else -KEY_OLD := $(shell cat $(KEY_LIST)) +PRIVKEY_OLD := $(shell cat $(PRIVKEY_LIST)) endif -ifneq ($(KEY_OLD),$(KEY)) -$(shell $(ECHO) "$(KEY)" > $(KEY_LIST)) +ifneq ($(PRIVKEY_OLD),$(PRIVKEY)) +$(shell $(ECHO) "$(PRIVKEY)" > $(PRIVKEY_LIST)) endif -$(KEY_LIST) : +$(PRIVKEY_LIST) : -VERYCLEANUP += $(KEY_LIST) +VERYCLEANUP += $(PRIVKEY_LIST) # Embedded client private key # -KEY_INC := $(BIN)/.private_key.der +PRIVKEY_INC := $(BIN)/.private_key.der -ifdef KEY -$(KEY_INC) : $(KEY) $(KEY_LIST) +ifdef PRIVKEY +$(PRIVKEY_INC) : $(PRIVKEY) $(PRIVKEY_LIST) $(Q)$(OPENSSL) rsa -in $< -outform DER -out $@ -clientcert_DEPS += $(KEY_INC) +clientcert_DEPS += $(PRIVKEY_INC) endif -CLEANUP += $(KEY_INC) +CLEANUP += $(PRIVKEY_INC) -clientcert_DEPS += $(KEY_LIST) +clientcert_DEPS += $(PRIVKEY_LIST) -CFLAGS_clientcert += $(if $(KEY),-DPRIVATE_KEY="\"$(KEY_INC)\"") +CFLAGS_clientcert += $(if $(PRIVKEY),-DPRIVATE_KEY="\"$(PRIVKEY_INC)\"") # These files use .incbin inline assembly to include a binary file. # Unfortunately ccache does not detect this dependency and caches diff --git a/src/crypto/clientcert.c b/src/crypto/clientcert.c index 159a3f4e..01ab2e38 100644 --- a/src/crypto/clientcert.c +++ b/src/crypto/clientcert.c @@ -99,8 +99,8 @@ static struct setting cert_setting __setting ( SETTING_CRYPTO ) = { }; /** Client private key setting */ -static struct setting key_setting __setting ( SETTING_CRYPTO ) = { - .name = "key", +static struct setting privkey_setting __setting ( SETTING_CRYPTO ) = { + .name = "privkey", .description = "Client private key", .tag = DHCP_EB_KEY, .type = &setting_type_hex, @@ -146,7 +146,7 @@ static int clientcert_apply_settings ( void ) { /* Fetch new client private key, if any */ free ( key ); - len = fetch_setting_copy ( NULL, &key_setting, &key ); + len = fetch_setting_copy ( NULL, &privkey_setting, &key ); if ( len < 0 ) { rc = len; DBGC ( &client_certificate, "CLIENTCERT cannot fetch " From 8a5ba6733d066ff302264ed2f9c3e8adf7146453 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 11:17:50 +0100 Subject: [PATCH 023/250] [http] Reopen connections when server does not keep connection alive Signed-off-by: Michael Brown --- src/net/tcp/httpcore.c | 149 ++++++++++++++++++++++++++++++++--------- 1 file changed, 118 insertions(+), 31 deletions(-) diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index d0ad952e..95e132f9 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -57,6 +57,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH ) #define EINFO_EIO_CONTENT_LENGTH \ __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" ) +#define EIO_CHUNK __einfo_error ( EINFO_EIO_CHUNK ) +#define EINFO_EIO_CHUNK \ + __einfo_uniqify ( EINFO_EIO, 0x03, "Terminated mid-chunk" ) #define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE ) #define EINFO_EINVAL_RESPONSE \ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" ) @@ -88,8 +91,10 @@ enum http_flags { HTTP_TX_PENDING = 0x0001, /** Fetch header only */ HTTP_HEAD_ONLY = 0x0002, - /** Keep connection alive */ - HTTP_KEEPALIVE = 0x0004, + /** Client would like to keep connection alive */ + HTTP_CLIENT_KEEPALIVE = 0x0004, + /** Server will keep connection alive */ + HTTP_SERVER_KEEPALIVE = 0x0008, }; /** HTTP receive state */ @@ -117,6 +122,12 @@ struct http_request { /** URI being fetched */ struct uri *uri; + /** Default port */ + unsigned int default_port; + /** Filter (if any) */ + int ( * filter ) ( struct interface *xfer, + const char *name, + struct interface **next ); /** Transport layer interface */ struct interface socket; @@ -171,15 +182,8 @@ static void http_close ( struct http_request *http, int rc ) { /* Prevent further processing of any current packet */ http->rx_state = HTTP_RX_DEAD; - /* If we had a Content-Length, and the received content length - * isn't correct, flag an error - */ - if ( http->remaining != 0 ) { - DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n", - http, http->rx_len, ( http->rx_len + http->remaining ) ); - if ( rc == 0 ) - rc = -EIO_CONTENT_LENGTH; - } + /* Prevent reconnection */ + http->flags &= ~HTTP_CLIENT_KEEPALIVE; /* Remove process */ process_del ( &http->process ); @@ -190,17 +194,55 @@ static void http_close ( struct http_request *http, int rc ) { intf_shutdown ( &http->xfer, rc ); } +/** + * Open HTTP socket + * + * @v http HTTP request + * @ret rc Return status code + */ +static int http_socket_open ( struct http_request *http ) { + struct uri *uri = http->uri; + struct sockaddr_tcpip server; + struct interface *socket; + int rc; + + /* Open socket */ + memset ( &server, 0, sizeof ( server ) ); + server.st_port = htons ( uri_port ( uri, http->default_port ) ); + socket = &http->socket; + if ( http->filter ) { + if ( ( rc = http->filter ( socket, uri->host, &socket ) ) != 0 ) + return rc; + } + if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM, + ( struct sockaddr * ) &server, + uri->host, NULL ) ) != 0 ) + return rc; + + return 0; +} + /** * Mark HTTP request as completed successfully * * @v http HTTP request */ static void http_done ( struct http_request *http ) { + int rc; + + /* If we are in the middle of a chunked transfer, force an error */ + if ( http->chunked ) { + DBGC ( http, "HTTP %p terminated mid-chunk\n", http ); + http_close ( http, -EIO_CHUNK ); + return; + } /* If we had a Content-Length, and the received content length * isn't correct, force an error */ if ( http->remaining != 0 ) { + DBGC ( http, "HTTP %p incorrect length %zd, should be %zd\n", + http, http->rx_len, ( http->rx_len + http->remaining ) ); http_close ( http, -EIO_CONTENT_LENGTH ); return; } @@ -215,9 +257,24 @@ static void http_done ( struct http_request *http ) { /* Close partial transfer interface */ intf_restart ( &http->partial, 0 ); - /* Close everything unless we are keeping the connection alive */ - if ( ! ( http->flags & HTTP_KEEPALIVE ) ) + /* Close everything unless we want to keep the connection alive */ + if ( ! ( http->flags & HTTP_CLIENT_KEEPALIVE ) ) { http_close ( http, 0 ); + return; + } + + /* If the server is not intending to keep the connection + * alive, then reopen the socket. + */ + if ( ! ( http->flags & HTTP_SERVER_KEEPALIVE ) ) { + DBGC ( http, "HTTP %p reopening connection\n", http ); + intf_restart ( &http->socket, 0 ); + if ( ( rc = http_socket_open ( http ) ) != 0 ) { + http_close ( http, rc ); + return; + } + } + http->flags &= ~HTTP_SERVER_KEEPALIVE; } /** @@ -354,7 +411,7 @@ static int http_rx_content_length ( struct http_request *http, static int http_rx_transfer_encoding ( struct http_request *http, const char *value ) { - if ( strcmp ( value, "chunked" ) == 0 ) { + if ( strcasecmp ( value, "chunked" ) == 0 ) { /* Mark connection as using chunked transfer encoding */ http->chunked = 1; } @@ -362,6 +419,23 @@ static int http_rx_transfer_encoding ( struct http_request *http, return 0; } +/** + * Handle HTTP Connection header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_connection ( struct http_request *http, const char *value ) { + + if ( strcasecmp ( value, "keep-alive" ) == 0 ) { + /* Mark connection as being kept alive by the server */ + http->flags |= HTTP_SERVER_KEEPALIVE; + } + + return 0; +} + /** An HTTP header handler */ struct http_header_handler { /** Name (e.g. "Content-Length") */ @@ -391,6 +465,10 @@ static struct http_header_handler http_header_handlers[] = { .header = "Transfer-Encoding", .rx = http_rx_transfer_encoding, }, + { + .header = "Connection", + .rx = http_rx_connection, + }, { NULL, NULL } }; @@ -630,6 +708,24 @@ static size_t http_socket_window ( struct http_request *http __unused ) { return ( ~( ( size_t ) 0 ) ); } +/** + * Close HTTP socket + * + * @v http HTTP request + * @v rc Reason for close + */ +static void http_socket_close ( struct http_request *http, int rc ) { + + /* If we have an error, terminate */ + if ( rc != 0 ) { + http_close ( http, rc ); + return; + } + + /* Mark HTTP request as complete */ + http_done ( http ); +} + /** * HTTP process * @@ -688,7 +784,7 @@ static void http_step ( struct http_request *http ) { /* Force a HEAD request if we have nowhere to send any received data */ if ( ( xfer_window ( &http->xfer ) == 0 ) && ( http->rx_buffer == UNULL ) ) { - http->flags |= ( HTTP_HEAD_ONLY | HTTP_KEEPALIVE ); + http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE ); } /* Determine type of request */ @@ -715,8 +811,8 @@ static void http_step ( struct http_request *http ) { ":" : "" ), ( http->uri->port ? http->uri->port : "" ), - ( ( http->flags & HTTP_KEEPALIVE ) ? - "Connection: Keep-Alive\r\n" : "" ), + ( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ? + "Connection: keep-alive\r\n" : "" ), ( partial ? "Range: bytes=" : "" ), ( partial ? dynamic->range : "" ), ( partial ? "\r\n" : "" ), @@ -772,7 +868,7 @@ static int http_partial_read ( struct http_request *http, /* Schedule request */ http->rx_state = HTTP_RX_RESPONSE; - http->flags = ( HTTP_TX_PENDING | HTTP_KEEPALIVE ); + http->flags = ( HTTP_TX_PENDING | HTTP_CLIENT_KEEPALIVE ); if ( ! len ) http->flags |= HTTP_HEAD_ONLY; process_add ( &http->process ); @@ -840,7 +936,7 @@ static struct interface_operation http_socket_operations[] = { INTF_OP ( xfer_window, struct http_request *, http_socket_window ), INTF_OP ( xfer_deliver, struct http_request *, http_socket_deliver ), INTF_OP ( xfer_window_changed, struct http_request *, http_step ), - INTF_OP ( intf_close, struct http_request *, http_close ), + INTF_OP ( intf_close, struct http_request *, http_socket_close ), }; /** HTTP socket interface descriptor */ @@ -891,8 +987,6 @@ int http_open_filter ( struct interface *xfer, struct uri *uri, const char *name, struct interface **next ) ) { struct http_request *http; - struct sockaddr_tcpip server; - struct interface *socket; int rc; /* Sanity checks */ @@ -907,21 +1001,14 @@ int http_open_filter ( struct interface *xfer, struct uri *uri, intf_init ( &http->xfer, &http_xfer_desc, &http->refcnt ); intf_init ( &http->partial, &http_partial_desc, &http->refcnt ); http->uri = uri_get ( uri ); + http->default_port = default_port; + http->filter = filter; intf_init ( &http->socket, &http_socket_desc, &http->refcnt ); process_init ( &http->process, &http_process_desc, &http->refcnt ); http->flags = HTTP_TX_PENDING; /* Open socket */ - memset ( &server, 0, sizeof ( server ) ); - server.st_port = htons ( uri_port ( http->uri, default_port ) ); - socket = &http->socket; - if ( filter ) { - if ( ( rc = filter ( socket, uri->host, &socket ) ) != 0 ) - goto err; - } - if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM, - ( struct sockaddr * ) &server, - uri->host, NULL ) ) != 0 ) + if ( ( rc = http_socket_open ( http ) ) != 0 ) goto err; /* Attach to parent interface, mortalise self, and return */ From 46df5c92a86a3a72b5f415d05260acc315fe56c0 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 12:23:34 +0100 Subject: [PATCH 024/250] [http] Defer processing response code until after receiving all headers Some headers can modify the meaning of the response code. For example, a WWW-Authenticate header can change the interpretation of a 401 Unauthorized response from "Access denied" to "Please authenticate". Signed-off-by: Michael Brown --- src/net/tcp/httpcore.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 95e132f9..27d32bfd 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -143,6 +143,8 @@ struct http_request { /** RX state */ enum http_rx_state rx_state; + /** Response code */ + unsigned int code; /** Received length */ size_t rx_len; /** Length remaining (or 0 if unknown) */ @@ -311,8 +313,6 @@ static int http_response_to_rc ( unsigned int response ) { */ static int http_rx_response ( struct http_request *http, char *response ) { char *spc; - unsigned int code; - int rc; DBGC ( http, "HTTP %p response \"%s\"\n", http, response ); @@ -320,13 +320,11 @@ static int http_rx_response ( struct http_request *http, char *response ) { if ( strncmp ( response, "HTTP/", 5 ) != 0 ) return -EINVAL_RESPONSE; - /* Locate and check response code */ + /* Locate and store response code */ spc = strchr ( response, ' ' ); if ( ! spc ) return -EINVAL_RESPONSE; - code = strtoul ( spc, NULL, 10 ); - if ( ( rc = http_response_to_rc ( code ) ) != 0 ) - return rc; + http->code = strtoul ( spc, NULL, 10 ); /* Move to received headers */ http->rx_state = HTTP_RX_HEADER; @@ -488,6 +486,12 @@ static int http_rx_header ( struct http_request *http, char *header ) { /* An empty header line marks the end of this phase */ if ( ! header[0] ) { empty_line_buffer ( &http->linebuf ); + + /* Handle response code */ + if ( ( rc = http_response_to_rc ( http->code ) ) != 0 ) + return rc; + + /* Move to next state */ if ( ( http->rx_state == HTTP_RX_HEADER ) && ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) { DBGC ( http, "HTTP %p start of data\n", http ); From 8f5d44b5c6b12964e2678739a24f45da1c5d2c11 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 14:14:35 +0100 Subject: [PATCH 025/250] [http] Split construction of Authorization header out of http_step() Signed-off-by: Michael Brown --- src/net/tcp/httpcore.c | 159 +++++++++++++++++++++++++---------------- 1 file changed, 99 insertions(+), 60 deletions(-) diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 27d32bfd..52989514 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -730,28 +730,57 @@ static void http_socket_close ( struct http_request *http, int rc ) { http_done ( http ); } +/** + * Generate HTTP Basic authorisation string + * + * @v http HTTP request + * @ret auth Authorisation string, or NULL on error + * + * The authorisation string is dynamically allocated, and must be + * freed by the caller. + */ +static char * http_basic_auth ( struct http_request *http ) { + const char *user = http->uri->user; + const char *password = + ( http->uri->password ? http->uri->password : "" ); + size_t user_pw_len = + ( strlen ( user ) + 1 /* ":" */ + strlen ( password ) ); + char user_pw[ user_pw_len + 1 /* NUL */ ]; + size_t user_pw_base64_len = base64_encoded_len ( user_pw_len ); + char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ]; + char *auth; + int len; + + /* Sanity check */ + assert ( user != NULL ); + + /* Make "user:password" string from decoded fields */ + snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", user, password ); + + /* Base64-encode the "user:password" string */ + base64_encode ( ( void * ) user_pw, user_pw_len, user_pw_base64 ); + + /* Generate the authorisation string */ + len = asprintf ( &auth, "Authorization: Basic %s\r\n", + user_pw_base64 ); + if ( len < 0 ) + return NULL; + + return auth; +} + /** * HTTP process * * @v http HTTP request */ static void http_step ( struct http_request *http ) { - const char *host = http->uri->host; - const char *user = http->uri->user; - const char *password = - ( http->uri->password ? http->uri->password : "" ); - size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ + - strlen ( password ) ) : 0 ); - size_t user_pw_base64_len = base64_encoded_len ( user_pw_len ); - int request_len = unparse_uri ( NULL, 0, http->uri, - URI_PATH_BIT | URI_QUERY_BIT ); - struct { - uint8_t user_pw[ user_pw_len + 1 /* NUL */ ]; - char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ]; - char request[ request_len + 1 /* NUL */ ]; - char range[48]; /* Enough for two 64-bit integers in decimal */ - } *dynamic; - int partial; + size_t uri_len; + char *method; + char *uri; + char *range; + char *auth; + int len; int rc; /* Do nothing if we have already transmitted the request */ @@ -762,74 +791,84 @@ static void http_step ( struct http_request *http ) { if ( ! xfer_window ( &http->socket ) ) return; - /* Allocate dynamic storage */ - dynamic = malloc ( sizeof ( *dynamic ) ); - if ( ! dynamic ) { - rc = -ENOMEM; - goto err_alloc; - } - - /* Construct path?query request */ - unparse_uri ( dynamic->request, sizeof ( dynamic->request ), http->uri, - URI_PATH_BIT | URI_QUERY_BIT ); - - /* Construct authorisation, if applicable */ - if ( user ) { - /* Make "user:password" string from decoded fields */ - snprintf ( ( ( char * ) dynamic->user_pw ), - sizeof ( dynamic->user_pw ), "%s:%s", - user, password ); - - /* Base64-encode the "user:password" string */ - base64_encode ( dynamic->user_pw, user_pw_len, - dynamic->user_pw_base64 ); - } - /* Force a HEAD request if we have nowhere to send any received data */ if ( ( xfer_window ( &http->xfer ) == 0 ) && ( http->rx_buffer == UNULL ) ) { http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE ); } - /* Determine type of request */ - partial = ( http->partial_len != 0 ); - snprintf ( dynamic->range, sizeof ( dynamic->range ), - "%zd-%zd", http->partial_start, - ( http->partial_start + http->partial_len - 1 ) ); + /* Determine method */ + method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : "GET" ); + + /* Construct path?query request */ + uri_len = ( unparse_uri ( NULL, 0, http->uri, + URI_PATH_BIT | URI_QUERY_BIT ) + + 1 /* possible "/" */ + 1 /* NUL */ ); + uri = malloc ( uri_len ); + if ( ! uri ) { + rc = -ENOMEM; + goto err_uri; + } + unparse_uri ( uri, uri_len, http->uri, URI_PATH_BIT | URI_QUERY_BIT ); + if ( ! uri[0] ) { + uri[0] = '/'; + uri[1] = '\0'; + } + + /* Calculate range request parameters if applicable */ + if ( http->partial_len ) { + len = asprintf ( &range, "Range: bytes=%zd-%zd\r\n", + http->partial_start, + ( http->partial_start + http->partial_len + - 1 ) ); + if ( len < 0 ) { + rc = len; + goto err_range; + } + } else { + range = NULL; + } + + /* Construct authorisation, if applicable */ + if ( http->uri->user ) { + auth = http_basic_auth ( http ); + if ( ! auth ) { + rc = -ENOMEM; + goto err_auth; + } + } else { + auth = NULL; + } /* Mark request as transmitted */ http->flags &= ~HTTP_TX_PENDING; - /* Send GET request */ + /* Send request */ if ( ( rc = xfer_printf ( &http->socket, - "%s %s%s HTTP/1.1\r\n" + "%s %s HTTP/1.1\r\n" "User-Agent: iPXE/" VERSION "\r\n" "Host: %s%s%s\r\n" - "%s%s%s%s%s%s%s" + "%s%s%s" "\r\n", - ( ( http->flags & HTTP_HEAD_ONLY ) ? - "HEAD" : "GET" ), - ( http->uri->path ? "" : "/" ), - dynamic->request, host, + method, uri, http->uri->host, ( http->uri->port ? ":" : "" ), ( http->uri->port ? http->uri->port : "" ), ( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ? "Connection: keep-alive\r\n" : "" ), - ( partial ? "Range: bytes=" : "" ), - ( partial ? dynamic->range : "" ), - ( partial ? "\r\n" : "" ), - ( user ? - "Authorization: Basic " : "" ), - ( user ? dynamic->user_pw_base64 : "" ), - ( user ? "\r\n" : "" ) ) ) != 0 ) { + ( range ? range : "" ), + ( auth ? auth : "" ) ) ) != 0 ) { goto err_xfer; } err_xfer: - free ( dynamic ); - err_alloc: + free ( auth ); + err_auth: + free ( range ); + err_range: + free ( uri ); + err_uri: if ( rc != 0 ) http_close ( http, rc ); } From 5f2226aa3664d20b72ba622a4425d040390eaf2e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 12:32:28 +0100 Subject: [PATCH 026/250] [http] Provide credentials only when requested by server Provide HTTP Basic authentication credentials only in response to a 401 Unauthorized response from the server. Signed-off-by: Michael Brown --- src/net/tcp/httpcore.c | 144 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 128 insertions(+), 16 deletions(-) diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 52989514..1eebf683 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -95,6 +95,10 @@ enum http_flags { HTTP_CLIENT_KEEPALIVE = 0x0004, /** Server will keep connection alive */ HTTP_SERVER_KEEPALIVE = 0x0008, + /** Discard the current request and try again */ + HTTP_TRY_AGAIN = 0x0010, + /** Provide Basic authentication details */ + HTTP_BASIC_AUTH = 0x0020, }; /** HTTP receive state */ @@ -257,10 +261,11 @@ static void http_done ( struct http_request *http ) { assert ( http->chunk_remaining == 0 ); /* Close partial transfer interface */ - intf_restart ( &http->partial, 0 ); + if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) + intf_restart ( &http->partial, 0 ); /* Close everything unless we want to keep the connection alive */ - if ( ! ( http->flags & HTTP_CLIENT_KEEPALIVE ) ) { + if ( ! ( http->flags & ( HTTP_CLIENT_KEEPALIVE | HTTP_TRY_AGAIN ) ) ) { http_close ( http, 0 ); return; } @@ -277,6 +282,14 @@ static void http_done ( struct http_request *http ) { } } http->flags &= ~HTTP_SERVER_KEEPALIVE; + + /* Retry the request if applicable */ + if ( http->flags & HTTP_TRY_AGAIN ) { + http->flags &= ~HTTP_TRY_AGAIN; + http->flags |= HTTP_TX_PENDING; + http->rx_state = HTTP_RX_RESPONSE; + process_add ( &http->process ); + } } /** @@ -338,7 +351,7 @@ static int http_rx_response ( struct http_request *http, char *response ) { * @v value HTTP header value * @ret rc Return status code */ -static int http_rx_location ( struct http_request *http, const char *value ) { +static int http_rx_location ( struct http_request *http, char *value ) { int rc; /* Redirect to new location */ @@ -360,8 +373,7 @@ static int http_rx_location ( struct http_request *http, const char *value ) { * @v value HTTP header value * @ret rc Return status code */ -static int http_rx_content_length ( struct http_request *http, - const char *value ) { +static int http_rx_content_length ( struct http_request *http, char *value ) { struct block_device_capacity capacity; size_t content_len; char *endp; @@ -385,6 +397,10 @@ static int http_rx_content_length ( struct http_request *http, if ( ! ( http->flags & HTTP_HEAD_ONLY ) ) http->remaining = content_len; + /* Do nothing more if we are retrying the request */ + if ( http->flags & HTTP_TRY_AGAIN ) + return 0; + /* Use seek() to notify recipient of filesize */ xfer_seek ( &http->xfer, http->remaining ); xfer_seek ( &http->xfer, 0 ); @@ -406,8 +422,7 @@ static int http_rx_content_length ( struct http_request *http, * @v value HTTP header value * @ret rc Return status code */ -static int http_rx_transfer_encoding ( struct http_request *http, - const char *value ) { +static int http_rx_transfer_encoding ( struct http_request *http, char *value ){ if ( strcasecmp ( value, "chunked" ) == 0 ) { /* Mark connection as using chunked transfer encoding */ @@ -424,7 +439,7 @@ static int http_rx_transfer_encoding ( struct http_request *http, * @v value HTTP header value * @ret rc Return status code */ -static int http_rx_connection ( struct http_request *http, const char *value ) { +static int http_rx_connection ( struct http_request *http, char *value ) { if ( strcasecmp ( value, "keep-alive" ) == 0 ) { /* Mark connection as being kept alive by the server */ @@ -434,6 +449,88 @@ static int http_rx_connection ( struct http_request *http, const char *value ) { return 0; } +/** + * Handle WWW-Authenticate Basic header + * + * @v http HTTP request + * @v params Parameters + * @ret rc Return status code + */ +static int http_rx_basic_auth ( struct http_request *http, char *params ) { + + DBGC ( http, "HTTP %p Basic authentication required (%s)\n", + http, params ); + + /* If we received a 401 Unauthorized response, then retry + * using Basic authentication + */ + if ( ( http->code == 401 ) && + ( ! ( http->flags & HTTP_BASIC_AUTH ) ) && + ( http->uri->user != NULL ) ) { + http->flags |= ( HTTP_TRY_AGAIN | HTTP_BASIC_AUTH ); + } + + return 0; +} + +/** An HTTP WWW-Authenticate header handler */ +struct http_auth_header_handler { + /** Scheme (e.g. "Basic") */ + const char *scheme; + /** Handle received parameters + * + * @v http HTTP request + * @v params Parameters + * @ret rc Return status code + */ + int ( * rx ) ( struct http_request *http, char *params ); +}; + +/** List of HTTP WWW-Authenticate header handlers */ +static struct http_auth_header_handler http_auth_header_handlers[] = { + { + .scheme = "Basic", + .rx = http_rx_basic_auth, + }, + { NULL, NULL }, +}; + +/** + * Handle HTTP WWW-Authenticate header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_www_authenticate ( struct http_request *http, char *value ) { + struct http_auth_header_handler *handler; + char *separator; + char *scheme; + char *params; + int rc; + + /* Extract scheme */ + separator = strchr ( value, ' ' ); + if ( ! separator ) { + DBGC ( http, "HTTP %p malformed WWW-Authenticate header\n", + http ); + return -EINVAL_HEADER; + } + *separator = '\0'; + scheme = value; + params = ( separator + 1 ); + + /* Hand off to header handler, if one exists */ + for ( handler = http_auth_header_handlers; handler->scheme; handler++ ){ + if ( strcasecmp ( scheme, handler->scheme ) == 0 ) { + if ( ( rc = handler->rx ( http, params ) ) != 0 ) + return rc; + break; + } + } + return 0; +} + /** An HTTP header handler */ struct http_header_handler { /** Name (e.g. "Content-Length") */ @@ -446,7 +543,7 @@ struct http_header_handler { * * If an error is returned, the download will be aborted. */ - int ( * rx ) ( struct http_request *http, const char *value ); + int ( * rx ) ( struct http_request *http, char *value ); }; /** List of HTTP header handlers */ @@ -467,6 +564,10 @@ static struct http_header_handler http_header_handlers[] = { .header = "Connection", .rx = http_rx_connection, }, + { + .header = "WWW-Authenticate", + .rx = http_rx_www_authenticate, + }, { NULL, NULL } }; @@ -488,8 +589,10 @@ static int http_rx_header ( struct http_request *http, char *header ) { empty_line_buffer ( &http->linebuf ); /* Handle response code */ - if ( ( rc = http_response_to_rc ( http->code ) ) != 0 ) - return rc; + if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) { + if ( ( rc = http_response_to_rc ( http->code ) ) != 0 ) + return rc; + } /* Move to next state */ if ( ( http->rx_state == HTTP_RX_HEADER ) && @@ -497,6 +600,10 @@ static int http_rx_header ( struct http_request *http, char *header ) { DBGC ( http, "HTTP %p start of data\n", http ); http->rx_state = ( http->chunked ? HTTP_RX_CHUNK_LEN : HTTP_RX_DATA ); + if ( ( http->partial_len != 0 ) && + ( ! ( http->flags & HTTP_TRY_AGAIN ) ) ) { + http->remaining = http->partial_len; + } return 0; } else { DBGC ( http, "HTTP %p end of trailer\n", http ); @@ -560,8 +667,11 @@ static int http_rx_chunk_len ( struct http_request *http, char *length ) { /* Use seek() to notify recipient of new filesize */ DBGC ( http, "HTTP %p start of chunk of length %zd\n", http, http->chunk_remaining ); - xfer_seek ( &http->xfer, ( http->rx_len + http->chunk_remaining ) ); - xfer_seek ( &http->xfer, http->rx_len ); + if ( ! ( http->flags & HTTP_TRY_AGAIN ) ) { + xfer_seek ( &http->xfer, + ( http->rx_len + http->chunk_remaining ) ); + xfer_seek ( &http->xfer, http->rx_len ); + } /* Start receiving data */ http->rx_state = HTTP_RX_DATA; @@ -630,7 +740,10 @@ static int http_socket_deliver ( struct http_request *http, ( http->remaining < data_len ) ) { data_len = http->remaining; } - if ( http->rx_buffer != UNULL ) { + if ( http->flags & HTTP_TRY_AGAIN ) { + /* Discard all received data */ + iob_pull ( iobuf, data_len ); + } else if ( http->rx_buffer != UNULL ) { /* Copy to partial transfer buffer */ copy_to_user ( http->rx_buffer, http->rx_len, iobuf->data, data_len ); @@ -830,7 +943,7 @@ static void http_step ( struct http_request *http ) { } /* Construct authorisation, if applicable */ - if ( http->uri->user ) { + if ( http->flags & HTTP_BASIC_AUTH ) { auth = http_basic_auth ( http ); if ( ! auth ) { rc = -ENOMEM; @@ -907,7 +1020,6 @@ static int http_partial_read ( struct http_request *http, http->rx_buffer = buffer; http->partial_start = offset; http->partial_len = len; - http->remaining = len; /* Schedule request */ http->rx_state = HTTP_RX_RESPONSE; From 658c25aa8260f87eb9a2a0c5ca586376026d0d03 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 22 May 2012 23:10:59 +0100 Subject: [PATCH 027/250] [http] Add support for Digest authentication Signed-off-by: Michael Brown --- src/net/tcp/httpcore.c | 173 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 1eebf683..70f2a2a3 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -43,6 +43,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include #include #include @@ -99,6 +101,8 @@ enum http_flags { HTTP_TRY_AGAIN = 0x0010, /** Provide Basic authentication details */ HTTP_BASIC_AUTH = 0x0020, + /** Provide Digest authentication details */ + HTTP_DIGEST_AUTH = 0x0040, }; /** HTTP receive state */ @@ -161,6 +165,13 @@ struct http_request { struct line_buffer linebuf; /** Receive data buffer (if applicable) */ userptr_t rx_buffer; + + /** Authentication realm (if any) */ + char *auth_realm; + /** Authentication nonce (if any) */ + char *auth_nonce; + /** Authentication opaque string (if any) */ + char *auth_opaque; }; /** @@ -174,6 +185,9 @@ static void http_free ( struct refcnt *refcnt ) { uri_put ( http->uri ); empty_line_buffer ( &http->linebuf ); + free ( http->auth_realm ); + free ( http->auth_nonce ); + free ( http->auth_opaque ); free ( http ); }; @@ -473,6 +487,81 @@ static int http_rx_basic_auth ( struct http_request *http, char *params ) { return 0; } +/** + * Parse Digest authentication parameter + * + * @v params Parameters + * @v name Parameter name (including trailing "=\"") + * @ret value Parameter value, or NULL + */ +static char * http_digest_param ( char *params, const char *name ) { + char *key; + char *value; + char *terminator; + + /* Locate parameter */ + key = strstr ( params, name ); + if ( ! key ) + return NULL; + + /* Extract value */ + value = ( key + strlen ( name ) ); + terminator = strchr ( value, '"' ); + if ( ! terminator ) + return NULL; + return strndup ( value, ( terminator - value ) ); +} + +/** + * Handle WWW-Authenticate Digest header + * + * @v http HTTP request + * @v params Parameters + * @ret rc Return status code + */ +static int http_rx_digest_auth ( struct http_request *http, char *params ) { + + DBGC ( http, "HTTP %p Digest authentication required (%s)\n", + http, params ); + + /* If we received a 401 Unauthorized response, then retry + * using Digest authentication + */ + if ( ( http->code == 401 ) && + ( ! ( http->flags & HTTP_DIGEST_AUTH ) ) && + ( http->uri->user != NULL ) ) { + + /* Extract realm */ + free ( http->auth_realm ); + http->auth_realm = http_digest_param ( params, "realm=\"" ); + if ( ! http->auth_realm ) { + DBGC ( http, "HTTP %p Digest prompt missing realm\n", + http ); + return -EINVAL_HEADER; + } + + /* Extract nonce */ + free ( http->auth_nonce ); + http->auth_nonce = http_digest_param ( params, "nonce=\"" ); + if ( ! http->auth_nonce ) { + DBGC ( http, "HTTP %p Digest prompt missing nonce\n", + http ); + return -EINVAL_HEADER; + } + + /* Extract opaque */ + free ( http->auth_opaque ); + http->auth_opaque = http_digest_param ( params, "opaque=\"" ); + if ( ! http->auth_opaque ) { + /* Not an error; "opaque" is optional */ + } + + http->flags |= ( HTTP_TRY_AGAIN | HTTP_DIGEST_AUTH ); + } + + return 0; +} + /** An HTTP WWW-Authenticate header handler */ struct http_auth_header_handler { /** Scheme (e.g. "Basic") */ @@ -492,6 +581,10 @@ static struct http_auth_header_handler http_auth_header_handlers[] = { .scheme = "Basic", .rx = http_rx_basic_auth, }, + { + .scheme = "Digest", + .rx = http_rx_digest_auth, + }, { NULL, NULL }, }; @@ -882,6 +975,80 @@ static char * http_basic_auth ( struct http_request *http ) { return auth; } +/** + * Generate HTTP Digest authorisation string + * + * @v http HTTP request + * @v method HTTP method (e.g. "GET") + * @v uri HTTP request URI (e.g. "/index.html") + * @ret auth Authorisation string, or NULL on error + * + * The authorisation string is dynamically allocated, and must be + * freed by the caller. + */ +static char * http_digest_auth ( struct http_request *http, + const char *method, const char *uri ) { + const char *user = http->uri->user; + const char *password = + ( http->uri->password ? http->uri->password : "" ); + const char *realm = http->auth_realm; + const char *nonce = http->auth_nonce; + const char *opaque = http->auth_opaque; + static const char colon = ':'; + uint8_t ctx[MD5_CTX_SIZE]; + uint8_t digest[MD5_DIGEST_SIZE]; + char ha1[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ]; + char ha2[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ]; + char response[ base16_encoded_len ( sizeof ( digest ) ) + 1 /* NUL */ ]; + char *auth; + int len; + + /* Sanity checks */ + assert ( user != NULL ); + assert ( realm != NULL ); + assert ( nonce != NULL ); + + /* Generate HA1 */ + digest_init ( &md5_algorithm, ctx ); + digest_update ( &md5_algorithm, ctx, user, strlen ( user ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, realm, strlen ( realm ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, password, strlen ( password ) ); + digest_final ( &md5_algorithm, ctx, digest ); + base16_encode ( digest, sizeof ( digest ), ha1 ); + + /* Generate HA2 */ + digest_init ( &md5_algorithm, ctx ); + digest_update ( &md5_algorithm, ctx, method, strlen ( method ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, uri, strlen ( uri ) ); + digest_final ( &md5_algorithm, ctx, digest ); + base16_encode ( digest, sizeof ( digest ), ha2 ); + + /* Generate response */ + digest_init ( &md5_algorithm, ctx ); + digest_update ( &md5_algorithm, ctx, ha1, strlen ( ha1 ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, nonce, strlen ( nonce ) ); + digest_update ( &md5_algorithm, ctx, &colon, sizeof ( colon ) ); + digest_update ( &md5_algorithm, ctx, ha2, strlen ( ha2 ) ); + digest_final ( &md5_algorithm, ctx, digest ); + base16_encode ( digest, sizeof ( digest ), response ); + + /* Generate the authorisation string */ + len = asprintf ( &auth, "Authorization: Digest username=\"%s\", " + "realm=\"%s\", nonce=\"%s\", uri=\"%s\", " + "%s%s%sresponse=\"%s\"\r\n", user, realm, nonce, uri, + ( opaque ? "opaque=\"" : "" ), + ( opaque ? opaque : "" ), + ( opaque ? "\", " : "" ), response ); + if ( len < 0 ) + return NULL; + + return auth; +} + /** * HTTP process * @@ -949,6 +1116,12 @@ static void http_step ( struct http_request *http ) { rc = -ENOMEM; goto err_auth; } + } else if ( http->flags & HTTP_DIGEST_AUTH ) { + auth = http_digest_auth ( http, method, uri ); + if ( ! auth ) { + rc = -ENOMEM; + goto err_auth; + } } else { auth = NULL; } From 5af9ad51c8804d7992d14bbadf3ca4e4ac3ce314 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 23 May 2012 23:48:12 +0100 Subject: [PATCH 028/250] [crypto] Fix unused-but-set variable warning Reported-by: Brandon Penglase Signed-off-by: Michael Brown --- src/net/validator.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/net/validator.c b/src/net/validator.c index c4051d48..d61cb92f 100644 --- a/src/net/validator.c +++ b/src/net/validator.c @@ -455,7 +455,6 @@ static struct interface_descriptor validator_xfer_desc = */ static void validator_step ( struct validator *validator ) { struct x509_link *link; - struct x509_link *previous; struct x509_certificate *cert; struct x509_certificate *issuer = NULL; struct x509_certificate *last; @@ -479,7 +478,6 @@ static void validator_step ( struct validator *validator ) { list_for_each_entry ( link, &validator->chain->links, list ) { cert = issuer; issuer = link->cert; - previous = link; if ( ! cert ) continue; if ( ! issuer->valid ) From 734de43585f9e7176c45657058b78e890c2b03d2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Jun 2012 15:21:34 +0100 Subject: [PATCH 029/250] [build] Merge i386 and x86_64 versions of errfile.h Signed-off-by: Michael Brown --- src/arch/{i386 => x86}/include/bits/errfile.h | 0 src/arch/x86_64/include/bits/errfile.h | 11 ----------- 2 files changed, 11 deletions(-) rename src/arch/{i386 => x86}/include/bits/errfile.h (100%) delete mode 100644 src/arch/x86_64/include/bits/errfile.h diff --git a/src/arch/i386/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h similarity index 100% rename from src/arch/i386/include/bits/errfile.h rename to src/arch/x86/include/bits/errfile.h diff --git a/src/arch/x86_64/include/bits/errfile.h b/src/arch/x86_64/include/bits/errfile.h deleted file mode 100644 index dcda26ba..00000000 --- a/src/arch/x86_64/include/bits/errfile.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _BITS_ERRFILE_H -#define _BITS_ERRFILE_H - -/** - * @addtogroup errfile Error file identifiers - * @{ - */ - -/** @} */ - -#endif /* _BITS_ERRFILE_H */ From 10501351597c09c70f7ec0b158eb7b1fbfa2a4d6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Jun 2012 20:37:53 +0100 Subject: [PATCH 030/250] [contrib] Update bochsrc.txt to latest version of bochs Signed-off-by: Michael Brown --- contrib/vm/bochsrc.txt | 720 +++++++++++++++++++++++++++++++---------- 1 file changed, 550 insertions(+), 170 deletions(-) diff --git a/contrib/vm/bochsrc.txt b/contrib/vm/bochsrc.txt index 32842a3b..22ba40fb 100644 --- a/contrib/vm/bochsrc.txt +++ b/contrib/vm/bochsrc.txt @@ -1,15 +1,29 @@ # You may now use double quotes around pathnames, in case # your pathname includes spaces. +#======================================================================= +# PLUGIN_CTRL: +# Controls the presence of optional device plugins. These plugins are loaded +# directly with this option and some of them install a config option that is +# only available when the plugin device is loaded. The value "1" means to load +# the plugin and "0" will unload it (if loaded before). +# These plugins are currently supported: 'biosdev', 'e1000', 'es1370', +# 'extfpuirq', 'gameport', 'iodebug', 'ne2k', 'parallel', 'pcidev', 'pcipnic', +# 'sb16', 'serial', 'speaker', 'unmapped', 'usb_ohci', 'usb_uhci' and 'usb_xhci'. +#======================================================================= +plugin_ctrl: unmapped=1, biosdev=1, speaker=1, e1000=1, parallel=1, serial=1 + #======================================================================= # CONFIG_INTERFACE # # The configuration interface is a series of menus or dialog boxes that # allows you to change all the settings that control Bochs's behavior. -# There are two choices of configuration interface: a text mode version -# called "textconfig" and a graphical version called "wx". The text -# mode version uses stdin/stdout and is always compiled in. The graphical -# version is only available when you use "--with-wx" on the configure +# Depending on the platform there are up to 3 choices of configuration +# interface: a text mode version called "textconfig" and two graphical versions +# called "win32config" and "wx". The text mode version uses stdin/stdout and +# is always compiled in, unless Bochs is compiled for wx only. The choice +# "win32config" is only available on win32 and it is the default there. +# The choice "wx" is only available when you use "--with-wx" on the configure # command. If you do not write a config_interface line, Bochs will # choose a default for you. # @@ -17,6 +31,7 @@ # the "wx" display library. #======================================================================= #config_interface: textconfig +#config_interface: win32config #config_interface: wx #======================================================================= @@ -33,7 +48,6 @@ # x use X windows interface, cross platform # win32 use native win32 libraries # carbon use Carbon library (for MacOS X) -# beos use native BeOS libraries # macintosh use MacOS pre-10 # amigaos use native AmigaOS libraries # sdl use SDL library, cross platform @@ -47,18 +61,23 @@ # the "wx" display library. # # Specific options: -# Some display libraries now support specific option to control their -# behaviour. See the examples below for currently supported options. +# Some display libraries now support specific options to control their +# behaviour. These options are supported by more than one display library: +# +# "gui_debug" - use GTK debugger gui (sdl, x) / Win32 debugger gui (win32) +# "hideIPS" - disable IPS output in status bar (sdl, wx, x) +# "nokeyrepeat" - turn off host keyboard repeat (sdl, win32, x) +# +# See the examples below for other currently supported options. #======================================================================= #display_library: amigaos -#display_library: beos #display_library: carbon #display_library: macintosh #display_library: nogui #display_library: rfb, options="timeout=60" # time to wait for client #display_library: sdl, options="fullscreen" # startup in fullscreen mode #display_library: term -#display_library: win32, options="legacyF12" # use F12 to toggle mouse +#display_library: win32 #display_library: wx #display_library: x @@ -67,67 +86,245 @@ # The ROM BIOS controls what the PC does when it first powers on. # Normally, you can use a precompiled BIOS in the source or binary # distribution called BIOS-bochs-latest. The ROM BIOS is usually loaded -# starting at address 0xf0000, and it is exactly 64k long. +# starting at address 0xf0000, and it is exactly 64k long. Another option +# is 128k BIOS which is loaded at address 0xe0000. # You can also use the environment variable $BXSHARE to specify the # location of the BIOS. # The usage of external large BIOS images (up to 512k) at memory top is # now supported, but we still recommend to use the BIOS distributed with -# Bochs. Now the start address can be calculated from image size. +# Bochs. The start address optional, since it can be calculated from image size. #======================================================================= -romimage: file=bochs/bios/BIOS-bochs-latest, address=0xe0000 +#romimage: file=$BXSHARE/BIOS-bochs-latest +#romimage: file=bios/seabios-1.6.3.bin #romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top -#romimage: file=mybios.bin # calculate start address from image size +romimage: file=bochs/bios/BIOS-bochs-latest #======================================================================= # CPU: # This defines cpu-related parameters inside Bochs: # +# MODEL: +# Selects CPU configuration to emulate from pre-defined list of all +# supported configurations. When this option is used, the CPUID option +# has no effect anymore. +# +# CPU configurations that can be selected: +# ----------------------------------------------------------------- +# pentium_mmx Intel Pentium MMX +# amd_k6_2_chomper AMD-K6(tm) 3D processor (Chomper) +# p2_klamath Intel Pentium II (Klamath) +# p3_katmai Intel Pentium III (Katmai) +# p4_willamette Intel(R) Pentium(R) 4 (Willamette) +# core_duo_t2400_yonah Intel(R) Core(TM) Duo CPU T2400 (Yonah) +# atom_n270 Intel(R) Atom(TM) CPU N270 +# athlon64_clawhammer AMD Athlon(tm) 64 Processor 2800+ (Clawhammer) +# athlon64_venice AMD Athlon(tm) 64 Processor 3000+ (Venice) +# turion64_tyler AMD Turion(tm) 64 X2 Mobile TL-60 (Tyler) +# phenom_8650_toliman AMD Phenom X3 8650 (Toliman) +# p4_prescott_celeron_336 Intel(R) Celeron(R) 336 (Prescott) +# core2_penryn_t9600 Intel Mobile Core 2 Duo T9600 (Penryn) +# corei5_lynnfield_750 Intel(R) Core(TM) i5 750 (Lynnfield) +# corei5_arrandale_m520 Intel(R) Core(TM) i5 M 520 (Arrandale) +# corei7_sandy_bridge_2600k Intel(R) Core(TM) i7-2600K (Sandy Bridge) +# corei7_ivy_bridge_3770k Intel(R) Core(TM) i7-3770K CPU (Ivy Bridge) +# # COUNT: -# Set the number of processors:cores per processor:threads per core -# when Bochs is compiled for SMP emulation. -# Bochs currently supports up to 8 threads running simultaniosly. -# If Bochs is compiled without SMP support, it won't accept values -# different from 1. +# Set the number of processors:cores per processor:threads per core +# when Bochs is compiled for SMP emulation. +# Bochs currently supports up to 8 threads running simultaniosly. +# If Bochs is compiled without SMP support, it won't accept values +# different from 1. +# +# QUANTUM: +# Maximum amount of instructions allowed to execute by processor before +# returning control to another cpu. This option exists only in Bochs +# binary compiled with SMP support. # # RESET_ON_TRIPLE_FAULT: -# Reset the CPU when triple fault occur (highly recommended) rather than -# PANIC. Remember that if you trying to continue after triple fault the -# simulation will be completely bogus ! +# Reset the CPU when triple fault occur (highly recommended) rather than +# PANIC. Remember that if you trying to continue after triple fault the +# simulation will be completely bogus ! +# +# CPUID_LIMIT_WINNT: +# Determine whether to limit maximum CPUID function to 2. This mode is +# required to workaround WinNT installation and boot issues. +# +# MSRS: +# Define path to user CPU Model Specific Registers (MSRs) specification. +# See example in msrs.def. +# +# IGNORE_BAD_MSRS: +# Ignore MSR references that Bochs does not understand; print a warning +# message instead of generating #GP exception. This option is enabled +# by default but will not be avaiable if configurable MSRs are enabled. +# +# MWAIT_IS_NOP: +# When this option is enabled MWAIT will not put the CPU into a sleep state. +# This option exists only if Bochs compiled with --enable-monitor-mwait. # # IPS: -# Emulated Instructions Per Second. This is the number of IPS that bochs -# is capable of running on your machine. You can recompile Bochs with -# --enable-show-ips option enabled, to find your workstation's capability. -# Measured IPS value will then be logged into your log file or status bar -# (if supported by the gui). +# Emulated Instructions Per Second. This is the number of IPS that bochs +# is capable of running on your machine. You can recompile Bochs with +# --enable-show-ips option enabled, to find your host's capability. +# Measured IPS value will then be logged into your log file or shown +# in the status bar (if supported by the gui). # -# IPS is used to calibrate many time-dependent events within the bochs -# simulation. For example, changing IPS affects the frequency of VGA -# updates, the duration of time before a key starts to autorepeat, and -# the measurement of BogoMips and other benchmarks. +# IPS is used to calibrate many time-dependent events within the bochs +# simulation. For example, changing IPS affects the frequency of VGA +# updates, the duration of time before a key starts to autorepeat, and +# the measurement of BogoMips and other benchmarks. # # Examples: -# Machine Mips -# ________________________________________________________________ -# 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips -# 1.6Ghz Intel P4 with Win2000/g++ 3.3 5 to 7 Mips -# 650Mhz Athlon K-7 with Linux 2.4.4/egcs-2.91.66 2 to 2.5 Mips -# 400Mhz Pentium II with Linux 2.0.36/egcs-1.0.3 1 to 1.8 Mips +# +# Bochs Machine/Compiler Mips +# ______________________________________________________________________ +# 2.4.6 3.4Ghz Intel Core i7 2600 with Win7x64/g++ 4.5.2 85 to 95 Mips +# 2.3.7 3.2Ghz Intel Core 2 Q9770 with WinXP/g++ 3.4 50 to 55 Mips +# 2.3.7 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 38 to 43 Mips +# 2.2.6 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 21 to 25 Mips +# 2.2.6 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips #======================================================================= -cpu: count=1, ips=10000000, reset_on_triple_fault=1 +cpu: model=core2_penryn_t9600, count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def" +cpu: cpuid_limit_winnt=0 #======================================================================= -# MEGS -# Set the number of Megabytes of physical memory you want to emulate. -# The default is 32MB, most OS's won't need more than that. -# The maximum amount of memory supported is 2048Mb. +# CPUID: +# +# This defines features and functionality supported by Bochs emulated CPU. +# The option has no offect if CPU model was selected in CPU option. +# +# MMX: +# Select MMX instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. +# +# APIC: +# Select APIC configuration (LEGACY/XAPIC/XAPIC_EXT/X2APIC). +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. +# +# SEP: +# Select SYSENTER/SYSEXIT instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# SSE: +# Select SSE instruction set support. +# Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 could be selected. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# SSE4A: +# Select AMD SSE4A instructions support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# AES: +# Select AES instruction set support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# MOVBE: +# Select MOVBE Intel(R) Atom instruction support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# XSAVE: +# Select XSAVE extensions support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# XSAVEOPT: +# Select XSAVEOPT instruction support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# AVX: +# Select AVX/AVX2 instruction set support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# AVX_F16C: +# Select AVX float16 convert instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# AVX_FMA: +# Select AVX fused multiply add (FMA) instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# BMI: +# Select BMI1/BMI2 instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# XOP: +# Select AMD XOP instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# FMA4: +# Select AMD four operand FMA instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# TBM: +# Select AMD Trailing Bit Manipulation (TBM) instructions support. +# This option exists only if Bochs compiled with --enable-avx option. +# +# X86-64: +# Enable x86-64 and long mode support. +# This option exists only if Bochs compiled with x86-64 support. +# +# 1G_PAGES: +# Enable 1G page size support in long mode. +# This option exists only if Bochs compiled with x86-64 support. +# +# PCID: +# Enable Process-Context Identifiers (PCID) support in long mode. +# This option exists only if Bochs compiled with x86-64 support. +# +# FSGSBASE: +# Enable GS/GS BASE access instructions support in long mode. +# This option exists only if Bochs compiled with x86-64 support. +# +# SMEP: +# Enable Supervisor Mode Execution Protection (SMEP) support. +# This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. +# +# MWAIT: +# Select MONITOR/MWAIT instructions support. +# This option exists only if Bochs compiled with --enable-monitor-mwait. +# +# VMX: +# Select VMX extensions emulation support. +# This option exists only if Bochs compiled with --enable-vmx option. +# +# VENDOR_STRING: +# Set the CPUID vendor string returned by CPUID(0x0). This should be a +# twelve-character ASCII string. +# +# BRAND_STRING: +# Set the CPUID vendor string returned by CPUID(0x80000002 .. 0x80000004). +# This should be at most a forty-eight-character ASCII string. +# +# FAMILY: +# Set model information returned by CPUID. Default family value determined +# by configure option --enable-cpu-level. +# +# MODEL: +# Set model information returned by CPUID. Default model value is 3. +# +# STEPPING: +# Set stepping information returned by CPUID. Default stepping value is 3. #======================================================================= -#megs: 256 -#megs: 128 -#megs: 64 -megs: 32 -#megs: 16 -#megs: 8 +#cpuid: x86_64=1, mmx=1, sep=1, sse=sse4_2, apic=xapic, aes=1, movbe=1, xsave=1 +#cpuid: family=6, model=0x1a, stepping=5 + +#======================================================================= +# MEMORY +# Set the amount of physical memory you want to emulate. +# +# GUEST: +# Set amount of guest physical memory to emulate. The default is 32MB, +# the maximum amount limited only by physical address space limitations. +# +# HOST: +# Set amount of host memory you want to allocate for guest RAM emulation. +# It is possible to allocate less memory than you want to emulate in guest +# system. This will fake guest to see the non-existing memory. Once guest +# system touches new memory block it will be dynamically taken from the +# memory pool. You will be warned (by FATAL PANIC) in case guest already +# used all allocated host memory and wants more. +# +#======================================================================= +memory: guest=512, host=256 #======================================================================= # OPTROMIMAGE[1-4]: @@ -144,8 +341,7 @@ megs: 32 #optromimage2: file=optionalrom.bin, address=0xd1000 #optromimage3: file=optionalrom.bin, address=0xd2000 #optromimage4: file=optionalrom.bin, address=0xd3000 -optromimage1: file=../../src/bin/pnic.rom, address=0xd0000 -#optromimage1: file=../../src/bin/rtl8029.rom, address=0xd0000 +optromimage1: file=../../src/bin/intel.rom, address=0xd0000 #optramimage1: file=/path/file1.img, address=0x0010000 #optramimage2: file=/path/file2.img, address=0x0020000 @@ -157,18 +353,31 @@ optromimage1: file=../../src/bin/pnic.rom, address=0xd0000 # You now need to load a VGA ROM BIOS into C0000. #======================================================================= #vgaromimage: file=bios/VGABIOS-elpin-2.40 -vgaromimage: file=bochs/bios/VGABIOS-lgpl-latest +#vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest #vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus +vgaromimage: file=bochs/bios/VGABIOS-lgpl-latest #======================================================================= # VGA: -# Here you can specify the display extension to be used. With the value -# 'none' you can use standard VGA with no extension. Other supported -# values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support. +# This defines parameters related to the VGA display +# +# EXTENSION +# Here you can specify the display extension to be used. With the value +# 'none' you can use standard VGA with no extension. Other supported +# values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support. +# +# UPDATE_FREQ +# The VGA update frequency is based on the emulated clock and the default +# value is 5. Keep in mind that you must tweak the 'cpu: ips=N' directive +# to be as close to the number of emulated instructions-per-second your +# workstation can do, for this to be accurate. If the realtime sync is +# enabled with the 'clock' option, the value is based on the real time. +# This parameter can be changed at runtime. +# +# Examples: +# vga: extension=cirrus, update_freq=10 #======================================================================= -#vga: extension=cirrus -#vga: extension=vbe -vga: extension=none +#vga: extension=vbe, update_freq=5 #======================================================================= # FLOPPYA: @@ -177,36 +386,42 @@ vga: extension=none # booting from 'a' (or 'floppy'). # # You can set the initial status of the media to 'ejected' or 'inserted'. -# floppya: 2_88=path, status=ejected (2.88M 3.5" floppy) -# floppya: 1_44=path, status=inserted (1.44M 3.5" floppy) -# floppya: 1_2=path, status=ejected (1.2M 5.25" floppy) -# floppya: 720k=path, status=inserted (720K 3.5" floppy) -# floppya: 360k=path, status=inserted (360K 5.25" floppy) -# floppya: 320k=path, status=inserted (320K 5.25" floppy) -# floppya: 180k=path, status=inserted (180K 5.25" floppy) -# floppya: 160k=path, status=inserted (160K 5.25" floppy) -# floppya: image=path, status=inserted (guess type from image size) +# floppya: 2_88=path, status=ejected (2.88M 3.5" media) +# floppya: 1_44=path, status=inserted (1.44M 3.5" media) +# floppya: 1_2=path, status=ejected (1.2M 5.25" media) +# floppya: 720k=path, status=inserted (720K 3.5" media) +# floppya: 360k=path, status=inserted (360K 5.25" media) +# floppya: 320k=path, status=inserted (320K 5.25" media) +# floppya: 180k=path, status=inserted (180K 5.25" media) +# floppya: 160k=path, status=inserted (160K 5.25" media) +# floppya: image=path, status=inserted (guess media type from image size) +# floppya: 1_44=vvfat:path, status=inserted (use directory as VFAT media) +# floppya: type=1_44 (1.44M 3.5" floppy drive, no media) # # The path should be the name of a disk image file. On Unix, you can use a raw # device name such as /dev/fd0 on Linux. On win32 platforms, use drive letters # such as a: or b: as the path. The parameter 'image' works with image files # only. In that case the size must match one of the supported types. +# The parameter 'type' can be used to enable the floppy drive without media +# and status specified. Usually the drive type is set up based on the media type. +# The optional parameter 'write_protected' can be used to control the media +# write protect switch. By default it is turned off. #======================================================================= #floppya: 1_44=/dev/fd0, status=inserted #floppya: image=../1.44, status=inserted #floppya: 1_44=/dev/fd0H1440, status=inserted #floppya: 1_2=../1_2, status=inserted #floppya: 1_44=a:, status=inserted -#floppya: 1_44=a.img, status=inserted +#floppya: 1_44=a.img, status=inserted, write_protected=1 #floppya: 1_44=/dev/rfd0a, status=inserted -floppya: 1_44=../../src/bin/pnic.dsk, status=inserted +floppya: 1_44=../../src/bin/ipxe.dsk, status=inserted #======================================================================= # FLOPPYB: # See FLOPPYA above for syntax #======================================================================= #floppyb: 1_44=b:, status=inserted -floppyb: 1_44=b.img, status=inserted +#floppyb: 1_44=b.img, status=inserted #======================================================================= # ATA0, ATA1, ATA2, ATA3 @@ -236,8 +451,8 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # This defines the type and characteristics of all attached ata devices: # type= type of attached device [disk|cdrom] # mode= only valid for disks [flat|concat|external|dll|sparse|vmware3] -# mode= only valid for disks [undoable|growing|volatile] -# path= path of the image +# mode= only valid for disks [undoable|growing|volatile|vvfat] +# path= path of the image / directory # cylinders= only valid for disks # heads= only valid for disks # spt= only valid for disks @@ -245,7 +460,7 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos] # translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto] # model= string returned by identify device command -# journal= optional filename of the redolog for undoable and volatile disks +# journal= optional filename of the redolog for undoable, volatile and vvfat disks # # Point this at a hard disk image file, cdrom iso file, or physical cdrom # device. To create a hard disk image, try running bximage. It will help you @@ -259,10 +474,11 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # access the "first" cdrom in the system. On MacOSX, use path="drive" # to access the physical drive. # -# The path is always mandatory. For flat hard disk images created with -# bximage geometry autodetection can be used (cylinders=0 -> cylinders are -# calculated using heads=16 and spt=63). For other hard disk images and modes -# the cylinders, heads, and spt are mandatory. +# The path is mandatory for hard disks. Disk geometry autodetection works with +# images created by bximage if CHS is set to 0/0/0 (cylinders are calculated +# using heads=16 and spt=63). For other hard disk images and modes the +# cylinders, heads, and spt are mandatory. In all cases the disk size reported +# from the image must be exactly C*H*S*512. # # Default values are: # mode=flat, biosdetect=auto, translation=auto, model="Generic 1234" @@ -279,7 +495,10 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 # ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63 # ata3-slave: type=cdrom, path=iso.sample, status=inserted #======================================================================= +#ata0-master: type=disk, mode=flat, path="30M.sample" #ata0-master: type=disk, mode=flat, path="30M.sample", cylinders=615, heads=6, spt=17 +#ata0-master: type=disk, mode=flat, path="c.img", cylinders=0 # autodetect +#ata0-slave: type=disk, mode=vvfat, path=/bochs/images/vvfat, journal=vvfat.redolog #ata0-slave: type=cdrom, path=D:, status=inserted #ata0-slave: type=cdrom, path=/dev/cdrom, status=inserted #ata0-slave: type=cdrom, path="drive", status=inserted @@ -287,15 +506,13 @@ ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 #======================================================================= # BOOT: -# This defines the boot sequence. Now you can specify up to 3 boot drives. -# You can either boot from 'floppy', 'disk' or 'cdrom' -# legacy 'a' and 'c' are also supported +# This defines the boot sequence. Now you can specify up to 3 boot drives, +# which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM). +# Legacy 'a' and 'c' are also supported. # Examples: # boot: floppy -# boot: disk -# boot: cdrom -# boot: c -# boot: a +# boot: cdrom, disk +# boot: network, disk # boot: cdrom, floppy, disk #======================================================================= #boot: floppy @@ -307,7 +524,17 @@ boot: network, floppy # This defines the parameters of the clock inside Bochs: # # SYNC: -# TO BE COMPLETED (see Greg explanation in feature request #536329) +# This defines the method how to synchronize the Bochs internal time +# with realtime. With the value 'none' the Bochs time relies on the IPS +# value and no host time synchronization is used. The 'slowdown' method +# sacrifices performance to preserve reproducibility while allowing host +# time correlation. The 'realtime' method sacrifices reproducibility to +# preserve performance and host-time correlation. +# It is possible to enable both synchronization methods. +# +# RTC_SYNC: +# If this option is enabled together with the realtime synchronization, +# the RTC runs at realtime speed. This feature is disabled by default. # # TIME0: # Specifies the start (boot) time of the virtual machine. Use a time @@ -342,7 +569,6 @@ boot: network, floppy # floppy_bootsig_check: disabled=0 # floppy_bootsig_check: disabled=1 #======================================================================= -#floppy_bootsig_check: disabled=1 floppy_bootsig_check: disabled=0 #======================================================================= @@ -378,7 +604,7 @@ log: bochsout.txt #======================================================================= # LOG CONTROLS # -# Bochs now has four severity levels for event logging. +# Bochs has four severity levels for event logging. # panic: cannot proceed. If you choose to continue after a panic, # don't be surprised if you get strange behavior or crashes. # error: something went wrong, but it is probably safe to continue the @@ -387,9 +613,13 @@ log: bochsout.txt # debug: messages useful only when debugging the code. This may # spit out thousands per second. # -# For events of each level, you can choose to crash, report, or ignore. -# TODO: allow choice based on the facility: e.g. crash on panics from -# everything except the cdrom, and only report those. +# For events of each level, you can choose to exit Bochs ('fatal'), 'report' +# or 'ignore'. On some guis you have the additional choice 'ask'. A gui dialog +# appears asks how to proceed. +# +# It is also possible to specify the 'action' to do for each Bochs facility +# separately (e.g. crash on panics from everything except the cdrom, and only +# report those). See the 'log function' module list in the user documentation. # # If you are experiencing many panics, it can be helpful to change # the panic action to report instead of fatal. However, be aware @@ -400,8 +630,7 @@ log: bochsout.txt panic: action=ask error: action=report info: action=report -debug: action=ignore -#pass: action=fatal +debug: action=ignore, pci=report # report BX_DEBUG from module 'pci' #======================================================================= # DEBUGGER_LOG: @@ -425,18 +654,29 @@ debugger_log: - # Then do `sleep 1000000' in the com1 window to keep the shell from # messing with things, and run bochs in the other window. Serial I/O to # com1 (port 0x3f8) will all go to the other window. +# In socket* and pipe* (win32 only) modes Bochs becomes either socket/named pipe +# client or server. In client mode it connects to an already running server (if +# connection fails Bochs treats com port as not connected). In server mode it +# opens socket/named pipe and waits until a client application connects to it +# before starting simulation. This mode is useful for remote debugging (e.g. +# with gdb's "target remote host:port" command or windbg's command line option +# -k com:pipe,port=\\.\pipe\pipename). Note: 'socket' is a shorthand for +# 'socket-client' and 'pipe' for 'pipe-client'. Socket modes use simple TCP +# communication, pipe modes use duplex byte mode pipes. # Other serial modes are 'null' (no input/output), 'file' (output to a file # specified as the 'dev' parameter), 'raw' (use the real serial port - under # construction for win32), 'mouse' (standard serial mouse - requires -# mouse option setting 'type=serial' or 'type=serial_wheel') and 'socket' -# (connect a networking socket). +# mouse option setting 'type=serial', 'type=serial_wheel' or 'type=serial_msys'). # # Examples: # com1: enabled=1, mode=null # com1: enabled=1, mode=mouse # com2: enabled=1, mode=file, dev=serial.out # com3: enabled=1, mode=raw, dev=com1 -# com3: enabled=1, mode=socket, dev=localhost:8888 +# com3: enabled=1, mode=socket-client, dev=localhost:8888 +# com3: enabled=1, mode=socket-server, dev=localhost:8888 +# com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe +# com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe #======================================================================= #com1: enabled=1, mode=term, dev=/dev/ttyp9 @@ -461,6 +701,9 @@ parport1: enabled=1, file="parport.out" # This defines the SB16 sound emulation. It can have several of the # following properties. # All properties are in the format sb16: property=value +# enabled: +# This optional property controls the presence of the SB16 emulation. +# The emulation is turned on unless this property is used and set to 0. # midi: The filename is where the midi data is sent. This can be a # device or just a file if you want to record the midi data. # midimode: @@ -488,26 +731,25 @@ parport1: enabled=1, file="parport.out" # non-continuous sound. 750000 is usually a good value. This needs a # reasonably correct setting for the IPS parameter of the CPU option. # -# For an example look at the next line: +# Examples for output devices: +# sb16: midimode=1, midi="", wavemode=1, wave="" # win32 +# sb16: midimode=1, midi=alsa:128:0, wavemode=1, wave=alsa # Linux with ALSA #======================================================================= - #sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000 #======================================================================= -# VGA_UPDATE_INTERVAL: -# Video memory is scanned for updates and screen updated every so many -# virtual seconds. The default is 40000, about 25Hz. Keep in mind that -# you must tweak the 'cpu: ips=N' directive to be as close to the number -# of emulated instructions-per-second your workstation can do, for this -# to be accurate. +# ES1370: +# This defines the ES1370 sound emulation. The parameter 'enabled' controls the +# presence of the device. In addition to this, it must be loaded with 'plugin_ctrl' +# and assigned to a PCI slot. The 'wavedev' parameter is similar to the 'wave' +# parameter of the SB16 soundcard. The emulation supports recording and playback +# (except DAC1+DAC2 output at the same time). # # Examples: -# vga_update_interval: 250000 +# es1370: enabled=1, wavedev="" # win32 +# es1370: enabled=1, wavedev=alsa # Linux with ALSA #======================================================================= -vga_update_interval: 300000 - -# using for Winstone '98 tests -#vga_update_interval: 100000 +#es1370: enabled=1, wavedev=alsa #======================================================================= # KEYBOARD_SERIAL_DELAY: @@ -537,24 +779,34 @@ keyboard_paste_delay: 100000 #======================================================================= # MOUSE: -# This option prevents Bochs from creating mouse "events" unless a mouse -# is enabled. The hardware emulation itself is not disabled by this. -# You can turn the mouse on by setting enabled to 1, or turn it off by -# setting enabled to 0. Unless you have a particular reason for enabling -# the mouse by default, it is recommended that you leave it off. -# You can also toggle the mouse usage at runtime (control key + middle -# mouse button on X11, SDL, wxWidgets and Win32). -# With the mouse type option you can select the type of mouse to emulate. -# The default value is 'ps2'. The other choices are 'imps2' (wheel mouse -# on PS/2), 'serial', 'serial_wheel' (one com port requires setting -# 'mode=mouse') and 'usb' (3-button mouse - one of the USB ports must be -# connected with the 'mouse' device - requires PCI and USB support). +# This defines parameters for the emulated mouse type, the initial status +# of the mouse capture and the runtime method to toggle it. +# +# TYPE: +# With the mouse type option you can select the type of mouse to emulate. +# The default value is 'ps2'. The other choices are 'imps2' (wheel mouse +# on PS/2), 'serial', 'serial_wheel' and 'serial_msys' (one com port requires +# setting 'mode=mouse'). To connect a mouse to an USB port, see the 'usb_uhci', +# 'usb_ohci' or 'usb_xhci' options (requires PCI and USB support). +# +# ENABLED: +# The Bochs gui creates mouse "events" unless the 'enabled' option is +# set to 0. The hardware emulation itself is not disabled by this. +# Unless you have a particular reason for enabling the mouse by default, +# it is recommended that you leave it off. You can also toggle the mouse +# usage at runtime (RFB, SDL, Win32, wxWidgets and X11 - see below). +# +# TOGGLE: +# The default method to toggle the mouse capture at runtime is to press the +# CTRL key and the middle mouse button ('ctrl+mbutton'). This option allows +# to change the method to 'ctrl+f10' (like DOSBox), 'ctrl+alt' (like QEMU) +# or 'f12' (replaces win32 'legacyF12' option). # # Examples: # mouse: enabled=1 -# mouse: enabled=1, type=imps2 -# mouse: enabled=1, type=serial -# mouse: enabled=0 +# mouse: type=imps2, enabled=1 +# mouse: type=serial, enabled=1 +# mouse: enabled=0, toggle=ctrl+f10 #======================================================================= mouse: enabled=0 @@ -586,54 +838,86 @@ private_colormap: enabled=0 #======================================================================= # ne2k: NE2000 compatible ethernet adapter # -# Examples: -# ne2k: ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT +# Format: +# ne2k: enabled=1, ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, +# ethdev=DEVICE, script=SCRIPT, bootrom=BOOTROM # -# ioaddr, irq: You probably won't need to change ioaddr and irq, unless there -# are IRQ conflicts. +# IOADDR, IRQ: You probably won't need to change ioaddr and irq, unless there +# are IRQ conflicts. These arguments are ignored when assign the ne2k to a +# PCI slot. # -# mac: The MAC address MUST NOT match the address of any machine on the net. +# MAC: The MAC address MUST NOT match the address of any machine on the net. # Also, the first byte must be an even number (bit 0 set means a multicast # address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast # address. For the ethertap module, you must use fe:fd:00:00:00:01. There may # be other restrictions too. To be safe, just use the b0:c4... address. # -# ethdev: The ethdev value is the name of the network interface on your host +# ETHDEV: The ethdev value is the name of the network interface on your host # platform. On UNIX machines, you can get the name by running ifconfig. On # Windows machines, you must run niclist to get the name of the ethdev. # Niclist source code is in misc/niclist.c and it is included in Windows # binary releases. # -# script: The script value is optional, and is the name of a script that +# SCRIPT: The script value is optional, and is the name of a script that # is executed after bochs initialize the network interface. You can use # this script to configure this network interface, or enable masquerading. # This is mainly useful for the tun/tap devices that only exist during # Bochs execution. The network interface name is supplied to the script -# as first parameter +# as first parameter. +# +# BOOTROM: The bootrom value is optional, and is the name of the ROM image +# to load. Note that this feature is only implemented for the PCI version of +# the NE2000. # # If you don't want to make connections to any physical networks, # you can use the following 'ethmod's to simulate a virtual network. # null: All packets are discarded, but logged to a few files. -# arpback: ARP is simulated. Disabled by default. # vde: Virtual Distributed Ethernet # vnet: ARP, ICMP-echo(ping), DHCP and read/write TFTP are simulated. # The virtual host uses 192.168.10.1. # DHCP assigns 192.168.10.2 to the guest. -# TFTP uses the ethdev value for the root directory and doesn't +# TFTP uses the 'ethdev' value for the root directory and doesn't # overwrite files. # #======================================================================= -# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=fbsd, ethdev=en0 #macosx -# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0 -# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 -# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD -# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 -# ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig -# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0 -# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" -# ne2k: ioaddr=0x240, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" -pnic: mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun:tap0 -#ne2k: ioaddr=0x240, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun:tap0 +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=fbsd, ethdev=en0 #macosx +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0 +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 +# ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0 +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" +# ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" +# ne2k: mac=b0:c4:20:00:00:01, ethmod=slirp, script=/usr/local/bin/slirp, bootrom=ne2k_pci.rom + +#======================================================================= +# pnic: Bochs/Etherboot pseudo-NIC +# +# Format: +# pnic: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT, +# bootrom=BOOTROM +# +# The pseudo-NIC accepts the same syntax (for mac, ethmod, ethdev, script, +# bootrom) and supports the same networking modules as the NE2000 adapter. +# In addition to this, it must be loaded with 'plugin_ctrl' and assigned +# to a PCI slot. +#======================================================================= +#pnic: enabled=1, mac=b0:c4:20:00:00:00, ethmod=vnet + +#======================================================================= +# e1000: Intel(R) 82540EM Gigabit Ethernet adapter +# +# Format: +# e1000: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT +# bootrom=BOOTROM +# +# The E1000 accepts the same syntax (for mac, ethmod, ethdev, script, bootrom) +# and supports the same networking modules as the NE2000 adapter. In addition +# to this, it must be loaded with 'plugin_ctrl' and assigned to a PCI slot. +#======================================================================= +#e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=slirp, script=/usr/local/bin/slirp +e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=tuntap, ethdev=/dev/net/tun:tap0 #======================================================================= # KEYBOARD_MAPPING: @@ -662,45 +946,88 @@ keyboard_mapping: enabled=0, map= # USER_SHORTCUT: # This defines the keyboard shortcut to be sent when you press the "user" # button in the headerbar. The shortcut string is a combination of maximum -# 3 key names (listed below) separated with a '-' character. The old-style -# syntax (without the '-') still works for the key combinations supported -# in Bochs 2.2.1. +# 3 key names (listed below) separated with a '-' character. # Valid key names: # "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc", # "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup", -# "plus", "right", "shift", "space", "tab", "up", and "win". +# "plus", "right", "shift", "space", "tab", "up", "win", "print" and "power". # # Example: # user_shortcut: keys=ctrl-alt-del #======================================================================= -user_shortcut: keys=ctrl-alt-del +#user_shortcut: keys=ctrl-alt-del #======================================================================= -# I440FXSUPPORT: -# This option controls the presence of the i440FX PCI chipset. You can -# also specify the devices connected to PCI slots. Up to 5 slots are -# available now. These devices are currently supported: ne2k, pcivga, -# pcidev and pcipnic. If Bochs is compiled with Cirrus SVGA support -# you'll have the additional choice 'cirrus'. +# PCI: +# This option controls the presence of a PCI chipset in Bochs. Currently it only +# supports the i440FX chipset. You can also specify the devices connected to +# PCI slots. Up to 5 slots are available. These devices are currently supported: +# cirrus, e1000, es1370, ne2k, pcivga, pcidev, pcipnic, usb_ohci and usb_xhci. # # Example: -# i440fxsupport: enabled=1, slot1=pcivga, slot2=ne2k +# pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=ne2k #======================================================================= -i440fxsupport: enabled=1, slot1=pcipnic -#i440fxsupport: enabled=1, slot1=ne2k +pci: enabled=1, chipset=i440fx, slot1=e1000 #======================================================================= -# USB1: +# USB_UHCI: # This option controls the presence of the USB root hub which is a part -# of the i440FX PCI chipset. With the portX option you can connect devices -# to the hub (currently supported: 'mouse' and 'keypad'). If you connect -# the mouse to one of the ports and use the mouse option 'type=usb' you'll -# have a 3-button USB mouse. +# of the i440FX PCI chipset. With the portX parameter you can connect devices +# to the hub (currently supported: 'mouse', 'tablet', 'keypad', 'disk', 'cdrom' +# 'hub' and 'printer'). NOTE: UHCI must be loaded with 'plugin_ctrl'. # -# Example: -# usb1: enabled=1, port1=mouse, port2=keypad +# The optionsX parameter can be used to assign specific options to the device +# connected to the corresponding USB port. Currently this feature is only used +# to set the speed reported by device and by the 'disk' device to specify +# an alternative redolog file of some image modes. +# +# If you connect the mouse or tablet to one of the ports, Bochs forwards the +# mouse movement data to the USB device instead of the selected mouse type. +# When connecting the keypad to one of the ports, Bochs forwards the input of +# the numeric keypad to the USB device instead of the PS/2 keyboard. +# +# To connect a 'flat' mode image as an USB hardisk you can use the 'disk' device +# with the path to the image separated with a colon. To use other disk image modes +# similar to ATA disks the syntax 'disk:mode:filename' must be used (see below). +# +# To emulate an USB cdrom you can use the 'cdrom' device name and the path to +# an ISO image or raw device name also separated with a colon. An option to +# insert/eject media is available in the runtime configuration. +# +# The device name 'hub' connects an external hub with max. 8 ports (default: 4) +# to the root hub. To specify the number of ports you have to add the value +# separated with a colon. Connecting devices to the external hub ports is only +# available in the runtime configuration. +# +# The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is +# sent to a file specified in bochsrc.txt. The current code appends the PCL +# code to the file if the file already existed. It would probably be nice to +# overwrite the file instead, asking user first. #======================================================================= -#usb1: enabled=1 +#usb_uhci: enabled=1 +#usb_uhci: enabled=1, port1=mouse, port2=disk:usbstick.img +#usb_uhci: enabled=1, port1=hub:7, port2=disk:growing:usbdisk.img +#usb_uhci: enabled=1, port2=disk:undoable:usbdisk.img, options1=journal:redo.log +#usb_uhci: enabled=1, port1=printer:printdata.bin, port2=cdrom:image.iso + +#======================================================================= +# USB_OHCI: +# This option controls the presence of the USB OHCI host controller with a +# 2-port hub. The portX option accepts the same device types with the same +# syntax as the UHCI controller (see above). The OHCI HC must be assigned to +# a PCI slot and loaded with 'plugin_ctrl'. +#======================================================================= +#usb_ohci: enabled=1 +#usb_ohci: enabled=1, port1=printer:usbprinter.bin + +#======================================================================= +# USB_XHCI: +# This option controls the presence of the experimental USB xHCI host controller +# with a 4-port hub. The portX option accepts the same device types with the +# same syntax as the UHCI controller (see above). The xHCI HC must be assigned +# to a PCI slot and loaded with 'plugin_ctrl'. +#======================================================================= +#usb_xhci: enabled=1 #======================================================================= # CMOSIMAGE: @@ -714,13 +1041,51 @@ i440fxsupport: enabled=1, slot1=pcipnic #======================================================================= #cmosimage: file=cmos.img, rtc_init=time0 +#======================================================================= +# MAGIC_BREAK: +# This enables the "magic breakpoint" feature when using the debugger. +# The useless cpu instruction XCHG BX, BX causes Bochs to enter the +# debugger mode. This might be useful for software development. +# +# Example: +# magic_break: enabled=1 +#======================================================================= +#magic_break: enabled=1 +magic_break: enabled=1 + +#======================================================================= +# PORT_E9_HACK: +# The 0xE9 port doesn't exists in normal ISA architecture. However, we +# define a convention here, to display on the console of the system running +# Bochs anything that is written to it. The idea is to provide debug output +# very early when writing BIOS or OS code for example, without having to +# bother with setting up a serial port or etc. Reading from port 0xE9 will +# will return 0xe9 to let you know if the feature is available. +# Leave this 0 unless you have a reason to use it. +# +# Example: +# port_e9_hack: enabled=1 +#======================================================================= +#port_e9_hack: enabled=1 + +#======================================================================= +# DEBUG_SYMBOLS: +# This loads symbols from the specified file for use in Bochs' internal +# debugger. Symbols are loaded into global context. This is equivalent to +# issuing ldsym debugger command at start up. +# +# Example: +# debug_symbols: file="kernel.sym" +# debug_symbols: file="kernel.sym", offset=0x80000000 +#======================================================================= +#debug_symbols: file="kernel.sym" + #======================================================================= # other stuff #======================================================================= -magic_break: enabled=1 #load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log #load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img -#text_snapshot_check: enable +#print_timestamps: enabled=1 #------------------------- # PCI host device mapping @@ -735,11 +1100,12 @@ magic_break: enabled=1 #gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0 #======================================================================= -# IPS: -# The IPS directive is DEPRECATED. Use the parameter IPS of the CPU -# directive instead. +# USER_PLUGIN: +# Load user-defined plugin. This option is available only if Bochs is +# compiled with plugin support. Maximum 8 different plugins are supported. +# See the example in the Bochs sources how to write a plugin device. #======================================================================= -#ips: 10000000 +#user_plugin: name=testdev #======================================================================= # for Macintosh, use the style of pathnames in the following @@ -749,3 +1115,17 @@ magic_break: enabled=1 # romimage: file=:bios:BIOS-bochs-latest, address=0xf0000 # floppya: 1_44=[fd:], status=inserted #======================================================================= + +#======================================================================= +# MEGS +# Set the number of Megabytes of physical memory you want to emulate. +# The default is 32MB, most OS's won't need more than that. +# The maximum amount of memory supported is 2048Mb. +# The 'MEGS' option is deprecated. Use 'MEMORY' option instead. +#======================================================================= +#megs: 256 +#megs: 128 +#megs: 64 +#megs: 32 +#megs: 16 +#megs: 8 From 591541af667dbf3617b81d89f92abf01e9e1a16d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Jun 2012 16:08:24 +0100 Subject: [PATCH 031/250] [cmdline] Add "cpuid" command Allow x86 CPU feature flags (such as support for 64-bit mode) to be checked using the "cpuid" command. Signed-off-by: Michael Brown --- src/arch/i386/core/cpu.c | 73 ------------ src/arch/i386/include/bits/cpu.h | 86 -------------- src/arch/x86/Makefile | 1 + src/arch/x86/core/cpuid.c | 154 ++++++++++++++++++++++++++ src/arch/x86/hci/commands/cpuid_cmd.c | 94 ++++++++++++++++ src/arch/x86/include/bits/errfile.h | 6 +- src/arch/x86/include/ipxe/cpuid.h | 53 +++++++++ src/config/config.c | 3 + src/config/defaults/pcbios.h | 1 + 9 files changed, 310 insertions(+), 161 deletions(-) delete mode 100644 src/arch/i386/core/cpu.c delete mode 100644 src/arch/i386/include/bits/cpu.h create mode 100644 src/arch/x86/core/cpuid.c create mode 100644 src/arch/x86/hci/commands/cpuid_cmd.c create mode 100644 src/arch/x86/include/ipxe/cpuid.h diff --git a/src/arch/i386/core/cpu.c b/src/arch/i386/core/cpu.c deleted file mode 100644 index c24fa4e6..00000000 --- a/src/arch/i386/core/cpu.c +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include - -/** @file - * - * CPU identification - * - */ - -/** - * Test to see if CPU flag is changeable - * - * @v flag Flag to test - * @ret can_change Flag is changeable - */ -static inline int flag_is_changeable ( unsigned int flag ) { - uint32_t f1, f2; - - __asm__ ( "pushfl\n\t" - "pushfl\n\t" - "popl %0\n\t" - "movl %0,%1\n\t" - "xorl %2,%0\n\t" - "pushl %0\n\t" - "popfl\n\t" - "pushfl\n\t" - "popl %0\n\t" - "popfl\n\t" - : "=&r" ( f1 ), "=&r" ( f2 ) - : "ir" ( flag ) ); - - return ( ( ( f1 ^ f2 ) & flag ) != 0 ); -} - -/** - * Get CPU information - * - * @v cpu CPU information structure to fill in - */ -void get_cpuinfo ( struct cpuinfo_x86 *cpu ) { - unsigned int cpuid_level; - unsigned int cpuid_extlevel; - unsigned int discard_1, discard_2, discard_3; - - memset ( cpu, 0, sizeof ( *cpu ) ); - - /* Check for CPUID instruction */ - if ( ! flag_is_changeable ( X86_EFLAGS_ID ) ) { - DBG ( "CPUID not supported\n" ); - return; - } - - /* Get features, if present */ - cpuid ( 0x00000000, &cpuid_level, &discard_1, - &discard_2, &discard_3 ); - if ( cpuid_level >= 0x00000001 ) { - cpuid ( 0x00000001, &discard_1, &discard_2, - &discard_3, &cpu->features ); - } else { - DBG ( "CPUID cannot return capabilities\n" ); - } - - /* Get 64-bit features, if present */ - cpuid ( 0x80000000, &cpuid_extlevel, &discard_1, - &discard_2, &discard_3 ); - if ( ( cpuid_extlevel & 0xffff0000 ) == 0x80000000 ) { - if ( cpuid_extlevel >= 0x80000001 ) { - cpuid ( 0x80000001, &discard_1, &discard_2, - &discard_3, &cpu->amd_features ); - } - } -} diff --git a/src/arch/i386/include/bits/cpu.h b/src/arch/i386/include/bits/cpu.h deleted file mode 100644 index 83339ddd..00000000 --- a/src/arch/i386/include/bits/cpu.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef I386_BITS_CPU_H -#define I386_BITS_CPU_H - -/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */ -#define X86_FEATURE_FPU 0 /* Onboard FPU */ -#define X86_FEATURE_VME 1 /* Virtual Mode Extensions */ -#define X86_FEATURE_DE 2 /* Debugging Extensions */ -#define X86_FEATURE_PSE 3 /* Page Size Extensions */ -#define X86_FEATURE_TSC 4 /* Time Stamp Counter */ -#define X86_FEATURE_MSR 5 /* Model-Specific Registers, RDMSR, WRMSR */ -#define X86_FEATURE_PAE 6 /* Physical Address Extensions */ -#define X86_FEATURE_MCE 7 /* Machine Check Architecture */ -#define X86_FEATURE_CX8 8 /* CMPXCHG8 instruction */ -#define X86_FEATURE_APIC 9 /* Onboard APIC */ -#define X86_FEATURE_SEP 11 /* SYSENTER/SYSEXIT */ -#define X86_FEATURE_MTRR 12 /* Memory Type Range Registers */ -#define X86_FEATURE_PGE 13 /* Page Global Enable */ -#define X86_FEATURE_MCA 14 /* Machine Check Architecture */ -#define X86_FEATURE_CMOV 15 /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ -#define X86_FEATURE_PAT 16 /* Page Attribute Table */ -#define X86_FEATURE_PSE36 17 /* 36-bit PSEs */ -#define X86_FEATURE_PN 18 /* Processor serial number */ -#define X86_FEATURE_CLFLSH 19 /* Supports the CLFLUSH instruction */ -#define X86_FEATURE_DTES 21 /* Debug Trace Store */ -#define X86_FEATURE_ACPI 22 /* ACPI via MSR */ -#define X86_FEATURE_MMX 23 /* Multimedia Extensions */ -#define X86_FEATURE_FXSR 24 /* FXSAVE and FXRSTOR instructions (fast save and restore */ - /* of FPU context), and CR4.OSFXSR available */ -#define X86_FEATURE_XMM 25 /* Streaming SIMD Extensions */ -#define X86_FEATURE_XMM2 26 /* Streaming SIMD Extensions-2 */ -#define X86_FEATURE_SELFSNOOP 27 /* CPU self snoop */ -#define X86_FEATURE_HT 28 /* Hyper-Threading */ -#define X86_FEATURE_ACC 29 /* Automatic clock control */ -#define X86_FEATURE_IA64 30 /* IA-64 processor */ - -/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ -/* Don't duplicate feature flags which are redundant with Intel! */ -#define X86_FEATURE_SYSCALL 11 /* SYSCALL/SYSRET */ -#define X86_FEATURE_MMXEXT 22 /* AMD MMX extensions */ -#define X86_FEATURE_LM 29 /* Long Mode (x86-64) */ -#define X86_FEATURE_3DNOWEXT 30 /* AMD 3DNow! extensions */ -#define X86_FEATURE_3DNOW 31 /* 3DNow! */ - -/** x86 CPU information */ -struct cpuinfo_x86 { - /** CPU features */ - unsigned int features; - /** 64-bit CPU features */ - unsigned int amd_features; -}; - -/* - * EFLAGS bits - */ -#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ -#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ -#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ -#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ -#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ -#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ -#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ -#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ -#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ -#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ -#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ -#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ -#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ -#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ -#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ -#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ -#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ - -/* - * Generic CPUID function - */ -static inline __attribute__ (( always_inline )) void -cpuid ( int op, unsigned int *eax, unsigned int *ebx, - unsigned int *ecx, unsigned int *edx ) { - __asm__ ( "cpuid" : - "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx ) - : "0" ( op ) ); -} - -extern void get_cpuinfo ( struct cpuinfo_x86 *cpu ); - -#endif /* I386_BITS_CPU_H */ diff --git a/src/arch/x86/Makefile b/src/arch/x86/Makefile index 37e03aaf..cdd397d4 100644 --- a/src/arch/x86/Makefile +++ b/src/arch/x86/Makefile @@ -7,6 +7,7 @@ INCDIRS += arch/x86/include SRCDIRS += arch/x86/core SRCDIRS += arch/x86/interface/efi SRCDIRS += arch/x86/prefix +SRCDIRS += arch/x86/hci/commands # breaks building some of the linux-related objects CFLAGS += -Ulinux diff --git a/src/arch/x86/core/cpuid.c b/src/arch/x86/core/cpuid.c new file mode 100644 index 00000000..cf9dd6dd --- /dev/null +++ b/src/arch/x86/core/cpuid.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +/** @file + * + * x86 CPU feature detection + * + */ + +/** + * Check whether or not CPUID instruction is supported + * + * @ret is_supported CPUID instruction is supported + */ +static int cpuid_is_supported ( void ) { + unsigned long original; + unsigned long inverted; + + __asm__ ( "pushf\n\t" + "pushf\n\t" + "pop %0\n\t" + "mov %0,%1\n\t" + "xor %2,%1\n\t" + "push %1\n\t" + "popf\n\t" + "pushf\n\t" + "pop %1\n\t" + "popf\n\t" + : "=&r" ( original ), "=&r" ( inverted ) + : "ir" ( CPUID_FLAG ) ); + return ( ( original ^ inverted ) & CPUID_FLAG ); +} + +/** + * Issue CPUID instruction + * + * @v operation CPUID operation + * @v eax Output via %eax + * @v ebx Output via %ebx + * @v ecx Output via %ecx + * @v edx Output via %edx + */ +static inline __attribute__ (( always_inline )) void +cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, + uint32_t *edx ) { + + __asm__ ( "cpuid" + : "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx ) + : "0" ( operation ) ); +} + +/** + * Get Intel-defined x86 CPU features + * + * @v features x86 CPU features to fill in + */ +static void x86_intel_features ( struct x86_features *features ) { + uint32_t max_level; + uint32_t discard_a; + uint32_t discard_b; + uint32_t discard_c; + uint32_t discard_d; + + /* Check that features are available via CPUID */ + cpuid ( CPUID_VENDOR_ID, &max_level, &discard_b, &discard_c, + &discard_d ); + if ( max_level < CPUID_FEATURES ) { + DBGC ( features, "CPUID has no Intel-defined features (max " + "level %08x)\n", max_level ); + return; + } + + /* Get features */ + cpuid ( CPUID_FEATURES, &discard_a, &discard_b, + &features->intel.ecx, &features->intel.edx ); + DBGC ( features, "CPUID Intel features: %%ecx=%08x, %%edx=%08x\n", + features->intel.ecx, features->intel.edx ); + +} + +/** + * Get AMD-defined x86 CPU features + * + * @v features x86 CPU features to fill in + */ +static void x86_amd_features ( struct x86_features *features ) { + uint32_t max_level; + uint32_t discard_a; + uint32_t discard_b; + uint32_t discard_c; + uint32_t discard_d; + + /* Check that features are available via CPUID */ + cpuid ( CPUID_AMD_MAX_FN, &max_level, &discard_b, &discard_c, + &discard_d ); + if ( ( max_level & CPUID_AMD_CHECK_MASK ) != CPUID_AMD_CHECK ) { + DBGC ( features, "CPUID has no extended functions\n" ); + return; + } + if ( max_level < CPUID_AMD_FEATURES ) { + DBGC ( features, "CPUID has no AMD-defined features (max " + "level %08x)\n", max_level ); + return; + } + + /* Get features */ + cpuid ( CPUID_AMD_FEATURES, &discard_a, &discard_b, + &features->amd.ecx, &features->amd.edx ); + DBGC ( features, "CPUID AMD features: %%ecx=%08x, %%edx=%08x\n", + features->amd.ecx, features->amd.edx ); +} + +/** + * Get x86 CPU features + * + * @v features x86 CPU features to fill in + */ +void x86_features ( struct x86_features *features ) { + + /* Clear all features */ + memset ( features, 0, sizeof ( *features ) ); + + /* Check that CPUID instruction is available */ + if ( ! cpuid_is_supported() ) { + DBGC ( features, "CPUID instruction is not supported\n" ); + return; + } + + /* Get Intel-defined features */ + x86_intel_features ( features ); + + /* Get AMD-defined features */ + x86_amd_features ( features ); +} diff --git a/src/arch/x86/hci/commands/cpuid_cmd.c b/src/arch/x86/hci/commands/cpuid_cmd.c new file mode 100644 index 00000000..3172727e --- /dev/null +++ b/src/arch/x86/hci/commands/cpuid_cmd.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * x86 CPU feature detection command + * + */ + +/** "cpuid" options */ +struct cpuid_options { + /** Check AMD-defined features (%eax=0x80000001) */ + int amd; + /** Check features defined via %ecx */ + int ecx; +}; + +/** "cpuid" option list */ +static struct option_descriptor cpuid_opts[] = { + OPTION_DESC ( "amd", 'a', no_argument, + struct cpuid_options, amd, parse_flag ), + OPTION_DESC ( "ecx", 'c', no_argument, + struct cpuid_options, ecx, parse_flag ), +}; + +/** "cpuid" command descriptor */ +static struct command_descriptor cpuid_cmd = + COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1, + "[--amd] [--ecx] " ); + +/** + * The "cpuid" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int cpuid_exec ( int argc, char **argv ) { + struct cpuid_options opts; + struct x86_features features; + struct x86_feature_registers *feature_regs; + uint32_t feature_reg; + unsigned int bit; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &cpuid_cmd, &opts ) ) != 0 ) + return rc; + + /* Parse bit number */ + if ( ( rc = parse_integer ( argv[optind], &bit ) ) != 0 ) + return rc; + + /* Get CPU features */ + x86_features ( &features ); + + /* Extract relevant feature register */ + feature_regs = ( opts.amd ? &features.amd : &features.intel ); + feature_reg = ( opts.ecx ? feature_regs->ecx : feature_regs->edx ); + + /* Check presence of specified feature */ + return ( ( feature_reg & ( 1 << bit ) ) ? 0 : -ENOENT ); +} + +/** x86 CPU feature detection command */ +struct command cpuid_command __command = { + .name = "cpuid", + .exec = cpuid_exec, +}; diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index ccf00b86..f66cbaa1 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -38,8 +38,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_undionly ( ERRFILE_ARCH | ERRFILE_NET | 0x00030000 ) #define ERRFILE_undirom ( ERRFILE_ARCH | ERRFILE_NET | 0x00040000 ) -#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 ) -#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 ) +#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 ) +#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 ) + +#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 ) /** @} */ diff --git a/src/arch/x86/include/ipxe/cpuid.h b/src/arch/x86/include/ipxe/cpuid.h new file mode 100644 index 00000000..9705137c --- /dev/null +++ b/src/arch/x86/include/ipxe/cpuid.h @@ -0,0 +1,53 @@ +#ifndef _IPXE_CPUID_H +#define _IPXE_CPUID_H + +/** @file + * + * x86 CPU feature detection + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** An x86 CPU feature register set */ +struct x86_feature_registers { + /** Features returned via %ecx */ + uint32_t ecx; + /** Features returned via %edx */ + uint32_t edx; +}; + +/** x86 CPU features */ +struct x86_features { + /** Intel-defined features (%eax=0x00000001) */ + struct x86_feature_registers intel; + /** AMD-defined features (%eax=0x80000001) */ + struct x86_feature_registers amd; +}; + +/** CPUID support flag */ +#define CPUID_FLAG 0x00200000UL + +/** Get vendor ID and largest standard function */ +#define CPUID_VENDOR_ID 0x00000000UL + +/** Get standard features */ +#define CPUID_FEATURES 0x00000001UL + +/** Get largest extended function */ +#define CPUID_AMD_MAX_FN 0x80000000UL + +/** Extended function existence check */ +#define CPUID_AMD_CHECK 0x80000000UL + +/** Extended function existence check mask */ +#define CPUID_AMD_CHECK_MASK 0xffff0000UL + +/** Get extended features */ +#define CPUID_AMD_FEATURES 0x80000001UL + +extern void x86_features ( struct x86_features *features ); + +#endif /* _IPXE_CPUID_H */ diff --git a/src/config/config.c b/src/config/config.c index 9c1df1f3..eebd849b 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -238,6 +238,9 @@ REQUIRE_OBJECT ( vlan_cmd ); #ifdef REBOOT_CMD REQUIRE_OBJECT ( reboot_cmd ); #endif +#ifdef CPUID_CMD +REQUIRE_OBJECT ( cpuid_cmd ); +#endif /* * Drag in miscellaneous objects diff --git a/src/config/defaults/pcbios.h b/src/config/defaults/pcbios.h index b68186f1..c52fca97 100644 --- a/src/config/defaults/pcbios.h +++ b/src/config/defaults/pcbios.h @@ -36,5 +36,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define SANBOOT_PROTO_FCP /* Fibre Channel protocol */ #define REBOOT_CMD /* Reboot command */ +#define CPUID_CMD /* x86 CPU feature detection command */ #endif /* CONFIG_DEFAULTS_PCBIOS_H */ From 021d7b21b7f30a8de9ff56ae3a70026bafcdc542 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 9 Jun 2012 18:48:09 +0100 Subject: [PATCH 032/250] [pending] Add concept of "pending operations" iPXE is fundamentally asynchronous in operation: some operations continue in the background even after the foreground has continued to a new task. For example, the closing FIN/ACK exchanges of a TCP connection will take place in the background after an HTTP download has completed. Signed-off-by: Michael Brown --- src/core/pending.c | 79 ++++++++++++++++++++++++++++++++++++++ src/include/ipxe/errfile.h | 1 + src/include/ipxe/pending.h | 34 ++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/core/pending.c create mode 100644 src/include/ipxe/pending.h diff --git a/src/core/pending.c b/src/core/pending.c new file mode 100644 index 00000000..da540fec --- /dev/null +++ b/src/core/pending.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include + +/** @file + * + * Pending operations + * + */ + +/** Total count of pending operations */ +static int pending_total; + +/** + * Mark an operation as pending + * + * @v pending Pending operation + */ +void pending_get ( struct pending_operation *pending ) { + + pending->count++; + pending_total++; + DBGC ( pending, "PENDING %p incremented to %d (total %d)\n", + pending, pending->count, pending_total ); +} + +/** + * Mark an operation as no longer pending + * + * @v pending Pending operation + */ +void pending_put ( struct pending_operation *pending ) { + + if ( pending->count ) { + pending_total--; + pending->count--; + DBGC ( pending, "PENDING %p decremented to %d (total %d)\n", + pending, pending->count, pending_total ); + } +} + +/** + * Wait for pending operations to complete + * + * @v timeout Timeout period, in ticks (0=indefinite) + * @ret rc Return status code + */ +int pending_wait ( unsigned long timeout ) { + unsigned long start = currticks(); + + do { + if ( pending_total == 0 ) + return 0; + step(); + } while ( ( timeout == 0 ) || ( ( currticks() - start ) < timeout ) ); + + return -ETIMEDOUT; +} diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 108efc7a..5fc0e082 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -62,6 +62,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_parseopt ( ERRFILE_CORE | 0x00160000 ) #define ERRFILE_test ( ERRFILE_CORE | 0x00170000 ) #define ERRFILE_xferbuf ( ERRFILE_CORE | 0x00180000 ) +#define ERRFILE_pending ( ERRFILE_CORE | 0x00190000 ) #define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 ) #define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 ) diff --git a/src/include/ipxe/pending.h b/src/include/ipxe/pending.h new file mode 100644 index 00000000..51afb437 --- /dev/null +++ b/src/include/ipxe/pending.h @@ -0,0 +1,34 @@ +#ifndef _IPXE_PENDING_H +#define _IPXE_PENDING_H + +/** @file + * + * Pending operations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** A pending operation */ +struct pending_operation { + /** Pending count */ + unsigned int count; +}; + +/** + * Check if an operation is pending + * + * @v pending Pending operation + * @v is_pending Operation is pending + */ +static inline int is_pending ( struct pending_operation *pending ) { + return ( pending->count != 0 ); +} + +extern void pending_get ( struct pending_operation *pending ); +extern void pending_put ( struct pending_operation *pending ); +extern int pending_wait ( unsigned long timeout ); + +#endif /* _IPXE_PENDING_H */ From 5482b0abb6518916b4036aafab0d65e7bad7b2e8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 9 Jun 2012 18:56:07 +0100 Subject: [PATCH 033/250] [tcp] Mark any unacknowledged transmission as a pending operation Signed-off-by: Michael Brown --- src/net/tcp.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/net/tcp.c b/src/net/tcp.c index b1533915..c6bb4a66 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -95,6 +96,11 @@ struct tcp_connection { struct retry_timer timer; /** Shutdown (TIME_WAIT) timer */ struct retry_timer wait; + + /** Pending operations for SYN and FIN */ + struct pending_operation pending_flags; + /** Pending operations for transmit queue */ + struct pending_operation pending_data; }; /** TCP flags */ @@ -291,6 +297,9 @@ static int tcp_open ( struct interface *xfer, struct sockaddr *peer, /* Start timer to initiate SYN */ start_timer_nodelay ( &tcp->timer ); + /* Add a pending operation for the SYN */ + pending_get ( &tcp->pending_flags ); + /* Attach parent interface, transfer reference to connection * list and return */ @@ -340,7 +349,13 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) { list_for_each_entry_safe ( iobuf, tmp, &tcp->tx_queue, list ) { list_del ( &iobuf->list ); free_iob ( iobuf ); + pending_put ( &tcp->pending_data ); } + assert ( ! is_pending ( &tcp->pending_data ) ); + + /* Remove pending operations for SYN and FIN, if applicable */ + pending_put ( &tcp->pending_flags ); + pending_put ( &tcp->pending_flags ); /* Remove from list and drop reference */ stop_timer ( &tcp->timer ); @@ -359,9 +374,14 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) { tcp_rx_ack ( tcp, ( tcp->snd_seq + 1 ), 0 ); /* If we have no data remaining to send, start sending FIN */ - if ( list_empty ( &tcp->tx_queue ) ) { + if ( list_empty ( &tcp->tx_queue ) && + ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) { + tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN ); tcp_dump_state ( tcp ); + + /* Add a pending operation for the FIN */ + pending_get ( &tcp->pending_flags ); } } @@ -446,6 +466,7 @@ static size_t tcp_process_tx_queue ( struct tcp_connection *tcp, size_t max_len, if ( ! iob_len ( iobuf ) ) { list_del ( &iobuf->list ); free_iob ( iobuf ); + pending_put ( &tcp->pending_data ); } } len += frag_len; @@ -869,8 +890,10 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack, len = ack_len; acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) & ( TCP_SYN | TCP_FIN ) ); - if ( acked_flags ) + if ( acked_flags ) { len--; + pending_put ( &tcp->pending_flags ); + } /* Update SEQ and sent counters, and window size */ tcp->snd_seq = ack; @@ -885,8 +908,12 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack, tcp->tcp_state |= TCP_STATE_ACKED ( acked_flags ); /* Start sending FIN if we've had all possible data ACKed */ - if ( list_empty ( &tcp->tx_queue ) && ( tcp->flags & TCP_XFER_CLOSED ) ) + if ( list_empty ( &tcp->tx_queue ) && + ( tcp->flags & TCP_XFER_CLOSED ) && + ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) { tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN ); + pending_get ( &tcp->pending_flags ); + } return 0; } @@ -1320,6 +1347,9 @@ static int tcp_xfer_deliver ( struct tcp_connection *tcp, /* Enqueue packet */ list_add_tail ( &iobuf->list, &tcp->tx_queue ); + /* Each enqueued packet is a pending operation */ + pending_get ( &tcp->pending_data ); + /* Transmit data, if possible */ tcp_xmit ( tcp ); From af47789ef2276fdb3b081955025b778d16ed2188 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 9 Jun 2012 18:58:54 +0100 Subject: [PATCH 034/250] [tls] Mark security negotiation as a pending operation Signed-off-by: Michael Brown --- src/include/ipxe/tls.h | 9 +++++---- src/net/tls.c | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 7de1f19e..4273e4e5 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** A TLS header */ struct tls_header { @@ -240,10 +241,10 @@ struct tls_session { /** Certificate validator */ struct interface validator; - /** Client has finished security negotiation */ - unsigned int client_finished; - /** Server has finished security negotiation */ - unsigned int server_finished; + /** Client security negotiation pending operation */ + struct pending_operation client_negotiation; + /** Server security negotiation pending operation */ + struct pending_operation server_negotiation; /** TX sequence number */ uint64_t tx_seq; diff --git a/src/net/tls.c b/src/net/tls.c index 97e013d7..8d6620d3 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -101,7 +102,8 @@ static void tls_set_uint24 ( uint8_t field24[3], unsigned long value ) { * @ret is_ready TLS session is ready */ static int tls_ready ( struct tls_session *tls ) { - return ( tls->client_finished && tls->server_finished ); + return ( ( ! is_pending ( &tls->client_negotiation ) ) && + ( ! is_pending ( &tls->server_negotiation ) ) ); } /****************************************************************************** @@ -205,6 +207,10 @@ static void free_tls ( struct refcnt *refcnt ) { */ static void tls_close ( struct tls_session *tls, int rc ) { + /* Remove pending operations, if applicable */ + pending_put ( &tls->client_negotiation ); + pending_put ( &tls->server_negotiation ); + /* Remove process */ process_del ( &tls->process ); @@ -1141,7 +1147,7 @@ static int tls_send_finished ( struct tls_session *tls ) { return rc; /* Mark client as finished */ - tls->client_finished = 1; + pending_put ( &tls->client_negotiation ); return 0; } @@ -1489,7 +1495,7 @@ static int tls_new_finished ( struct tls_session *tls, } /* Mark server as finished */ - tls->server_finished = 1; + pending_put ( &tls->server_negotiation ); /* Send notification of a window change */ xfer_window_changed ( &tls->plainstream ); @@ -2396,6 +2402,10 @@ int add_tls ( struct interface *xfer, const char *name, tls->handshake_ctx = tls->handshake_sha256_ctx; tls->tx_pending = TLS_TX_CLIENT_HELLO; + /* Add pending operations for server and client Finished messages */ + pending_get ( &tls->client_negotiation ); + pending_get ( &tls->server_negotiation ); + /* Attach to parent interface, mortalise self, and return */ intf_plug_plug ( &tls->plainstream, xfer ); *next = &tls->cipherstream; From addf699c86ae18edd7de13433da78be926c22504 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 9 Jun 2012 19:00:04 +0100 Subject: [PATCH 035/250] [cmdline] Add "sync" command Add "sync" command (loosely based on the Unix "sync"), which will wait for any pending operations to complete. Signed-off-by: Michael Brown --- src/config/config.c | 3 ++ src/config/general.h | 1 + src/hci/commands/sync_cmd.c | 82 +++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 src/hci/commands/sync_cmd.c diff --git a/src/config/config.c b/src/config/config.c index eebd849b..202da726 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -241,6 +241,9 @@ REQUIRE_OBJECT ( reboot_cmd ); #ifdef CPUID_CMD REQUIRE_OBJECT ( cpuid_cmd ); #endif +#ifdef SYNC_CMD +REQUIRE_OBJECT ( sync_cmd ); +#endif /* * Drag in miscellaneous objects diff --git a/src/config/general.h b/src/config/general.h index 22a901d6..6fc39831 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -117,6 +117,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define SANBOOT_CMD /* SAN boot commands */ #define MENU_CMD /* Menu commands */ #define LOGIN_CMD /* Login command */ +#define SYNC_CMD /* Sync command */ //#define TIME_CMD /* Time commands */ //#define DIGEST_CMD /* Image crypto digest commands */ //#define LOTEST_CMD /* Loopback testing commands */ diff --git a/src/hci/commands/sync_cmd.c b/src/hci/commands/sync_cmd.c new file mode 100644 index 00000000..f0845133 --- /dev/null +++ b/src/hci/commands/sync_cmd.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * "sync" command + * + */ + +/** "sync" options */ +struct sync_options { + /** Timeout */ + unsigned int timeout; +}; + +/** "sync" option list */ +static struct option_descriptor sync_opts[] = { + OPTION_DESC ( "timeout", 't', required_argument, + struct sync_options, timeout, parse_integer ), +}; + +/** "sync" command descriptor */ +static struct command_descriptor sync_cmd = + COMMAND_DESC ( struct sync_options, sync_opts, 0, 0, + "[--timeout ]" ); + +/** + * "sync" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int sync_exec ( int argc, char **argv ) { + struct sync_options opts; + unsigned long timeout; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &sync_cmd, &opts ) ) != 0 ) + return rc; + + /* Wait for pending operations to complete */ + timeout = ( ( opts.timeout * TICKS_PER_SEC ) / 1000 ); + if ( ( rc = pending_wait ( timeout ) ) != 0 ) { + printf ( "Operations did not complete: %s\n", strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** Sync commands */ +struct command sync_command __command = { + .name = "sync", + .exec = sync_exec, +}; From cdee7866f5d81e873a4ac70a3c10d0a02141b163 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 12 Jun 2012 11:32:24 +0100 Subject: [PATCH 036/250] [cmdline] Use "cpuid --ext" instead of "cpuid --amd" Avoid potential confusion in the documentation by using a vendor-neutral name for the extended (AMD-defined) feature set. Signed-off-by: Michael Brown --- src/arch/x86/hci/commands/cpuid_cmd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/arch/x86/hci/commands/cpuid_cmd.c b/src/arch/x86/hci/commands/cpuid_cmd.c index 3172727e..6659bf60 100644 --- a/src/arch/x86/hci/commands/cpuid_cmd.c +++ b/src/arch/x86/hci/commands/cpuid_cmd.c @@ -42,6 +42,9 @@ struct cpuid_options { /** "cpuid" option list */ static struct option_descriptor cpuid_opts[] = { + OPTION_DESC ( "ext", 'e', no_argument, + struct cpuid_options, amd, parse_flag ), + /* "--amd" retained for backwards compatibility */ OPTION_DESC ( "amd", 'a', no_argument, struct cpuid_options, amd, parse_flag ), OPTION_DESC ( "ecx", 'c', no_argument, @@ -51,7 +54,7 @@ static struct option_descriptor cpuid_opts[] = { /** "cpuid" command descriptor */ static struct command_descriptor cpuid_cmd = COMMAND_DESC ( struct cpuid_options, cpuid_opts, 1, 1, - "[--amd] [--ecx] " ); + "[--ext] [--ecx] " ); /** * The "cpuid" command From f2e5f8813e9a867cae76305d4186dcf26e5fa22a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 10 Jun 2012 18:23:24 +0100 Subject: [PATCH 037/250] [util] Allow Option::ROM to access multiple ROM images Signed-off-by: Michael Brown --- src/util/Option/ROM.pm | 74 ++++++++++++++++++++++++++++-- src/util/disrom.pl | 100 ++++++++++++++++++++++------------------- src/util/fixrom.pl | 8 +++- 3 files changed, 129 insertions(+), 53 deletions(-) diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm index 9fea4d34..b2b94c3e 100644 --- a/src/util/Option/ROM.pm +++ b/src/util/Option/ROM.pm @@ -169,9 +169,11 @@ use Exporter 'import'; use constant ROM_SIGNATURE => 0xaa55; use constant PCI_SIGNATURE => 'PCIR'; +use constant PCI_LAST_IMAGE => 0x80; use constant PNP_SIGNATURE => '$PnP'; -our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PNP_SIGNATURE ); +our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE + PNP_SIGNATURE ); our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); use constant JMP_SHORT => 0xeb; @@ -241,6 +243,53 @@ sub new { =pod +=item C<< set ( $data ) >> + +Set option ROM contents. + +=cut + +sub set { + my $hash = shift; + my $self = tied(%$hash); + my $data = shift; + + # Store data + $self->{data} = \$data; + + # Split out any data belonging to the next image + delete $self->{next_image}; + my $length = ( $hash->{length} * 512 ); + my $pci_header = $hash->pci_header(); + if ( ( $length < length $data ) && + ( defined $pci_header ) && + ( ! ( $pci_header->{last_image} & PCI_LAST_IMAGE ) ) ) { + my $remainder = substr ( $data, $length ); + $data = substr ( $data, 0, $length ); + $self->{next_image} = new Option::ROM; + $self->{next_image}->set ( $remainder ); + } +} + +=pod + +=item C<< get () >> + +Get option ROM contents. + +=cut + +sub get { + my $hash = shift; + my $self = tied(%$hash); + + my $data = ${$self->{data}}; + $data .= $self->{next_image}->get() if $self->{next_image}; + return $data; +} + +=pod + =item C<< load ( $filename ) >> Load option ROM contents from the file C<$filename>. @@ -256,8 +305,8 @@ sub load { open my $fh, "<$filename" or croak "Cannot open $filename for reading: $!"; - read $fh, my $data, ( 128 * 1024 ); # 128kB is theoretical max size - $self->{data} = \$data; + read $fh, my $data, -s $fh; + $hash->set ( $data ); close $fh; } @@ -279,7 +328,8 @@ sub save { open my $fh, ">$filename" or croak "Cannot open $filename for writing: $!"; - print $fh ${$self->{data}}; + my $data = $hash->get(); + print $fh $data; close $fh; } @@ -339,6 +389,22 @@ sub pnp_header { =pod +=item C<< next_image () >> + +Return a C object representing the next image within the +ROM, if present. + +=cut + +sub next_image { + my $hash = shift; + my $self = tied(%$hash); + + return $self->{next_image}; +} + +=pod + =item C<< checksum () >> Calculate the byte checksum of the ROM. diff --git a/src/util/disrom.pl b/src/util/disrom.pl index 1fb4cc3c..aff972ea 100755 --- a/src/util/disrom.pl +++ b/src/util/disrom.pl @@ -27,55 +27,61 @@ my $romfile = shift || "-"; my $rom = new Option::ROM; $rom->load ( $romfile ); -die "Not an option ROM image\n" - unless $rom->{signature} == ROM_SIGNATURE; +do { -my $romlength = ( $rom->{length} * 512 ); -my $filelength = $rom->length; -die "ROM image truncated (is $filelength, should be $romlength)\n" - if $filelength < $romlength; + die "Not an option ROM image\n" + unless $rom->{signature} == ROM_SIGNATURE; -printf "ROM header:\n\n"; -printf " %-16s 0x%02x (%d)\n", "Length:", $rom->{length}, ( $rom->{length} * 512 ); -printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $rom->{checksum}, - ( ( $rom->checksum == 0 ) ? "" : "INCORRECT: " ), $rom->checksum; -printf " %-16s 0x%04x\n", "Init:", $rom->{init}; -printf " %-16s 0x%04x\n", "UNDI header:", $rom->{undi_header}; -printf " %-16s 0x%04x\n", "PCI header:", $rom->{pci_header}; -printf " %-16s 0x%04x\n", "PnP header:", $rom->{pnp_header}; -printf "\n"; + my $romlength = ( $rom->{length} * 512 ); + my $filelength = $rom->length; + die "ROM image truncated (is $filelength, should be $romlength)\n" + if $filelength < $romlength; -my $pci = $rom->pci_header(); -if ( $pci ) { - printf "PCI header:\n\n"; - printf " %-16s %s\n", "Signature:", $pci->{signature}; - printf " %-16s 0x%04x\n", "Vendor ID:", $pci->{vendor_id}; - printf " %-16s 0x%04x\n", "Device ID:", $pci->{device_id}; - printf " %-16s 0x%02x%02x%02x\n", "Device class:", - $pci->{base_class}, $pci->{sub_class}, $pci->{prog_intf}; - printf " %-16s 0x%04x (%d)\n", "Image length:", - $pci->{image_length}, ( $pci->{image_length} * 512 ); - printf " %-16s 0x%04x (%d)\n", "Runtime length:", - $pci->{runtime_length}, ( $pci->{runtime_length} * 512 ); - if ( exists $pci->{conf_header} ) { - printf " %-16s 0x%04x\n", "Config header:", $pci->{conf_header}; - printf " %-16s 0x%04x\n", "CLP entry:", $pci->{clp_entry}; + printf "ROM header:\n\n"; + printf " %-16s 0x%02x (%d)\n", "Length:", + $rom->{length}, ( $rom->{length} * 512 ); + printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $rom->{checksum}, + ( ( $rom->checksum == 0 ) ? "" : "INCORRECT: " ), $rom->checksum; + printf " %-16s 0x%04x\n", "Init:", $rom->{init}; + printf " %-16s 0x%04x\n", "UNDI header:", $rom->{undi_header}; + printf " %-16s 0x%04x\n", "PCI header:", $rom->{pci_header}; + printf " %-16s 0x%04x\n", "PnP header:", $rom->{pnp_header}; + printf "\n"; + + my $pci = $rom->pci_header(); + if ( $pci ) { + printf "PCI header:\n\n"; + printf " %-16s %s\n", "Signature:", $pci->{signature}; + printf " %-16s 0x%04x\n", "Vendor ID:", $pci->{vendor_id}; + printf " %-16s 0x%04x\n", "Device ID:", $pci->{device_id}; + printf " %-16s 0x%02x%02x%02x\n", "Device class:", + $pci->{base_class}, $pci->{sub_class}, $pci->{prog_intf}; + printf " %-16s 0x%04x (%d)\n", "Image length:", + $pci->{image_length}, ( $pci->{image_length} * 512 ); + printf " %-16s 0x%04x (%d)\n", "Runtime length:", + $pci->{runtime_length}, ( $pci->{runtime_length} * 512 ); + printf " %-16s 0x%02x\n", "Code type:", $pci->{code_type}; + if ( exists $pci->{conf_header} ) { + printf " %-16s 0x%04x\n", "Config header:", $pci->{conf_header}; + printf " %-16s 0x%04x\n", "CLP entry:", $pci->{clp_entry}; + } + printf "\n"; } - printf "\n"; -} -my $pnp = $rom->pnp_header(); -if ( $pnp ) { - printf "PnP header:\n\n"; - printf " %-16s %s\n", "Signature:", $pnp->{signature}; - printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $pnp->{checksum}, - ( ( $pnp->checksum == 0 ) ? "" : "INCORRECT: " ), $pnp->checksum; - printf " %-16s 0x%04x \"%s\"\n", "Manufacturer:", - $pnp->{manufacturer}, $pnp->manufacturer; - printf " %-16s 0x%04x \"%s\"\n", "Product:", - $pnp->{product}, $pnp->product; - printf " %-16s 0x%04x\n", "BCV:", $pnp->{bcv}; - printf " %-16s 0x%04x\n", "BDV:", $pnp->{bdv}; - printf " %-16s 0x%04x\n", "BEV:", $pnp->{bev}; - printf "\n"; -} + my $pnp = $rom->pnp_header(); + if ( $pnp ) { + printf "PnP header:\n\n"; + printf " %-16s %s\n", "Signature:", $pnp->{signature}; + printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $pnp->{checksum}, + ( ( $pnp->checksum == 0 ) ? "" : "INCORRECT: " ), $pnp->checksum; + printf " %-16s 0x%04x \"%s\"\n", "Manufacturer:", + $pnp->{manufacturer}, $pnp->manufacturer; + printf " %-16s 0x%04x \"%s\"\n", "Product:", + $pnp->{product}, $pnp->product; + printf " %-16s 0x%04x\n", "BCV:", $pnp->{bcv}; + printf " %-16s 0x%04x\n", "BDV:", $pnp->{bdv}; + printf " %-16s 0x%04x\n", "BEV:", $pnp->{bev}; + printf "\n"; + } + +} while ( $rom = $rom->next_image ); diff --git a/src/util/fixrom.pl b/src/util/fixrom.pl index c3a31f41..88f8cb83 100755 --- a/src/util/fixrom.pl +++ b/src/util/fixrom.pl @@ -28,7 +28,11 @@ my @romfiles = @ARGV; foreach my $romfile ( @romfiles ) { my $rom = new Option::ROM; $rom->load ( $romfile ); - $rom->pnp_header->fix_checksum() if $rom->pnp_header; - $rom->fix_checksum(); + my $image = $rom; + while ( $image ) { + $image->pnp_header->fix_checksum() if $image->pnp_header; + $image->fix_checksum(); + $image = $image->next_image(); + } $rom->save ( $romfile ); } From 12be8bc544b25fbed1fa5ef6c89cad42aaa268ea Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 11 Jun 2012 01:42:33 +0100 Subject: [PATCH 038/250] [util] Rewrite catrom.pl to use Option::ROM library Signed-off-by: Michael Brown --- src/util/catrom.pl | 49 ++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/src/util/catrom.pl b/src/util/catrom.pl index fe37e6b6..da99d7b9 100755 --- a/src/util/catrom.pl +++ b/src/util/catrom.pl @@ -3,46 +3,27 @@ use warnings; use strict; -use bytes; +use FindBin; +use lib "$FindBin::Bin"; +use Option::ROM qw ( :all ); -use constant MAX_ROM_LEN => 1024*1024; -use constant PCI_OFF => 0x18; -use constant INDICATOR_OFF => 0x15; - -my $total_len = 0; my @romfiles = @ARGV or die "Usage: $0 rom-file-1 rom-file-2 ... > multi-rom-file\n"; while ( my $romfile = shift @romfiles ) { - my $last = @romfiles ? 0 : 1; - open ROM, "<$romfile" or die "Could not open $romfile: $!\n"; - my $len = read ( ROM, my $romdata, MAX_ROM_LEN ) - or die "Could not read $romfile: $!\n"; - close ROM; + # Read ROM file + my $rom = new Option::ROM; + $rom->load ( $romfile ); - die "$romfile is not a ROM file\n" - unless substr ( $romdata, 0, 2 ) eq "\x55\xAA"; + # Tag final image as non-final in all except the final ROM + if ( @romfiles ) { + my $image = $rom; + $image = $image->next_image() while $image->next_image(); + $image->pci_header->{last_image} &= ~PCI_LAST_IMAGE; + $image->fix_checksum(); + } - ( my $checklen ) = unpack ( 'C', substr ( $romdata, 2, 1 ) ); - $checklen *= 512; - die "$romfile has incorrect length field $checklen (should be $len)\n" - unless $len == $checklen; - - ( my $pci ) = unpack ( 'v', substr ( $romdata, PCI_OFF, 2 ) ); - die "Invalid PCI offset field in $romfile\n" - if $pci >= $len; - die "No PCIR signature in $romfile\n" - unless substr ( $romdata, $pci, 4 ) eq "PCIR"; - - ( my $indicator ) = - unpack ( 'C', substr ( $romdata, $pci + INDICATOR_OFF, 1 ) ); - my $msg = sprintf ( "$romfile: indicator was %02x, ", $indicator ); - $indicator &= ! ( 1 << 7 ); - $indicator |= ( $last << 7 ); - $msg .= sprintf ( "now %02x\n", $indicator ); - substr ( $romdata, $pci + INDICATOR_OFF, 1 ) = pack ( 'C', $indicator ); - warn $msg; - - print $romdata; + # Write ROM file to STDOUT + $rom->save ( "-" ); } From 9e8d431a0d58caba3c5f65d4e30fd259d2f782e1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 10 Jun 2012 18:25:26 +0100 Subject: [PATCH 039/250] [romprefix] Add a dummy ROM header to cover the .mrom payload The header of a .mrom image declares its length to be only a few kilobytes; the remainder is accessed via a sideband mechanism. This makes it difficult to append an additional ROM image, such as an EFI ROM. Add a second, dummy ROM header covering the payload portion of the .mrom image, allowing consumers to locate any appended ROM images in the usual way. Signed-off-by: Michael Brown --- src/arch/i386/prefix/libprefix.S | 26 ++++---- src/arch/i386/prefix/mromprefix.S | 105 +++++++++++++++++++++++------- src/arch/i386/prefix/romprefix.S | 46 +++++-------- src/arch/i386/scripts/i386.lds | 25 ++++++- src/util/zbin.c | 70 +++++++++++++++++--- 5 files changed, 198 insertions(+), 74 deletions(-) diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S index 0962debb..e5bc7bb1 100644 --- a/src/arch/i386/prefix/libprefix.S +++ b/src/arch/i386/prefix/libprefix.S @@ -663,18 +663,22 @@ install_prealloc: /* Save decompression temporary area physical address */ pushl %edi - /* Install .text16.early */ + /* Install .text16.early and calculate %ecx as offset to next block */ progress " .text16.early\n" pushl %esi xorl %esi, %esi movw %cs, %si shll $4, %esi + pushl %esi /* Save original %cs:0000 */ addl $_text16_early_lma, %esi movzwl %ax, %edi shll $4, %edi movl $_text16_early_filesz, %ecx movl $_text16_early_memsz, %edx call install_block /* .text16.early */ + popl %ecx /* Calculate offset to next block */ + subl %esi, %ecx + negl %ecx popl %esi #ifndef KEEP_IT_REAL @@ -729,7 +733,7 @@ payload_death_message: jnz 1f movw %cs, %si shll $4, %esi -1: addl payload_lma, %esi +1: addl %ecx, %esi /* Install .text16.late and .data16 */ progress " .text16.late\n" @@ -850,17 +854,6 @@ close_payload_vector: .word 0 .size close_payload_vector, . - close_payload_vector - /* Payload address */ - .section ".prefix.lib", "awx", @progbits -payload_lma: - .long 0 - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADHL" - .long payload_lma - .long 1 - .long 0 - .previous - /* Dummy routines to open and close payload */ .section ".text16.early.data", "aw", @progbits .weak open_payload @@ -914,6 +907,10 @@ uninstall: .ascii "PAYL" .long 0 .long 0 + .long _payload_align + .ascii "COPY" + .long _pprefix_lma + .long _pprefix_filesz .long _max_align .ascii PACK_OR_COPY .long _text16_late_lma @@ -927,3 +924,6 @@ uninstall: .long _textdata_lma .long _textdata_filesz .long _max_align + + .weak _payload_align + .equ _payload_align, 1 diff --git a/src/arch/i386/prefix/mromprefix.S b/src/arch/i386/prefix/mromprefix.S index 7bbe44c4..d7b7fc3f 100644 --- a/src/arch/i386/prefix/mromprefix.S +++ b/src/arch/i386/prefix/mromprefix.S @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) #define PCI_BAR_EXPROM 0x30 #define ROMPREFIX_EXCLUDE_PAYLOAD 1 +#define ROMPREFIX_MORE_IMAGES 1 #define _rom_start _mrom_start #include "romprefix.S" @@ -46,8 +47,10 @@ FILE_LICENCE ( GPL2_OR_LATER ) * Parameters: * %ds:0000 : Prefix * %esi : Buffer for copy of image source (or zero if no buffer available) + * %ecx : Expected offset within buffer of first payload block * Returns: * %esi : Valid image source address (buffered or unbuffered) + * %ecx : Actual offset within buffer of first payload block * CF set on error */ .section ".text16.early", "awx", @progbits @@ -56,23 +59,25 @@ open_payload: /* Preserve registers */ pushl %eax pushw %bx - pushl %ecx pushl %edx pushl %edi pushw %bp + pushw %es pushw %ds - /* Retrieve bus:dev.fn and image source length from .prefix */ + /* Retrieve bus:dev.fn from .prefix */ movw init_pci_busdevfn, %bx - movl image_source_len_dword, %ecx /* Set up %ds for access to .text16.early */ pushw %cs popw %ds - /* Store bus:dev.fn and image source length to .text16.early */ + /* Set up %es for access to flat address space */ + xorw %ax, %ax + movw %ax, %es + + /* Store bus:dev.fn to .text16.early */ movw %bx, payload_pci_busdevfn - movl %ecx, rom_bar_copy_len_dword /* Get expansion ROM BAR current value */ movw $PCI_BAR_EXPROM, %di @@ -159,27 +164,32 @@ find_mem_bar: * properly support flat real mode, it will die horribly.) */ pushl %esi - pushw %es movl %esi, %edi movl %eax, %esi - movl rom_bar_copy_len_dword, %ecx - xorw %ax, %ax - movw %ax, %es + addr32 es movzbl 2(%esi), %ecx + shll $7, %ecx + addr32 es movzbl 2(%esi,%ecx,4), %edx + shll $7, %edx + addl %edx, %ecx addr32 es rep movsl - popw %es popl %esi jmp 2f 1: /* We have no buffer; set %esi to the BAR address */ movl %eax, %esi 2: + /* Locate first payload block (after the dummy ROM header) */ + addr32 es movzbl 2(%esi), %ecx + shll $9, %ecx + addl $_pprefix_skip, %ecx + clc /* Restore registers and return */ 99: popw %ds + popw %es popw %bp popl %edi popl %edx - popl %ecx popw %bx popl %eax lret @@ -200,11 +210,6 @@ rom_bar_size: .long 0 .size rom_bar_size, . - rom_bar_size - .section ".text16.early.data", "aw", @progbits -rom_bar_copy_len_dword: - .long 0 - .size rom_bar_copy_len_dword, . - rom_bar_copy_len_dword - .section ".text16.early.data", "aw", @progbits stolen_bar_register: .word 0 @@ -419,16 +424,68 @@ pci_set_mem_access: ret .size pci_set_mem_access, . - pci_set_mem_access -/* Image source area length (in dwords) +/* Payload prefix * + * We include a dummy ROM header to cover the "hidden" portion of the + * overall ROM image. */ - .section ".prefix", "ax", @progbits -image_source_len_dword: - .long 0 - .size image_source_len_dword, . - image_source_len_dword + .globl _payload_align + .equ _payload_align, 512 + .section ".pprefix", "ax", @progbits + .org 0x00 +mromheader: + .word 0xaa55 /* BIOS extension signature */ +mromheader_size: .byte 0 /* Size in 512-byte blocks */ + .org 0x18 + .word mpciheader + .org 0x1a + .word 0 + .size mromheader, . - mromheader + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDL" - .long image_source_len_dword - .long 4 + .ascii "APPB" + .long mromheader_size + .long 512 + .long 0 + .previous + +mpciheader: + .ascii "PCIR" /* Signature */ + .word pci_vendor_id /* Vendor identification */ + .word pci_device_id /* Device identification */ + .word 0x0000 /* Device list pointer */ + .word mpciheader_len /* PCI data structure length */ + .byte 0x03 /* PCI data structure revision */ + .byte 0x02, 0x00, 0x00 /* Class code */ +mpciheader_image_length: + .word 0 /* Image length */ + .word 0x0001 /* Revision level */ + .byte 0xff /* Code type */ + .byte 0x80 /* Last image indicator */ +mpciheader_runtime_length: + .word 0 /* Maximum run-time image length */ + .word 0x0000 /* Configuration utility code header */ + .word 0x0000 /* DMTF CLP entry point */ + .equ mpciheader_len, . - mpciheader + .size mpciheader, . - mpciheader + + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "APPW" + .long mpciheader_image_length + .long 512 + .long 0 + .ascii "APPW" + .long mpciheader_runtime_length + .long 512 + .long 0 + .previous + +/* Fix up additional image source size + * + */ + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "ADPW" + .long extra_size + .long 512 .long 0 .previous diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 0f924153..950e0845 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -39,6 +39,14 @@ FILE_LICENCE ( GPL2_OR_LATER ) #else #define ZINFO_TYPE_ADxB "ADDB" #define ZINFO_TYPE_ADxW "ADDW" +#endif + +/* Allow ROM to be marked as containing multiple images + */ +#if ROMPREFIX_MORE_IMAGES +#define INDICATOR 0x00 +#else +#define INDICATOR 0x80 #endif .text @@ -85,7 +93,7 @@ pciheader_image_length: .word 0 /* Image length */ .word 0x0001 /* Revision level */ .byte 0x00 /* Code type */ - .byte 0x80 /* Last image indicator */ + .byte INDICATOR /* Last image indicator */ pciheader_runtime_length: .word 0 /* Maximum run-time image length */ .word 0x0000 /* Configuration utility code header */ @@ -98,7 +106,7 @@ pciheader_runtime_length: .long pciheader_image_length .long 512 .long 0 - .ascii ZINFO_TYPE_ADxW + .ascii "ADHW" .long pciheader_runtime_length .long 512 .long 0 @@ -327,7 +335,8 @@ pmm_scan: /* We have PMM and so a 1kB stack: preserve whole registers */ pushal /* Allocate image source PMM block */ - movzwl image_source_size, %ecx + movzbl romheader_size, %ecx + addw extra_size, %cx shll $5, %ecx movl $PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx movw $get_pmm_image_source, %bp @@ -341,11 +350,11 @@ pmm_scan: movl %esi, %edi xorl %esi, %esi movzbl romheader_size, %ecx - shll $9, %ecx - addr32 rep movsb /* PMM presence implies flat real mode */ + shll $7, %ecx + addr32 rep movsl /* PMM presence implies flat real mode */ popw %es /* Shrink ROM */ - movb shrunk_rom_size, %al + movw pciheader_runtime_length, %ax movb %al, romheader_size 1: /* Allocate decompression PMM block. Round up the size to the * nearest 128kB and use the size within the PMM handle; this @@ -573,31 +582,12 @@ image_source: .long 0 .size image_source, . - image_source -/* Image source size (in 512-byte sectors) +/* Additional image source size (in 512-byte sectors) * */ -image_source_size: +extra_size: .word 0 - .size image_source_size, . - image_source_size - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADDW" - .long image_source_size - .long 512 - .long 0 - .previous - -/* Shrunk ROM size (in 512-byte sectors) - * - */ -shrunk_rom_size: - .byte 0 - .size shrunk_rom_size, . - shrunk_rom_size - .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ - .ascii "ADHB" - .long shrunk_rom_size - .long 512 - .long 0 - .previous + .size extra_size, . - extra_size /* Temporary decompression area * diff --git a/src/arch/i386/scripts/i386.lds b/src/arch/i386/scripts/i386.lds index 763b80d6..fb763656 100644 --- a/src/arch/i386/scripts/i386.lds +++ b/src/arch/i386/scripts/i386.lds @@ -1,4 +1,4 @@ -/* -*- sh -*- */ +/* -*- ld-script -*- */ /* * Linker script for i386 images @@ -121,6 +121,23 @@ SECTIONS { _textdata_filesz = ABSOLUTE ( _mtextdata ) - ABSOLUTE ( _textdata ); _textdata_memsz = ABSOLUTE ( _etextdata ) - ABSOLUTE ( _textdata ); + /* + * Payload prefix + * + * If present, this will be placed between .text16.early and .text16.late. + * + */ + .pprefix 0x0 : AT ( _pprefix_lma ) { + _pprefix = .; + KEEP(*(.pprefix)) + KEEP(*(.pprefix.*)) + _mpprefix = .; + } .bss.pprefix (NOLOAD) : AT ( _end_lma ) { + _epprefix = .; + } + _pprefix_filesz = ABSOLUTE ( _mpprefix ) - ABSOLUTE ( _pprefix ); + _pprefix_memsz = ABSOLUTE ( _epprefix ) - ABSOLUTE ( _pprefix ); + /* * Compressor information block * @@ -187,8 +204,14 @@ SECTIONS { _text16_early_lma = .; . += _text16_early_filesz; + . = ALIGN ( _max_align ); + . = ALIGN ( _payload_align ); + _pprefix_lma = .; + . += _pprefix_filesz; + . = ALIGN ( _max_align ); _payload_lma = .; + _pprefix_skip = ABSOLUTE ( _payload_lma ) - ABSOLUTE ( _pprefix_lma ); _text16_late_lma = .; . += _text16_late_filesz; diff --git a/src/util/zbin.c b/src/util/zbin.c index a9195164..0dabaf1e 100644 --- a/src/util/zbin.c +++ b/src/util/zbin.c @@ -237,15 +237,15 @@ static int process_zinfo_add ( struct input_file *input __attribute__ (( unused )), struct output_file *output, size_t len, - struct zinfo_add *add, + struct zinfo_add *add, size_t offset, size_t datasize ) { - size_t offset = add->offset; void *target; signed long addend; unsigned long size; signed long val; unsigned long mask; + offset += add->offset; if ( ( offset + datasize ) > output->len ) { fprintf ( stderr, "Add at %#zx outside output buffer\n", offset ); @@ -319,42 +319,90 @@ static int process_zinfo_addb ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { return process_zinfo_add ( input, output, output->len, - &zinfo->add, 1 ); + &zinfo->add, 0, 1 ); } static int process_zinfo_addw ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { return process_zinfo_add ( input, output, output->len, - &zinfo->add, 2 ); + &zinfo->add, 0, 2 ); } static int process_zinfo_addl ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { return process_zinfo_add ( input, output, output->len, - &zinfo->add, 4 ); + &zinfo->add, 0, 4 ); } static int process_zinfo_adhb ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { return process_zinfo_add ( input, output, output->hdr_len, - &zinfo->add, 1 ); + &zinfo->add, 0, 1 ); } static int process_zinfo_adhw ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { return process_zinfo_add ( input, output, output->hdr_len, - &zinfo->add, 2 ); + &zinfo->add, 0, 2 ); } static int process_zinfo_adhl ( struct input_file *input, struct output_file *output, union zinfo_record *zinfo ) { return process_zinfo_add ( input, output, output->hdr_len, - &zinfo->add, 4 ); + &zinfo->add, 0, 4 ); +} + +static int process_zinfo_adpb ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, 0, 1 ); +} + +static int process_zinfo_adpw ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, 0, 2 ); +} + +static int process_zinfo_adpl ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, 0, 4 ); +} + +static int process_zinfo_appb ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, output->hdr_len, 1 ); +} + +static int process_zinfo_appw ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, output->hdr_len, 2 ); +} + +static int process_zinfo_appl ( struct input_file *input, + struct output_file *output, + union zinfo_record *zinfo ) { + return process_zinfo_add ( input, output, + ( output->len - output->hdr_len ), + &zinfo->add, output->hdr_len, 4 ); } struct zinfo_processor { @@ -374,6 +422,12 @@ static struct zinfo_processor zinfo_processors[] = { { "ADHB", process_zinfo_adhb }, { "ADHW", process_zinfo_adhw }, { "ADHL", process_zinfo_adhl }, + { "ADPB", process_zinfo_adpb }, + { "ADPW", process_zinfo_adpw }, + { "ADPL", process_zinfo_adpl }, + { "APPB", process_zinfo_appb }, + { "APPW", process_zinfo_appw }, + { "APPL", process_zinfo_appl }, }; static int process_zinfo ( struct input_file *input, From b58374fe91a4d599c18f2b99501a54f73850f4de Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 10 Jun 2012 19:01:20 +0100 Subject: [PATCH 040/250] [romprefix] Allow .mrom image to be placed anywhere within the BAR A .mrom image currently assumes that it is the first image within the expansion ROM BAR, which may not be correct when multiple images are present. Fix by scanning through the BAR until we locate an image matching our build ID. Signed-off-by: Michael Brown --- src/arch/i386/prefix/mromprefix.S | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/arch/i386/prefix/mromprefix.S b/src/arch/i386/prefix/mromprefix.S index d7b7fc3f..abe1c9e3 100644 --- a/src/arch/i386/prefix/mromprefix.S +++ b/src/arch/i386/prefix/mromprefix.S @@ -154,6 +154,18 @@ find_mem_bar: movw $PCI_BAR_EXPROM, %di call pci_write_config_dword + /* Locate our ROM image */ +1: addr32 es cmpw $0xaa55, (%eax) + stc + jne 99f + addr32 es cmpl $_build_id, build_id(%eax) + je 2f + addr32 es movzbl 2(%eax), %ecx + shll $9, %ecx + addl %ecx, %eax + jmp 1b +2: + /* Copy payload to buffer, or set buffer address to BAR address */ testl %esi, %esi jz 1f From a3cba84bab36fe39abd853f0cfdcb3cfd744df41 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 11 Jun 2012 19:27:23 +0100 Subject: [PATCH 041/250] [util] Update mergerom.pl to handle .mrom images Signed-off-by: Michael Brown --- src/util/mergerom.pl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/util/mergerom.pl b/src/util/mergerom.pl index f9c52502..a1b456e2 100755 --- a/src/util/mergerom.pl +++ b/src/util/mergerom.pl @@ -87,12 +87,15 @@ foreach my $rom ( @roms ) { # Fix checksum for this ROM segment $rom->fix_checksum(); + # Add this ROM to base ROM + my $data = substr ( $baserom->get(), 0, $baserom->length() ); + $data .= $rom->get(); + $data .= $baserom->next_image()->get() if $baserom->next_image(); + $baserom->set ( $data ); + $offset += $rom->length; } $baserom->pnp_header->fix_checksum() if $baserom->pnp_header; $baserom->fix_checksum(); $baserom->save ( "-" ); -foreach my $rom ( @roms ) { - $rom->save ( "-" ); -} From b9ef880c8d50ccb89aef7e820aa737f66b63fd90 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 19 Jun 2012 18:54:22 +0100 Subject: [PATCH 042/250] [romprefix] Treat 0xffffffff as an error return from PMM PMM defines the return code 0xffffffff as meaning "unsupported function". It's hard to imagine a PMM BIOS that doesn't support pmmAllocate(), but apparently such things do exist. Signed-off-by: Michael Brown --- src/arch/i386/prefix/romprefix.S | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 950e0845..2719a70a 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -342,7 +342,7 @@ pmm_scan: movw $get_pmm_image_source, %bp call get_pmm movl %esi, image_source - jc 1f + jz 1f /* Copy ROM to image source PMM block */ pushw %es xorw %ax, %ax @@ -448,7 +448,7 @@ no_pmm: * %es:0000 : PMM structure * Returns: * %ebx : PMM handle - * %esi : allocated block address, or zero (with CF set) if allocation failed + * %esi : allocated block address, or zero (with ZF set) if allocation failed */ get_pmm: /* Preserve registers */ @@ -464,7 +464,10 @@ get_pmm_find: pushw %dx pushw %ax popl %esi - testl %esi, %esi + /* Treat 0xffffffff (not supported) as 0x00000000 (not found) */ + incl %esi + jz get_pmm_allocate + decl %esi jz get_pmm_allocate /* Block found - check acceptability */ call *%bp @@ -484,19 +487,20 @@ get_pmm_allocate: pushw %ax popl %esi movw $( '+' ), %di /* Indicate allocation attempt */ - testl %esi, %esi - jnz get_pmm_done - stc get_pmm_done: /* Print block address */ - pushfw movw %di, %ax xorw %di, %di call print_character movl %esi, %eax call print_hex_dword - popfw - /* Restore registers and return */ + /* Treat 0xffffffff (not supported) as 0x00000000 (allocation + * failed), and set ZF to indicate a zero result. + */ + incl %esi + jz 1f + decl %esi +1: /* Restore registers and return */ popw %di popl %eax ret From c0942408b7ab30745952e801381e931b1b947e1f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Jun 2012 11:56:43 +0100 Subject: [PATCH 043/250] [dhcp] Request broadcast responses when we already have an IPv4 address FCoE requires the use of multiple local unicast link-layer addresses. To avoid the complexity of managing multiple addresses, iPXE operates in promiscuous mode. As a consequence, any unicast packets with non-matching IPv4 addresses are rejected at the IPv4 layer (rather than at the link layer). This can cause problems when issuing a second DHCP request: if the address chosen by the DHCP server does not match the existing address, then the DHCP response will itself be rejected. Fix by requesting a broadcast response from the DHCP server if the network interface already has any IPv4 addresses. Signed-off-by: Michael Brown --- src/include/ipxe/ip.h | 2 ++ src/net/ipv4.c | 2 +- src/net/udp/dhcp.c | 7 +++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/include/ipxe/ip.h b/src/include/ipxe/ip.h index 4366d9ab..ca508e27 100644 --- a/src/include/ipxe/ip.h +++ b/src/include/ipxe/ip.h @@ -86,4 +86,6 @@ extern struct list_head ipv4_miniroutes; extern struct net_protocol ipv4_protocol __net_protocol; +extern int ipv4_has_any_addr ( struct net_device *netdev ); + #endif /* _IPXE_IP_H */ diff --git a/src/net/ipv4.c b/src/net/ipv4.c index 08249d41..791d4195 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -408,7 +408,7 @@ static int ipv4_tx ( struct io_buffer *iobuf, * @v netdev Network device * @ret has_any_addr Network device has any IPv4 address */ -static int ipv4_has_any_addr ( struct net_device *netdev ) { +int ipv4_has_any_addr ( struct net_device *netdev ) { struct ipv4_miniroute *miniroute; list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) { diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 10482e94..9a231840 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -941,6 +941,13 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt, &dhcphdr->flags ); memcpy ( dhcphdr->options, options, options_len ); + /* If the network device already has an IPv4 address then + * unicast responses from the DHCP server may be rejected, so + * request broadcast responses. + */ + if ( ipv4_has_any_addr ( netdev ) ) + dhcphdr->flags |= htons ( BOOTP_FL_BROADCAST ); + /* Initialise DHCP packet structure */ memset ( dhcppkt, 0, sizeof ( *dhcppkt ) ); dhcppkt_init ( dhcppkt, data, max_len ); From 4010890a3940433927f34f71417719167ad58275 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Jun 2012 12:15:42 +0100 Subject: [PATCH 044/250] [crypto] Allow an error margin on X.509 certificate validity periods iPXE has no concept of the local time zone, mainly because there is no viable way to obtain time zone information in the absence of local state. This causes potential problems with newly-issued certificates and certificates that are about to expire. Avoid such problems by allowing an error margin of around 12 hours on certificate validity periods, similar to the error margin already allowed for OCSP response timestamps. Signed-off-by: Michael Brown --- src/crypto/ocsp.c | 4 ++-- src/crypto/x509.c | 4 ++-- src/include/ipxe/ocsp.h | 8 -------- src/include/ipxe/x509.h | 8 ++++++++ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/crypto/ocsp.c b/src/crypto/ocsp.c index f5d03dc6..ab75dea3 100644 --- a/src/crypto/ocsp.c +++ b/src/crypto/ocsp.c @@ -794,12 +794,12 @@ int ocsp_validate ( struct ocsp_check *ocsp, time_t time ) { /* Check OCSP response is valid at the specified time * (allowing for some margin of error). */ - if ( response->this_update > ( time + OCSP_ERROR_MARGIN_TIME ) ) { + if ( response->this_update > ( time + X509_ERROR_MARGIN_TIME ) ) { DBGC ( ocsp, "OCSP %p \"%s\" response is not yet valid (at " "time %lld)\n", ocsp, ocsp->cert->subject.name, time ); return -EACCES_STALE; } - if ( response->next_update < ( time - OCSP_ERROR_MARGIN_TIME ) ) { + if ( response->next_update < ( time - X509_ERROR_MARGIN_TIME ) ) { DBGC ( ocsp, "OCSP %p \"%s\" response is stale (at time " "%lld)\n", ocsp, ocsp->cert->subject.name, time ); return -EACCES_STALE; diff --git a/src/crypto/x509.c b/src/crypto/x509.c index 1a27eb24..a99f6ab9 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -1264,12 +1264,12 @@ int x509_check_time ( struct x509_certificate *cert, time_t time ) { struct x509_validity *validity = &cert->validity; /* Check validity period */ - if ( time < validity->not_before.time ) { + if ( validity->not_before.time > ( time + X509_ERROR_MARGIN_TIME ) ) { DBGC ( cert, "X509 %p \"%s\" is not yet valid (at time %lld)\n", cert, cert->subject.name, time ); return -EACCES_EXPIRED; } - if ( time > validity->not_after.time ) { + if ( validity->not_after.time < ( time - X509_ERROR_MARGIN_TIME ) ) { DBGC ( cert, "X509 %p \"%s\" has expired (at time %lld)\n", cert, cert->subject.name, time ); return -EACCES_EXPIRED; diff --git a/src/include/ipxe/ocsp.h b/src/include/ipxe/ocsp.h index 2521681c..fe825fd0 100644 --- a/src/include/ipxe/ocsp.h +++ b/src/include/ipxe/ocsp.h @@ -28,14 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define OCSP_STATUS_SIG_REQUIRED 0x05 #define OCSP_STATUS_UNAUTHORIZED 0x06 -/** Margin of error allowed in OCSP response times - * - * We allow a generous margin of error: 12 hours to allow for the - * local time zone being non-GMT, plus 30 minutes to allow for general - * clock drift. - */ -#define OCSP_ERROR_MARGIN_TIME ( ( 12 * 60 + 30 ) * 60 ) - /** An OCSP request */ struct ocsp_request { /** Request builder */ diff --git a/src/include/ipxe/x509.h b/src/include/ipxe/x509.h index a5626c8a..a47942a7 100644 --- a/src/include/ipxe/x509.h +++ b/src/include/ipxe/x509.h @@ -42,6 +42,14 @@ struct x509_validity { struct x509_time not_after; }; +/** Margin of error allowed in X.509 response times + * + * We allow a generous margin of error: 12 hours to allow for the + * local time zone being non-GMT, plus 30 minutes to allow for general + * clock drift. + */ +#define X509_ERROR_MARGIN_TIME ( ( 12 * 60 + 30 ) * 60 ) + /** An X.509 certificate public key */ struct x509_public_key { /** Raw public key information */ From 7ea6764031da5a9d2d981ab25c24712603b9cac3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Jun 2012 14:38:22 +0100 Subject: [PATCH 045/250] [settings] Move "domain" setting from dns.c to settings.c Signed-off-by: Michael Brown --- src/core/settings.c | 8 ++++++++ src/include/ipxe/settings.h | 1 + src/net/udp/dns.c | 8 -------- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index c84e1bc2..ba5329bb 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -1838,6 +1838,14 @@ struct setting hostname_setting __setting ( SETTING_HOST ) = { .type = &setting_type_string, }; +/** Domain name setting */ +struct setting domain_setting __setting ( SETTING_IPv4_EXTRA ) = { + .name = "domain", + .description = "DNS domain", + .tag = DHCP_DOMAIN_NAME, + .type = &setting_type_string, +}; + /** TFTP server setting */ struct setting next_server_setting __setting ( SETTING_BOOT ) = { .name = "next-server", diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index d0a142fa..cd446202 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -304,6 +304,7 @@ extern struct setting netmask_setting __setting ( SETTING_IPv4 ); extern struct setting gateway_setting __setting ( SETTING_IPv4 ); extern struct setting dns_setting __setting ( SETTING_IPv4_EXTRA ); extern struct setting hostname_setting __setting ( SETTING_HOST ); +extern struct setting domain_setting __setting ( SETTING_IPv4_EXTRA ); extern struct setting filename_setting __setting ( SETTING_BOOT ); extern struct setting root_path_setting __setting ( SETTING_SANBOOT ); extern struct setting username_setting __setting ( SETTING_AUTH ); diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index 124a0e49..6b4335d7 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -600,14 +600,6 @@ struct setting dns_setting __setting ( SETTING_IPv4_EXTRA ) = { .type = &setting_type_ipv4, }; -/** Domain name setting */ -struct setting domain_setting __setting ( SETTING_IPv4_EXTRA ) = { - .name = "domain", - .description = "DNS domain", - .tag = DHCP_DOMAIN_NAME, - .type = &setting_type_string, -}; - /** * Apply DNS settings * From cbc54bf559ce257991a4c87001d7a5c41dbe1869 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Jun 2012 14:39:33 +0100 Subject: [PATCH 046/250] [syslog] Include hostname within syslog messages where possible Signed-off-by: Michael Brown --- src/include/ipxe/syslog.h | 3 +++ src/net/tcp/syslogs.c | 6 ++--- src/net/udp/syslog.c | 56 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/include/ipxe/syslog.h b/src/include/ipxe/syslog.h index 035ca670..13169265 100644 --- a/src/include/ipxe/syslog.h +++ b/src/include/ipxe/syslog.h @@ -35,4 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** Syslog priority */ #define SYSLOG_PRIORITY( facility, severity ) ( 8 * (facility) + (severity) ) +extern int syslog_send ( struct interface *xfer, unsigned int severity, + const char *message, const char *terminator ); + #endif /* _IPXE_SYSLOG_H */ diff --git a/src/net/tcp/syslogs.c b/src/net/tcp/syslogs.c index e7480e56..854e2152 100644 --- a/src/net/tcp/syslogs.c +++ b/src/net/tcp/syslogs.c @@ -162,10 +162,8 @@ static void syslogs_putchar ( int character ) { syslogs_entered = 1; /* Send log message */ - if ( ( rc = xfer_printf ( &syslogs, "<%d>ipxe: %s\n", - SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY, - syslogs_severity ), - syslogs_buffer ) ) != 0 ) { + if ( ( rc = syslog_send ( &syslogs, syslogs_severity, + syslogs_buffer, "\n" ) ) != 0 ) { DBG ( "SYSLOGS could not send log message: %s\n", strerror ( rc ) ); } diff --git a/src/net/udp/syslog.c b/src/net/udp/syslog.c index 4a265314..9e55d211 100644 --- a/src/net/udp/syslog.c +++ b/src/net/udp/syslog.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #include +#include #include #include #include @@ -58,6 +59,41 @@ static struct interface_descriptor syslogger_desc = /** The syslog UDP interface */ static struct interface syslogger = INTF_INIT ( syslogger_desc ); +/****************************************************************************** + * + * Console driver + * + ****************************************************************************** + */ + +/** Host name (for log messages) */ +static char *syslog_hostname; + +/** Domain name (for log messages) */ +static char *syslog_domain; + +/** + * Transmit formatted syslog message + * + * @v xfer Data transfer interface + * @v severity Severity + * @v message Message + * @v terminator Message terminator + * @ret rc Return status code + */ +int syslog_send ( struct interface *xfer, unsigned int severity, + const char *message, const char *terminator ) { + + return xfer_printf ( xfer, "<%d>%s%s%s%sipxe: %s%s", + SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY, + severity ), + ( syslog_hostname ? syslog_hostname : "" ), + ( syslog_domain ? "." : "" ), + ( syslog_domain ? syslog_domain : "" ), + ( ( syslog_hostname || syslog_domain ) ? " " : ""), + message, terminator ); +} + /****************************************************************************** * * Console driver @@ -124,10 +160,8 @@ static void syslog_putchar ( int character ) { syslog_entered = 1; /* Send log message */ - if ( ( rc = xfer_printf ( &syslogger, "<%d>ipxe: %s", - SYSLOG_PRIORITY ( SYSLOG_DEFAULT_FACILITY, - syslog_severity ), - syslog_buffer ) ) != 0 ) { + if ( ( rc = syslog_send ( &syslogger, syslog_severity, + syslog_buffer, "" ) ) != 0 ) { DBG ( "SYSLOG could not send log message: %s\n", strerror ( rc ) ); } @@ -170,6 +204,20 @@ static int apply_syslog_settings ( void ) { int len; int rc; + /* Fetch hostname and domain name */ + free ( syslog_hostname ); + if ( ( len = fetch_string_setting_copy ( NULL, &hostname_setting, + &syslog_hostname ) ) < 0 ) { + rc = len; + DBG ( "SYSLOG could not fetch hostname: %s\n", strerror ( rc )); + } + free ( syslog_domain ); + if ( ( len = fetch_string_setting_copy ( NULL, &domain_setting, + &syslog_domain ) ) < 0 ) { + rc = len; + DBG ( "SYSLOG could not fetch domain: %s\n", strerror ( rc ) ); + } + /* Fetch log server */ syslog_console.disabled = 1; old_addr.s_addr = sin_logserver->sin_addr.s_addr; From edcca8e91b047b891475dc8fd1d8c56a50ccae55 Mon Sep 17 00:00:00 2001 From: Valentine Barshak Date: Sat, 2 Jun 2012 17:38:00 +0400 Subject: [PATCH 047/250] [sky2] Fix invalid memory access Use hw pointer in PCI driver data as expected by sky2_remove(). Signed-off-by: Valentine Barshak Signed-off-by: Michael Brown --- src/drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/net/sky2.c b/src/drivers/net/sky2.c index 5b5bd6b0..d60ef113 100644 --- a/src/drivers/net/sky2.c +++ b/src/drivers/net/sky2.c @@ -2334,7 +2334,7 @@ static int sky2_probe(struct pci_device *pdev) sky2_show_addr(dev1); } - pci_set_drvdata(pdev, dev); + pci_set_drvdata(pdev, hw); return 0; From 567b9bf9e78cdf904f8e885465cf03afd0d541ba Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 27 Jun 2012 18:01:33 +0100 Subject: [PATCH 048/250] [ui] Change "login" colours to match other UIs Signed-off-by: Michael Brown --- src/hci/tui/login_ui.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hci/tui/login_ui.c b/src/hci/tui/login_ui.c index 04aabfa8..4143a607 100644 --- a/src/hci/tui/login_ui.c +++ b/src/hci/tui/login_ui.c @@ -35,8 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); /* Colour pairs */ #define CPAIR_NORMAL 1 -#define CPAIR_LABEL 2 -#define CPAIR_EDITBOX 3 +#define CPAIR_EDIT 2 /* Screen layout */ #define USERNAME_LABEL_ROW 8 @@ -65,9 +64,8 @@ int login_ui ( void ) { /* Initialise UI */ initscr(); start_color(); - init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLACK ); - init_pair ( CPAIR_LABEL, COLOR_WHITE, COLOR_BLACK ); - init_pair ( CPAIR_EDITBOX, COLOR_WHITE, COLOR_BLUE ); + init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE ); + init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_CYAN ); init_editbox ( &username_box, username, sizeof ( username ), NULL, USERNAME_ROW, EDITBOX_COL, EDITBOX_WIDTH, 0 ); init_editbox ( &password_box, password, sizeof ( password ), NULL, @@ -75,11 +73,13 @@ int login_ui ( void ) { EDITBOX_STARS ); /* Draw initial UI */ + color_set ( CPAIR_NORMAL, NULL ); erase(); - color_set ( CPAIR_LABEL, NULL ); + attron ( A_BOLD ); mvprintw ( USERNAME_LABEL_ROW, LABEL_COL, "Username:" ); mvprintw ( PASSWORD_LABEL_ROW, LABEL_COL, "Password:" ); - color_set ( CPAIR_EDITBOX, NULL ); + attroff ( A_BOLD ); + color_set ( CPAIR_EDIT, NULL ); draw_editbox ( &username_box ); draw_editbox ( &password_box ); From 512ed2b921e89a5e5208a7c6ddb9837b0d184a3e Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 27 Jun 2012 18:39:46 +0100 Subject: [PATCH 049/250] [ui] Allow colours to be configured via config/colour.h Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/config/colour.h | 32 ++++++++++++++++++++++++++++++++ src/hci/tui/login_ui.c | 5 +++-- src/hci/tui/menu_ui.c | 7 ++++--- src/hci/tui/settings_ui.c | 11 ++++++----- 4 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 src/config/colour.h diff --git a/src/config/colour.h b/src/config/colour.h new file mode 100644 index 00000000..d32d46dc --- /dev/null +++ b/src/config/colour.h @@ -0,0 +1,32 @@ +#ifndef CONFIG_COLOUR_H +#define CONFIG_COLOUR_H + +/** @file + * + * Display colour configuration + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#define COLOR_NORMAL_FG COLOR_WHITE +#define COLOR_NORMAL_BG COLOR_BLUE + +#define COLOR_SELECT_FG COLOR_WHITE +#define COLOR_SELECT_BG COLOR_RED + +#define COLOR_SEPARATOR_FG COLOR_CYAN +#define COLOR_SEPARATOR_BG COLOR_BLUE + +#define COLOR_EDIT_FG COLOR_BLACK +#define COLOR_EDIT_BG COLOR_CYAN + +#define COLOR_ALERT_FG COLOR_WHITE +#define COLOR_ALERT_BG COLOR_RED + +#define COLOR_URL_FG COLOR_CYAN +#define COLOR_URL_BG COLOR_BLUE + +#include + +#endif /* CONFIG_COLOUR_H */ diff --git a/src/hci/tui/login_ui.c b/src/hci/tui/login_ui.c index 4143a607..c33cbcf2 100644 --- a/src/hci/tui/login_ui.c +++ b/src/hci/tui/login_ui.c @@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /* Colour pairs */ #define CPAIR_NORMAL 1 @@ -64,8 +65,8 @@ int login_ui ( void ) { /* Initialise UI */ initscr(); start_color(); - init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE ); - init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_CYAN ); + init_pair ( CPAIR_NORMAL, COLOR_NORMAL_FG, COLOR_NORMAL_BG ); + init_pair ( CPAIR_EDIT, COLOR_EDIT_FG, COLOR_EDIT_BG ); init_editbox ( &username_box, username, sizeof ( username ), NULL, USERNAME_ROW, EDITBOX_COL, EDITBOX_WIDTH, 0 ); init_editbox ( &password_box, password, sizeof ( password ), NULL, diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c index 30d93ad2..61625622 100644 --- a/src/hci/tui/menu_ui.c +++ b/src/hci/tui/menu_ui.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /* Colour pairs */ #define CPAIR_NORMAL 1 @@ -339,9 +340,9 @@ int show_menu ( struct menu *menu, unsigned int timeout_ms, /* Initialise screen */ initscr(); start_color(); - init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE ); - init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED ); - init_pair ( CPAIR_SEPARATOR, COLOR_CYAN, COLOR_BLUE ); + init_pair ( CPAIR_NORMAL, COLOR_NORMAL_FG, COLOR_NORMAL_BG ); + init_pair ( CPAIR_SELECT, COLOR_SELECT_FG, COLOR_SELECT_BG ); + init_pair ( CPAIR_SEPARATOR, COLOR_SEPARATOR_FG, COLOR_SEPARATOR_BG ); color_set ( CPAIR_NORMAL, NULL ); erase(); diff --git a/src/hci/tui/settings_ui.c b/src/hci/tui/settings_ui.c index ed076101..258f0cf9 100644 --- a/src/hci/tui/settings_ui.c +++ b/src/hci/tui/settings_ui.c @@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -557,11 +558,11 @@ int settings_ui ( struct settings *settings ) { initscr(); start_color(); - init_pair ( CPAIR_NORMAL, COLOR_WHITE, COLOR_BLUE ); - init_pair ( CPAIR_SELECT, COLOR_WHITE, COLOR_RED ); - init_pair ( CPAIR_EDIT, COLOR_BLACK, COLOR_CYAN ); - init_pair ( CPAIR_ALERT, COLOR_WHITE, COLOR_RED ); - init_pair ( CPAIR_URL, COLOR_CYAN, COLOR_BLUE ); + init_pair ( CPAIR_NORMAL, COLOR_NORMAL_FG, COLOR_NORMAL_BG ); + init_pair ( CPAIR_SELECT, COLOR_SELECT_FG, COLOR_SELECT_BG ); + init_pair ( CPAIR_EDIT, COLOR_EDIT_FG, COLOR_EDIT_BG ); + init_pair ( CPAIR_ALERT, COLOR_ALERT_FG, COLOR_ALERT_BG ); + init_pair ( CPAIR_URL, COLOR_URL_FG, COLOR_URL_BG ); color_set ( CPAIR_NORMAL, NULL ); erase(); From cc3e9f068bec051645695579907a5e2e46b7cfe4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 14 Jun 2012 12:54:04 +0100 Subject: [PATCH 050/250] [realtek] Add missing cpu_to_le16() Reported-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index c906f251..104ff76e 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -478,7 +478,7 @@ static void realtek_refill_rx ( struct realtek_nic *rtl ) { /* Populate receive descriptor */ address = virt_to_bus ( iobuf->data ); rx->address = cpu_to_le64 ( address ); - rx->length = RTL_RX_MAX_LEN; + rx->length = cpu_to_le16 ( RTL_RX_MAX_LEN ); wmb(); rx->flags = ( cpu_to_le16 ( RTL_DESC_OWN ) | ( is_last ? cpu_to_le16 ( RTL_DESC_EOR ) : 0 ) ); From ba480730dc2759aad76729102400b2265eb87aac Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 26 Jun 2012 12:42:06 +0100 Subject: [PATCH 051/250] [cmdline] Increase resolution of "time" command A reasonably large (512MB) file transferred via HTTP over Gigabit Ethernet should complete in around 4.6 seconds. Increase the resolution of the "time" command to tenths of a second, to allow such transfers to be meaningfully measured. Signed-off-by: Michael Brown --- src/hci/commands/time_cmd.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hci/commands/time_cmd.c b/src/hci/commands/time_cmd.c index 6c9556ce..ce26f9d2 100644 --- a/src/hci/commands/time_cmd.c +++ b/src/hci/commands/time_cmd.c @@ -56,7 +56,8 @@ static struct command_descriptor time_cmd = static int time_exec ( int argc, char **argv ) { struct time_options opts; unsigned long start; - int secs; + unsigned long elapsed; + int decisecs; int rc; /* Parse options */ @@ -65,9 +66,11 @@ static int time_exec ( int argc, char **argv ) { start = currticks(); rc = execv ( argv[1], argv + 1 ); - secs = (currticks() - start) / ticks_per_sec(); + elapsed = ( currticks() - start ); + decisecs = ( 10 * elapsed / ticks_per_sec() ); - printf ( "%s: %ds\n", argv[0], secs ); + printf ( "%s: %d.%ds\n", argv[0], + ( decisecs / 10 ), ( decisecs % 10 ) ); return rc; } From 80cdf6acc7ab27060ce1bd164ada214e20a69e1a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 26 Jun 2012 12:42:19 +0100 Subject: [PATCH 052/250] [test] Add memcpy() self-tests Signed-off-by: Michael Brown --- src/tests/memcpy_test.c | 290 +++++++++++++++++++++++++++++++++++----- src/tests/tests.c | 1 + 2 files changed, 257 insertions(+), 34 deletions(-) diff --git a/src/tests/memcpy_test.c b/src/tests/memcpy_test.c index 7626e639..b405a9f2 100644 --- a/src/tests/memcpy_test.c +++ b/src/tests/memcpy_test.c @@ -1,39 +1,261 @@ -#include - /* - * This file exists for testing the compilation of memcpy() with the - * various constant-length optimisations. + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * memcpy() self-tests * */ -#define __regparm __attribute__ (( regparm(3) )) +/* Forcibly enable assertions */ +#undef NDEBUG -void __regparm memcpy_0 ( void *dest, void *src ) { memcpy ( dest, src, 0 ); } -void __regparm memcpy_1 ( void *dest, void *src ) { memcpy ( dest, src, 1 ); } -void __regparm memcpy_2 ( void *dest, void *src ) { memcpy ( dest, src, 2 ); } -void __regparm memcpy_3 ( void *dest, void *src ) { memcpy ( dest, src, 3 ); } -void __regparm memcpy_4 ( void *dest, void *src ) { memcpy ( dest, src, 4 ); } -void __regparm memcpy_5 ( void *dest, void *src ) { memcpy ( dest, src, 5 ); } -void __regparm memcpy_6 ( void *dest, void *src ) { memcpy ( dest, src, 6 ); } -void __regparm memcpy_7 ( void *dest, void *src ) { memcpy ( dest, src, 7 ); } -void __regparm memcpy_8 ( void *dest, void *src ) { memcpy ( dest, src, 8 ); } -void __regparm memcpy_9 ( void *dest, void *src ) { memcpy ( dest, src, 9 ); } -void __regparm memcpy_10 ( void *dest, void *src ) { memcpy ( dest, src, 10 ); } -void __regparm memcpy_11 ( void *dest, void *src ) { memcpy ( dest, src, 11 ); } -void __regparm memcpy_12 ( void *dest, void *src ) { memcpy ( dest, src, 12 ); } -void __regparm memcpy_13 ( void *dest, void *src ) { memcpy ( dest, src, 13 ); } -void __regparm memcpy_14 ( void *dest, void *src ) { memcpy ( dest, src, 14 ); } -void __regparm memcpy_15 ( void *dest, void *src ) { memcpy ( dest, src, 15 ); } -void __regparm memcpy_16 ( void *dest, void *src ) { memcpy ( dest, src, 16 ); } -void __regparm memcpy_17 ( void *dest, void *src ) { memcpy ( dest, src, 17 ); } -void __regparm memcpy_18 ( void *dest, void *src ) { memcpy ( dest, src, 18 ); } -void __regparm memcpy_19 ( void *dest, void *src ) { memcpy ( dest, src, 19 ); } -void __regparm memcpy_20 ( void *dest, void *src ) { memcpy ( dest, src, 20 ); } -void __regparm memcpy_21 ( void *dest, void *src ) { memcpy ( dest, src, 21 ); } -void __regparm memcpy_22 ( void *dest, void *src ) { memcpy ( dest, src, 22 ); } -void __regparm memcpy_23 ( void *dest, void *src ) { memcpy ( dest, src, 23 ); } -void __regparm memcpy_24 ( void *dest, void *src ) { memcpy ( dest, src, 24 ); } -void __regparm memcpy_25 ( void *dest, void *src ) { memcpy ( dest, src, 25 ); } -void __regparm memcpy_26 ( void *dest, void *src ) { memcpy ( dest, src, 26 ); } -void __regparm memcpy_27 ( void *dest, void *src ) { memcpy ( dest, src, 27 ); } -void __regparm memcpy_28 ( void *dest, void *src ) { memcpy ( dest, src, 28 ); } +#include +#include +#include +#include +#include + +/* Provide global functions to allow inspection of generated code */ + +void memcpy_0 ( void *dest, void *src ) { memcpy ( dest, src, 0 ); } +void memcpy_1 ( void *dest, void *src ) { memcpy ( dest, src, 1 ); } +void memcpy_2 ( void *dest, void *src ) { memcpy ( dest, src, 2 ); } +void memcpy_3 ( void *dest, void *src ) { memcpy ( dest, src, 3 ); } +void memcpy_4 ( void *dest, void *src ) { memcpy ( dest, src, 4 ); } +void memcpy_5 ( void *dest, void *src ) { memcpy ( dest, src, 5 ); } +void memcpy_6 ( void *dest, void *src ) { memcpy ( dest, src, 6 ); } +void memcpy_7 ( void *dest, void *src ) { memcpy ( dest, src, 7 ); } +void memcpy_8 ( void *dest, void *src ) { memcpy ( dest, src, 8 ); } +void memcpy_9 ( void *dest, void *src ) { memcpy ( dest, src, 9 ); } +void memcpy_10 ( void *dest, void *src ) { memcpy ( dest, src, 10 ); } +void memcpy_11 ( void *dest, void *src ) { memcpy ( dest, src, 11 ); } +void memcpy_12 ( void *dest, void *src ) { memcpy ( dest, src, 12 ); } +void memcpy_13 ( void *dest, void *src ) { memcpy ( dest, src, 13 ); } +void memcpy_14 ( void *dest, void *src ) { memcpy ( dest, src, 14 ); } +void memcpy_15 ( void *dest, void *src ) { memcpy ( dest, src, 15 ); } +void memcpy_16 ( void *dest, void *src ) { memcpy ( dest, src, 16 ); } +void memcpy_17 ( void *dest, void *src ) { memcpy ( dest, src, 17 ); } +void memcpy_18 ( void *dest, void *src ) { memcpy ( dest, src, 18 ); } +void memcpy_19 ( void *dest, void *src ) { memcpy ( dest, src, 19 ); } +void memcpy_20 ( void *dest, void *src ) { memcpy ( dest, src, 20 ); } +void memcpy_21 ( void *dest, void *src ) { memcpy ( dest, src, 21 ); } +void memcpy_22 ( void *dest, void *src ) { memcpy ( dest, src, 22 ); } +void memcpy_23 ( void *dest, void *src ) { memcpy ( dest, src, 23 ); } +void memcpy_24 ( void *dest, void *src ) { memcpy ( dest, src, 24 ); } +void memcpy_25 ( void *dest, void *src ) { memcpy ( dest, src, 25 ); } +void memcpy_26 ( void *dest, void *src ) { memcpy ( dest, src, 26 ); } +void memcpy_27 ( void *dest, void *src ) { memcpy ( dest, src, 27 ); } +void memcpy_28 ( void *dest, void *src ) { memcpy ( dest, src, 28 ); } +void memcpy_29 ( void *dest, void *src ) { memcpy ( dest, src, 29 ); } +void memcpy_30 ( void *dest, void *src ) { memcpy ( dest, src, 30 ); } +void memcpy_31 ( void *dest, void *src ) { memcpy ( dest, src, 31 ); } + +/** + * Force a call to the variable-length implementation of memcpy() + * + * @v dest Destination address + * @v src Source address + * @v len Length of data + * @ret dest Destination address + */ +__attribute__ (( noinline )) void * memcpy_var ( void *dest, const void *src, + size_t len ) { + return memcpy ( dest, src, len ); +} + +/** + * Perform a constant-length memcpy() test + * + * ... Data to copy + */ +#define MEMCPY_TEST_CONSTANT( ... ) do { \ + static const uint8_t src[] = { __VA_ARGS__ }; \ + uint8_t dest_const[ 1 + sizeof ( src ) + 1 ]; \ + uint8_t dest_var[ 1 + sizeof ( src ) + 1 ]; \ + \ + dest_const[0] = 0x33; \ + dest_const[ sizeof ( dest_const ) - 1 ] = 0x44; \ + memcpy ( ( dest_const + 1 ), src, \ + ( sizeof ( dest_const ) - 2 ) ); \ + ok ( dest_const[0] == 0x33 ); \ + ok ( dest_const[ sizeof ( dest_const ) - 1 ] == 0x44 ); \ + ok ( memcmp ( ( dest_const + 1 ), src, \ + ( sizeof ( dest_const ) - 2 ) ) == 0 ); \ + \ + dest_var[0] = 0x55; \ + dest_var[ sizeof ( dest_var ) - 1 ] = 0x66; \ + memcpy_var ( ( dest_var + 1 ), src, \ + ( sizeof ( dest_var ) - 2 ) ); \ + ok ( dest_var[0] == 0x55 ); \ + ok ( dest_var[ sizeof ( dest_var ) - 1 ] == 0x66 ); \ + ok ( memcmp ( ( dest_var + 1 ), src, \ + ( sizeof ( dest_var ) - 2 ) ) == 0 ); \ + } while ( 0 ) + +/** + * Test memcpy() speed + * + * @v dest_offset Destination alignment offset + * @v src_offset Source alignment offset + * @v len Length of data to copy + */ +static void memcpy_test_speed ( unsigned int dest_offset, + unsigned int src_offset, size_t len ) { + uint8_t *dest; + uint8_t *src; + unsigned int i; + unsigned long elapsed; + + /* Allocate blocks */ + dest = malloc ( len + dest_offset ); + assert ( dest != NULL ); + src = malloc ( len + src_offset ); + assert ( src != NULL ); + + /* Generate random source data */ + for ( i = 0 ; i < len ; i++ ) + src[ src_offset + i ] = random(); + + /* Perform memcpy() */ + simple_profile(); + memcpy ( ( dest + dest_offset ), ( src + src_offset ), len ); + elapsed = simple_profile(); + + /* Check copied data */ + ok ( memcmp ( ( dest + dest_offset ), ( src + src_offset ), + len ) == 0 ); + + /* Free blocks */ + free ( dest ); + free ( src ); + + DBG ( "MEMCPY copied %zd bytes (+%d => +%d) in %ld ticks\n", + len, src_offset, dest_offset, elapsed ); +} + +/** + * Perform memcpy() self-tests + * + */ +static void memcpy_test_exec ( void ) { + unsigned int dest_offset; + unsigned int src_offset; + + /* Constant-length tests */ + MEMCPY_TEST_CONSTANT ( ); + MEMCPY_TEST_CONSTANT ( 0x86 ); + MEMCPY_TEST_CONSTANT ( 0x8c, 0xd3 ); + MEMCPY_TEST_CONSTANT ( 0x4e, 0x08, 0xed ); + MEMCPY_TEST_CONSTANT ( 0xcc, 0x61, 0x8f, 0x70 ); + MEMCPY_TEST_CONSTANT ( 0x6d, 0x28, 0xe0, 0x9e, 0x6d ); + MEMCPY_TEST_CONSTANT ( 0x7d, 0x13, 0x4f, 0xef, 0x17, 0xb3 ); + MEMCPY_TEST_CONSTANT ( 0x38, 0xa7, 0xd4, 0x8d, 0x44, 0x01, 0xfd ); + MEMCPY_TEST_CONSTANT ( 0x45, 0x9f, 0xf4, 0xf9, 0xf3, 0x0f, 0x99, 0x43 ); + MEMCPY_TEST_CONSTANT ( 0x69, 0x8c, 0xf6, 0x12, 0x79, 0x70, 0xd8, 0x1e, + 0x9d ); + MEMCPY_TEST_CONSTANT ( 0xbe, 0x53, 0xb4, 0xb7, 0xdd, 0xe6, 0x35, 0x10, + 0x3c, 0xe7 ); + MEMCPY_TEST_CONSTANT ( 0xaf, 0x41, 0x8a, 0x88, 0xb1, 0x4e, 0x52, 0xd4, + 0xe6, 0xc3, 0x76 ); + MEMCPY_TEST_CONSTANT ( 0xdf, 0x43, 0xe4, 0x5d, 0xad, 0x17, 0x35, 0x38, + 0x1a, 0x1d, 0x57, 0x58 ); + MEMCPY_TEST_CONSTANT ( 0x20, 0x52, 0x83, 0x92, 0xb9, 0x85, 0xa4, 0x06, + 0x94, 0xe0, 0x3d, 0x57, 0xd4 ); + MEMCPY_TEST_CONSTANT ( 0xf1, 0x67, 0x31, 0x9e, 0x32, 0x98, 0x27, 0xe9, + 0x8e, 0x62, 0xb4, 0x82, 0x7e, 0x02 ); + MEMCPY_TEST_CONSTANT ( 0x93, 0xc1, 0x55, 0xe3, 0x60, 0xce, 0xac, 0x1e, + 0xae, 0x9d, 0xca, 0xec, 0x92, 0xb3, 0x38 ); + MEMCPY_TEST_CONSTANT ( 0xb3, 0xc1, 0xfa, 0xe7, 0x8a, 0x1c, 0xe4, 0xce, + 0x85, 0xe6, 0x3c, 0xab, 0x1c, 0xa2, 0xaf, 0x7a ); + MEMCPY_TEST_CONSTANT ( 0x9b, 0x6e, 0x1c, 0x48, 0x82, 0xd3, 0x6e, 0x58, + 0xa7, 0xb0, 0xe6, 0xea, 0x6d, 0xee, 0xc8, 0xf8, + 0xaf ); + MEMCPY_TEST_CONSTANT ( 0x86, 0x6d, 0xb0, 0xf5, 0xf2, 0xc9, 0xcd, 0xfe, + 0xfb, 0x38, 0x67, 0xbc, 0x51, 0x9d, 0x25, 0xbc, + 0x09, 0x88 ); + MEMCPY_TEST_CONSTANT ( 0x58, 0xa4, 0x96, 0x9e, 0x98, 0x36, 0xdb, 0xae, + 0x8a, 0x08, 0x7c, 0x64, 0xf9, 0xfb, 0x25, 0xb4, + 0x8e, 0xf3, 0xed ); + MEMCPY_TEST_CONSTANT ( 0xc6, 0x3b, 0x84, 0x3c, 0x76, 0x24, 0x8e, 0x42, + 0x11, 0x1f, 0x09, 0x2e, 0x24, 0xbb, 0x67, 0x71, + 0x3a, 0xca, 0x60, 0xdd ); + MEMCPY_TEST_CONSTANT ( 0x8e, 0x2d, 0xa9, 0x58, 0x87, 0xe2, 0xac, 0x4b, + 0xc8, 0xbf, 0xa2, 0x4e, 0xee, 0x3a, 0xa6, 0x71, + 0x76, 0xee, 0x42, 0x05, 0x6e ); + MEMCPY_TEST_CONSTANT ( 0x8a, 0xda, 0xdf, 0x7b, 0x55, 0x41, 0x8c, 0xcd, + 0x42, 0x40, 0x18, 0xe2, 0x60, 0xc4, 0x7d, 0x64, + 0x00, 0xd5, 0xef, 0xa1, 0x7b, 0x31 ); + MEMCPY_TEST_CONSTANT ( 0xd9, 0x25, 0xcb, 0xbb, 0x9c, 0x1d, 0xdd, 0xcd, + 0xde, 0x96, 0xd9, 0x74, 0x13, 0x95, 0xfe, 0x68, + 0x0b, 0x3d, 0x30, 0x8d, 0x0c, 0x1e, 0x6d ); + MEMCPY_TEST_CONSTANT ( 0x2d, 0x0d, 0x02, 0x33, 0xd6, 0xbe, 0x6c, 0xa6, + 0x0a, 0xab, 0xe5, 0xda, 0xe2, 0xab, 0x78, 0x3c, + 0xd3, 0xdd, 0xea, 0xfa, 0x1a, 0xe4, 0xf4, 0xb3 ); + MEMCPY_TEST_CONSTANT ( 0x6a, 0x34, 0x39, 0xea, 0x29, 0x5f, 0xa6, 0x18, + 0xc1, 0x53, 0x39, 0x78, 0xdb, 0x40, 0xf2, 0x98, + 0x78, 0xcf, 0xee, 0xfd, 0xcd, 0xf8, 0x56, 0xf8, + 0x30 ); + MEMCPY_TEST_CONSTANT ( 0xe4, 0xe5, 0x5a, 0x8d, 0xcf, 0x04, 0x29, 0x7c, + 0xa7, 0xd8, 0x43, 0xbf, 0x0b, 0xbf, 0xe7, 0x68, + 0xf7, 0x8c, 0x81, 0xf9, 0x3f, 0xad, 0xa4, 0x40, + 0x38, 0x82 ); + MEMCPY_TEST_CONSTANT ( 0x71, 0xcd, 0x3d, 0x26, 0xde, 0x11, 0x23, 0xd5, + 0x42, 0x6e, 0x63, 0x72, 0x53, 0xfc, 0x28, 0x06, + 0x4b, 0xe0, 0x2c, 0x07, 0x6b, 0xe8, 0xd9, 0x5f, + 0xf8, 0x74, 0xed ); + MEMCPY_TEST_CONSTANT ( 0x05, 0xb2, 0xae, 0x81, 0x91, 0xc9, 0xa2, 0x5f, + 0xa9, 0x1b, 0x25, 0x7f, 0x32, 0x0c, 0x04, 0x00, + 0xf1, 0x46, 0xab, 0x77, 0x1e, 0x12, 0x27, 0xe7, + 0xf6, 0x1e, 0x0c, 0x29 ); + MEMCPY_TEST_CONSTANT ( 0x0e, 0xca, 0xa5, 0x56, 0x3d, 0x99, 0x99, 0xf9, + 0x6e, 0xdd, 0x93, 0x98, 0xec, 0x8b, 0x5c, 0x71, + 0x0c, 0xb0, 0xe6, 0x12, 0xf2, 0x10, 0x1a, 0xbe, + 0x4a, 0xe0, 0xe3, 0x00, 0xf8 ); + MEMCPY_TEST_CONSTANT ( 0x40, 0xa8, 0x28, 0x5b, 0x12, 0x0d, 0x80, 0x8e, + 0x8a, 0xd9, 0x92, 0x7a, 0x6e, 0x48, 0x8d, 0x14, + 0x4b, 0xc6, 0xce, 0x21, 0x2f, 0x0e, 0x47, 0xbd, + 0xf1, 0xca, 0x0e, 0x1f, 0x65, 0xc4 ); + MEMCPY_TEST_CONSTANT ( 0x84, 0x83, 0x44, 0xe8, 0x1c, 0xbf, 0x23, 0x05, + 0xdf, 0xed, 0x3b, 0xb7, 0x0b, 0x4a, 0x05, 0xec, + 0xb7, 0x6f, 0x1c, 0xfe, 0x05, 0x05, 0x4e, 0xd1, + 0x50, 0x88, 0x81, 0x87, 0x68, 0xf6, 0x66 ); + MEMCPY_TEST_CONSTANT ( 0x0d, 0x1d, 0xcf, 0x3e, 0x7c, 0xf8, 0x12, 0x1b, + 0x96, 0x7f, 0xff, 0x27, 0xca, 0xfe, 0xd3, 0x8b, + 0x10, 0xb9, 0x5d, 0x05, 0xad, 0x50, 0xed, 0x35, + 0x32, 0x9c, 0xe6, 0x3b, 0x73, 0xe0, 0x7d ); + + /* Speed tests */ + memcpy_test_speed ( 0, 0, 64 ); + memcpy_test_speed ( 0, 0, 128 ); + memcpy_test_speed ( 0, 0, 256 ); + for ( dest_offset = 0 ; dest_offset < 4 ; dest_offset++ ) { + for ( src_offset = 0 ; src_offset < 4 ; src_offset++ ) { + memcpy_test_speed ( dest_offset, src_offset, 4096 ); + } + } +} + +/** memcpy() self-test */ +struct self_test memcpy_test __self_test = { + .name = "memcpy", + .exec = memcpy_test_exec, +}; diff --git a/src/tests/tests.c b/src/tests/tests.c index 95a3c4ba..0fb5bb5b 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /* Drag in all applicable self-tests */ +REQUIRE_OBJECT ( memcpy_test ); REQUIRE_OBJECT ( list_test ); REQUIRE_OBJECT ( byteswap_test ); REQUIRE_OBJECT ( base64_test ); From 6a4ff519c8c21c8acbedb5e2db4d92c14e99d9f1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 26 Jun 2012 12:42:24 +0100 Subject: [PATCH 053/250] [libc] Simplify memcpy() implementation The "rep" prefix can be used with an iteration count of zero, which allows the variable-length memcpy() to be implemented without using any conditional jumps. Signed-off-by: Michael Brown --- src/arch/x86/core/x86_string.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 5838ebac..8c3a4d2a 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -43,21 +43,15 @@ void * __memcpy ( void *dest, const void *src, size_t len ) { * moves. Using movsl rather than movsb speeds these up by * around 32%. */ - if ( len >> 2 ) { - __asm__ __volatile__ ( "rep movsl" - : "=&D" ( edi ), "=&S" ( esi ), - "=&c" ( discard_ecx ) - : "0" ( edi ), "1" ( esi ), - "2" ( len >> 2 ) - : "memory" ); - } - if ( len & 0x02 ) { - __asm__ __volatile__ ( "movsw" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - } - if ( len & 0x01 ) { - __asm__ __volatile__ ( "movsb" : "=&D" ( edi ), "=&S" ( esi ) - : "0" ( edi ), "1" ( esi ) : "memory" ); - } + __asm__ __volatile__ ( "rep movsl" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), "2" ( len >> 2 ) + : "memory" ); + __asm__ __volatile__ ( "rep movsb" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), "2" ( len & 3 ) + : "memory" ); return dest; } From 1d77d032168bd495c53589cca596131a992473c4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 27 Jun 2012 12:02:58 +0100 Subject: [PATCH 054/250] [tcpip] Allow for architecture-specific TCP/IP checksum routines Calculating the TCP/IP checksum on received packets accounts for a substantial fraction of the response latency. Signed-off-by: Michael Brown --- src/arch/x86/include/bits/tcpip.h | 12 ++++++++++++ src/include/ipxe/tcpip.h | 12 ++++++++++-- src/net/tcpip.c | 4 ++-- 3 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 src/arch/x86/include/bits/tcpip.h diff --git a/src/arch/x86/include/bits/tcpip.h b/src/arch/x86/include/bits/tcpip.h new file mode 100644 index 00000000..9ae8d920 --- /dev/null +++ b/src/arch/x86/include/bits/tcpip.h @@ -0,0 +1,12 @@ +#ifndef _BITS_TCPIP_H +#define _BITS_TCPIP_H + +/** @file + * + * Transport-network layer interface + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#endif /* _BITS_TCPIP_H */ diff --git a/src/include/ipxe/tcpip.h b/src/include/ipxe/tcpip.h index cdf554ea..34d7f88f 100644 --- a/src/include/ipxe/tcpip.h +++ b/src/include/ipxe/tcpip.h @@ -13,6 +13,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include struct io_buffer; struct net_device; @@ -121,8 +122,15 @@ extern int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum ); -extern uint16_t tcpip_continue_chksum ( uint16_t partial, - const void *data, size_t len ); +extern uint16_t generic_tcpip_continue_chksum ( uint16_t partial, + const void *data, size_t len ); extern uint16_t tcpip_chksum ( const void *data, size_t len ); +/* Use generic_tcpip_continue_chksum() if no architecture-specific + * version is available + */ +#ifndef tcpip_continue_chksum +#define tcpip_continue_chksum generic_tcpip_continue_chksum +#endif + #endif /* _IPXE_TCPIP_H */ diff --git a/src/net/tcpip.c b/src/net/tcpip.c index 4451bf11..8e187f7e 100644 --- a/src/net/tcpip.c +++ b/src/net/tcpip.c @@ -97,8 +97,8 @@ int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, * or both. Deciding which to swap is left as an exercise for the * interested reader. */ -uint16_t tcpip_continue_chksum ( uint16_t partial, const void *data, - size_t len ) { +uint16_t generic_tcpip_continue_chksum ( uint16_t partial, + const void *data, size_t len ) { unsigned int cksum = ( ( ~partial ) & 0xffff ); unsigned int value; unsigned int i; From bb9961fb548068f769c666970c1de6c68743ed07 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 26 Jun 2012 14:49:26 +0100 Subject: [PATCH 055/250] [test] Add self-tests for TCP/IP checksum calculation Signed-off-by: Michael Brown --- src/tests/tcpip_test.c | 213 +++++++++++++++++++++++++++++++++++++++++ src/tests/tests.c | 1 + 2 files changed, 214 insertions(+) create mode 100644 src/tests/tcpip_test.c diff --git a/src/tests/tcpip_test.c b/src/tests/tcpip_test.c new file mode 100644 index 00000000..13423c39 --- /dev/null +++ b/src/tests/tcpip_test.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * TCP/IP self-tests + * + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include +#include +#include +#include +#include +#include +#include + +/** A TCP/IP fixed-data test */ +struct tcpip_test { + /** Data */ + const void *data; + /** Length of data */ + size_t len; +}; + +/** A TCP/IP pseudorandom-data test */ +struct tcpip_random_test { + /** Seed */ + unsigned int seed; + /** Length of data */ + size_t len; + /** Alignment offset */ + size_t offset; +}; + +/** Define inline data */ +#define DATA(...) { __VA_ARGS__ } + +/** Define a TCP/IP fixed-data test */ +#define TCPIP_TEST( name, DATA ) \ + static const uint8_t __attribute__ (( aligned ( 16 ) )) \ + name ## _data[] = DATA; \ + static struct tcpip_test name = { \ + .data = name ## _data, \ + .len = sizeof ( name ## _data ), \ + } + +/** Define a TCP/IP pseudorandom-data test */ +#define TCPIP_RANDOM_TEST( name, SEED, LEN, OFFSET ) \ + static struct tcpip_random_test name = { \ + .seed = SEED, \ + .len = LEN, \ + .offset = OFFSET, \ + } + +/** Buffer for pseudorandom-data tests */ +static uint8_t __attribute__ (( aligned ( 16 ) )) + tcpip_data[ 4096 + 7 /* offset */ ]; + +/** Empty data */ +TCPIP_TEST ( empty, DATA() ); + +/** Single byte */ +TCPIP_TEST ( one_byte, DATA ( 0xeb ) ); + +/** Double byte */ +TCPIP_TEST ( two_bytes, DATA ( 0xba, 0xbe ) ); + +/** Final wrap-around carry (big-endian) */ +TCPIP_TEST ( final_carry_big, + DATA ( 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ) ); + +/** Final wrap-around carry (little-endian) */ +TCPIP_TEST ( final_carry_little, + DATA ( 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 ) ); + +/** Random data (aligned) */ +TCPIP_RANDOM_TEST ( random_aligned, 0x12345678UL, 4096, 0 ); + +/** Random data (unaligned, +1) */ +TCPIP_RANDOM_TEST ( random_unaligned_1, 0x12345678UL, 4096, 1 ); + +/** Random data (unaligned, +2) */ +TCPIP_RANDOM_TEST ( random_unaligned_2, 0x12345678UL, 4096, 2 ); + +/** Random data (aligned, truncated) */ +TCPIP_RANDOM_TEST ( random_aligned_truncated, 0x12345678UL, 4095, 0 ); + +/** Random data (unaligned start and finish) */ +TCPIP_RANDOM_TEST ( partial, 0xcafebabe, 121, 5 ); + +/** + * Calculate TCP/IP checksum + * + * @v data Data to sum + * @v len Length of data + * @ret cksum Checksum + * + * This is a reference implementation taken from RFC1071 (and modified + * to fix compilation without warnings under gcc). + */ +static uint16_t rfc_tcpip_chksum ( const void *data, size_t len ) { + unsigned long sum = 0; + + while ( len > 1 ) { + sum += *( ( uint16_t * ) data ); + data += 2; + len -= 2; + } + + if ( len > 0 ) + sum += *( ( uint8_t * ) data ); + + while ( sum >> 16 ) + sum = ( ( sum & 0xffff ) + ( sum >> 16 ) ); + + return ~sum; +} + +/** + * Report TCP/IP fixed-data test result + * + * @v test TCP/IP test + */ +#define tcpip_ok( test ) do { \ + uint16_t expected; \ + uint16_t generic_sum; \ + uint16_t sum; \ + expected = rfc_tcpip_chksum ( (test)->data, (test)->len ); \ + generic_sum = generic_tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, \ + (test)->data, \ + (test)->len ); \ + ok ( generic_sum == expected ); \ + sum = tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, (test)->data, \ + (test)->len ); \ + ok ( sum == expected ); \ + } while ( 0 ) + +/** + * Report TCP/IP pseudorandom-data test result + * + * @v test TCP/IP test + */ +#define tcpip_random_ok( test ) do { \ + uint8_t *data = ( tcpip_data + (test)->offset ); \ + uint16_t expected; \ + uint16_t generic_sum; \ + uint16_t sum; \ + unsigned long elapsed; \ + unsigned int i; \ + assert ( ( (test)->len + (test)->offset ) <= \ + sizeof ( tcpip_data ) ); \ + srandom ( (test)->seed ); \ + for ( i = 0 ; i < (test)->len ; i++ ) \ + data[i] = random(); \ + expected = rfc_tcpip_chksum ( data, (test)->len ); \ + generic_sum = generic_tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, \ + data, \ + (test)->len ); \ + ok ( generic_sum == expected ); \ + simple_profile(); \ + sum = tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, \ + (test)->len ); \ + elapsed = simple_profile(); \ + ok ( sum == expected ); \ + DBG ( "TCPIP checksummed %zd bytes (+%zd) in %ld ticks\n", \ + (test)->len, (test)->offset, elapsed ); \ + } while ( 0 ) + +/** + * Perform TCP/IP self-tests + * + */ +static void tcpip_test_exec ( void ) { + + tcpip_ok ( &empty ); + tcpip_ok ( &one_byte ); + tcpip_ok ( &two_bytes ); + tcpip_ok ( &final_carry_big ); + tcpip_ok ( &final_carry_little ); + tcpip_random_ok ( &random_aligned ); + tcpip_random_ok ( &random_unaligned_1 ); + tcpip_random_ok ( &random_unaligned_2 ); + tcpip_random_ok ( &random_aligned_truncated ); + tcpip_random_ok ( &partial ); +} + +/** TCP/IP self-test */ +struct self_test tcpip_test __self_test = { + .name = "tcpip", + .exec = tcpip_test_exec, +}; diff --git a/src/tests/tests.c b/src/tests/tests.c index 0fb5bb5b..c0d9df5e 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -31,6 +31,7 @@ REQUIRE_OBJECT ( byteswap_test ); REQUIRE_OBJECT ( base64_test ); REQUIRE_OBJECT ( settings_test ); REQUIRE_OBJECT ( time_test ); +REQUIRE_OBJECT ( tcpip_test ); REQUIRE_OBJECT ( crc32_test ); REQUIRE_OBJECT ( md5_test ); REQUIRE_OBJECT ( sha1_test ); From ec22e08db1fa61f5276b2ed1efbde28a1a45101e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 26 Jun 2012 17:19:18 +0100 Subject: [PATCH 056/250] [tcpip] Add faster algorithm for calculating the TCP/IP checksum The generic TCP/IP checksum implementation requires approximately 10 CPU clocks per byte (as measured using the TSC). Improve this to approximately 0.5 CPU clocks per byte by using "lodsl ; adcl" in an unrolled loop. Signed-off-by: Michael Brown --- src/arch/x86/core/x86_tcpip.c | 169 ++++++++++++++++++++++++++++++ src/arch/x86/include/bits/tcpip.h | 5 + 2 files changed, 174 insertions(+) create mode 100644 src/arch/x86/core/x86_tcpip.c diff --git a/src/arch/x86/core/x86_tcpip.c b/src/arch/x86/core/x86_tcpip.c new file mode 100644 index 00000000..b4e7c3b8 --- /dev/null +++ b/src/arch/x86/core/x86_tcpip.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * TCP/IP checksum + * + */ + +#include +#include + +extern char x86_tcpip_loop_end[]; + +/** + * Calculate continued TCP/IP checkum + * + * @v partial Checksum of already-summed data, in network byte order + * @v data Data buffer + * @v len Length of data buffer + * @ret cksum Updated checksum, in network byte order + */ +uint16_t x86_tcpip_continue_chksum ( uint16_t partial, + const void *data, size_t len ) { + unsigned long sum = ( ( ~partial ) & 0xffff ); + unsigned long initial_word_count; + unsigned long loop_count; + unsigned long loop_partial_count; + unsigned long final_word_count; + unsigned long final_byte; + unsigned long discard_S; + unsigned long discard_c; + unsigned long discard_a; + unsigned long discard_r1; + unsigned long discard_r2; + + /* Calculate number of initial 16-bit words required to bring + * the main loop into alignment. (We don't care about the + * speed for data aligned to less than 16 bits, since this + * situation won't occur in practice.) + */ + if ( len >= sizeof ( sum ) ) { + initial_word_count = ( ( -( ( intptr_t ) data ) & + ( sizeof ( sum ) - 1 ) ) >> 1 ); + } else { + initial_word_count = 0; + } + len -= ( initial_word_count * 2 ); + + /* Calculate number of iterations of the main loop. This loop + * processes native machine words (32-bit or 64-bit), and is + * unrolled 16 times. We calculate an overall iteration + * count, and a starting point for the first iteration. + */ + loop_count = ( len / ( sizeof ( sum ) * 16 ) ); + loop_partial_count = + ( ( len % ( sizeof ( sum ) * 16 ) ) / sizeof ( sum ) ); + + /* Calculate number of 16-bit words remaining after the main + * loop completes. + */ + final_word_count = ( ( len % sizeof ( sum ) ) / 2 ); + + /* Calculate whether or not a final byte remains at the end */ + final_byte = ( len & 1 ); + + /* Calculate the checksum */ + __asm__ ( /* Calculate position at which to jump into the + * unrolled loop. + */ + "imul $( -x86_tcpip_loop_step_size ), %4\n\t" + "add %5, %4\n\t" + + /* Clear carry flag before starting checksumming */ + "clc\n\t" + + /* Checksum initial words */ + "jmp 2f\n\t" + "\n1:\n\t" + "lodsw\n\t" + "adcw %w2, %w0\n\t" + "\n2:\n\t" + "loop 1b\n\t" + + /* Main "lods;adc" loop, unrolled x16 */ + "mov %12, %3\n\t" + "jmp *%4\n\t" + "\nx86_tcpip_loop_start:\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "lods%z2\n\tadc %2, %0\n\t" + "\nx86_tcpip_loop_end:\n\t" + "loop x86_tcpip_loop_start\n\t" + ".equ x86_tcpip_loop_step_size, " + " ( ( x86_tcpip_loop_end - x86_tcpip_loop_start ) / 16 )\n\t" + + /* Checksum remaining whole words */ + "mov %13, %3\n\t" + "jmp 2f\n\t" + "\n1:\n\t" + "lodsw\n\t" + "adcw %w2, %w0\n\t" + "\n2:\n\t" + "loop 1b\n\t" + + /* Checksum final byte if applicable */ + "mov %14, %3\n\t" + "loop 1f\n\t" + "adcb (%1), %b0\n\t" + "adcb $0, %h0\n\t" + "\n1:\n\t" + + /* Fold down to a uint16_t */ + "push %0\n\t" + "popw %w0\n\t" + "popw %w2\n\t" + "adcw %w2, %w0\n\t" +#if ULONG_MAX > 0xffffffffUL /* 64-bit only */ + "popw %w2\n\t" + "adcw %w2, %w0\n\t" + "popw %w2\n\t" + "adcw %w2, %w0\n\t" +#endif /* 64-bit only */ + + /* Consume CF */ + "adcw $0, %w0\n\t" + "adcw $0, %w0\n\t" + + : "=&Q" ( sum ), "=&S" ( discard_S ), "=&a" ( discard_a ), + "=&c" ( discard_c ), "=&r" ( discard_r1 ), + "=&r" ( discard_r2 ) + : "0" ( sum ), "1" ( data ), "2" ( 0 ), + "3" ( initial_word_count + 1 ), "4" ( loop_partial_count ), + "5" ( x86_tcpip_loop_end ), "g" ( loop_count + 1 ), + "g" ( final_word_count + 1 ), "g" ( final_byte ) ); + + return ( ~sum & 0xffff ); +} diff --git a/src/arch/x86/include/bits/tcpip.h b/src/arch/x86/include/bits/tcpip.h index 9ae8d920..a4b335eb 100644 --- a/src/arch/x86/include/bits/tcpip.h +++ b/src/arch/x86/include/bits/tcpip.h @@ -9,4 +9,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); +extern uint16_t x86_tcpip_continue_chksum ( uint16_t partial, + const void *data, size_t len ); + +#define tcpip_continue_chksum x86_tcpip_continue_chksum + #endif /* _BITS_TCPIP_H */ From 85917ba8dd7814856be12f8c00ef755547166fad Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 28 Jun 2012 12:27:43 +0100 Subject: [PATCH 057/250] [monojob] Check for keypresses only once per timer tick Checking for keypresses takes a non-negligible amount of time, and measurably affects our RTT. Minimise the impact by checking for keypresses only once per timer tick. Signed-off-by: Michael Brown --- src/core/monojob.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/core/monojob.c b/src/core/monojob.c index 7917b427..d2161b3c 100644 --- a/src/core/monojob.c +++ b/src/core/monojob.c @@ -60,7 +60,9 @@ int monojob_wait ( const char *string ) { struct job_progress progress; int key; int rc; + unsigned long last_keycheck; unsigned long last_progress; + unsigned long now; unsigned long elapsed; unsigned long completed; unsigned long total; @@ -70,20 +72,32 @@ int monojob_wait ( const char *string ) { if ( string ) printf ( "%s...", string ); monojob_rc = -EINPROGRESS; - last_progress = currticks(); + last_keycheck = last_progress = currticks(); while ( monojob_rc == -EINPROGRESS ) { + + /* Allow job to progress */ step(); - if ( iskey() ) { - key = getchar(); - switch ( key ) { - case CTRL_C: - monojob_close ( &monojob, -ECANCELED ); - break; - default: - break; + now = currticks(); + + /* Check for keypresses. This can be time-consuming, + * so check only once per clock tick. + */ + if ( now != last_keycheck ) { + if ( iskey() ) { + key = getchar(); + switch ( key ) { + case CTRL_C: + monojob_close ( &monojob, -ECANCELED ); + break; + default: + break; + } } + last_keycheck = now; } - elapsed = ( currticks() - last_progress ); + + /* Display progress, if applicable */ + elapsed = ( now - last_progress ); if ( string && ( elapsed >= TICKS_PER_SEC ) ) { if ( shown_percentage ) printf ( "\b\b\b\b \b\b\b\b" ); @@ -99,7 +113,7 @@ int monojob_wait ( const char *string ) { printf ( "." ); shown_percentage = 0; } - last_progress = currticks(); + last_progress = now; } } rc = monojob_rc; From 76d9c1a00120d5b93d6f717bab867462a7a83f11 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 29 Jun 2012 01:03:38 +0100 Subject: [PATCH 058/250] [undi] Align the received frame payload for faster processing The undinet driver always has to make a copy of the received frame into an I/O buffer. Align this copy sensibly so that subsequent operations are as fast as possible. Signed-off-by: Michael Brown --- src/arch/i386/drivers/net/undinet.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index 19014415..def44113 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -70,6 +70,9 @@ struct undi_nic { /** Delay between retries of PXENV_UNDI_INITIALIZE */ #define UNDI_INITIALIZE_RETRY_DELAY_MS 200 +/** Alignment of received frame payload */ +#define UNDI_RX_ALIGN 16 + static void undinet_close ( struct net_device *netdev ); /** Address of UNDI entry point */ @@ -299,6 +302,7 @@ static void undinet_poll ( struct net_device *netdev ) { struct s_PXENV_UNDI_ISR undi_isr; struct io_buffer *iobuf = NULL; size_t len; + size_t reserve_len; size_t frag_len; size_t max_frag_len; int rc; @@ -346,6 +350,8 @@ static void undinet_poll ( struct net_device *netdev ) { /* Packet fragment received */ len = undi_isr.FrameLength; frag_len = undi_isr.BufferLength; + reserve_len = ( -undi_isr.FrameHeaderLength & + ( UNDI_RX_ALIGN - 1 ) ); if ( ( len == 0 ) || ( len < frag_len ) ) { /* Don't laugh. VMWare does it. */ DBGC ( undinic, "UNDINIC %p reported insane " @@ -354,15 +360,17 @@ static void undinet_poll ( struct net_device *netdev ) { netdev_rx_err ( netdev, NULL, -EINVAL ); break; } - if ( ! iobuf ) - iobuf = alloc_iob ( len ); if ( ! iobuf ) { - DBGC ( undinic, "UNDINIC %p could not " - "allocate %zd bytes for RX buffer\n", - undinic, len ); - /* Fragment will be dropped */ - netdev_rx_err ( netdev, NULL, -ENOMEM ); - goto done; + iobuf = alloc_iob ( reserve_len + len ); + if ( ! iobuf ) { + DBGC ( undinic, "UNDINIC %p could not " + "allocate %zd bytes for RX " + "buffer\n", undinic, len ); + /* Fragment will be dropped */ + netdev_rx_err ( netdev, NULL, -ENOMEM ); + goto done; + } + iob_reserve ( iobuf, reserve_len ); } max_frag_len = iob_tailroom ( iobuf ); if ( frag_len > max_frag_len ) { From ea61075c60e6417203bbb5fd54e1f313c99c164c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 29 Jun 2012 14:30:18 +0100 Subject: [PATCH 059/250] [tcp] Add support for TCP window scaling The maximum unscaled TCP window (64kB) implies a maximum bandwidth of around 300kB/s on a WAN link with an RTT of 200ms. Add support for the TCP window scaling option to remove this upper limit. Signed-off-by: Michael Brown --- src/include/ipxe/tcp.h | 30 +++++++++++++++++++++++++++++- src/net/tcp.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/include/ipxe/tcp.h b/src/include/ipxe/tcp.h index 7084af60..cb3309f2 100644 --- a/src/include/ipxe/tcp.h +++ b/src/include/ipxe/tcp.h @@ -54,6 +54,31 @@ struct tcp_mss_option { /** Code for the TCP MSS option */ #define TCP_OPTION_MSS 2 +/** TCP window scale option */ +struct tcp_window_scale_option { + uint8_t kind; + uint8_t length; + uint8_t scale; +} __attribute__ (( packed )); + +/** Padded TCP window scale option (used for sending) */ +struct tcp_window_scale_padded_option { + uint8_t nop; + struct tcp_window_scale_option wsopt; +} __attribute (( packed )); + +/** Code for the TCP window scale option */ +#define TCP_OPTION_WS 3 + +/** Advertised TCP window scale + * + * Using a scale factor of 2**9 provides for a maximum window of 32MB, + * which is sufficient to allow Gigabit-speed transfers with a 200ms + * RTT. The minimum advertised window is 512 bytes, which is still + * less than a single packet. + */ +#define TCP_RX_WINDOW_SCALE 9 + /** TCP timestamp option */ struct tcp_timestamp_option { uint8_t kind; @@ -75,7 +100,9 @@ struct tcp_timestamp_padded_option { struct tcp_options { /** MSS option, if present */ const struct tcp_mss_option *mssopt; - /** Timestampe option, if present */ + /** Window scale option, if present */ + const struct tcp_window_scale_option *wsopt; + /** Timestamp option, if present */ const struct tcp_timestamp_option *tsopt; }; @@ -316,6 +343,7 @@ struct tcp_options { ( MAX_LL_NET_HEADER_LEN + \ sizeof ( struct tcp_header ) + \ sizeof ( struct tcp_mss_option ) + \ + sizeof ( struct tcp_window_scale_padded_option ) + \ sizeof ( struct tcp_timestamp_padded_option ) ) /** diff --git a/src/net/tcp.c b/src/net/tcp.c index c6bb4a66..b30fb1b0 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -87,6 +87,16 @@ struct tcp_connection { * Equivalent to TS.Recent in RFC 1323 terminology. */ uint32_t ts_recent; + /** Send window scale + * + * Equivalent to Snd.Wind.Scale in RFC 1323 terminology + */ + uint8_t snd_win_scale; + /** Receive window scale + * + * Equivalent to Rcv.Wind.Scale in RFC 1323 terminology + */ + uint8_t rcv_win_scale; /** Transmit queue */ struct list_head tx_queue; @@ -490,6 +500,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { struct io_buffer *iobuf; struct tcp_header *tcphdr; struct tcp_mss_option *mssopt; + struct tcp_window_scale_padded_option *wsopt; struct tcp_timestamp_padded_option *tsopt; void *payload; unsigned int flags; @@ -497,6 +508,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { uint32_t seq_len; uint32_t app_win; uint32_t max_rcv_win; + uint32_t max_representable_win; int rc; /* If retransmission timer is already running, do nothing */ @@ -551,6 +563,9 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { app_win = xfer_window ( &tcp->xfer ); if ( max_rcv_win > app_win ) max_rcv_win = app_win; + max_representable_win = ( 0xffff << tcp->rcv_win_scale ); + if ( max_rcv_win > max_representable_win ) + max_rcv_win = max_representable_win; max_rcv_win &= ~0x03; /* Keep everything dword-aligned */ if ( tcp->rcv_win < max_rcv_win ) tcp->rcv_win = max_rcv_win; @@ -562,6 +577,11 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { mssopt->kind = TCP_OPTION_MSS; mssopt->length = sizeof ( *mssopt ); mssopt->mss = htons ( TCP_MSS ); + wsopt = iob_push ( iobuf, sizeof ( *wsopt ) ); + wsopt->nop = TCP_OPTION_NOP; + wsopt->wsopt.kind = TCP_OPTION_WS; + wsopt->wsopt.length = sizeof ( wsopt->wsopt ); + wsopt->wsopt.scale = TCP_RX_WINDOW_SCALE; } if ( ( flags & TCP_SYN ) || ( tcp->flags & TCP_TS_ENABLED ) ) { tsopt = iob_push ( iobuf, sizeof ( *tsopt ) ); @@ -581,7 +601,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { tcphdr->ack = htonl ( tcp->rcv_ack ); tcphdr->hlen = ( ( payload - iobuf->data ) << 2 ); tcphdr->flags = flags; - tcphdr->win = htons ( tcp->rcv_win ); + tcphdr->win = htons ( tcp->rcv_win >> tcp->rcv_win_scale ); tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) ); /* Dump header */ @@ -769,6 +789,9 @@ static void tcp_rx_opts ( struct tcp_connection *tcp, const void *data, case TCP_OPTION_MSS: options->mssopt = data; break; + case TCP_OPTION_WS: + options->wsopt = data; + break; case TCP_OPTION_TS: options->tsopt = data; break; @@ -825,6 +848,10 @@ static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq, tcp->rcv_ack = seq; if ( options->tsopt ) tcp->flags |= TCP_TS_ENABLED; + if ( options->wsopt ) { + tcp->snd_win_scale = options->wsopt->scale; + tcp->rcv_win_scale = TCP_RX_WINDOW_SCALE; + } } /* Ignore duplicate SYN */ @@ -1168,7 +1195,7 @@ static int tcp_rx ( struct io_buffer *iobuf, tcp = tcp_demux ( ntohs ( tcphdr->dest ) ); seq = ntohl ( tcphdr->seq ); ack = ntohl ( tcphdr->ack ); - win = ntohs ( tcphdr->win ); + win = ( ntohs ( tcphdr->win ) << tcp->snd_win_scale ); flags = tcphdr->flags; tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ), ( hlen - sizeof ( *tcphdr ) ), &options ); From 9a8c6b00d4433eb5c24f50c0c4a93c127d77def0 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 29 Jun 2012 15:28:15 +0100 Subject: [PATCH 060/250] [tls] Request a maximum fragment length of 2048 bytes The default maximum plaintext fragment length for TLS is 16kB, which is a substantial amount of memory for iPXE to have to allocate for a temporary decryption buffer. Reduce the memory footprint of TLS connections by requesting a maximum fragment length of 2kB. Signed-off-by: Michael Brown --- src/include/ipxe/tls.h | 9 ++++++++- src/net/tls.c | 11 +++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 4273e4e5..2af864df 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -89,10 +89,17 @@ struct tls_header { /* TLS signature algorithm identifiers */ #define TLS_RSA_ALGORITHM 1 -/* TLS extension types */ +/* TLS server name extension */ #define TLS_SERVER_NAME 0 #define TLS_SERVER_NAME_HOST_NAME 0 +/* TLS maximum fragment length extension */ +#define TLS_MAX_FRAGMENT_LENGTH 1 +#define TLS_MAX_FRAGMENT_LENGTH_512 1 +#define TLS_MAX_FRAGMENT_LENGTH_1024 2 +#define TLS_MAX_FRAGMENT_LENGTH_2048 3 +#define TLS_MAX_FRAGMENT_LENGTH_4096 4 + /** TLS RX state machine state */ enum tls_rx_state { TLS_RX_HEADER = 0, diff --git a/src/net/tls.c b/src/net/tls.c index 8d6620d3..a3433f92 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -869,6 +869,11 @@ static int tls_send_client_hello ( struct tls_session *tls ) { uint8_t name[ strlen ( tls->name ) ]; } __attribute__ (( packed )) list[1]; } __attribute__ (( packed )) server_name; + uint16_t max_fragment_length_type; + uint16_t max_fragment_length_len; + struct { + uint8_t max; + } __attribute__ (( packed )) max_fragment_length; } __attribute__ (( packed )) extensions; } __attribute__ (( packed )) hello; unsigned int i; @@ -894,6 +899,12 @@ static int tls_send_client_hello ( struct tls_session *tls ) { = htons ( sizeof ( hello.extensions.server_name.list[0].name )); memcpy ( hello.extensions.server_name.list[0].name, tls->name, sizeof ( hello.extensions.server_name.list[0].name ) ); + hello.extensions.max_fragment_length_type + = htons ( TLS_MAX_FRAGMENT_LENGTH ); + hello.extensions.max_fragment_length_len + = htons ( sizeof ( hello.extensions.max_fragment_length ) ); + hello.extensions.max_fragment_length.max + = TLS_MAX_FRAGMENT_LENGTH_2048; return tls_send_handshake ( tls, &hello, sizeof ( hello ) ); } From a5c016d93ee24e851cd8752b014170a308f231da Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 29 Jun 2012 16:07:12 +0100 Subject: [PATCH 061/250] [iobuf] Relax alignment requirement for small I/O buffers iPXE currently aligns all I/O buffers on a 2kB boundary. This is overkill for transmitted packets, which are typically much smaller than 2kB. Align I/O buffers on their own size. This reduces the alignment requirement for small buffers, while preserving the guarantee that I/O buffers will never cross boundaries that might cause problems for some DMA engines. Signed-off-by: Michael Brown --- src/core/iobuf.c | 18 +++++++++++++----- src/include/ipxe/iobuf.h | 11 ----------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/core/iobuf.c b/src/core/iobuf.c index d776d606..3dfaf18c 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include @@ -40,18 +41,24 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ struct io_buffer * alloc_iob ( size_t len ) { struct io_buffer *iobuf = NULL; + size_t align; void *data; /* Pad to minimum length */ if ( len < IOB_ZLEN ) len = IOB_ZLEN; - /* Align buffer length */ - len = ( len + __alignof__( *iobuf ) - 1 ) & - ~( __alignof__( *iobuf ) - 1 ); - + /* Align buffer length to ensure that struct io_buffer is aligned */ + len = ( len + __alignof__ ( *iobuf ) - 1 ) & + ~( __alignof__ ( *iobuf ) - 1 ); + + /* Align buffer on its own size to avoid potential problems + * with boundary-crossing DMA. + */ + align = ( 1 << fls ( len - 1 ) ); + /* Allocate memory for buffer plus descriptor */ - data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN ); + data = malloc_dma ( len + sizeof ( *iobuf ), align ); if ( ! data ) return NULL; @@ -61,6 +68,7 @@ struct io_buffer * alloc_iob ( size_t len ) { return iobuf; } + /** * Free I/O buffer * diff --git a/src/include/ipxe/iobuf.h b/src/include/ipxe/iobuf.h index 82c8b889..8134ae76 100644 --- a/src/include/ipxe/iobuf.h +++ b/src/include/ipxe/iobuf.h @@ -13,17 +13,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include -/** - * I/O buffer alignment - * - * I/O buffers allocated via alloc_iob() are guaranteed to be - * physically aligned to this boundary. Some cards cannot DMA across - * a 4kB boundary. With a standard Ethernet MTU, aligning to a 2kB - * boundary is sufficient to guarantee no 4kB boundary crossings. For - * a jumbo Ethernet MTU, a packet may be larger than 4kB anyway. - */ -#define IOB_ALIGN 2048 - /** * Minimum I/O buffer length * From 49ac629821dedb8b27bb8f03e1e6e7d5d621ced6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 30 Jun 2012 18:59:09 +0100 Subject: [PATCH 062/250] [tcp] Use a zero window size for RST packets Signed-off-by: Michael Brown --- src/net/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/tcp.c b/src/net/tcp.c index b30fb1b0..3cd357fc 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -714,7 +714,7 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp, tcphdr->ack = in_tcphdr->seq; tcphdr->hlen = ( ( sizeof ( *tcphdr ) / 4 ) << 4 ); tcphdr->flags = ( TCP_RST | TCP_ACK ); - tcphdr->win = htons ( TCP_MAX_WINDOW_SIZE ); + tcphdr->win = htons ( 0 ); tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) ); /* Dump header */ From 55f52bb77a708ede94176c354fb5f27177fd5e99 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 30 Jun 2012 19:02:36 +0100 Subject: [PATCH 063/250] [tcp] Avoid potential NULL pointer dereference Commit ea61075 ("[tcp] Add support for TCP window scaling") introduced a potential NULL pointer dereference by referring to the connection's send window scale before checking whether or not the connection is known. Signed-off-by: Michael Brown --- src/net/tcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/net/tcp.c b/src/net/tcp.c index 3cd357fc..7a127260 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -1155,6 +1155,7 @@ static int tcp_rx ( struct io_buffer *iobuf, uint16_t csum; uint32_t seq; uint32_t ack; + uint16_t raw_win; uint32_t win; unsigned int flags; size_t len; @@ -1195,7 +1196,7 @@ static int tcp_rx ( struct io_buffer *iobuf, tcp = tcp_demux ( ntohs ( tcphdr->dest ) ); seq = ntohl ( tcphdr->seq ); ack = ntohl ( tcphdr->ack ); - win = ( ntohs ( tcphdr->win ) << tcp->snd_win_scale ); + raw_win = ntohs ( tcphdr->win ); flags = tcphdr->flags; tcp_rx_opts ( tcp, ( ( ( void * ) tcphdr ) + sizeof ( *tcphdr ) ), ( hlen - sizeof ( *tcphdr ) ), &options ); @@ -1226,6 +1227,7 @@ static int tcp_rx ( struct io_buffer *iobuf, /* Handle ACK, if present */ if ( flags & TCP_ACK ) { + win = ( raw_win << tcp->snd_win_scale ); if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) { tcp_xmit_reset ( tcp, st_src, tcphdr ); goto discard; From 19859d8eada26eeeb881054efc242cf2ed5609fb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 1 Jul 2012 18:24:15 +0100 Subject: [PATCH 064/250] [arp] Prevent ARP cache entries from being deleted mid-transmission Each ARP cache entry maintains a transmission queue, which is sent out as soon as the link-layer address is known. If multiple packets are queued, then it is possible for memory pressure to cause the ARP cache discarder to be invoked during transmission of the first packet, which may cause the ARP cache entry to be deleted before the second packet can be sent. This results in an invalid pointer dereference. Avoid this problem by reference-counting ARP cache entries and ensuring that an extra reference is held while processing the transmission queue, and by using list_first_entry() rather than list_for_each_entry_safe() to traverse the queue. Signed-off-by: Michael Brown --- src/net/arp.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/net/arp.c b/src/net/arp.c index 4283b669..d6b4e731 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -51,6 +52,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** An ARP cache entry */ struct arp_entry { + /** Reference count */ + struct refcnt refcnt; /** List of ARP cache entries */ struct list_head list; /** Network device */ @@ -76,6 +79,25 @@ struct net_protocol arp_protocol __net_protocol; static void arp_expired ( struct retry_timer *timer, int over ); +/** + * Free ARP cache entry + * + * @v refcnt Reference count + */ +static void arp_free ( struct refcnt *refcnt ) { + struct arp_entry *arp = + container_of ( refcnt, struct arp_entry, refcnt ); + + /* Sanity check */ + assert ( list_empty ( &arp->tx_queue ) ); + + /* Drop reference to network device */ + netdev_put ( arp->netdev ); + + /* Free entry */ + free ( arp ); +} + /** * Create ARP cache entry * @@ -91,27 +113,28 @@ static struct arp_entry * arp_create ( struct net_device *netdev, const void *net_source ) { struct arp_entry *arp; - /* Allocate entry and add to cache */ + /* Allocate and initialise entry */ arp = zalloc ( sizeof ( *arp ) ); if ( ! arp ) return NULL; - - /* Initialise entry and add to cache */ + ref_init ( &arp->refcnt, arp_free ); arp->netdev = netdev_get ( netdev ); arp->net_protocol = net_protocol; memcpy ( arp->net_dest, net_dest, net_protocol->net_addr_len ); memcpy ( arp->net_source, net_source, net_protocol->net_addr_len ); - timer_init ( &arp->timer, arp_expired, NULL ); + timer_init ( &arp->timer, arp_expired, &arp->refcnt ); arp->timer.min_timeout = ARP_MIN_TIMEOUT; arp->timer.max_timeout = ARP_MAX_TIMEOUT; INIT_LIST_HEAD ( &arp->tx_queue ); - list_add ( &arp->list, &arp_entries ); /* Start timer running to trigger initial transmission */ start_timer_nodelay ( &arp->timer ); + /* Transfer ownership to cache */ + list_add ( &arp->list, &arp_entries ); + DBGC ( arp, "ARP %p %s %s %s created\n", arp, netdev->name, net_protocol->name, net_protocol->ntoa ( net_dest ) ); return arp; @@ -174,10 +197,9 @@ static void arp_destroy ( struct arp_entry *arp, int rc ) { net_protocol->name, net_protocol->ntoa ( arp->net_dest ), strerror ( rc ) ); - /* Drop reference to network device, remove from cache and free */ - netdev_put ( arp->netdev ); + /* Remove from cache and drop reference */ list_del ( &arp->list ); - free ( arp ); + ref_put ( &arp->refcnt ); } /** @@ -241,7 +263,6 @@ static void arp_update ( struct arp_entry *arp, const void *ll_dest ) { struct ll_protocol *ll_protocol = netdev->ll_protocol; struct net_protocol *net_protocol = arp->net_protocol; struct io_buffer *iobuf; - struct io_buffer *tmp; int rc; DBGC ( arp, "ARP %p %s %s %s updated => %s\n", arp, netdev->name, @@ -254,8 +275,13 @@ static void arp_update ( struct arp_entry *arp, const void *ll_dest ) { /* Stop retransmission timer */ stop_timer ( &arp->timer ); - /* Transmit any packets in queue */ - list_for_each_entry_safe ( iobuf, tmp, &arp->tx_queue, list ) { + /* Transmit any packets in queue. Take out a temporary + * reference on the entry to prevent it from going out of + * scope during the call to net_tx(). + */ + ref_get ( &arp->refcnt ); + while ( ( iobuf = list_first_entry ( &arp->tx_queue, struct io_buffer, + list ) ) != NULL ) { DBGC2 ( arp, "ARP %p %s %s %s transmitting deferred packet\n", arp, netdev->name, net_protocol->name, net_protocol->ntoa ( arp->net_dest ) ); @@ -267,6 +293,7 @@ static void arp_update ( struct arp_entry *arp, const void *ll_dest ) { /* Ignore error and continue */ } } + ref_put ( &arp->refcnt ); } /** From b3adabd07bcee35ced80fc8230b677e90ac50372 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 3 Jul 2012 14:12:47 +0100 Subject: [PATCH 065/250] [menu] Truncate menu title when necessary Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/hci/tui/menu_ui.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c index 61625622..e9250099 100644 --- a/src/hci/tui/menu_ui.c +++ b/src/hci/tui/menu_ui.c @@ -307,6 +307,7 @@ int show_menu ( struct menu *menu, unsigned int timeout_ms, const char *select, struct menu_item **selected ) { struct menu_item *item; struct menu_ui ui; + char buf[ MENU_COLS + 1 /* NUL */ ]; int labelled_count = 0; int rc; @@ -348,8 +349,8 @@ int show_menu ( struct menu *menu, unsigned int timeout_ms, /* Draw initial content */ attron ( A_BOLD ); - mvprintw ( TITLE_ROW, ( ( COLS - strlen ( ui.menu->title ) ) / 2 ), - "%s", ui.menu->title ); + snprintf ( buf, sizeof ( buf ), "%s", ui.menu->title ); + mvprintw ( TITLE_ROW, ( ( COLS - strlen ( buf ) ) / 2 ), "%s", buf ); attroff ( A_BOLD ); draw_menu_items ( &ui ); draw_menu_item ( &ui, ui.selected ); From bc93e8ab41b7641d5ebb89f35340a17445cd994e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 3 Jul 2012 18:47:50 +0100 Subject: [PATCH 066/250] [util] Avoid compiler warning on gcc 4.6 Commit 196751c ("[build] Enable warnings when building utilities") revealed a previously hidden compiler warning in util/nrv2b.c regarding an out-of-bounds array subscript in the code #if defined(SWD_BEST_OFF) if (s->best_pos[2] == 0) s->best_pos[2] = key + 1; #endif where best_pos[] is defined by #define SWD_BEST_OFF 1 #if defined(SWD_BEST_OFF) unsigned int best_off[ SWD_BEST_OFF ]; unsigned int best_pos[ SWD_BEST_OFF ]; #endif With SWD_BEST_OFF set to 1, it can be proven that all code paths referring to s->best_off[] and s->best_pos[] will never be executed, with the exception of the two lines above. Since these two lines alone can have no effect on execution, we can safely undefine SWD_BEST_OFF. Verified by comparing md5sums of bin/undionly.kpxe before and after the change. Signed-off-by: Michael Brown --- src/util/nrv2b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/nrv2b.c b/src/util/nrv2b.c index cbb94c0e..031f5d9c 100644 --- a/src/util/nrv2b.c +++ b/src/util/nrv2b.c @@ -209,7 +209,7 @@ struct ucl_compress #define SWD_HSIZE 16384 #define SWD_MAX_CHAIN 2048 -#define SWD_BEST_OFF 1 +#undef SWD_BEST_OFF #define HEAD3(b,p) \ (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1)) From f3d197a5296027899f51c1df573e2f8709295d65 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 4 Jul 2012 13:37:08 +0100 Subject: [PATCH 067/250] [cmdline] Do not ignore empty initial arguments in concat_args() Reported-by: Oliver Rath Signed-off-by: Michael Brown --- src/core/exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/exec.c b/src/core/exec.c index 49261194..139cf7a8 100644 --- a/src/core/exec.c +++ b/src/core/exec.c @@ -358,7 +358,7 @@ char * concat_args ( char **args ) { ptr = string; for ( arg = args ; *arg ; arg++ ) { ptr += sprintf ( ptr, "%s%s", - ( ( ptr == string ) ? "" : " " ), *arg ); + ( ( arg == args ) ? "" : " " ), *arg ); } assert ( ptr < ( string + len ) ); From b0e236a9ee512f61d85bc1dfea57fafa04b3f214 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 1 Jul 2012 22:47:06 +0100 Subject: [PATCH 068/250] [netdevice] Process all received packets in net_poll() The current logic is to process at most one received packet per call to net_poll(), on the basis that refilling the hardware descriptor ring should be delayed as little as possible. However, this limits the rate at which packets can be processed and ultimately ends up adding latency which, in turn, limits the achievable throughput. With temporary modifications in place to essentially remove all resource constraints (heap size increased to 16MB, RX descriptor ring increased to 64 descriptors) and a TCP window size of 1MB, the throughput on a gigabit (i.e. 119MBps) network can be observed to fall off exponentially from around 115MBps to around 75MBps. Changing net_poll() to process all received packets results in a steady 119MBps throughput. Signed-off-by: Michael Brown --- src/net/netdevice.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/net/netdevice.c b/src/net/netdevice.c index b9b1337a..6afe2d5f 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -750,13 +750,8 @@ void net_poll ( void ) { if ( netdev_rx_frozen ( netdev ) ) continue; - /* Process at most one received packet. Give priority - * to getting packets out of the NIC over processing - * the received packets, because we advertise a window - * that assumes that we can receive packets from the - * NIC faster than they arrive. - */ - if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) { + /* Process all received packets */ + while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) { DBGC2 ( netdev, "NETDEV %s processing %p (%p+%zx)\n", netdev->name, iobuf, iobuf->data, From 4a8a7bd91a6911779e3972a6d00d5a25bd7c0367 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 8 Jul 2012 17:14:08 +0100 Subject: [PATCH 069/250] [iobuf] Allocate I/O buffer descriptor separately to conserve aligned memory I/O buffers are allocated on aligned boundaries. The I/O buffer descriptor (the struct io_buffer) is currently attached to the end of the I/O buffer. When the size of the buffer is close to its alignment, this can waste large amounts of aligned memory. For example, a network card using 2048-byte receive buffers will end up allocating 2072 bytes on a 2048-byte boundary. This effectively wastes 50% of the available memory. Improve the situation by allocating the descriptor separately from the main I/O buffer if inline allocation would cause the total allocated size to cross the alignment boundary. Signed-off-by: Michael Brown --- src/core/iobuf.c | 66 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/src/core/iobuf.c b/src/core/iobuf.c index 3dfaf18c..0c61306e 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -40,7 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @c IOBUF_SIZE. */ struct io_buffer * alloc_iob ( size_t len ) { - struct io_buffer *iobuf = NULL; + struct io_buffer *iobuf; size_t align; void *data; @@ -57,14 +57,37 @@ struct io_buffer * alloc_iob ( size_t len ) { */ align = ( 1 << fls ( len - 1 ) ); - /* Allocate memory for buffer plus descriptor */ - data = malloc_dma ( len + sizeof ( *iobuf ), align ); - if ( ! data ) - return NULL; + /* Allocate buffer plus descriptor as a single unit, unless + * doing so will push the total size over the alignment + * boundary. + */ + if ( ( len + sizeof ( *iobuf ) ) <= align ) { - iobuf = ( struct io_buffer * ) ( data + len ); + /* Allocate memory for buffer plus descriptor */ + data = malloc_dma ( len + sizeof ( *iobuf ), align ); + if ( ! data ) + return NULL; + iobuf = ( data + len ); + + } else { + + /* Allocate memory for buffer */ + data = malloc_dma ( len, align ); + if ( ! data ) + return NULL; + + /* Allocate memory for descriptor */ + iobuf = malloc ( sizeof ( *iobuf ) ); + if ( ! iobuf ) { + free_dma ( data, len ); + return NULL; + } + } + + /* Populate descriptor */ iobuf->head = iobuf->data = iobuf->tail = data; - iobuf->end = iobuf; + iobuf->end = ( data + len ); + return iobuf; } @@ -75,12 +98,29 @@ struct io_buffer * alloc_iob ( size_t len ) { * @v iobuf I/O buffer */ void free_iob ( struct io_buffer *iobuf ) { - if ( iobuf ) { - assert ( iobuf->head <= iobuf->data ); - assert ( iobuf->data <= iobuf->tail ); - assert ( iobuf->tail <= iobuf->end ); - free_dma ( iobuf->head, - ( iobuf->end - iobuf->head ) + sizeof ( *iobuf ) ); + size_t len; + + /* Allow free_iob(NULL) to be valid */ + if ( ! iobuf ) + return; + + /* Sanity checks */ + assert ( iobuf->head <= iobuf->data ); + assert ( iobuf->data <= iobuf->tail ); + assert ( iobuf->tail <= iobuf->end ); + + /* Free buffer */ + len = ( iobuf->end - iobuf->head ); + if ( iobuf->end == iobuf ) { + + /* Descriptor is inline */ + free_dma ( iobuf->head, ( len + sizeof ( *iobuf ) ) ); + + } else { + + /* Descriptor is detached */ + free_dma ( iobuf->head, len ); + free ( iobuf ); } } From 8d95e1d6ff7b77ac6ea4d675c524c75d896c5d4b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 9 Jul 2012 09:54:24 +0100 Subject: [PATCH 070/250] [malloc] Discard cached items less aggressively Signed-off-by: Michael Brown --- src/core/malloc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/malloc.c b/src/core/malloc.c index 6633887b..8660f449 100644 --- a/src/core/malloc.c +++ b/src/core/malloc.c @@ -192,12 +192,14 @@ static inline void valgrind_make_blocks_noaccess ( void ) { */ static unsigned int discard_cache ( void ) { struct cache_discarder *discarder; - unsigned int discarded = 0; + unsigned int discarded; for_each_table_entry ( discarder, CACHE_DISCARDERS ) { - discarded += discarder->discard(); + discarded = discarder->discard(); + if ( discarded ) + return discarded; } - return discarded; + return 0; } /** From 024247317d50ffc4c44dd041aae19ae23b72788e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 9 Jul 2012 09:55:26 +0100 Subject: [PATCH 071/250] [arp] Try to avoid discarding ARP cache entries Discarding the active ARP cache entry in the middle of a download will substantially disrupt the TCP stream. Try to minimise any such disruption by treating ARP cache entries as expensive, and discarding them only when nothing else is available to discard. Signed-off-by: Michael Brown --- src/crypto/x509.c | 2 +- src/include/ipxe/malloc.h | 13 ++++++++++++- src/net/arp.c | 9 +++++++-- src/net/tcp.c | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/crypto/x509.c b/src/crypto/x509.c index a99f6ab9..a3a17991 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -143,7 +143,7 @@ static unsigned int x509_discard ( void ) { } /** X.509 cache discarder */ -struct cache_discarder x509_cache_discarder __cache_discarder = { +struct cache_discarder x509_discarder __cache_discarder ( CACHE_NORMAL ) = { .discard = x509_discard, }; diff --git a/src/include/ipxe/malloc.h b/src/include/ipxe/malloc.h index c435a7dd..d41b0562 100644 --- a/src/include/ipxe/malloc.h +++ b/src/include/ipxe/malloc.h @@ -76,6 +76,17 @@ struct cache_discarder { #define CACHE_DISCARDERS __table ( struct cache_discarder, "cache_discarders" ) /** Declare a cache discarder */ -#define __cache_discarder __table_entry ( CACHE_DISCARDERS, 01 ) +#define __cache_discarder( cost ) __table_entry ( CACHE_DISCARDERS, cost ) + +/** @defgroup cache_cost Cache discarder costs + * + * @{ + */ + +#define CACHE_CHEAP 01 /**< Items with a low replacement cost */ +#define CACHE_NORMAL 02 /**< Items with a normal replacement cost */ +#define CACHE_EXPENSIVE 03 /**< Items with a high replacement cost */ + +/** @} */ #endif /* _IPXE_MALLOC_H */ diff --git a/src/net/arp.c b/src/net/arp.c index d6b4e731..7cec73d5 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -525,7 +525,12 @@ static unsigned int arp_discard ( void ) { return 0; } -/** ARP cache discarder */ -struct cache_discarder arp_cache_discarder __cache_discarder = { +/** ARP cache discarder + * + * ARP cache entries are deemed to have a high replacement cost, since + * flushing an active ARP cache entry midway through a TCP transfer + * will cause substantial disruption. + */ +struct cache_discarder arp_discarder __cache_discarder ( CACHE_EXPENSIVE ) = { .discard = arp_discard, }; diff --git a/src/net/tcp.c b/src/net/tcp.c index 7a127260..e98d8b17 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -1315,7 +1315,7 @@ static unsigned int tcp_discard ( void ) { } /** TCP cache discarder */ -struct cache_discarder tcp_cache_discarder __cache_discarder = { +struct cache_discarder tcp_discarder __cache_discarder ( CACHE_NORMAL ) = { .discard = tcp_discard, }; From a5d16a91af4219d4166cf238ff5b9a99c0db4d70 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 8 Jul 2012 16:51:21 +0100 Subject: [PATCH 072/250] [tcp] Truncate TCP window to prevent future packet discards Whenever memory pressure causes a queued packet to be discarded (and so retransmitted), reduce the maximum TCP window to a size that would have prevented the discard. Signed-off-by: Michael Brown --- src/net/tcp.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/net/tcp.c b/src/net/tcp.c index e98d8b17..938edd57 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -97,6 +97,8 @@ struct tcp_connection { * Equivalent to Rcv.Wind.Scale in RFC 1323 terminology */ uint8_t rcv_win_scale; + /** Maximum receive window */ + uint32_t max_rcv_win; /** Transmit queue */ struct list_head tx_queue; @@ -295,6 +297,7 @@ static int tcp_open ( struct interface *xfer, struct sockaddr *peer, tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN ); tcp_dump_state ( tcp ); tcp->snd_seq = random(); + tcp->max_rcv_win = TCP_MAX_WINDOW_SIZE; INIT_LIST_HEAD ( &tcp->tx_queue ); INIT_LIST_HEAD ( &tcp->rx_queue ); memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) ); @@ -557,9 +560,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) { tcp_process_tx_queue ( tcp, len, iobuf, 0 ); /* Expand receive window if possible */ - max_rcv_win = ( ( freemem * 3 ) / 4 ); - if ( max_rcv_win > TCP_MAX_WINDOW_SIZE ) - max_rcv_win = TCP_MAX_WINDOW_SIZE; + max_rcv_win = tcp->max_rcv_win; app_win = xfer_window ( &tcp->xfer ); if ( max_rcv_win > app_win ) max_rcv_win = app_win; @@ -1299,13 +1300,29 @@ struct tcpip_protocol tcp_protocol __tcpip_protocol = { static unsigned int tcp_discard ( void ) { struct tcp_connection *tcp; struct io_buffer *iobuf; + struct tcp_rx_queued_header *tcpqhdr; + uint32_t max_win; unsigned int discarded = 0; /* Try to drop one queued RX packet from each connection */ list_for_each_entry ( tcp, &tcp_conns, list ) { list_for_each_entry_reverse ( iobuf, &tcp->rx_queue, list ) { + + /* Limit window to prevent future discards */ + tcpqhdr = iobuf->data; + max_win = ( tcpqhdr->seq - tcp->rcv_ack ); + if ( max_win < tcp->max_rcv_win ) { + DBGC ( tcp, "TCP %p reducing maximum window " + "from %d to %d\n", + tcp, tcp->max_rcv_win, max_win ); + tcp->max_rcv_win = max_win; + } + + /* Remove packet from queue */ list_del ( &iobuf->list ); free_iob ( iobuf ); + + /* Report discard */ discarded++; break; } From 6825b2e7bfc94e8758824bf0d81f8b98fde1968c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 8 Jul 2012 17:20:25 +0100 Subject: [PATCH 073/250] [malloc] Increase heap size to 512kB The maximum TCP throughput is fundamentally limited by the amount of available receive buffer space. Increase the heap size from 128kB to 512kB to allow the use of larger TCP windows. Signed-off-by: Michael Brown --- src/core/malloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/malloc.c b/src/core/malloc.c index 8660f449..1b8ac17e 100644 --- a/src/core/malloc.c +++ b/src/core/malloc.c @@ -91,9 +91,9 @@ size_t freemem; /** * Heap size * - * Currently fixed at 128kB. + * Currently fixed at 512kB. */ -#define HEAP_SIZE ( 128 * 1024 ) +#define HEAP_SIZE ( 512 * 1024 ) /** The heap itself */ static char heap[HEAP_SIZE] __attribute__ (( aligned ( __alignof__(void *) ))); From 07bc73e0872730d1e6784c7460f12b836c77838d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 8 Jul 2012 17:54:07 +0100 Subject: [PATCH 074/250] [tcp] Increase maximum window size to 256kB A window size of 256kB should be sufficient to allow for full-bandwidth transfers over a Gigabit LAN, and for acceptable transfer speeds over other typical links. Signed-off-by: Michael Brown --- src/include/ipxe/tcp.h | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/include/ipxe/tcp.h b/src/include/ipxe/tcp.h index cb3309f2..6b669117 100644 --- a/src/include/ipxe/tcp.h +++ b/src/include/ipxe/tcp.h @@ -287,29 +287,31 @@ struct tcp_options { /** * Maxmimum advertised TCP window size * - * We estimate the TCP window size as the amount of free memory we - * have. This is not strictly accurate (since it ignores any space - * already allocated as RX buffers), but it will do for now. + * The maximum bandwidth on any link is limited by * - * Since we don't store out-of-order received packets, the - * retransmission penalty is that the whole window contents must be - * resent. This suggests keeping the window size small, but bear in - * mind that the maximum bandwidth on any link is limited to + * max_bandwidth * round_trip_time = tcp_window * - * max_bandwidth = ( tcp_window / round_trip_time ) + * Some rough expectations for achievable bandwidths over various + * links are: * - * With a 48kB window, which probably accurately reflects our amount - * of free memory, and a WAN RTT of say 200ms, this gives a maximum - * bandwidth of 240kB/s. This is sufficiently close to realistic that - * we will need to be careful that our advertised window doesn't end - * up limiting WAN download speeds. + * a) Gigabit LAN: expected bandwidth 125MB/s, typical RTT 0.5ms, + * minimum required window 64kB * - * Finally, since the window goes into a 16-bit field and we cannot - * actually use 65536, we use a window size of (65536-4) to ensure - * that payloads remain dword-aligned. + * b) Home Internet connection: expected bandwidth 10MB/s, typical + * RTT 25ms, minimum required window 256kB + * + * c) WAN: expected bandwidth 2MB/s, typical RTT 100ms, minimum + * required window 200kB. + * + * The maximum possible value for the TCP window size is 1GB (using + * the maximum window scale of 2**14). However, it is advisable to + * keep the window size as small as possible (without limiting + * bandwidth), since in the event of a lost packet the window size + * represents the maximum amount that will need to be retransmitted. + * + * We therefore choose a maximum window size of 256kB. */ -//#define TCP_MAX_WINDOW_SIZE ( 65536 - 4 ) -#define TCP_MAX_WINDOW_SIZE 8192 +#define TCP_MAX_WINDOW_SIZE ( 256 * 1024 ) /** * Path MTU From 2c72ce04aef5cf3856ac822d182823847996bbc6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 9 Jul 2012 20:26:40 +0100 Subject: [PATCH 075/250] [bzimage] Update setup_move_size only for protocol versions 2.00 and 2.01 The setup_move_size field is not defined in protocol versions earlier than 2.00 (and is obsolete in versions later than 2.01). In binaries using versions earlier than 2.00, the relevant location is likely to contain executable code. Interestingly, this bug has been present since support for pre-2.00 protocol versions was added in 2009, and has been unexpectedly modifying the memtest86+ code fragment: mov $0x92, %dx inb %dx, %al Fortuitously, the modification exactly overwrote the value loaded into %dx, and so the net effect was limited to causing Fast Gate A20 detection to always fail. Signed-off-by: Michael Brown --- src/arch/i386/image/bzimage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index cc7aecab..08eb4d34 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -214,7 +214,8 @@ static void bzimage_update_header ( struct image *image, } else { bzimg->cmdline_magic.magic = BZI_CMDLINE_MAGIC; bzimg->cmdline_magic.offset = bzimg->rm_cmdline; - bzimg->bzhdr.setup_move_size = bzimg->rm_memsz; + if ( bzimg->version >= 0x0200 ) + bzimg->bzhdr.setup_move_size = bzimg->rm_memsz; } /* Set video mode */ From 8391ff3ee00583071def824231539004cc07fecb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 10 Jul 2012 09:32:58 +0100 Subject: [PATCH 076/250] [intel] Refill receive ring only after enabling receiver On 82576 (and probably others), the datasheet states that "the tail register of the queue (RDT[n]) should not be bumped until the queue is enabled". There is some confusion over exactly what constitutes "enabled": the initialisation blurb says that we should "poll the RXDCTL register until the ENABLE bit is set", while the description for the RXDCTL register says that the ENABLE bit is set by default (for queue zero). Empirical evidence suggests that the ENABLE bit reads as set immediately after writing to RCTL.EN, and so polling is not necessary. Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 3eb1a377..8153e095 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -491,9 +491,6 @@ static int intel_open ( struct net_device *netdev ) { if ( ( rc = intel_create_ring ( intel, &intel->rx ) ) != 0 ) goto err_create_rx; - /* Fill receive ring */ - intel_refill_rx ( intel ); - /* Program MAC address */ memset ( &mac, 0, sizeof ( mac ) ); memcpy ( mac.raw, netdev->ll_addr, sizeof ( mac.raw ) ); @@ -515,6 +512,9 @@ static int intel_open ( struct net_device *netdev ) { INTEL_RCTL_BAM | INTEL_RCTL_BSIZE_2048 | INTEL_RCTL_SECRC ); writel ( rctl, intel->regs + INTEL_RCTL ); + /* Fill receive ring */ + intel_refill_rx ( intel ); + /* Update link state */ intel_check_link ( netdev ); From 9f0b2d25a8e889899711b81213e91d042c58002f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 10 Jul 2012 10:52:56 +0100 Subject: [PATCH 077/250] [intel] Explicitly enable descriptor queues On i350 the datasheet contradicts itself in stating that the default value of RXDCTL.ENABLE for queue zero is both set (according to the "Receive Initialization" section) and unset (according to the "Receive Descriptor Control - RXDCTL" section). Empirical evidence suggests that the default value is unset. Explicitly enable both transmit and receive queues to avoid any ambiguity. Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 6 ++++++ src/drivers/net/intel.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 8153e095..1fdce1cb 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -363,6 +363,7 @@ static void intel_check_link ( struct net_device *netdev ) { static int intel_create_ring ( struct intel_nic *intel, struct intel_ring *ring ) { physaddr_t address; + uint32_t dctl; /* Allocate descriptor ring. Align ring on its own size to * prevent any possible page-crossing errors due to hardware @@ -393,6 +394,11 @@ static int intel_create_ring ( struct intel_nic *intel, writel ( 0, ( intel->regs + ring->reg + INTEL_xDH ) ); writel ( 0, ( intel->regs + ring->reg + INTEL_xDT ) ); + /* Enable ring */ + dctl = readl ( intel->regs + ring->reg + INTEL_xDCTL ); + dctl |= INTEL_xDCTL_ENABLE; + writel ( dctl, intel->regs + ring->reg + INTEL_xDCTL ); + DBGC ( intel, "INTEL %p ring %05x is at [%08llx,%08llx)\n", intel, ring->reg, ( ( unsigned long long ) address ), ( ( unsigned long long ) address + ring->len ) ); diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h index 6f941d17..b38a7139 100644 --- a/src/drivers/net/intel.h +++ b/src/drivers/net/intel.h @@ -170,6 +170,10 @@ enum intel_descriptor_status { /** Receive/Transmit Descriptor Tail (offset) */ #define INTEL_xDT 0x18 +/** Receive/Transmit Descriptor Control (offset) */ +#define INTEL_xDCTL 0x28 +#define INTEL_xDCTL_ENABLE 0x02000000UL /**< Queue enable */ + /** Receive Descriptor Head */ #define INTEL_RDH ( INTEL_RD + INTEL_xDH ) From 9e5152e095d8115d951af8cbb1cb6c1148609c68 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 10 Jul 2012 16:10:49 +0100 Subject: [PATCH 078/250] [pxeprefix] Place temporary stack after iPXE binary Some BIOSes (observed on a Supermicro system with an AMI BIOS) seem to use the area immediately below 0x7c00 to store data related to the boot process. This data is currently liable to be overwritten by the temporary stack used while decompressing and installing iPXE. Try to avoid any such problems by placing the temporary stack immediately after the loaded iPXE binary. Any memory used by the stack could then potentially have been overwritten anyway by a larger binary. Signed-off-by: Michael Brown --- src/arch/i386/prefix/pxeprefix.S | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S index f59e347a..9ccc4a2b 100644 --- a/src/arch/i386/prefix/pxeprefix.S +++ b/src/arch/i386/prefix/pxeprefix.S @@ -19,6 +19,8 @@ FILE_LICENCE ( GPL2_OR_LATER ) #define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) ) #define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) ) +#define PREFIX_STACK_SIZE 2048 + /***************************************************************************** * Entry point: set operating context, print welcome message ***************************************************************************** @@ -46,10 +48,11 @@ _pxe_start: movw %ax, %ds movw $0x40, %ax /* BIOS data segment access */ movw %ax, %fs - /* Set up stack just below 0x7c00 */ - xorw %ax, %ax + /* Set up temporary stack immediately after the iPXE image */ + movw %cs, %ax + addw image_size_pgh, %ax movw %ax, %ss - movl $0x7c00, %esp + movl $PREFIX_STACK_SIZE, %esp /* Clear direction flag, for the sake of sanity */ cld /* Print welcome message */ @@ -60,6 +63,18 @@ _pxe_start: 10: .asciz "PXE->EB:" .previous + /* Image size (for stack placement calculation) */ + .section ".prefix.data", "aw", @progbits +image_size_pgh: + .word 0 + .previous + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "ADDW" + .long image_size_pgh + .long 16 + .long 0 + .previous + /***************************************************************************** * Find us a usable !PXE or PXENV+ entry point ***************************************************************************** From a814eff38ea0e300b56a899138505abf5a8f9dff Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 11 Jul 2012 18:16:13 +0100 Subject: [PATCH 079/250] [pxe] Add PXENV_FILE_CMDLINE API call Allow a PXE NBP to obtain its command line (if any) via the new PXE API call PXENV_FILE_CMDLINE. Signed-off-by: Michael Brown --- src/arch/i386/image/pxe_image.c | 9 ++++++ src/arch/i386/include/pxe.h | 1 + src/arch/i386/include/pxe_api.h | 21 ++++++++++++++ src/arch/i386/interface/pxe/pxe_file.c | 38 ++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) diff --git a/src/arch/i386/image/pxe_image.c b/src/arch/i386/image/pxe_image.c index bdccc93d..e037c793 100644 --- a/src/arch/i386/image/pxe_image.c +++ b/src/arch/i386/image/pxe_image.c @@ -35,6 +35,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 ); +/** PXE command line */ +const char *pxe_cmdline; + /** * Execute PXE image * @@ -66,9 +69,15 @@ static int pxe_exec ( struct image *image ) { /* Activate PXE */ pxe_activate ( netdev ); + /* Set PXE command line */ + pxe_cmdline = image->cmdline; + /* Start PXE NBP */ rc = pxe_start_nbp(); + /* Clear PXE command line */ + pxe_cmdline = NULL; + /* Deactivate PXE */ pxe_deactivate(); diff --git a/src/arch/i386/include/pxe.h b/src/arch/i386/include/pxe.h index a6bb65c0..0206f683 100644 --- a/src/arch/i386/include/pxe.h +++ b/src/arch/i386/include/pxe.h @@ -188,6 +188,7 @@ struct pcir_header { ( ( 'P' << 0 ) + ( 'C' << 8 ) + ( 'I' << 16 ) + ( 'R' << 24 ) ) extern struct net_device *pxe_netdev; +extern const char *pxe_cmdline; extern void pxe_set_netdev ( struct net_device *netdev ); extern PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE diff --git a/src/arch/i386/include/pxe_api.h b/src/arch/i386/include/pxe_api.h index d01c262d..fd179ddb 100644 --- a/src/arch/i386/include/pxe_api.h +++ b/src/arch/i386/include/pxe_api.h @@ -1690,6 +1690,27 @@ typedef struct s_PXENV_FILE_EXIT_HOOK PXENV_FILE_EXIT_HOOK_t; /** @} */ /* pxenv_file_exit_hook */ +/** @defgroup pxenv_file_cmdline PXENV_FILE_CMDLINE + * + * FILE CMDLINE + * + * @{ + */ + +/** PXE API function code for pxenv_file_cmdline() */ +#define PXENV_FILE_CMDLINE 0x00e8 + +/** Parameter block for pxenv_file_cmdline() */ +struct s_PXENV_FILE_CMDLINE { + PXENV_STATUS_t Status; /**< PXE status code */ + UINT16_t BufferSize; /**< Data buffer size */ + SEGOFF16_t Buffer; /**< Data buffer */ +} __attribute__ (( packed )); + +typedef struct s_PXENV_FILE_CMDLINE PXENV_FILE_CMDLINE_t; + +/** @} */ /* pxe_file_cmdline */ + /** @} */ /* pxe_file_api */ /** @defgroup pxe_loader_api PXE Loader API diff --git a/src/arch/i386/interface/pxe/pxe_file.c b/src/arch/i386/interface/pxe/pxe_file.c index 7daaf919..ffb27087 100644 --- a/src/arch/i386/interface/pxe/pxe_file.c +++ b/src/arch/i386/interface/pxe/pxe_file.c @@ -232,6 +232,42 @@ static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) { return PXENV_EXIT_SUCCESS; } +/** + * FILE CMDLINE + * + * @v file_cmdline Pointer to a struct s_PXENV_FILE_CMDLINE + * @v s_PXENV_FILE_CMDLINE::Buffer Buffer to contain command line + * @v s_PXENV_FILE_CMDLINE::BufferSize Size of buffer + * @ret #PXENV_EXIT_SUCCESS Command was executed successfully + * @ret #PXENV_EXIT_FAILURE Command was not executed successfully + * @ret s_PXENV_FILE_EXEC::Status PXE status code + * @ret s_PXENV_FILE_EXEC::BufferSize Length of command line (including NUL) + * + */ +static PXENV_EXIT_t +pxenv_file_cmdline ( struct s_PXENV_FILE_CMDLINE *file_cmdline ) { + userptr_t buffer; + size_t max_len; + size_t len; + + DBG ( "PXENV_FILE_CMDLINE to %04x:%04x+%04x \"%s\"\n", + file_cmdline->Buffer.segment, file_cmdline->Buffer.offset, + file_cmdline->BufferSize, pxe_cmdline ); + + buffer = real_to_user ( file_cmdline->Buffer.segment, + file_cmdline->Buffer.offset ); + len = file_cmdline->BufferSize; + max_len = ( pxe_cmdline ? + ( strlen ( pxe_cmdline ) + 1 /* NUL */ ) : 0 ); + if ( len > max_len ) + len = max_len; + copy_to_user ( buffer, 0, pxe_cmdline, len ); + file_cmdline->BufferSize = max_len; + + file_cmdline->Status = PXENV_STATUS_SUCCESS; + return PXENV_EXIT_SUCCESS; +} + /** * FILE API CHECK * @@ -298,6 +334,8 @@ struct pxe_api_call pxe_file_api[] __pxe_api_call = { struct s_PXENV_GET_FILE_SIZE ), PXE_API_CALL ( PXENV_FILE_EXEC, pxenv_file_exec, struct s_PXENV_FILE_EXEC ), + PXE_API_CALL ( PXENV_FILE_CMDLINE, pxenv_file_cmdline, + struct s_PXENV_FILE_CMDLINE ), PXE_API_CALL ( PXENV_FILE_API_CHECK, pxenv_file_api_check, struct s_PXENV_FILE_API_CHECK ), }; From e84e19d4edbb3bd6bc8c43b72cc25c46dcd0ac63 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 11 Jul 2012 21:26:53 +0100 Subject: [PATCH 080/250] [pxeprefix] Fetch command line (if any) via PXENV_FILE_CMDLINE Use PXENV_FILE_CMDLINE to retrieve the command line (if any) provided by the invoking PXE stack. Signed-off-by: Michael Brown --- src/arch/i386/prefix/pxeprefix.S | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S index 9ccc4a2b..3c851dca 100644 --- a/src/arch/i386/prefix/pxeprefix.S +++ b/src/arch/i386/prefix/pxeprefix.S @@ -5,6 +5,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) #define PXENV_UNDI_GET_IFACE_INFO 0x0013 #define PXENV_STOP_UNDI 0x0015 #define PXENV_UNLOAD_STACK 0x0070 +#define PXENV_FILE_CMDLINE 0x00e8 #define PXE_HACK_EB54 0x0001 @@ -381,6 +382,37 @@ get_iface_type: 99: movb $0x0a, %al call print_character + +/***************************************************************************** + * Check for a command line + ***************************************************************************** + */ +get_cmdline: + /* Issue PXENV_FILE_CMDLINE */ + xorl %esi, %esi + movw %ss, %si + movw %si, ( pxe_parameter_structure + 0x06 ) + movw $PREFIX_STACK_SIZE, ( pxe_parameter_structure + 0x04 ) + movw $0xffff, ( pxe_parameter_structure + 0x02 ) + movw $PXENV_FILE_CMDLINE, %bx + call pxe_call + jnc 1f + call print_pxe_error + jmp 99f +1: /* Check for non-NULL command line */ + movw ( pxe_parameter_structure + 0x02 ), %ax + testw %ax, %ax + jz 99f + /* Record command line */ + shll $4, %esi + addl $PREFIX_STACK_SIZE, %esi + movl %esi, pxe_cmdline +99: + .section ".prefix.data", "aw", @progbits +pxe_cmdline: + .long 0 + .previous + /***************************************************************************** * Leave NIC in a safe state ***************************************************************************** @@ -728,6 +760,9 @@ run_ipxe: movw pxe_ss, %di movl pxe_esp, %ebp + /* Retrieve PXE command line, if any */ + movl pxe_cmdline, %esi + /* Jump to .text16 segment with %ds pointing to .data16 */ movw %bx, %ds pushw %ax @@ -738,6 +773,9 @@ run_ipxe: /* Update the exit hook */ movw %cs, ( pxe_exit_hook + 2 ) + /* Store command-line pointer */ + movl %esi, cmdline_phys + /* Run main program */ pushl $main pushw %cs From 5b4958388ded47c93686076e318195393a4c4b9f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 12 Jul 2012 15:28:09 +0100 Subject: [PATCH 081/250] [cmdline] Store exit status of failed command in errno Signed-off-by: Michael Brown --- src/core/exec.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/core/exec.c b/src/core/exec.c index 139cf7a8..5b3d1489 100644 --- a/src/core/exec.c +++ b/src/core/exec.c @@ -59,18 +59,22 @@ static int stop_state; int execv ( const char *command, char * const argv[] ) { struct command *cmd; int argc; + int rc; /* Count number of arguments */ for ( argc = 0 ; argv[argc] ; argc++ ) {} /* An empty command is deemed to do nothing, successfully */ - if ( command == NULL ) - return 0; + if ( command == NULL ) { + rc = 0; + goto done; + } /* Sanity checks */ if ( argc == 0 ) { DBG ( "%s: empty argument list\n", command ); - return -EINVAL; + rc = -EINVAL; + goto done; } /* Reset getopt() library ready for use by the command. This @@ -82,12 +86,24 @@ int execv ( const char *command, char * const argv[] ) { /* Hand off to command implementation */ for_each_table_entry ( cmd, COMMANDS ) { - if ( strcmp ( command, cmd->name ) == 0 ) - return cmd->exec ( argc, ( char ** ) argv ); + if ( strcmp ( command, cmd->name ) == 0 ) { + rc = cmd->exec ( argc, ( char ** ) argv ); + goto done; + } } printf ( "%s: command not found\n", command ); - return -ENOEXEC; + rc = -ENOEXEC; + + done: + /* Store error number, if an error occurred */ + if ( rc ) { + errno = rc; + if ( errno < 0 ) + errno = -errno; + } + + return rc; } /** From c5c257788f36d178176eb59b0d4c5fdd88080c19 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 12 Jul 2012 15:28:37 +0100 Subject: [PATCH 082/250] [settings] Expose exit status of failed command via ${errno} Allow scripts to report errors in more detail by exposing the most recent error via the ${errno} setting. For example: chain ${filename} || goto failed ... :failed imgfree http://192.168.0.1/ipxe_error.php?error=${errno} Note that ${errno} is valid only immediately after executing a failed command. Signed-off-by: Michael Brown --- src/core/settings.c | 120 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/src/core/settings.c b/src/core/settings.c index ba5329bb..02dd07e3 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -1893,3 +1894,122 @@ struct setting priority_setting __setting ( SETTING_MISC ) = { .tag = DHCP_EB_PRIORITY, .type = &setting_type_int8, }; + +/****************************************************************************** + * + * Built-in settings block + * + ****************************************************************************** + */ + +/** Built-in setting tag magic */ +#define BUILTIN_SETTING_TAG_MAGIC 0xb1 + +/** + * Construct built-in setting tag + * + * @v id Unique identifier + * @ret tag Setting tag + */ +#define BUILTIN_SETTING_TAG( id ) ( ( BUILTIN_SETTING_TAG_MAGIC << 24 ) | (id) ) + +/** "errno" setting tag */ +#define BUILTIN_SETTING_TAG_ERRNO BUILTIN_SETTING_TAG ( 0x01 ) + +/** Error number setting */ +struct setting errno_setting __setting ( SETTING_MISC ) = { + .name = "errno", + .description = "Last error", + .tag = BUILTIN_SETTING_TAG_ERRNO, + .type = &setting_type_uint32, +}; + +/** + * Fetch error number setting + * + * @v settings Settings block + * @v setting Setting to fetch + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ +static int errno_fetch ( struct settings *settings __unused, + struct setting *setting __unused, + void *data, size_t len ) { + uint32_t content; + + /* Return current error */ + content = htonl ( errno ); + if ( len > sizeof ( content ) ) + len = sizeof ( content ); + memcpy ( data, &content, len ); + return sizeof ( content ); +} + +/** + * Fetch built-in setting + * + * @v settings Settings block + * @v setting Setting to fetch + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data + * @ret rc Return status code + */ +static int builtin_fetch ( struct settings *settings __unused, + struct setting *setting, + void *data, size_t len ) { + + if ( setting_cmp ( setting, &errno_setting ) == 0 ) { + return errno_fetch ( settings, setting, data, len ); + } else { + return -ENOENT; + } +} + +/** + * Check applicability of built-in setting + * + * @v settings Settings block + * @v setting Setting + * @ret applies Setting applies within this settings block + */ +static int builtin_applies ( struct settings *settings __unused, + struct setting *setting ) { + unsigned int tag_magic; + + /* Check tag magic */ + tag_magic = ( setting->tag >> 24 ); + return ( tag_magic == BUILTIN_SETTING_TAG_MAGIC ); +} + +/** Built-in settings operations */ +static struct settings_operations builtin_settings_operations = { + .applies = builtin_applies, + .fetch = builtin_fetch, +}; + +/** Built-in settings */ +static struct settings builtin_settings = { + .refcnt = NULL, + .tag_magic = BUILTIN_SETTING_TAG ( 0 ), + .siblings = LIST_HEAD_INIT ( builtin_settings.siblings ), + .children = LIST_HEAD_INIT ( builtin_settings.children ), + .op = &builtin_settings_operations, +}; + +/** Initialise built-in settings */ +static void builtin_init ( void ) { + int rc; + + if ( ( rc = register_settings ( &builtin_settings, NULL, + "builtin" ) ) != 0 ) { + DBG ( "Could not register built-in settings: %s\n", + strerror ( rc ) ); + return; + } +} + +/** Built-in settings initialiser */ +struct init_fn builtin_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = builtin_init, +}; From 88016deccf05e4370c1362fbc13405a2123a89a1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 12 Jul 2012 16:04:41 +0100 Subject: [PATCH 083/250] [pxe] Reopen network device if NBP exits Attempt to restore the network device to the state it was in prior to calling the NBP. This simplifies the task of taking follow-up action in an iPXE script. Signed-off-by: Michael Brown --- src/arch/i386/image/pxe_image.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/arch/i386/image/pxe_image.c b/src/arch/i386/image/pxe_image.c index e037c793..722f6bbc 100644 --- a/src/arch/i386/image/pxe_image.c +++ b/src/arch/i386/image/pxe_image.c @@ -65,6 +65,7 @@ static int pxe_exec ( struct image *image ) { image ); return -ENODEV; } + netdev_get ( netdev ); /* Activate PXE */ pxe_activate ( netdev ); @@ -81,6 +82,12 @@ static int pxe_exec ( struct image *image ) { /* Deactivate PXE */ pxe_deactivate(); + /* Try to reopen network device. Ignore errors, since the NBP + * may have called PXENV_STOP_UNDI. + */ + netdev_open ( netdev ); + netdev_put ( netdev ); + return rc; } From 73ba1541244604d1cbebba284a0d5a092bb7c2c4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 17 Jul 2012 21:20:50 +0100 Subject: [PATCH 084/250] [b44] Eliminate call to get_memmap() get_memmap() is not available under all runtime environments. Signed-off-by: Michael Brown --- src/drivers/net/b44.c | 57 +++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/src/drivers/net/b44.c b/src/drivers/net/b44.c index 66fa8ea3..f9e47980 100644 --- a/src/drivers/net/b44.c +++ b/src/drivers/net/b44.c @@ -78,24 +78,21 @@ static inline void bflush(const struct b44_private *bp, u32 reg, u32 timeout) /** - * Return non-zero if the installed RAM is within - * the limit given and zero if it is outside. - * Hopefully will be removed soon. + * Check if card can access address + * + * @v address Virtual address + * @v address_ok Card can access address */ -int phys_ram_within_limit(u64 limit) -{ - struct memory_map memmap; - struct memory_region *highest = NULL; - get_memmap(&memmap); +static inline __attribute__ (( always_inline )) int +b44_address_ok ( void *address ) { - if (memmap.count == 0) - return 0; - highest = &memmap.regions[memmap.count - 1]; + /* Card can address anything with a 30-bit address */ + if ( ( virt_to_bus ( address ) & ~B44_30BIT_DMA_MASK ) == 0 ) + return 1; - return (highest->end < limit); + return 0; } - /** * Ring cells waiting to be processed are between 'tx_cur' and 'pending' * indexes in the ring. @@ -404,6 +401,7 @@ static void b44_populate_rx_descriptor(struct b44_private *bp, u32 idx) */ static void b44_rx_refill(struct b44_private *bp, u32 pending) { + struct io_buffer *iobuf; u32 i; // skip pending @@ -411,11 +409,17 @@ static void b44_rx_refill(struct b44_private *bp, u32 pending) if (bp->rx_iobuf[i] != NULL) continue; - bp->rx_iobuf[i] = alloc_iob(RX_PKT_BUF_SZ); - if (!bp->rx_iobuf[i]) { + iobuf = alloc_iob(RX_PKT_BUF_SZ); + if (!iobuf) { DBG("Refill rx ring failed!!\n"); break; } + if (!b44_address_ok(iobuf->data)) { + DBG("Refill rx ring bad address!!\n"); + free_iob(iobuf); + break; + } + bp->rx_iobuf[i] = iobuf; b44_populate_rx_descriptor(bp, i); } @@ -444,6 +448,10 @@ static int b44_init_rx_ring(struct b44_private *bp) bp->rx = malloc_dma(B44_RX_RING_LEN_BYTES, B44_DMA_ALIGNMENT); if (!bp->rx) return -ENOMEM; + if (!b44_address_ok(bp->rx)) { + free_dma(bp->rx, B44_RX_RING_LEN_BYTES); + return -ENOTSUP; + } memset(bp->rx_iobuf, 0, sizeof(bp->rx_iobuf)); @@ -472,6 +480,10 @@ static int b44_init_tx_ring(struct b44_private *bp) bp->tx = malloc_dma(B44_TX_RING_LEN_BYTES, B44_DMA_ALIGNMENT); if (!bp->tx) return -ENOMEM; + if (!b44_address_ok(bp->tx)) { + free_dma(bp->tx, B44_TX_RING_LEN_BYTES); + return -ENOTSUP; + } memset(bp->tx, 0, B44_TX_RING_LEN_BYTES); memset(bp->tx_iobuf, 0, sizeof(bp->tx_iobuf)); @@ -644,17 +656,6 @@ static int b44_probe(struct pci_device *pci) struct b44_private *bp; int rc; - /* - * Bail out if more than 1GB of physical RAM is installed. - * This limitation will be removed later when dma mapping - * is merged into mainline. - */ - if (!phys_ram_within_limit(B44_30BIT_DMA_MASK)) { - DBG("Sorry, this version of the driver does not\n" - "support systems with more than 1GB of RAM.\n"); - return -ENOMEM; - } - /* Set up netdev */ netdev = alloc_etherdev(sizeof(*bp)); if (!netdev) @@ -793,6 +794,10 @@ static int b44_transmit(struct net_device *netdev, struct io_buffer *iobuf) return -ENOBUFS; } + /* Check for addressability */ + if (!b44_address_ok(iobuf->data)) + return -ENOTSUP; + /* Will call netdev_tx_complete() on the iobuf later */ bp->tx_iobuf[cur] = iobuf; From 4dc3f8141fdd08482594c3ab79cbc79d3a613de1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 17 Jul 2012 20:53:25 +0100 Subject: [PATCH 085/250] [ioapi] Generalise i386 raw I/O API to x86 Signed-off-by: Michael Brown --- src/arch/{i386 => x86}/core/x86_io.c | 13 +++++++++---- src/arch/{i386 => x86}/include/bits/io.h | 2 +- src/arch/{i386 => x86}/include/ipxe/x86_io.h | 18 ++++++++++++------ src/arch/x86_64/include/bits/io.h | 10 ---------- 4 files changed, 22 insertions(+), 21 deletions(-) rename src/arch/{i386 => x86}/core/x86_io.c (88%) rename src/arch/{i386 => x86}/include/bits/io.h (77%) rename src/arch/{i386 => x86}/include/ipxe/x86_io.h (90%) delete mode 100644 src/arch/x86_64/include/bits/io.h diff --git a/src/arch/i386/core/x86_io.c b/src/arch/x86/core/x86_io.c similarity index 88% rename from src/arch/i386/core/x86_io.c rename to src/arch/x86/core/x86_io.c index 2fba0680..f1c3eb03 100644 --- a/src/arch/i386/core/x86_io.c +++ b/src/arch/x86/core/x86_io.c @@ -35,7 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * This routine uses MMX instructions. */ -static uint64_t x86_readq ( volatile uint64_t *io_addr ) { +static __unused uint64_t i386_readq ( volatile uint64_t *io_addr ) { uint64_t data; __asm__ __volatile__ ( "pushl %%edx\n\t" "pushl %%eax\n\t" @@ -56,7 +56,7 @@ static uint64_t x86_readq ( volatile uint64_t *io_addr ) { * * This routine uses MMX instructions. */ -static void x86_writeq ( uint64_t data, volatile uint64_t *io_addr ) { +static __unused void i386_writeq ( uint64_t data, volatile uint64_t *io_addr ) { __asm__ __volatile__ ( "pushl %%edx\n\t" "pushl %%eax\n\t" "movq (%%esp), %%mm0\n\t" @@ -75,11 +75,9 @@ PROVIDE_IOAPI_INLINE ( x86, io_to_bus ); PROVIDE_IOAPI_INLINE ( x86, readb ); PROVIDE_IOAPI_INLINE ( x86, readw ); PROVIDE_IOAPI_INLINE ( x86, readl ); -PROVIDE_IOAPI ( x86, readq, x86_readq ); PROVIDE_IOAPI_INLINE ( x86, writeb ); PROVIDE_IOAPI_INLINE ( x86, writew ); PROVIDE_IOAPI_INLINE ( x86, writel ); -PROVIDE_IOAPI ( x86, writeq, x86_writeq ); PROVIDE_IOAPI_INLINE ( x86, inb ); PROVIDE_IOAPI_INLINE ( x86, inw ); PROVIDE_IOAPI_INLINE ( x86, inl ); @@ -94,3 +92,10 @@ PROVIDE_IOAPI_INLINE ( x86, outsw ); PROVIDE_IOAPI_INLINE ( x86, outsl ); PROVIDE_IOAPI_INLINE ( x86, iodelay ); PROVIDE_IOAPI_INLINE ( x86, mb ); +#ifdef __x86_64__ +PROVIDE_IOAPI_INLINE ( x86, readq ); +PROVIDE_IOAPI_INLINE ( x86, writeq ); +#else +PROVIDE_IOAPI ( x86, readq, i386_readq ); +PROVIDE_IOAPI ( x86, writeq, i386_writeq ); +#endif diff --git a/src/arch/i386/include/bits/io.h b/src/arch/x86/include/bits/io.h similarity index 77% rename from src/arch/i386/include/bits/io.h rename to src/arch/x86/include/bits/io.h index f3ecf89b..cb1b67a6 100644 --- a/src/arch/i386/include/bits/io.h +++ b/src/arch/x86/include/bits/io.h @@ -3,7 +3,7 @@ /** @file * - * i386-specific I/O API implementations + * x86-specific I/O API implementations * */ diff --git a/src/arch/i386/include/ipxe/x86_io.h b/src/arch/x86/include/ipxe/x86_io.h similarity index 90% rename from src/arch/i386/include/ipxe/x86_io.h rename to src/arch/x86/include/ipxe/x86_io.h index a79501e2..adb00a68 100644 --- a/src/arch/i386/include/ipxe/x86_io.h +++ b/src/arch/x86/include/ipxe/x86_io.h @@ -5,14 +5,14 @@ * * iPXE I/O API for x86 * - * i386 uses direct pointer dereferences for accesses to memory-mapped + * x86 uses direct pointer dereferences for accesses to memory-mapped * I/O space, and the inX/outX instructions for accesses to * port-mapped I/O space. * - * 64-bit atomic accesses (readq() and writeq()) use MMX instructions, - * and will crash original Pentium and earlier CPUs. Fortunately, no - * hardware that requires atomic 64-bit accesses will physically fit - * into a machine with such an old CPU anyway. + * 64-bit atomic accesses (readq() and writeq()) use MMX instructions + * under i386, and will crash original Pentium and earlier CPUs. + * Fortunately, no hardware that requires atomic 64-bit accesses will + * physically fit into a machine with such an old CPU anyway. */ FILE_LICENCE ( GPL2_OR_LATER ); @@ -59,7 +59,7 @@ IOAPI_INLINE ( x86, io_to_bus ) ( volatile const void *io_addr ) { } /* - * MMIO reads and writes up to 32 bits + * MMIO reads and writes up to native word size * */ @@ -71,6 +71,9 @@ IOAPI_INLINE ( x86, _api_func ) ( volatile _type *io_addr ) { \ X86_READX ( readb, uint8_t ); X86_READX ( readw, uint16_t ); X86_READX ( readl, uint32_t ); +#ifdef __x86_64__ +X86_READX ( readq, uint64_t ); +#endif #define X86_WRITEX( _api_func, _type ) \ static inline __always_inline void \ @@ -81,6 +84,9 @@ IOAPI_INLINE ( x86, _api_func ) ( _type data, \ X86_WRITEX ( writeb, uint8_t ); X86_WRITEX ( writew, uint16_t ); X86_WRITEX ( writel, uint32_t ); +#ifdef __x86_64__ +X86_WRITEX ( writeq, uint64_t ); +#endif /* * PIO reads and writes up to 32 bits diff --git a/src/arch/x86_64/include/bits/io.h b/src/arch/x86_64/include/bits/io.h deleted file mode 100644 index 921fdcc0..00000000 --- a/src/arch/x86_64/include/bits/io.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _BITS_IO_H -#define _BITS_IO_H - -/** @file - * - * x86_64-specific I/O API implementations - * - */ - -#endif /* _BITS_IO_H */ From 2d7c966e77f504dc9b53f6d18a2f01deb7b9cb4a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 17 Jul 2012 21:28:24 +0100 Subject: [PATCH 086/250] [efi] Default to using raw x86 I/O The EFI_CPU_IO_PROTOCOL is not available on all EFI platforms. In particular, it is not available under OVMF, as used for qemu. Since the EFI_CPU_IO_PROTOCOL is an abomination of unnecessary complexity, banish it and use raw I/O instead. Signed-off-by: Michael Brown --- src/config/defaults/efi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/defaults/efi.h b/src/config/defaults/efi.h index 16a44dd5..923360ae 100644 --- a/src/config/defaults/efi.h +++ b/src/config/defaults/efi.h @@ -8,7 +8,7 @@ */ #define UACCESS_EFI -#define IOAPI_EFI +#define IOAPI_X86 #define PCIAPI_EFI #define CONSOLE_EFI #define TIMER_EFI From 9200049c80f69280aaacc0bd917fd18d6d23ecce Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 18 Jul 2012 18:18:28 +0100 Subject: [PATCH 087/250] [pxeprefix] Ignore errors from PXENV_FILE_CMDLINE PXENV_FILE_CMDLINE is an iPXE extension, and will not be supported by most PXE stacks. Do not report any errors to the user, since in almost all cases the error will mean simply "not loaded by iPXE". Reported-by: Patrick Domack Signed-off-by: Michael Brown --- src/arch/i386/prefix/pxeprefix.S | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/arch/i386/prefix/pxeprefix.S b/src/arch/i386/prefix/pxeprefix.S index 3c851dca..05db9894 100644 --- a/src/arch/i386/prefix/pxeprefix.S +++ b/src/arch/i386/prefix/pxeprefix.S @@ -396,10 +396,8 @@ get_cmdline: movw $0xffff, ( pxe_parameter_structure + 0x02 ) movw $PXENV_FILE_CMDLINE, %bx call pxe_call - jnc 1f - call print_pxe_error - jmp 99f -1: /* Check for non-NULL command line */ + jc 99f /* Suppress errors; this is an iPXE extension API call */ + /* Check for non-NULL command line */ movw ( pxe_parameter_structure + 0x02 ), %ax testw %ax, %ax jz 99f From 34576e5ff40756f362c61a409280619f45fb0bdb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 10:08:50 +0100 Subject: [PATCH 088/250] [efi] Standardise #include guard in ipxe_download.h The script include/ipxe/efi/import.pl relies on a particular format for the #include guard in order to detect EFI headers that are not imported. Signed-off-by: Michael Brown --- src/include/ipxe/efi/ipxe_download.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/include/ipxe/efi/ipxe_download.h b/src/include/ipxe/efi/ipxe_download.h index 282d1eed..22e3cef0 100644 --- a/src/include/ipxe/efi/ipxe_download.h +++ b/src/include/ipxe/efi/ipxe_download.h @@ -1,3 +1,6 @@ +#ifndef _IPXE_DOWNLOAD_H +#define _IPXE_DOWNLOAD_H + /* * Copyright (C) 2010 VMware, Inc. All Rights Reserved. * @@ -16,9 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef IPXE_DOWNLOAD_H -#define IPXE_DOWNLOAD_H - FILE_LICENCE ( GPL2_OR_LATER ); /** @file @@ -151,4 +151,4 @@ struct _IPXE_DOWNLOAD_PROTOCOL { 0x3eaeaebd, 0xdecf, 0x493b, { 0x9b, 0xd1, 0xcd, 0xb2, 0xde, 0xca, 0xe7, 0x19 } \ } -#endif +#endif /* _IPXE_DOWNLOAD_H */ From bc41c6ef02041fd961a7b19c4d7471d7e796a51c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 10:19:55 +0100 Subject: [PATCH 089/250] [efi] Update to current EDK2 headers Signed-off-by: Michael Brown --- src/include/ipxe/efi/Base.h | 51 +- src/include/ipxe/efi/Ia32/ProcessorBind.h | 22 +- src/include/ipxe/efi/Library/BaseLib.h | 7218 +++++++++++++++++ src/include/ipxe/efi/Pi/PiDxeCis.h | 13 +- src/include/ipxe/efi/Pi/PiFirmwareFile.h | 24 +- src/include/ipxe/efi/Pi/PiFirmwareVolume.h | 13 +- src/include/ipxe/efi/Pi/PiHob.h | 21 +- src/include/ipxe/efi/Pi/PiStatusCode.h | 78 +- .../ipxe/efi/Protocol/ComponentName2.h | 5 +- src/include/ipxe/efi/Protocol/Cpu.h | 4 +- src/include/ipxe/efi/Protocol/DevicePath.h | 211 +- src/include/ipxe/efi/Protocol/FormBrowser2.h | 4 + .../ipxe/efi/Protocol/HiiConfigAccess.h | 6 + .../efi/Protocol/NetworkInterfaceIdentifier.h | 25 +- .../ipxe/efi/Protocol/PciRootBridgeIo.h | 10 +- src/include/ipxe/efi/Protocol/SimpleTextIn.h | 4 +- .../ipxe/efi/Protocol/SimpleTextInEx.h | 327 + src/include/ipxe/efi/Uefi/UefiBaseType.h | 4 +- src/include/ipxe/efi/Uefi/UefiGpt.h | 3 +- .../efi/Uefi/UefiInternalFormRepresentation.h | 33 +- src/include/ipxe/efi/Uefi/UefiMultiPhase.h | 42 +- src/include/ipxe/efi/Uefi/UefiSpec.h | 29 +- src/include/ipxe/efi/X64/ProcessorBind.h | 6 +- src/include/ipxe/efi/efi_pci.h | 5 + 24 files changed, 8014 insertions(+), 144 deletions(-) create mode 100644 src/include/ipxe/efi/Library/BaseLib.h create mode 100644 src/include/ipxe/efi/Protocol/SimpleTextInEx.h diff --git a/src/include/ipxe/efi/Base.h b/src/include/ipxe/efi/Base.h index 999b4147..2fb4ec6f 100644 --- a/src/include/ipxe/efi/Base.h +++ b/src/include/ipxe/efi/Base.h @@ -6,7 +6,7 @@ environment. There are a set of base libraries in the Mde Package that can be used to implement base modules. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -395,6 +395,7 @@ struct _LIST_ENTRY { // VA_END (VA_LIST Marker) - Clear Marker // VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argument from // the ... list. You must know the size and pass it in this macro. +// VA_COPY (VA_LIST Dest, VA_LIST Start) - Initialize Dest as a copy of Start. // // example: // @@ -456,6 +457,13 @@ struct _LIST_ENTRY { #define VA_END(Marker) ((void)0) +// For some ARM RVCT compilers, __va_copy is not defined +#ifndef __va_copy + #define __va_copy(dest, src) ((void)((dest) = (src))) +#endif + +#define VA_COPY(Dest, Start) __va_copy (Dest, Start) + #elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS) // // Use GCC built-in macros for variable argument lists. @@ -473,6 +481,8 @@ typedef __builtin_va_list VA_LIST; #define VA_END(Marker) __builtin_va_end (Marker) +#define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start) + #else /// /// Variable used to traverse the list of arguments. This type can vary by @@ -528,6 +538,19 @@ typedef CHAR8 *VA_LIST; **/ #define VA_END(Marker) (Marker = (VA_LIST) 0) +/** + Initializes a VA_LIST as a copy of an existing VA_LIST. + + This macro initializes Dest as a copy of Start, as if the VA_START macro had been applied to Dest + followed by the same sequence of uses of the VA_ARG macro as had previously been used to reach + the present state of Start. + + @param Dest VA_LIST used to traverse the list of arguments. + @param Start VA_LIST used to traverse the list of arguments. + +**/ +#define VA_COPY(Dest, Start) ((void)((Dest) = (Start))) + #endif /// @@ -678,10 +701,22 @@ typedef UINTN *BASE_LIST; @return Minimum of two operands. **/ - #define MIN(a, b) \ (((a) < (b)) ? (a) : (b)) +/** + Return the absolute value of a signed operand. + + This macro returns the absolute value of the signed operand specified by a. + + @param a The signed operand. + + @return The absolute value of the signed operand. + +**/ +#define ABS(a) \ + (((a) < 0) ? (-(a)) : (a)) + // // Status codes common to all execution phases // @@ -884,6 +919,12 @@ typedef UINTN RETURN_STATUS; /// #define RETURN_INVALID_LANGUAGE ENCODE_ERROR (32) +/// +/// The security status of the data is unknown or compromised +/// and the data must be updated or replaced to restore a valid +/// security status. +/// +#define RETURN_COMPROMISED_DATA ENCODE_ERROR (33) /// /// The string contained one or more characters that @@ -908,6 +949,12 @@ typedef UINTN RETURN_STATUS; /// #define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) +/// +/// The data has not been updated within the timeframe set by +/// local policy for this type of data. +/// +#define RETURN_WARN_STALE_DATA ENCODE_WARNING (5) + /** Returns a 16-bit signature built from 2 ASCII characters. diff --git a/src/include/ipxe/efi/Ia32/ProcessorBind.h b/src/include/ipxe/efi/Ia32/ProcessorBind.h index 20cf407b..89bce6ff 100644 --- a/src/include/ipxe/efi/Ia32/ProcessorBind.h +++ b/src/include/ipxe/efi/Ia32/ProcessorBind.h @@ -1,7 +1,7 @@ /** @file Processor or Compiler specific defines and types for IA-32 architecture. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -149,7 +149,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value. /// - typedef char INT8; + typedef signed char INT8; #else /// /// 8-byte unsigned value. @@ -196,7 +196,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value /// - typedef char INT8; + typedef signed char INT8; #endif /// @@ -247,13 +247,17 @@ typedef INT32 INTN; /// Microsoft* compiler specific method for EFIAPI calling convention. /// #define EFIAPI __cdecl +#elif defined(__GNUC__) + /// + /// GCC specific method for EFIAPI calling convention. + /// + #define EFIAPI __attribute__((cdecl)) #else - #if defined(__GNUC__) - /// - /// GCC specific method for EFIAPI calling convention. - /// - #define EFIAPI __attribute__((cdecl)) - #endif + /// + /// The default for a non Microsoft* or GCC compiler is to assume the EFI ABI + /// is the standard. + /// + #define EFIAPI #endif #if defined(__GNUC__) diff --git a/src/include/ipxe/efi/Library/BaseLib.h b/src/include/ipxe/efi/Library/BaseLib.h new file mode 100644 index 00000000..af4c8743 --- /dev/null +++ b/src/include/ipxe/efi/Library/BaseLib.h @@ -0,0 +1,7218 @@ +/** @file + Provides string functions, linked list functions, math functions, synchronization + functions, and CPU architecture-specific functions. + +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BASE_LIB__ +#define __BASE_LIB__ + +// +// Definitions for architecture-specific types +// +#if defined (MDE_CPU_IA32) +/// +/// The IA-32 architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT32 Ebx; + UINT32 Esi; + UINT32 Edi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Eip; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 + +#endif // defined (MDE_CPU_IA32) + +#if defined (MDE_CPU_IPF) + +/// +/// The Itanium architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[2]; + UINT64 F16[2]; + UINT64 F17[2]; + UINT64 F18[2]; + UINT64 F19[2]; + UINT64 F20[2]; + UINT64 F21[2]; + UINT64 F22[2]; + UINT64 F23[2]; + UINT64 F24[2]; + UINT64 F25[2]; + UINT64 F26[2]; + UINT64 F27[2]; + UINT64 F28[2]; + UINT64 F29[2]; + UINT64 F30[2]; + UINT64 F31[2]; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 SP; + UINT64 BR0; + UINT64 BR1; + UINT64 BR2; + UINT64 BR3; + UINT64 BR4; + UINT64 BR5; + UINT64 InitialUNAT; + UINT64 AfterSpillUNAT; + UINT64 PFS; + UINT64 BSP; + UINT64 Predicates; + UINT64 LoopCount; + UINT64 FPSR; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 0x10 + +#endif // defined (MDE_CPU_IPF) + +#if defined (MDE_CPU_X64) +/// +/// The x64 architecture context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + UINT64 Rdi; + UINT64 Rsi; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; + UINT64 MxCsr; + UINT8 XmmBuffer[160]; ///< XMM6-XMM15. +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 + +#endif // defined (MDE_CPU_X64) + +#if defined (MDE_CPU_EBC) +/// +/// The EBC context buffer used by SetJump() and LongJump(). +/// +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 IP; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 8 + +#endif // defined (MDE_CPU_EBC) + +#if defined (MDE_CPU_ARM) + +typedef struct { + UINT32 R3; ///< A copy of R13. + UINT32 R4; + UINT32 R5; + UINT32 R6; + UINT32 R7; + UINT32 R8; + UINT32 R9; + UINT32 R10; + UINT32 R11; + UINT32 R12; + UINT32 R14; +} BASE_LIBRARY_JUMP_BUFFER; + +#define BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT 4 + +#endif // defined (MDE_CPU_ARM) + +// +// String Services +// + +/** + Copies one Null-terminated Unicode string to another Null-terminated Unicode + string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + + +/** + Copies up to a specified length from one Null-terminated Unicode string to + another Null-terminated Unicode string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. At most, Length Unicode + characters are copied from Source to Destination. If Length is 0, then + Destination is returned unmodified. If Length is greater that the number of + Unicode characters in Source, then Destination is padded with Null Unicode + characters. If Source and Destination overlap, then the results are + undefined. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to copy. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrnCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ); + + +/** + Returns the length of a Null-terminated Unicode string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +EFIAPI +StrLen ( + IN CONST CHAR16 *String + ); + + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated Unicode string + specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @return The size of String. + +**/ +UINTN +EFIAPI +StrSize ( + IN CONST CHAR16 *String + ); + + +/** + Compares two Null-terminated Unicode strings, and returns the difference + between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched Unicode character in SecondString subtracted from the first + mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param FirstString The pointer to a Null-terminated Unicode string. + @param SecondString The pointer to a Null-terminated Unicode string. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString + ); + + +/** + Compares up to a specified length the contents of two Null-terminated Unicode strings, + and returns the difference between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString The pointer to a Null-terminated Unicode string. + @param SecondString The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to compare. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrnCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString, + IN UINTN Length + ); + + +/** + Concatenates one Null-terminated Unicode string to another Null-terminated + Unicode string, and returns the concatenated Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination. The Null-terminated concatenated + Unicode String is returned. If Source and Destination overlap, then the + results are undefined. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + + +/** + Concatenates up to a specified length one Null-terminated Unicode to the end + of another Null-terminated Unicode string, and returns the concatenated + Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination, and Destination is returned. At + most, Length Unicode characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Destination is NULL, then ASSERT(). + If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than PcdMaximumUnicodeStringLength + Unicode characters, not including the Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated Unicode string. + @param Source The pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to concatenate from + Source. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +StrnCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ); + +/** + Returns the first occurrence of a Null-terminated Unicode sub-string + in a Null-terminated Unicode string. + + This function scans the contents of the Null-terminated Unicode string + specified by String and returns the first occurrence of SearchString. + If SearchString is not found in String, then NULL is returned. If + the length of SearchString is zero, then String is returned. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If SearchString is NULL, then ASSERT(). + If SearchString is not aligned on a 16-bit boundary, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and SearchString + or String contains more than PcdMaximumUnicodeStringLength Unicode + characters, not including the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + @param SearchString The pointer to a Null-terminated Unicode string to search for. + + @retval NULL If the SearchString does not appear in String. + @return others If there is a match. + +**/ +CHAR16 * +EFIAPI +StrStr ( + IN CONST CHAR16 *String, + IN CONST CHAR16 *SearchString + ); + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINTN, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrDecimalToUintn ( + IN CONST CHAR16 *String + ); + +/** + Convert a Null-terminated Unicode decimal string to a value of + type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a decimal number. The format + of the input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The + function will ignore the pad space, which includes spaces or + tab characters, before [decimal digits]. The running zero in the + beginning of [decimal digits] will be ignored. Then, the function + stops at the first character that is a not a valid decimal character + or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, + then 0 is returned. + If the number represented by String overflows according + to the range defined by UINT64, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains + more than PcdMaximumUnicodeStringLength Unicode characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrDecimalToUint64 ( + IN CONST CHAR16 *String + ); + + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character + that is a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINTN, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +StrHexToUintn ( + IN CONST CHAR16 *String + ); + + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the Unicode string specified by String as a hexadecimal number. + The format of the input Unicode string String is + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab characters, + before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or + [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the + first valid hexadecimal digit. Then, the function stops at the first character that is + a not a valid hexadecimal character or NULL, whichever one comes first. + + If String is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If String has only pad spaces, then zero is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, + then zero is returned. + If the number represented by String overflows according to the range defined by + UINT64, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated Unicode string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +StrHexToUint64 ( + IN CONST CHAR16 *String + ); + +/** + Convert a Null-terminated Unicode string to a Null-terminated + ASCII string and returns the ASCII string. + + This function converts the content of the Unicode string Source + to the ASCII string Destination by copying the lower 8 bits of + each Unicode character. It returns Destination. + + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes. + + If any Unicode characters in Source contain non-zero value in + the upper 8 bits, then ASSERT(). + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source is not aligned on a 16-bit boundary, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero, and Source contains + more than PcdMaximumUnicodeStringLength Unicode characters not including + the Null-terminator, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero, and Source contains more + than PcdMaximumAsciiStringLength Unicode characters not including the + Null-terminator, then ASSERT(). + + @param Source The pointer to a Null-terminated Unicode string. + @param Destination The pointer to a Null-terminated ASCII string. + + @return Destination. + +**/ +CHAR8 * +EFIAPI +UnicodeStrToAsciiStr ( + IN CONST CHAR16 *Source, + OUT CHAR8 *Destination + ); + + +/** + Copies one Null-terminated ASCII string to another Null-terminated ASCII + string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + + +/** + Copies up to a specified length one Null-terminated ASCII string to another + Null-terminated ASCII string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. At most, Length ASCII characters + are copied from Source to Destination. If Length is 0, then Destination is + returned unmodified. If Length is greater that the number of ASCII characters + in Source, then Destination is padded with Null ASCII characters. If Source + and Destination overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters to copy. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ); + + +/** + Returns the length of a Null-terminated ASCII string. + + This function returns the number of ASCII characters in the Null-terminated + ASCII string specified by String. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @return The length of String. + +**/ +UINTN +EFIAPI +AsciiStrLen ( + IN CONST CHAR8 *String + ); + + +/** + Returns the size of a Null-terminated ASCII string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated ASCII string + specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @return The size of String. + +**/ +UINTN +EFIAPI +AsciiStrSize ( + IN CONST CHAR8 *String + ); + + +/** + Compares two Null-terminated ASCII strings, and returns the difference + between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched ASCII character in SecondString subtracted from the first + mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters not including the + Null-terminator, then ASSERT(). + + @param FirstString The pointer to a Null-terminated ASCII string. + @param SecondString The pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ); + + +/** + Performs a case insensitive comparison of two Null-terminated ASCII strings, + and returns the difference between the first mismatched ASCII characters. + + This function performs a case insensitive comparison of the Null-terminated + ASCII string FirstString to the Null-terminated ASCII string SecondString. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched lower case ASCII character in + SecondString subtracted from the first mismatched lower case ASCII character + in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters not including the + Null-terminator, then ASSERT(). + + @param FirstString The pointer to a Null-terminated ASCII string. + @param SecondString The pointer to a Null-terminated ASCII string. + + @retval ==0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStriCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ); + + +/** + Compares two Null-terminated ASCII strings with maximum lengths, and returns + the difference between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. At most, Length ASCII characters + will be compared. If Length is 0, then 0 is returned. If FirstString is + identical to SecondString, then 0 is returned. Otherwise, the value returned + is the first mismatched ASCII character in SecondString subtracted from the + first mismatched ASCII character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and SecondString contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString The pointer to a Null-terminated ASCII string. + @param SecondString The pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters for compare. + + @retval ==0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrnCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ); + + +/** + Concatenates one Null-terminated ASCII string to another Null-terminated + ASCII string, and returns the concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents of + Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination. The Null-terminated concatenated ASCII + String is returned. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + + +/** + Concatenates up to a specified length one Null-terminated ASCII string to + the end of another Null-terminated ASCII string, and returns the + concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents + of Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination, and Destination is returned. At most, + Length ASCII characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Length > 0 and Destination is NULL, then ASSERT(). + If Length > 0 and Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Length is greater than + PcdMaximumAsciiStringLength, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, not including the Null-terminator, then ASSERT(). + + @param Destination The pointer to a Null-terminated ASCII string. + @param Source The pointer to a Null-terminated ASCII string. + @param Length The maximum number of ASCII characters to concatenate from + Source. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ); + + +/** + Returns the first occurrence of a Null-terminated ASCII sub-string + in a Null-terminated ASCII string. + + This function scans the contents of the ASCII string specified by String + and returns the first occurrence of SearchString. If SearchString is not + found in String, then NULL is returned. If the length of SearchString is zero, + then String is returned. + + If String is NULL, then ASSERT(). + If SearchString is NULL, then ASSERT(). + + If PcdMaximumAsciiStringLength is not zero, and SearchString or + String contains more than PcdMaximumAsciiStringLength Unicode characters + not including the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + @param SearchString The pointer to a Null-terminated ASCII string to search for. + + @retval NULL If the SearchString does not appear in String. + @retval others If there is a match return the first occurrence of SearchingString. + If the length of SearchString is zero,return String. + +**/ +CHAR8 * +EFIAPI +AsciiStrStr ( + IN CONST CHAR8 *String, + IN CONST CHAR8 *SearchString + ); + + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINTN. + + This function returns a value of type UINTN by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINTN, then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval The value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrDecimalToUintn ( + IN CONST CHAR8 *String + ); + + +/** + Convert a Null-terminated ASCII decimal string to a value of type + UINT64. + + This function returns a value of type UINT64 by interpreting the contents + of the ASCII string String as a decimal number. The format of the input + ASCII string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before the digits. + The running zero in the beginning of [decimal digits] will be ignored. Then, the + function stops at the first character that is a not a valid decimal character or + Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no pad spaces or valid decimal digits, then 0 is returned. + If the number represented by String overflows according to the range defined by + UINT64, then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and String contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrDecimalToUint64 ( + IN CONST CHAR8 *String + ); + + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINTN. + + This function returns a value of type UINTN by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINTN, + then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINTN +EFIAPI +AsciiStrHexToUintn ( + IN CONST CHAR8 *String + ); + + +/** + Convert a Null-terminated ASCII hexadecimal string to a value of type UINT64. + + This function returns a value of type UINT64 by interpreting the contents of + the ASCII string String as a hexadecimal number. The format of the input ASCII + string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. If "x" + appears in the input string, it must be prefixed with at least one 0. The function + will ignore the pad space, which includes spaces or tab characters, before [zeros], + [x] or [hexadecimal digits]. The running zero before [x] or [hexadecimal digits] + will be ignored. Then, the decoding starts after [x] or the first valid hexadecimal + digit. Then, the function stops at the first character that is a not a valid + hexadecimal character or Null-terminator, whichever on comes first. + + If String has only pad spaces, then 0 is returned. + If String has no leading pad spaces, leading zeros or valid hexadecimal digits, then + 0 is returned. + + If the number represented by String overflows according to the range defined by UINT64, + then ASSERT(). + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, + and String contains more than PcdMaximumAsciiStringLength ASCII characters not including + the Null-terminator, then ASSERT(). + + @param String The pointer to a Null-terminated ASCII string. + + @retval Value translated from String. + +**/ +UINT64 +EFIAPI +AsciiStrHexToUint64 ( + IN CONST CHAR8 *String + ); + + +/** + Convert one Null-terminated ASCII string to a Null-terminated + Unicode string and returns the Unicode string. + + This function converts the contents of the ASCII string Source to the Unicode + string Destination, and returns Destination. The function terminates the + Unicode string Destination by appending a Null-terminator character at the end. + The caller is responsible to make sure Destination points to a buffer with size + equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes. + + If Destination is NULL, then ASSERT(). + If Destination is not aligned on a 16-bit boundary, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength ASCII characters not including the + Null-terminator, then ASSERT(). + + @param Source The pointer to a Null-terminated ASCII string. + @param Destination The pointer to a Null-terminated Unicode string. + + @return Destination. + +**/ +CHAR16 * +EFIAPI +AsciiStrToUnicodeStr ( + IN CONST CHAR8 *Source, + OUT CHAR16 *Destination + ); + + +/** + Converts an 8-bit value to an 8-bit BCD value. + + Converts the 8-bit value specified by Value to BCD. The BCD value is + returned. + + If Value >= 100, then ASSERT(). + + @param Value The 8-bit value to convert to BCD. Range 0..99. + + @return The BCD value. + +**/ +UINT8 +EFIAPI +DecimalToBcd8 ( + IN UINT8 Value + ); + + +/** + Converts an 8-bit BCD value to an 8-bit value. + + Converts the 8-bit BCD value specified by Value to an 8-bit value. The 8-bit + value is returned. + + If Value >= 0xA0, then ASSERT(). + If (Value & 0x0F) >= 0x0A, then ASSERT(). + + @param Value The 8-bit BCD value to convert to an 8-bit value. + + @return The 8-bit value is returned. + +**/ +UINT8 +EFIAPI +BcdToDecimal8 ( + IN UINT8 Value + ); + + +// +// Linked List Functions and Macros +// + +/** + Initializes the head node of a doubly linked list that is declared as a + global variable in a module. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this macro, the other linked list functions + may be used to add and remove nodes from the linked list. This macro results + in smaller executables by initializing the linked list in the data section, + instead if calling the InitializeListHead() function to perform the + equivalent operation. + + @param ListHead The head note of a list to initialize. + +**/ +#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead) {&(ListHead), &(ListHead)} + + +/** + Initializes the head node of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this function, the other linked list + functions may be used to add and remove nodes from the linked list. It is up + to the caller of this function to allocate the memory for ListHead. + + If ListHead is NULL, then ASSERT(). + + @param ListHead A pointer to the head node of a new doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InitializeListHead ( + IN OUT LIST_ENTRY *ListHead + ); + + +/** + Adds a node to the beginning of a doubly linked list, and returns the pointer + to the head node of the doubly linked list. + + Adds the node Entry at the beginning of the doubly linked list denoted by + ListHead, and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be inserted at the beginning + of a doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertHeadList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ); + + +/** + Adds a node to the end of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Adds the node Entry to the end of the doubly linked list denoted by ListHead, + and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number + of nodes in ListHead, including the ListHead node, is greater than or + equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be added at the end of the + doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertTailList ( + IN OUT LIST_ENTRY *ListHead, + IN OUT LIST_ENTRY *Entry + ); + + +/** + Retrieves the first node of a doubly linked list. + + Returns the first node of a doubly linked list. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + + @return The first node of a doubly linked list. + @retval NULL The list is empty. + +**/ +LIST_ENTRY * +EFIAPI +GetFirstNode ( + IN CONST LIST_ENTRY *List + ); + + +/** + Retrieves the next node of a doubly linked list. + + Returns the node of a doubly linked list that follows Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @return The pointer to the next node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetNextNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Retrieves the previous node of a doubly linked list. + + Returns the node of a doubly linked list that precedes Node. + List must have been initialized with INTIALIZE_LIST_HEAD_VARIABLE() + or InitializeListHead(). If List is empty, then List is returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @return The pointer to the previous node if one exists. Otherwise List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetPreviousNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Checks to see if a doubly linked list is empty or not. + + Checks to see if the doubly linked list is empty. If the linked list contains + zero nodes, this function returns TRUE. Otherwise, it returns FALSE. + + If ListHead is NULL, then ASSERT(). + If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + + @retval TRUE The linked list is empty. + @retval FALSE The linked list is not empty. + +**/ +BOOLEAN +EFIAPI +IsListEmpty ( + IN CONST LIST_ENTRY *ListHead + ); + + +/** + Determines if a node in a doubly linked list is the head node of a the same + doubly linked list. This function is typically used to terminate a loop that + traverses all the nodes in a doubly linked list starting with the head node. + + Returns TRUE if Node is equal to List. Returns FALSE if Node is one of the + nodes in the doubly linked list specified by List. List must have been + initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), + then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List the and Node is not equal + to List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is the head of the doubly-linked list pointed by List. + @retval FALSE Node is not the head of the doubly-linked list pointed by List. + +**/ +BOOLEAN +EFIAPI +IsNull ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Determines if a node the last node in a doubly linked list. + + Returns TRUE if Node is the last node in the doubly linked list specified by + List. Otherwise, FALSE is returned. List must have been initialized with + INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or + InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the number of nodes + in List, including the List node, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is the last node in the linked list. + @retval FALSE Node is not the last node in the linked list. + +**/ +BOOLEAN +EFIAPI +IsNodeAtEnd ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + + +/** + Swaps the location of two nodes in a doubly linked list, and returns the + first node after the swap. + + If FirstEntry is identical to SecondEntry, then SecondEntry is returned. + Otherwise, the location of the FirstEntry node is swapped with the location + of the SecondEntry node in a doubly linked list. SecondEntry must be in the + same double linked list as FirstEntry and that double linked list must have + been initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(). + SecondEntry is returned after the nodes are swapped. + + If FirstEntry is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(). + If PcdVerifyNodeInList is TRUE and SecondEntry and FirstEntry are not in the + same linked list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing the FirstEntry and SecondEntry nodes, including + the FirstEntry and SecondEntry nodes, is greater than or equal to + PcdMaximumLinkedListLength, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to another node in the same linked list. + + @return SecondEntry. + +**/ +LIST_ENTRY * +EFIAPI +SwapListEntries ( + IN OUT LIST_ENTRY *FirstEntry, + IN OUT LIST_ENTRY *SecondEntry + ); + + +/** + Removes a node from a doubly linked list, and returns the node that follows + the removed node. + + Removes the node Entry from a doubly linked list. It is up to the caller of + this function to release the memory used by this node if that is required. On + exit, the node following Entry in the doubly linked list is returned. If + Entry is the only node in the linked list, then the head node of the linked + list is returned. + + If Entry is NULL, then ASSERT(). + If Entry is the head node of an empty list, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and the number of nodes in the + linked list containing Entry, including the Entry node, is greater than + or equal to PcdMaximumLinkedListLength, then ASSERT(). + + @param Entry A pointer to a node in a linked list. + + @return Entry. + +**/ +LIST_ENTRY * +EFIAPI +RemoveEntryList ( + IN CONST LIST_ENTRY *Entry + ); + +// +// Math Services +// + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled + with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count. + +**/ +UINT64 +EFIAPI +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits are + filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits are filled + with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +ARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Rotates a 32-bit integer left between 0 and 31 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 32-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT32 +EFIAPI +LRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ); + + +/** + Rotates a 32-bit integer right between 0 and 31 bits, filling the high bits + with the low bits that were rotated. + + This function rotates the 32-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count + +**/ +UINT32 +EFIAPI +RRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ); + + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +LRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling the high bits + with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +RRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + + +/** + Returns the bit position of the lowest bit set in a 32-bit value. + + This function computes the bit position of the lowest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet32 ( + IN UINT32 Operand + ); + + +/** + Returns the bit position of the lowest bit set in a 64-bit value. + + This function computes the bit position of the lowest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 The lowest bit set in Operand was found. + @retval -1 Operand is zero. + + +**/ +INTN +EFIAPI +LowBitSet64 ( + IN UINT64 Operand + ); + + +/** + Returns the bit position of the highest bit set in a 32-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @retval 0..31 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet32 ( + IN UINT32 Operand + ); + + +/** + Returns the bit position of the highest bit set in a 64-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @retval 0..63 Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet64 ( + IN UINT64 Operand + ); + + +/** + Returns the value of the highest bit set in a 32-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 32-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 32-bit operand to evaluate. + + @return 1 << HighBitSet32(Operand) + @retval 0 Operand is zero. + +**/ +UINT32 +EFIAPI +GetPowerOfTwo32 ( + IN UINT32 Operand + ); + + +/** + Returns the value of the highest bit set in a 64-bit value. Equivalent to + 1 << log2(x). + + This function computes the value of the highest bit set in the 64-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 64-bit operand to evaluate. + + @return 1 << HighBitSet64(Operand) + @retval 0 Operand is zero. + +**/ +UINT64 +EFIAPI +GetPowerOfTwo64 ( + IN UINT64 Operand + ); + + +/** + Switches the endianness of a 16-bit integer. + + This function swaps the bytes in a 16-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 16-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT16 +EFIAPI +SwapBytes16 ( + IN UINT16 Value + ); + + +/** + Switches the endianness of a 32-bit integer. + + This function swaps the bytes in a 32-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 32-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT32 +EFIAPI +SwapBytes32 ( + IN UINT32 Value + ); + + +/** + Switches the endianness of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Value A 64-bit unsigned value. + + @return The byte swapped Value. + +**/ +UINT64 +EFIAPI +SwapBytes64 ( + IN UINT64 Value + ); + + +/** + Multiples a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ); + + +/** + Multiples a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier. + +**/ +UINT64 +EFIAPI +MultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ); + + +/** + Multiples a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result. + + This function multiples the 64-bit signed value Multiplicand by the 64-bit + signed value Multiplier and generates a 64-bit signed result. This 64-bit + signed result is returned. + + @param Multiplicand A 64-bit signed value. + @param Multiplier A 64-bit signed value. + + @return Multiplicand * Multiplier + +**/ +INT64 +EFIAPI +MultS64x64 ( + IN INT64 Multiplicand, + IN INT64 Multiplier + ); + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +DivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor. + +**/ +UINT32 +EFIAPI +ModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +DivU64x32Remainder ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ); + + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and generates + a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +UINT64 +EFIAPI +DivU64x64Remainder ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ); + + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result and a optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit signed + value Divisor and generates a 64-bit signed quotient. If Remainder is not + NULL, then the 64-bit signed remainder is returned in Remainder. This + function returns the 64-bit signed quotient. + + It is the caller's responsibility to not call this function with a Divisor of 0. + If Divisor is 0, then the quotient and remainder should be assumed to be + the largest negative integer. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor. + +**/ +INT64 +EFIAPI +DivS64x64Remainder ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ); + + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 16-bit value that may be unaligned. + + @return The 16-bit value read from Buffer. + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Buffer + ); + + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return The 16-bit value to write to Buffer. + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Buffer, + IN UINT16 Value + ); + + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 24-bit value that may be unaligned. + + @return The 24-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ); + + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The 24-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ); + + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 32-bit value that may be unaligned. + + @return The 32-bit value read from Buffer. + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Buffer + ); + + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 32-bit value that may be unaligned. + @param Value 32-bit value to write to Buffer. + + @return The 32-bit value to write to Buffer. + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ); + + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 64-bit value that may be unaligned. + + @return The 64-bit value read from Buffer. + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Buffer + ); + + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer The pointer to a 64-bit value that may be unaligned. + @param Value 64-bit value to write to Buffer. + + @return The 64-bit value to write to Buffer. + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Buffer, + IN UINT64 Value + ); + + +// +// Bit Field Functions +// + +/** + Returns a bit field from an 8-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The bit field read. + +**/ +UINT8 +EFIAPI +BitFieldRead8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to an 8-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 8-bit value is + returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldWrite8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + + +/** + Reads a bit field from an 8-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the value + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAnd8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAndThenOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + + +/** + Returns a bit field from a 16-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The bit field read. + +**/ +UINT16 +EFIAPI +BitFieldRead16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to a 16-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 16-bit value is + returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldWrite16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + + +/** + Reads a bit field from a 16-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAnd16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAndThenOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + + +/** + Returns a bit field from a 32-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read. + +**/ +UINT32 +EFIAPI +BitFieldRead32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to a 32-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 32-bit value is + returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldWrite32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + + +/** + Reads a bit field from a 32-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the value. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAnd32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAndThenOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + + +/** + Returns a bit field from a 64-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The bit field read. + +**/ +UINT64 +EFIAPI +BitFieldRead64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to a 64-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 64-bit value is + returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldWrite64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + + +/** + Reads a bit field from a 64-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAnd64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + OR with value specified by OrData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAndThenOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + +// +// Base Library Checksum Functions +// + +/** + Returns the sum of all elements in a buffer in unit of UINT8. + During calculation, the carry bits are dropped. + + This function calculates the sum of all elements in a buffer + in unit of UINT8. The carry bits in result of addition are dropped. + The result is returned as UINT8. If Length is Zero, then Zero is + returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT8 +EFIAPI +CalculateSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer + of 8-bit values. + + This function first calculates the sum of the 8-bit values in the + buffer specified by Buffer and Length. The carry bits in the result + of addition are dropped. Then, the two's complement of the sum is + returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT8 +EFIAPI +CalculateCheckSum8 ( + IN CONST UINT8 *Buffer, + IN UINTN Length + ); + + +/** + Returns the sum of all elements in a buffer of 16-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 16-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT16 +EFIAPI +CalculateSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer of + 16-bit values. + + This function first calculates the sum of the 16-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT16 +EFIAPI +CalculateCheckSum16 ( + IN CONST UINT16 *Buffer, + IN UINTN Length + ); + + +/** + Returns the sum of all elements in a buffer of 32-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 32-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT32 +EFIAPI +CalculateSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer of + 32-bit values. + + This function first calculates the sum of the 32-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT32 +EFIAPI +CalculateCheckSum32 ( + IN CONST UINT32 *Buffer, + IN UINTN Length + ); + + +/** + Returns the sum of all elements in a buffer of 64-bit values. During + calculation, the carry bits are dropped. + + This function calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in result of addition are dropped. + The 64-bit result is returned. If Length is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the sum operation. + @param Length The size, in bytes, of Buffer. + + @return Sum The sum of Buffer with carry bits dropped during additions. + +**/ +UINT64 +EFIAPI +CalculateSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ); + + +/** + Returns the two's complement checksum of all elements in a buffer of + 64-bit values. + + This function first calculates the sum of the 64-bit values in the buffer + specified by Buffer and Length. The carry bits in the result of addition + are dropped. Then, the two's complement of the sum is returned. If Length + is 0, then 0 is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the buffer to carry out the checksum operation. + @param Length The size, in bytes, of Buffer. + + @return Checksum The two's complement checksum of Buffer. + +**/ +UINT64 +EFIAPI +CalculateCheckSum64 ( + IN CONST UINT64 *Buffer, + IN UINTN Length + ); + + +// +// Base Library CPU Functions +// + +/** + Function entry point used when a stack switch is requested with SwitchStack() + + @param Context1 Context1 parameter passed into SwitchStack(). + @param Context2 Context2 parameter passed into SwitchStack(). + +**/ +typedef +VOID +(EFIAPI *SWITCH_STACK_ENTRY_POINT)( + IN VOID *Context1, OPTIONAL + IN VOID *Context2 OPTIONAL + ); + + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ); + + +/** + Saves the current CPU context that can be restored with a call to LongJump() + and returns 0. + + Saves the current CPU context in the buffer specified by JumpBuffer and + returns 0. The initial call to SetJump() must always return 0. Subsequent + calls to LongJump() cause a non-zero value to be returned by SetJump(). + + If JumpBuffer is NULL, then ASSERT(). + For Itanium processors, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + + NOTE: The structure BASE_LIBRARY_JUMP_BUFFER is CPU architecture specific. + The same structure must never be used for more than one CPU architecture context. + For example, a BASE_LIBRARY_JUMP_BUFFER allocated by an IA-32 module must never be used from an x64 module. + SetJump()/LongJump() is not currently supported for the EBC processor type. + + @param JumpBuffer A pointer to CPU context buffer. + + @retval 0 Indicates a return from SetJump(). + +**/ +UINTN +EFIAPI +SetJump ( + OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ); + + +/** + Restores the CPU context that was saved with SetJump(). + + Restores the CPU context from the buffer specified by JumpBuffer. This + function never returns to the caller. Instead is resumes execution based on + the state of JumpBuffer. + + If JumpBuffer is NULL, then ASSERT(). + For Itanium processors, if JumpBuffer is not aligned on a 16-byte boundary, then ASSERT(). + If Value is 0, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is + restored and must be non-zero. + +**/ +VOID +EFIAPI +LongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ); + + +/** + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ); + + +/** + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ); + + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +EFIAPI +SaveAndDisableInterrupts ( + VOID + ); + + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +EnableDisableInterrupts ( + VOID + ); + + +/** + Retrieves the current CPU interrupt state. + + Returns TRUE if interrupts are currently enabled. Otherwise + returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ); + + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +SetInterruptState ( + IN BOOLEAN InterruptState + ); + + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ); + + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the + new stack specified by NewStack and passing in the parameters specified + by Context1 and Context2. Context1 and Context2 are optional and may + be NULL. The function EntryPoint must never return. This function + supports a variable number of arguments following the NewStack parameter. + These additional arguments are ignored on IA-32, x64, and EBC architectures. + Itanium processors expect one additional parameter of type VOID * that specifies + the new backing store pointer. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + @param ... This variable argument list is ignored for IA-32, x64, and + EBC architectures. For Itanium processors, this variable + argument list is expected to contain a single parameter of + type VOID * that specifies the new backing store pointer. + + +**/ +VOID +EFIAPI +SwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack, + ... + ); + + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ); + + +/** + Executes an infinite loop. + + Forces the CPU to execute an infinite loop. A debugger may be used to skip + past the loop and the code that follows the loop must execute properly. This + implies that the infinite loop must not cause the code that follow it to be + optimized away. + +**/ +VOID +EFIAPI +CpuDeadLoop ( + VOID + ); + +#if defined (MDE_CPU_IPF) + +/** + Flush a range of cache lines in the cache coherency domain of the calling + CPU. + + Flushes the cache lines specified by Address and Length. If Address is not aligned + on a cache line boundary, then entire cache line containing Address is flushed. + If Address + Length is not aligned on a cache line boundary, then the entire cache + line containing Address + Length - 1 is flushed. This function may choose to flush + the entire cache if that is more efficient than flushing the specified range. If + Length is 0, the no cache lines are flushed. Address is returned. + This function is only available on Itanium processors. + + If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT(). + + @param Address The base address of the instruction lines to invalidate. If + the CPU is in a physical addressing mode, then Address is a + physical address. If the CPU is in a virtual addressing mode, + then Address is a virtual address. + + @param Length The number of bytes to invalidate from the instruction cache. + + @return Address. + +**/ +VOID * +EFIAPI +AsmFlushCacheRange ( + IN VOID *Address, + IN UINTN Length + ); + + +/** + Executes an FC instruction. + Executes an FC instruction on the cache line specified by Address. + The cache line size affected is at least 32-bytes (aligned on a 32-byte boundary). + An implementation may flush a larger region. This function is only available on Itanium processors. + + @param Address The Address of cache line to be flushed. + + @return The address of FC instruction executed. + +**/ +UINT64 +EFIAPI +AsmFc ( + IN UINT64 Address + ); + + +/** + Executes an FC.I instruction. + Executes an FC.I instruction on the cache line specified by Address. + The cache line size affected is at least 32-bytes (aligned on a 32-byte boundary). + An implementation may flush a larger region. This function is only available on Itanium processors. + + @param Address The Address of cache line to be flushed. + + @return The address of the FC.I instruction executed. + +**/ +UINT64 +EFIAPI +AsmFci ( + IN UINT64 Address + ); + + +/** + Reads the current value of a Processor Identifier Register (CPUID). + + Reads and returns the current value of Processor Identifier Register specified by Index. + The Index of largest implemented CPUID (One less than the number of implemented CPUID + registers) is determined by CPUID [3] bits {7:0}. + No parameter checking is performed on Index. If the Index value is beyond the + implemented CPUID register range, a Reserved Register/Field fault may occur. The caller + must either guarantee that Index is valid, or the caller must set up fault handlers to + catch the faults. This function is only available on Itanium processors. + + @param Index The 8-bit Processor Identifier Register index to read. + + @return The current value of Processor Identifier Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadCpuid ( + IN UINT8 Index + ); + + +/** + Reads the current value of 64-bit Processor Status Register (PSR). + This function is only available on Itanium processors. + + @return The current value of PSR. + +**/ +UINT64 +EFIAPI +AsmReadPsr ( + VOID + ); + + +/** + Writes the current value of 64-bit Processor Status Register (PSR). + + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of PSR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to PSR. + + @return The 64-bit value written to the PSR. + +**/ +UINT64 +EFIAPI +AsmWritePsr ( + IN UINT64 Value + ); + + +/** + Reads the current value of 64-bit Kernel Register #0 (KR0). + + Reads and returns the current value of KR0. + This function is only available on Itanium processors. + + @return The current value of KR0. + +**/ +UINT64 +EFIAPI +AsmReadKr0 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #1 (KR1). + + Reads and returns the current value of KR1. + This function is only available on Itanium processors. + + @return The current value of KR1. + +**/ +UINT64 +EFIAPI +AsmReadKr1 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #2 (KR2). + + Reads and returns the current value of KR2. + This function is only available on Itanium processors. + + @return The current value of KR2. + +**/ +UINT64 +EFIAPI +AsmReadKr2 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #3 (KR3). + + Reads and returns the current value of KR3. + This function is only available on Itanium processors. + + @return The current value of KR3. + +**/ +UINT64 +EFIAPI +AsmReadKr3 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #4 (KR4). + + Reads and returns the current value of KR4. + This function is only available on Itanium processors. + + @return The current value of KR4. + +**/ +UINT64 +EFIAPI +AsmReadKr4 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #5 (KR5). + + Reads and returns the current value of KR5. + This function is only available on Itanium processors. + + @return The current value of KR5. + +**/ +UINT64 +EFIAPI +AsmReadKr5 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #6 (KR6). + + Reads and returns the current value of KR6. + This function is only available on Itanium processors. + + @return The current value of KR6. + +**/ +UINT64 +EFIAPI +AsmReadKr6 ( + VOID + ); + + +/** + Reads the current value of 64-bit Kernel Register #7 (KR7). + + Reads and returns the current value of KR7. + This function is only available on Itanium processors. + + @return The current value of KR7. + +**/ +UINT64 +EFIAPI +AsmReadKr7 ( + VOID + ); + + +/** + Write the current value of 64-bit Kernel Register #0 (KR0). + + Writes the current value of KR0. The 64-bit value written to + the KR0 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR0. + + @return The 64-bit value written to the KR0. + +**/ +UINT64 +EFIAPI +AsmWriteKr0 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #1 (KR1). + + Writes the current value of KR1. The 64-bit value written to + the KR1 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR1. + + @return The 64-bit value written to the KR1. + +**/ +UINT64 +EFIAPI +AsmWriteKr1 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #2 (KR2). + + Writes the current value of KR2. The 64-bit value written to + the KR2 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR2. + + @return The 64-bit value written to the KR2. + +**/ +UINT64 +EFIAPI +AsmWriteKr2 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #3 (KR3). + + Writes the current value of KR3. The 64-bit value written to + the KR3 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR3. + + @return The 64-bit value written to the KR3. + +**/ +UINT64 +EFIAPI +AsmWriteKr3 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #4 (KR4). + + Writes the current value of KR4. The 64-bit value written to + the KR4 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR4. + + @return The 64-bit value written to the KR4. + +**/ +UINT64 +EFIAPI +AsmWriteKr4 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #5 (KR5). + + Writes the current value of KR5. The 64-bit value written to + the KR5 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR5. + + @return The 64-bit value written to the KR5. + +**/ +UINT64 +EFIAPI +AsmWriteKr5 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #6 (KR6). + + Writes the current value of KR6. The 64-bit value written to + the KR6 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR6. + + @return The 64-bit value written to the KR6. + +**/ +UINT64 +EFIAPI +AsmWriteKr6 ( + IN UINT64 Value + ); + + +/** + Write the current value of 64-bit Kernel Register #7 (KR7). + + Writes the current value of KR7. The 64-bit value written to + the KR7 is returned. This function is only available on Itanium processors. + + @param Value The 64-bit value to write to KR7. + + @return The 64-bit value written to the KR7. + +**/ +UINT64 +EFIAPI +AsmWriteKr7 ( + IN UINT64 Value + ); + + +/** + Reads the current value of Interval Timer Counter Register (ITC). + + Reads and returns the current value of ITC. + This function is only available on Itanium processors. + + @return The current value of ITC. + +**/ +UINT64 +EFIAPI +AsmReadItc ( + VOID + ); + + +/** + Reads the current value of Interval Timer Vector Register (ITV). + + Reads and returns the current value of ITV. + This function is only available on Itanium processors. + + @return The current value of ITV. + +**/ +UINT64 +EFIAPI +AsmReadItv ( + VOID + ); + + +/** + Reads the current value of Interval Timer Match Register (ITM). + + Reads and returns the current value of ITM. + This function is only available on Itanium processors. + + @return The current value of ITM. +**/ +UINT64 +EFIAPI +AsmReadItm ( + VOID + ); + + +/** + Writes the current value of 64-bit Interval Timer Counter Register (ITC). + + Writes the current value of ITC. The 64-bit value written to the ITC is returned. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to ITC. + + @return The 64-bit value written to the ITC. + +**/ +UINT64 +EFIAPI +AsmWriteItc ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Interval Timer Match Register (ITM). + + Writes the current value of ITM. The 64-bit value written to the ITM is returned. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to ITM. + + @return The 64-bit value written to the ITM. + +**/ +UINT64 +EFIAPI +AsmWriteItm ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Interval Timer Vector Register (ITV). + + Writes the current value of ITV. The 64-bit value written to the ITV is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of ITV must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to ITV. + + @return The 64-bit value written to the ITV. + +**/ +UINT64 +EFIAPI +AsmWriteItv ( + IN UINT64 Value + ); + + +/** + Reads the current value of Default Control Register (DCR). + + Reads and returns the current value of DCR. This function is only available on Itanium processors. + + @return The current value of DCR. + +**/ +UINT64 +EFIAPI +AsmReadDcr ( + VOID + ); + + +/** + Reads the current value of Interruption Vector Address Register (IVA). + + Reads and returns the current value of IVA. This function is only available on Itanium processors. + + @return The current value of IVA. +**/ +UINT64 +EFIAPI +AsmReadIva ( + VOID + ); + + +/** + Reads the current value of Page Table Address Register (PTA). + + Reads and returns the current value of PTA. This function is only available on Itanium processors. + + @return The current value of PTA. + +**/ +UINT64 +EFIAPI +AsmReadPta ( + VOID + ); + + +/** + Writes the current value of 64-bit Default Control Register (DCR). + + Writes the current value of DCR. The 64-bit value written to the DCR is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of DCR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to DCR. + + @return The 64-bit value written to the DCR. + +**/ +UINT64 +EFIAPI +AsmWriteDcr ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Interruption Vector Address Register (IVA). + + Writes the current value of IVA. The 64-bit value written to the IVA is returned. + The size of vector table is 32 K bytes and is 32 K bytes aligned + the low 15 bits of Value is ignored when written. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to IVA. + + @return The 64-bit value written to the IVA. + +**/ +UINT64 +EFIAPI +AsmWriteIva ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Page Table Address Register (PTA). + + Writes the current value of PTA. The 64-bit value written to the PTA is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of DCR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to PTA. + + @return The 64-bit value written to the PTA. +**/ +UINT64 +EFIAPI +AsmWritePta ( + IN UINT64 Value + ); + + +/** + Reads the current value of Local Interrupt ID Register (LID). + + Reads and returns the current value of LID. This function is only available on Itanium processors. + + @return The current value of LID. + +**/ +UINT64 +EFIAPI +AsmReadLid ( + VOID + ); + + +/** + Reads the current value of External Interrupt Vector Register (IVR). + + Reads and returns the current value of IVR. This function is only available on Itanium processors. + + @return The current value of IVR. + +**/ +UINT64 +EFIAPI +AsmReadIvr ( + VOID + ); + + +/** + Reads the current value of Task Priority Register (TPR). + + Reads and returns the current value of TPR. This function is only available on Itanium processors. + + @return The current value of TPR. + +**/ +UINT64 +EFIAPI +AsmReadTpr ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #0 (IRR0). + + Reads and returns the current value of IRR0. This function is only available on Itanium processors. + + @return The current value of IRR0. + +**/ +UINT64 +EFIAPI +AsmReadIrr0 ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #1 (IRR1). + + Reads and returns the current value of IRR1. This function is only available on Itanium processors. + + @return The current value of IRR1. + +**/ +UINT64 +EFIAPI +AsmReadIrr1 ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #2 (IRR2). + + Reads and returns the current value of IRR2. This function is only available on Itanium processors. + + @return The current value of IRR2. + +**/ +UINT64 +EFIAPI +AsmReadIrr2 ( + VOID + ); + + +/** + Reads the current value of External Interrupt Request Register #3 (IRR3). + + Reads and returns the current value of IRR3. This function is only available on Itanium processors. + + @return The current value of IRR3. + +**/ +UINT64 +EFIAPI +AsmReadIrr3 ( + VOID + ); + + +/** + Reads the current value of Performance Monitor Vector Register (PMV). + + Reads and returns the current value of PMV. This function is only available on Itanium processors. + + @return The current value of PMV. + +**/ +UINT64 +EFIAPI +AsmReadPmv ( + VOID + ); + + +/** + Reads the current value of Corrected Machine Check Vector Register (CMCV). + + Reads and returns the current value of CMCV. This function is only available on Itanium processors. + + @return The current value of CMCV. + +**/ +UINT64 +EFIAPI +AsmReadCmcv ( + VOID + ); + + +/** + Reads the current value of Local Redirection Register #0 (LRR0). + + Reads and returns the current value of LRR0. This function is only available on Itanium processors. + + @return The current value of LRR0. + +**/ +UINT64 +EFIAPI +AsmReadLrr0 ( + VOID + ); + + +/** + Reads the current value of Local Redirection Register #1 (LRR1). + + Reads and returns the current value of LRR1. This function is only available on Itanium processors. + + @return The current value of LRR1. + +**/ +UINT64 +EFIAPI +AsmReadLrr1 ( + VOID + ); + + +/** + Writes the current value of 64-bit Page Local Interrupt ID Register (LID). + + Writes the current value of LID. The 64-bit value written to the LID is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of LID must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to LID. + + @return The 64-bit value written to the LID. + +**/ +UINT64 +EFIAPI +AsmWriteLid ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Task Priority Register (TPR). + + Writes the current value of TPR. The 64-bit value written to the TPR is returned. + No parameter checking is performed on Value. All bits of Value corresponding to + reserved fields of TPR must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to TPR. + + @return The 64-bit value written to the TPR. + +**/ +UINT64 +EFIAPI +AsmWriteTpr ( + IN UINT64 Value + ); + + +/** + Performs a write operation on End OF External Interrupt Register (EOI). + + Writes a value of 0 to the EOI Register. This function is only available on Itanium processors. + +**/ +VOID +EFIAPI +AsmWriteEoi ( + VOID + ); + + +/** + Writes the current value of 64-bit Performance Monitor Vector Register (PMV). + + Writes the current value of PMV. The 64-bit value written to the PMV is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of PMV must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to PMV. + + @return The 64-bit value written to the PMV. + +**/ +UINT64 +EFIAPI +AsmWritePmv ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Corrected Machine Check Vector Register (CMCV). + + Writes the current value of CMCV. The 64-bit value written to the CMCV is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of CMCV must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to CMCV. + + @return The 64-bit value written to the CMCV. + +**/ +UINT64 +EFIAPI +AsmWriteCmcv ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Local Redirection Register #0 (LRR0). + + Writes the current value of LRR0. The 64-bit value written to the LRR0 is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of LRR0 must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to LRR0. + + @return The 64-bit value written to the LRR0. + +**/ +UINT64 +EFIAPI +AsmWriteLrr0 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Local Redirection Register #1 (LRR1). + + Writes the current value of LRR1. The 64-bit value written to the LRR1 is returned. + No parameter checking is performed on Value. All bits of Value corresponding + to reserved fields of LRR1 must be 0 or a Reserved Register/Field fault may occur. + The caller must either guarantee that Value is valid, or the caller must + set up fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to LRR1. + + @return The 64-bit value written to the LRR1. + +**/ +UINT64 +EFIAPI +AsmWriteLrr1 ( + IN UINT64 Value + ); + + +/** + Reads the current value of Instruction Breakpoint Register (IBR). + + The Instruction Breakpoint Registers are used in pairs. The even numbered + registers contain breakpoint addresses, and the odd numbered registers contain + breakpoint mask conditions. At least four instruction registers pairs are implemented + on all processor models. Implemented registers are contiguous starting with + register 0. No parameter checking is performed on Index, and if the Index value + is beyond the implemented IBR register range, a Reserved Register/Field fault may + occur. The caller must either guarantee that Index is valid, or the caller must + set up fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Instruction Breakpoint Register index to read. + + @return The current value of Instruction Breakpoint Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadIbr ( + IN UINT8 Index + ); + + +/** + Reads the current value of Data Breakpoint Register (DBR). + + The Data Breakpoint Registers are used in pairs. The even numbered registers + contain breakpoint addresses, and odd numbered registers contain breakpoint + mask conditions. At least four data registers pairs are implemented on all processor + models. Implemented registers are contiguous starting with register 0. + No parameter checking is performed on Index. If the Index value is beyond + the implemented DBR register range, a Reserved Register/Field fault may occur. + The caller must either guarantee that Index is valid, or the caller must set up + fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Data Breakpoint Register index to read. + + @return The current value of Data Breakpoint Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadDbr ( + IN UINT8 Index + ); + + +/** + Reads the current value of Performance Monitor Configuration Register (PMC). + + All processor implementations provide at least four performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and four performance monitor counter overflow + status registers (PMC [0]... PMC [3]). Processor implementations may provide + additional implementation-dependent PMC and PMD to increase the number of + 'generic' performance counters (PMC/PMD pairs). The remainder of PMC and PMD + register set is implementation dependent. No parameter checking is performed + on Index. If the Index value is beyond the implemented PMC register range, + zero value will be returned. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Configuration Register index to read. + + @return The current value of Performance Monitor Configuration Register + specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT8 Index + ); + + +/** + Reads the current value of Performance Monitor Data Register (PMD). + + All processor implementations provide at least 4 performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and 4 performance monitor counter + overflow status registers (PMC [0]... PMC [3]). Processor implementations may + provide additional implementation-dependent PMC and PMD to increase the number + of 'generic' performance counters (PMC/PMD pairs). The remainder of PMC and PMD + register set is implementation dependent. No parameter checking is performed + on Index. If the Index value is beyond the implemented PMD register range, + zero value will be returned. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Data Register index to read. + + @return The current value of Performance Monitor Data Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmd ( + IN UINT8 Index + ); + + +/** + Writes the current value of 64-bit Instruction Breakpoint Register (IBR). + + Writes current value of Instruction Breakpoint Register specified by Index. + The Instruction Breakpoint Registers are used in pairs. The even numbered + registers contain breakpoint addresses, and odd numbered registers contain + breakpoint mask conditions. At least four instruction registers pairs are implemented + on all processor models. Implemented registers are contiguous starting with + register 0. No parameter checking is performed on Index. If the Index value + is beyond the implemented IBR register range, a Reserved Register/Field fault may + occur. The caller must either guarantee that Index is valid, or the caller must + set up fault handlers to catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Instruction Breakpoint Register index to write. + @param Value The 64-bit value to write to IBR. + + @return The 64-bit value written to the IBR. + +**/ +UINT64 +EFIAPI +AsmWriteIbr ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Data Breakpoint Register (DBR). + + Writes current value of Data Breakpoint Register specified by Index. + The Data Breakpoint Registers are used in pairs. The even numbered registers + contain breakpoint addresses, and odd numbered registers contain breakpoint + mask conditions. At least four data registers pairs are implemented on all processor + models. Implemented registers are contiguous starting with register 0. No parameter + checking is performed on Index. If the Index value is beyond the implemented + DBR register range, a Reserved Register/Field fault may occur. The caller must + either guarantee that Index is valid, or the caller must set up fault handlers to + catch the faults. + This function is only available on Itanium processors. + + @param Index The 8-bit Data Breakpoint Register index to write. + @param Value The 64-bit value to write to DBR. + + @return The 64-bit value written to the DBR. + +**/ +UINT64 +EFIAPI +AsmWriteDbr ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Performance Monitor Configuration Register (PMC). + + Writes current value of Performance Monitor Configuration Register specified by Index. + All processor implementations provide at least four performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and four performance monitor counter overflow status + registers (PMC [0]... PMC [3]). Processor implementations may provide additional + implementation-dependent PMC and PMD to increase the number of 'generic' performance + counters (PMC/PMD pairs). The remainder of PMC and PMD register set is implementation + dependent. No parameter checking is performed on Index. If the Index value is + beyond the implemented PMC register range, the write is ignored. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Configuration Register index to write. + @param Value The 64-bit value to write to PMC. + + @return The 64-bit value written to the PMC. + +**/ +UINT64 +EFIAPI +AsmWritePmc ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit Performance Monitor Data Register (PMD). + + Writes current value of Performance Monitor Data Register specified by Index. + All processor implementations provide at least four performance counters + (PMC/PMD [4]...PMC/PMD [7] pairs), and four performance monitor counter overflow + status registers (PMC [0]... PMC [3]). Processor implementations may provide + additional implementation-dependent PMC and PMD to increase the number of 'generic' + performance counters (PMC/PMD pairs). The remainder of PMC and PMD register set + is implementation dependent. No parameter checking is performed on Index. If the + Index value is beyond the implemented PMD register range, the write is ignored. + This function is only available on Itanium processors. + + @param Index The 8-bit Performance Monitor Data Register index to write. + @param Value The 64-bit value to write to PMD. + + @return The 64-bit value written to the PMD. + +**/ +UINT64 +EFIAPI +AsmWritePmd ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Reads the current value of 64-bit Global Pointer (GP). + + Reads and returns the current value of GP. + This function is only available on Itanium processors. + + @return The current value of GP. + +**/ +UINT64 +EFIAPI +AsmReadGp ( + VOID + ); + + +/** + Write the current value of 64-bit Global Pointer (GP). + + Writes the current value of GP. The 64-bit value written to the GP is returned. + No parameter checking is performed on Value. + This function is only available on Itanium processors. + + @param Value The 64-bit value to write to GP. + + @return The 64-bit value written to the GP. + +**/ +UINT64 +EFIAPI +AsmWriteGp ( + IN UINT64 Value + ); + + +/** + Reads the current value of 64-bit Stack Pointer (SP). + + Reads and returns the current value of SP. + This function is only available on Itanium processors. + + @return The current value of SP. + +**/ +UINT64 +EFIAPI +AsmReadSp ( + VOID + ); + + +/// +/// Valid Index value for AsmReadControlRegister(). +/// +#define IPF_CONTROL_REGISTER_DCR 0 +#define IPF_CONTROL_REGISTER_ITM 1 +#define IPF_CONTROL_REGISTER_IVA 2 +#define IPF_CONTROL_REGISTER_PTA 8 +#define IPF_CONTROL_REGISTER_IPSR 16 +#define IPF_CONTROL_REGISTER_ISR 17 +#define IPF_CONTROL_REGISTER_IIP 19 +#define IPF_CONTROL_REGISTER_IFA 20 +#define IPF_CONTROL_REGISTER_ITIR 21 +#define IPF_CONTROL_REGISTER_IIPA 22 +#define IPF_CONTROL_REGISTER_IFS 23 +#define IPF_CONTROL_REGISTER_IIM 24 +#define IPF_CONTROL_REGISTER_IHA 25 +#define IPF_CONTROL_REGISTER_LID 64 +#define IPF_CONTROL_REGISTER_IVR 65 +#define IPF_CONTROL_REGISTER_TPR 66 +#define IPF_CONTROL_REGISTER_EOI 67 +#define IPF_CONTROL_REGISTER_IRR0 68 +#define IPF_CONTROL_REGISTER_IRR1 69 +#define IPF_CONTROL_REGISTER_IRR2 70 +#define IPF_CONTROL_REGISTER_IRR3 71 +#define IPF_CONTROL_REGISTER_ITV 72 +#define IPF_CONTROL_REGISTER_PMV 73 +#define IPF_CONTROL_REGISTER_CMCV 74 +#define IPF_CONTROL_REGISTER_LRR0 80 +#define IPF_CONTROL_REGISTER_LRR1 81 + +/** + Reads a 64-bit control register. + + Reads and returns the control register specified by Index. The valid Index valued + are defined above in "Related Definitions". + If Index is invalid then 0xFFFFFFFFFFFFFFFF is returned. This function is only + available on Itanium processors. + + @param Index The index of the control register to read. + + @return The control register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadControlRegister ( + IN UINT64 Index + ); + + +/// +/// Valid Index value for AsmReadApplicationRegister(). +/// +#define IPF_APPLICATION_REGISTER_K0 0 +#define IPF_APPLICATION_REGISTER_K1 1 +#define IPF_APPLICATION_REGISTER_K2 2 +#define IPF_APPLICATION_REGISTER_K3 3 +#define IPF_APPLICATION_REGISTER_K4 4 +#define IPF_APPLICATION_REGISTER_K5 5 +#define IPF_APPLICATION_REGISTER_K6 6 +#define IPF_APPLICATION_REGISTER_K7 7 +#define IPF_APPLICATION_REGISTER_RSC 16 +#define IPF_APPLICATION_REGISTER_BSP 17 +#define IPF_APPLICATION_REGISTER_BSPSTORE 18 +#define IPF_APPLICATION_REGISTER_RNAT 19 +#define IPF_APPLICATION_REGISTER_FCR 21 +#define IPF_APPLICATION_REGISTER_EFLAG 24 +#define IPF_APPLICATION_REGISTER_CSD 25 +#define IPF_APPLICATION_REGISTER_SSD 26 +#define IPF_APPLICATION_REGISTER_CFLG 27 +#define IPF_APPLICATION_REGISTER_FSR 28 +#define IPF_APPLICATION_REGISTER_FIR 29 +#define IPF_APPLICATION_REGISTER_FDR 30 +#define IPF_APPLICATION_REGISTER_CCV 32 +#define IPF_APPLICATION_REGISTER_UNAT 36 +#define IPF_APPLICATION_REGISTER_FPSR 40 +#define IPF_APPLICATION_REGISTER_ITC 44 +#define IPF_APPLICATION_REGISTER_PFS 64 +#define IPF_APPLICATION_REGISTER_LC 65 +#define IPF_APPLICATION_REGISTER_EC 66 + +/** + Reads a 64-bit application register. + + Reads and returns the application register specified by Index. The valid Index + valued are defined above in "Related Definitions". + If Index is invalid then 0xFFFFFFFFFFFFFFFF is returned. This function is only + available on Itanium processors. + + @param Index The index of the application register to read. + + @return The application register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadApplicationRegister ( + IN UINT64 Index + ); + + +/** + Reads the current value of a Machine Specific Register (MSR). + + Reads and returns the current value of the Machine Specific Register specified by Index. No + parameter checking is performed on Index, and if the Index value is beyond the implemented MSR + register range, a Reserved Register/Field fault may occur. The caller must either guarantee that + Index is valid, or the caller must set up fault handlers to catch the faults. This function is + only available on Itanium processors. + + @param Index The 8-bit Machine Specific Register index to read. + + @return The current value of the Machine Specific Register specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr ( + IN UINT8 Index + ); + + +/** + Writes the current value of a Machine Specific Register (MSR). + + Writes Value to the Machine Specific Register specified by Index. Value is returned. No + parameter checking is performed on Index, and if the Index value is beyond the implemented MSR + register range, a Reserved Register/Field fault may occur. The caller must either guarantee that + Index is valid, or the caller must set up fault handlers to catch the faults. This function is + only available on Itanium processors. + + @param Index The 8-bit Machine Specific Register index to write. + @param Value The 64-bit value to write to the Machine Specific Register. + + @return The 64-bit value to write to the Machine Specific Register. + +**/ +UINT64 +EFIAPI +AsmWriteMsr ( + IN UINT8 Index, + IN UINT64 Value + ); + + +/** + Determines if the CPU is currently executing in virtual, physical, or mixed mode. + + Determines the current execution mode of the CPU. + If the CPU is in virtual mode(PSR.RT=1, PSR.DT=1, PSR.IT=1), then 1 is returned. + If the CPU is in physical mode(PSR.RT=0, PSR.DT=0, PSR.IT=0), then 0 is returned. + If the CPU is not in physical mode or virtual mode, then it is in mixed mode, + and -1 is returned. + This function is only available on Itanium processors. + + @retval 1 The CPU is in virtual mode. + @retval 0 The CPU is in physical mode. + @retval -1 The CPU is in mixed mode. + +**/ +INT64 +EFIAPI +AsmCpuVirtual ( + VOID + ); + + +/** + Makes a PAL procedure call. + + This is a wrapper function to make a PAL procedure call. Based on the Index + value this API will make static or stacked PAL call. The following table + describes the usage of PAL Procedure Index Assignment. Architected procedures + may be designated as required or optional. If a PAL procedure is specified + as optional, a unique return code of 0xFFFFFFFFFFFFFFFF is returned in the + Status field of the PAL_CALL_RETURN structure. + This indicates that the procedure is not present in this PAL implementation. + It is the caller's responsibility to check for this return code after calling + any optional PAL procedure. + No parameter checking is performed on the 5 input parameters, but there are + some common rules that the caller should follow when making a PAL call. Any + address passed to PAL as buffers for return parameters must be 8-byte aligned. + Unaligned addresses may cause undefined results. For those parameters defined + as reserved or some fields defined as reserved must be zero filled or the invalid + argument return value may be returned or undefined result may occur during the + execution of the procedure. If the PalEntryPoint does not point to a valid + PAL entry point then the system behavior is undefined. This function is only + available on Itanium processors. + + @param PalEntryPoint The PAL procedure calls entry point. + @param Index The PAL procedure Index number. + @param Arg2 The 2nd parameter for PAL procedure calls. + @param Arg3 The 3rd parameter for PAL procedure calls. + @param Arg4 The 4th parameter for PAL procedure calls. + + @return structure returned from the PAL Call procedure, including the status and return value. + +**/ +PAL_CALL_RETURN +EFIAPI +AsmPalCall ( + IN UINT64 PalEntryPoint, + IN UINT64 Index, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); +#endif + +#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64) +/// +/// IA32 and x64 Specific Functions. +/// Byte packed structure for 16-bit Real Mode EFLAGS. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + } Bits; + UINT16 Uint16; +} IA32_FLAGS16; + +/// +/// Byte packed structure for EFLAGS/RFLAGS. +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 CF:1; ///< Carry Flag. + UINT32 Reserved_0:1; ///< Reserved. + UINT32 PF:1; ///< Parity Flag. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AF:1; ///< Auxiliary Carry Flag. + UINT32 Reserved_2:1; ///< Reserved. + UINT32 ZF:1; ///< Zero Flag. + UINT32 SF:1; ///< Sign Flag. + UINT32 TF:1; ///< Trap Flag. + UINT32 IF:1; ///< Interrupt Enable Flag. + UINT32 DF:1; ///< Direction Flag. + UINT32 OF:1; ///< Overflow Flag. + UINT32 IOPL:2; ///< I/O Privilege Level. + UINT32 NT:1; ///< Nested Task. + UINT32 Reserved_3:1; ///< Reserved. + UINT32 RF:1; ///< Resume Flag. + UINT32 VM:1; ///< Virtual 8086 Mode. + UINT32 AC:1; ///< Alignment Check. + UINT32 VIF:1; ///< Virtual Interrupt Flag. + UINT32 VIP:1; ///< Virtual Interrupt Pending. + UINT32 ID:1; ///< ID Flag. + UINT32 Reserved_4:10; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_EFLAGS32; + +/// +/// Byte packed structure for Control Register 0 (CR0). +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 PE:1; ///< Protection Enable. + UINT32 MP:1; ///< Monitor Coprocessor. + UINT32 EM:1; ///< Emulation. + UINT32 TS:1; ///< Task Switched. + UINT32 ET:1; ///< Extension Type. + UINT32 NE:1; ///< Numeric Error. + UINT32 Reserved_0:10; ///< Reserved. + UINT32 WP:1; ///< Write Protect. + UINT32 Reserved_1:1; ///< Reserved. + UINT32 AM:1; ///< Alignment Mask. + UINT32 Reserved_2:10; ///< Reserved. + UINT32 NW:1; ///< Mot Write-through. + UINT32 CD:1; ///< Cache Disable. + UINT32 PG:1; ///< Paging. + } Bits; + UINTN UintN; +} IA32_CR0; + +/// +/// Byte packed structure for Control Register 4 (CR4). +/// 32-bits on IA-32. +/// 64-bits on x64. The upper 32-bits on x64 are reserved. +/// +typedef union { + struct { + UINT32 VME:1; ///< Virtual-8086 Mode Extensions. + UINT32 PVI:1; ///< Protected-Mode Virtual Interrupts. + UINT32 TSD:1; ///< Time Stamp Disable. + UINT32 DE:1; ///< Debugging Extensions. + UINT32 PSE:1; ///< Page Size Extensions. + UINT32 PAE:1; ///< Physical Address Extension. + UINT32 MCE:1; ///< Machine Check Enable. + UINT32 PGE:1; ///< Page Global Enable. + UINT32 PCE:1; ///< Performance Monitoring Counter + ///< Enable. + UINT32 OSFXSR:1; ///< Operating System Support for + ///< FXSAVE and FXRSTOR instructions + UINT32 OSXMMEXCPT:1; ///< Operating System Support for + ///< Unmasked SIMD Floating Point + ///< Exceptions. + UINT32 Reserved_0:2; ///< Reserved. + UINT32 VMXE:1; ///< VMX Enable + UINT32 Reserved_1:18; ///< Reserved. + } Bits; + UINTN UintN; +} IA32_CR4; + +/// +/// Byte packed structure for a segment descriptor in a GDT/LDT. +/// +typedef union { + struct { + UINT32 LimitLow:16; + UINT32 BaseLow:16; + UINT32 BaseMid:8; + UINT32 Type:4; + UINT32 S:1; + UINT32 DPL:2; + UINT32 P:1; + UINT32 LimitHigh:4; + UINT32 AVL:1; + UINT32 L:1; + UINT32 DB:1; + UINT32 G:1; + UINT32 BaseHigh:8; + } Bits; + UINT64 Uint64; +} IA32_SEGMENT_DESCRIPTOR; + +/// +/// Byte packed structure for an IDTR, GDTR, LDTR descriptor. +/// +#pragma pack (1) +typedef struct { + UINT16 Limit; + UINTN Base; +} IA32_DESCRIPTOR; +#pragma pack () + +#define IA32_IDT_GATE_TYPE_TASK 0x85 +#define IA32_IDT_GATE_TYPE_INTERRUPT_16 0x86 +#define IA32_IDT_GATE_TYPE_TRAP_16 0x87 +#define IA32_IDT_GATE_TYPE_INTERRUPT_32 0x8E +#define IA32_IDT_GATE_TYPE_TRAP_32 0x8F + + +#if defined (MDE_CPU_IA32) +/// +/// Byte packed structure for an IA-32 Interrupt Gate Descriptor. +/// +typedef union { + struct { + UINT32 OffsetLow:16; ///< Offset bits 15..0. + UINT32 Selector:16; ///< Selector. + UINT32 Reserved_0:8; ///< Reserved. + UINT32 GateType:8; ///< Gate Type. See #defines above. + UINT32 OffsetHigh:16; ///< Offset bits 31..16. + } Bits; + UINT64 Uint64; +} IA32_IDT_GATE_DESCRIPTOR; + +#endif + +#if defined (MDE_CPU_X64) +/// +/// Byte packed structure for an x64 Interrupt Gate Descriptor. +/// +typedef union { + struct { + UINT32 OffsetLow:16; ///< Offset bits 15..0. + UINT32 Selector:16; ///< Selector. + UINT32 Reserved_0:8; ///< Reserved. + UINT32 GateType:8; ///< Gate Type. See #defines above. + UINT32 OffsetHigh:16; ///< Offset bits 31..16. + UINT32 OffsetUpper:32; ///< Offset bits 63..32. + UINT32 Reserved_1:32; ///< Reserved. + } Bits; + struct { + UINT64 Uint64; + UINT64 Uint64_1; + } Uint128; +} IA32_IDT_GATE_DESCRIPTOR; + +#endif + +/// +/// Byte packed structure for an FP/SSE/SSE2 context. +/// +typedef struct { + UINT8 Buffer[512]; +} IA32_FX_BUFFER; + +/// +/// Structures for the 16-bit real mode thunks. +/// +typedef struct { + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT8 BL; + UINT8 BH; + UINT16 Reserved5; + UINT8 DL; + UINT8 DH; + UINT16 Reserved6; + UINT8 CL; + UINT8 CH; + UINT16 Reserved7; + UINT8 AL; + UINT8 AH; + UINT16 Reserved8; +} IA32_BYTE_REGS; + +typedef struct { + UINT16 DI; + UINT16 Reserved1; + UINT16 SI; + UINT16 Reserved2; + UINT16 BP; + UINT16 Reserved3; + UINT16 SP; + UINT16 Reserved4; + UINT16 BX; + UINT16 Reserved5; + UINT16 DX; + UINT16 Reserved6; + UINT16 CX; + UINT16 Reserved7; + UINT16 AX; + UINT16 Reserved8; +} IA32_WORD_REGS; + +typedef struct { + UINT32 EDI; + UINT32 ESI; + UINT32 EBP; + UINT32 ESP; + UINT32 EBX; + UINT32 EDX; + UINT32 ECX; + UINT32 EAX; + UINT16 DS; + UINT16 ES; + UINT16 FS; + UINT16 GS; + IA32_EFLAGS32 EFLAGS; + UINT32 Eip; + UINT16 CS; + UINT16 SS; +} IA32_DWORD_REGS; + +typedef union { + IA32_DWORD_REGS E; + IA32_WORD_REGS X; + IA32_BYTE_REGS H; +} IA32_REGISTER_SET; + +/// +/// Byte packed structure for an 16-bit real mode thunks. +/// +typedef struct { + IA32_REGISTER_SET *RealModeState; + VOID *RealModeBuffer; + UINT32 RealModeBufferSize; + UINT32 ThunkAttributes; +} THUNK_CONTEXT; + +#define THUNK_ATTRIBUTE_BIG_REAL_MODE 0x00000001 +#define THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 0x00000002 +#define THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL 0x00000004 + +/** + Retrieves CPUID information. + + Executes the CPUID instruction with EAX set to the value specified by Index. + This function always returns Index. + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + This function is only available on IA-32 and x64. + + @param Index The 32-bit value to load into EAX prior to invoking the CPUID + instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuid ( + IN UINT32 Index, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ); + + +/** + Retrieves CPUID information using an extended leaf identifier. + + Executes the CPUID instruction with EAX set to the value specified by Index + and ECX set to the value specified by SubIndex. This function always returns + Index. This function is only available on IA-32 and x64. + + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + + @param Index The 32-bit value to load into EAX prior to invoking the + CPUID instruction. + @param SubIndex The 32-bit value to load into ECX prior to invoking the + CPUID instruction. + @param Eax The pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ebx The pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Ecx The pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + @param Edx The pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be + NULL. + + @return Index. + +**/ +UINT32 +EFIAPI +AsmCpuidEx ( + IN UINT32 Index, + IN UINT32 SubIndex, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ); + + +/** + Set CD bit and clear NW bit of CR0 followed by a WBINVD. + + Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0, + and executing a WBINVD instruction. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmDisableCache ( + VOID + ); + + +/** + Perform a WBINVD and clear both the CD and NW bits of CR0. + + Enables the caches by executing a WBINVD instruction and then clear both the CD and NW + bits of CR0 to 0. This function is only available on IA-32 and x64. + +**/ +VOID +EFIAPI +AsmEnableCache ( + VOID + ); + + +/** + Returns the lower 32-bits of a Machine Specific Register(MSR). + + Reads and returns the lower 32-bits of the MSR specified by Index. + No parameter checking is performed on Index, and some Index values may cause + CPU exceptions. The caller must either guarantee that Index is valid, or the + caller must set up exception handlers to catch the exceptions. This function + is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The lower 32 bits of the MSR identified by Index. + +**/ +UINT32 +EFIAPI +AsmReadMsr32 ( + IN UINT32 Index + ); + + +/** + Writes a 32-bit value to a Machine Specific Register(MSR), and returns the value. + The upper 32-bits of the MSR are set to zero. + + Writes the 32-bit value specified by Value to the MSR specified by Index. The + upper 32-bits of the MSR write are set to zero. The 32-bit value written to + the MSR is returned. No parameter checking is performed on Index or Value, + and some of these may cause CPU exceptions. The caller must either guarantee + that Index and Value are valid, or the caller must establish proper exception + handlers. This function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 32-bit value to write to the MSR. + + @return Value + +**/ +UINT32 +EFIAPI +AsmWriteMsr32 ( + IN UINT32 Index, + IN UINT32 Value + ); + + +/** + Reads a 64-bit MSR, performs a bitwise OR on the lower 32-bits, and + writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the lower 32-bits of the read result and the value specified by + OrData, and writes the result to the 64-bit MSR specified by Index. The lower + 32-bits of the value written to the MSR is returned. No parameter checking is + performed on Index or OrData, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and OrData are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrOr32 ( + IN UINT32 Index, + IN UINT32 OrData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND on the lower 32-bits, and writes + the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData, and + writes the result to the 64-bit MSR specified by Index. The lower 32-bits of + the value written to the MSR is returned. No parameter checking is performed + on Index or AndData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index and AndData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAnd32 ( + IN UINT32 Index, + IN UINT32 AndData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise OR + on the lower 32-bits, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData + preserving the upper 32-bits, performs a bitwise OR between the + result of the AND operation and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Address. The lower 32-bits of the value + written to the MSR is returned. No parameter checking is performed on Index, + AndData, or OrData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index, AndData, and OrData are valid, or the + caller must establish proper exception handlers. This function is only + available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAndThenOr32 ( + IN UINT32 Index, + IN UINT32 AndData, + IN UINT32 OrData + ); + + +/** + Reads a bit field of an MSR. + + Reads the bit field in the lower 32-bits of a 64-bit MSR. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. The caller must either guarantee that Index is valid, or the caller + must set up exception handlers to catch the exceptions. This function is only + available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read from the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldRead32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in the lower 32-bits of a 64-bit MSR. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination MSR are preserved. The lower 32-bits of the MSR written is + returned. The caller must either guarantee that Index and the data written + is valid, or the caller must set up exception handlers to catch the exceptions. + This function is only available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldWrite32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The lower 32-bits of the value + written to the MSR are returned. Extra left bits in OrData are stripped. The + caller must either guarantee that Index and the data written is valid, or + the caller must set up exception handlers to catch the exceptions. This + function is only available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The lower 32-bits of the value written to the + MSR are returned. Extra left bits in AndData are stripped. The caller must + either guarantee that Index and the data written is valid, or the caller must + set up exception handlers to catch the exceptions. This function is only + available on IA-32 and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAnd32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by a + bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + lower 32-bits of the value written to the MSR are returned. Extra left bits + in both AndData and OrData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and x64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAndThenOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ); + + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ); + + +/** + Reads a 64-bit MSR, performs a bitwise OR, and writes the result + back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. No parameter checking is performed on Index or OrData, and some of + these may cause CPU exceptions. The caller must either guarantee that Index + and OrData are valid, or the caller must establish proper exception handlers. + This function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrOr64 ( + IN UINT32 Index, + IN UINT64 OrData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND, and writes the result back to the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by OrData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. No + parameter checking is performed on Index or OrData, and some of these may + cause CPU exceptions. The caller must either guarantee that Index and OrData + are valid, or the caller must establish proper exception handlers. This + function is only available on IA-32 and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAnd64 ( + IN UINT32 Index, + IN UINT64 AndData + ); + + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise + OR, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between read + result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit MSR specified by Index. The value written + to the MSR is returned. No parameter checking is performed on Index, AndData, + or OrData, and some of these may cause CPU exceptions. The caller must either + guarantee that Index, AndData, and OrData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and x64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAndThenOr64 ( + IN UINT32 Index, + IN UINT64 AndData, + IN UINT64 OrData + ); + + +/** + Reads a bit field of an MSR. + + Reads the bit field in the 64-bit MSR. The bit field is specified by the + StartBit and the EndBit. The value of the bit field is returned. The caller + must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read from the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldRead64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ); + + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in a 64-bit MSR. The bit field is specified by + the StartBit and the EndBit. All other bits in the destination MSR are + preserved. The MSR written is returned. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldWrite64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. Extra left bits in OrData are stripped. The caller must either + guarantee that Index and the data written is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. + Extra left bits in AndData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAnd64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by + a bitwise OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + value written to the MSR is returned. Extra left bits in both AndData and + OrData are stripped. The caller must either guarantee that Index and the data + written is valid, or the caller must set up exception handlers to catch the + exceptions. This function is only available on IA-32 and x64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAndThenOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and x64. This returns a 32-bit value on IA-32 and a + 64-bit value on x64. + + @return EFLAGS on IA-32 or RFLAGS on x64. + +**/ +UINTN +EFIAPI +AsmReadEflags ( + VOID + ); + + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ); + + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ); + + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ); + + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ); + + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ); + + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ); + + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ); + + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ); + + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ); + + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ); + + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ); + + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ); + + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ); + + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ); + + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ); + + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on + x64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ); + + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ); + + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ); + + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ); + + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ); + + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ); + + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ); + + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ); + + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ); + + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and x64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ); + + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and x64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ); + + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and x64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ); + + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and x64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ); + + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and x64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ); + + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and x64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ); + + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and x64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ); + + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ); + + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and x64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr The pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ); + + +/** + Reads the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ); + + +/** + Writes the current Interrupt Descriptor Table Register(IDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and x64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr The pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ); + + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and x64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ); + + +/** + Writes the current Local Descriptor Table Register (LDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and x64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ); + + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and x64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxSave ( + OUT IA32_FX_BUFFER *Buffer + ); + + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and x64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + If Buffer was not saved with AsmFxSave(), then ASSERT(). + + @param Buffer The pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ); + + +/** + Reads the current value of 64-bit MMX Register #0 (MM0). + + Reads and returns the current value of MM0. This function is only available + on IA-32 and x64. + + @return The current value of MM0. + +**/ +UINT64 +EFIAPI +AsmReadMm0 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #1 (MM1). + + Reads and returns the current value of MM1. This function is only available + on IA-32 and x64. + + @return The current value of MM1. + +**/ +UINT64 +EFIAPI +AsmReadMm1 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #2 (MM2). + + Reads and returns the current value of MM2. This function is only available + on IA-32 and x64. + + @return The current value of MM2. + +**/ +UINT64 +EFIAPI +AsmReadMm2 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #3 (MM3). + + Reads and returns the current value of MM3. This function is only available + on IA-32 and x64. + + @return The current value of MM3. + +**/ +UINT64 +EFIAPI +AsmReadMm3 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #4 (MM4). + + Reads and returns the current value of MM4. This function is only available + on IA-32 and x64. + + @return The current value of MM4. + +**/ +UINT64 +EFIAPI +AsmReadMm4 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #5 (MM5). + + Reads and returns the current value of MM5. This function is only available + on IA-32 and x64. + + @return The current value of MM5. + +**/ +UINT64 +EFIAPI +AsmReadMm5 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #6 (MM6). + + Reads and returns the current value of MM6. This function is only available + on IA-32 and x64. + + @return The current value of MM6. + +**/ +UINT64 +EFIAPI +AsmReadMm6 ( + VOID + ); + + +/** + Reads the current value of 64-bit MMX Register #7 (MM7). + + Reads and returns the current value of MM7. This function is only available + on IA-32 and x64. + + @return The current value of MM7. + +**/ +UINT64 +EFIAPI +AsmReadMm7 ( + VOID + ); + + +/** + Writes the current value of 64-bit MMX Register #0 (MM0). + + Writes the current value of MM0. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM0. + +**/ +VOID +EFIAPI +AsmWriteMm0 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #1 (MM1). + + Writes the current value of MM1. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM1. + +**/ +VOID +EFIAPI +AsmWriteMm1 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #2 (MM2). + + Writes the current value of MM2. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM2. + +**/ +VOID +EFIAPI +AsmWriteMm2 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #3 (MM3). + + Writes the current value of MM3. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM3. + +**/ +VOID +EFIAPI +AsmWriteMm3 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #4 (MM4). + + Writes the current value of MM4. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM4. + +**/ +VOID +EFIAPI +AsmWriteMm4 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #5 (MM5). + + Writes the current value of MM5. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM5. + +**/ +VOID +EFIAPI +AsmWriteMm5 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #6 (MM6). + + Writes the current value of MM6. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM6. + +**/ +VOID +EFIAPI +AsmWriteMm6 ( + IN UINT64 Value + ); + + +/** + Writes the current value of 64-bit MMX Register #7 (MM7). + + Writes the current value of MM7. This function is only available on IA32 and + x64. + + @param Value The 64-bit value to write to MM7. + +**/ +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ); + + +/** + Reads the current value of Time Stamp Counter (TSC). + + Reads and returns the current value of TSC. This function is only available + on IA-32 and x64. + + @return The current value of TSC + +**/ +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ); + + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and x64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ); + + +/** + Sets up a monitor buffer that is used by AsmMwait(). + + Executes a MONITOR instruction with the register state specified by Eax, Ecx + and Edx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + @param Edx The value to load into EDX or RDX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMonitor ( + IN UINTN Eax, + IN UINTN Ecx, + IN UINTN Edx + ); + + +/** + Executes an MWAIT instruction. + + Executes an MWAIT instruction with the register state specified by Eax and + Ecx. Returns Eax. This function is only available on IA-32 and x64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMwait ( + IN UINTN Eax, + IN UINTN Ecx + ); + + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ); + + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + x64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ); + + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and x64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress. +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ); + + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + If the current execution mode is not 32-bit paged mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode with flat + descriptors, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ); + + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on x64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ); + + +// +// 16-bit thunking services +// + +/** + Retrieves the properties for 16-bit thunk functions. + + Computes the size of the buffer and stack below 1MB required to use the + AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This + buffer size is returned in RealModeBufferSize, and the stack size is returned + in ExtraStackSize. If parameters are passed to the 16-bit real mode code, + then the actual minimum stack size is ExtraStackSize plus the maximum number + of bytes that need to be passed to the 16-bit real mode code. + + If RealModeBufferSize is NULL, then ASSERT(). + If ExtraStackSize is NULL, then ASSERT(). + + @param RealModeBufferSize A pointer to the size of the buffer below 1MB + required to use the 16-bit thunk functions. + @param ExtraStackSize A pointer to the extra size of stack below 1MB + that the 16-bit thunk functions require for + temporary storage in the transition to and from + 16-bit real mode. + +**/ +VOID +EFIAPI +AsmGetThunk16Properties ( + OUT UINT32 *RealModeBufferSize, + OUT UINT32 *ExtraStackSize + ); + + +/** + Prepares all structures a code required to use AsmThunk16(). + + Prepares all structures and code required to use AsmThunk16(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + + +/** + Transfers control to a 16-bit real mode entry point and returns the results. + + Transfers control to a 16-bit real mode entry point and returns the results. + AsmPrepareThunk16() must be called with ThunkContext before this function is used. + This function must be called with interrupts disabled. + + The register state from the RealModeState field of ThunkContext is restored just prior + to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState, + which is used to set the interrupt state when a 16-bit real mode entry point is called. + Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState. + The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to + the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function. + The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction, + so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment + and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry + point must exit with a RETF instruction. The register state is captured into RealModeState immediately + after the RETF instruction is executed. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure + the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode. + + If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts, + then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode. + This includes the base vectors, the interrupt masks, and the edge/level trigger mode. + + If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code + is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits. + + If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to + disable the A20 mask. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in + ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails, + then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in + ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports. + + If ThunkContext is NULL, then ASSERT(). + If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT(). + If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in + ThunkAttributes, then ASSERT(). + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer are mapped 1:1. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + + +/** + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. + + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. If the + caller only need to perform a single 16-bit real mode thunk, then this + service should be used. If the caller intends to make more than one 16-bit + real mode thunk, then it is more efficient if AsmPrepareThunk16() is called + once and AsmThunk16() can be called for each 16-bit real mode thunk. + + This interface is limited to be used in either physical mode or virtual modes with paging enabled where the + virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1. + + See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions. + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareAndThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + +#endif +#endif + + diff --git a/src/include/ipxe/efi/Pi/PiDxeCis.h b/src/include/ipxe/efi/Pi/PiDxeCis.h index 6c4f44b9..e007cab8 100644 --- a/src/include/ipxe/efi/Pi/PiDxeCis.h +++ b/src/include/ipxe/efi/Pi/PiDxeCis.h @@ -1,7 +1,7 @@ /** @file Include file matches things in PI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -11,7 +11,7 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. @par Revision Reference: - PI Version 1.0 + PI Version 1.2 **/ @@ -371,7 +371,8 @@ EFI_STATUS BaseAddress and Length cannot be modified. @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of the memory resource range. - + @retval EFI_NOT_AVAILABLE_YET The attributes cannot be set because CPU architectural protocol is + not available yet. **/ typedef EFI_STATUS @@ -656,8 +657,10 @@ EFI_STATUS // // DXE Services Table // -#define DXE_SERVICES_SIGNATURE 0x565245535f455844ULL -#define DXE_SERVICES_REVISION ((1<<16) | (00)) +#define DXE_SERVICES_SIGNATURE 0x565245535f455844ULL +#define DXE_SPECIFICATION_MAJOR_REVISION 1 +#define DXE_SPECIFICATION_MINOR_REVISION 20 +#define DXE_SERVICES_REVISION ((DXE_SPECIFICATION_MAJOR_REVISION<<16) | (DXE_SPECIFICATION_MINOR_REVISION)) typedef struct { /// diff --git a/src/include/ipxe/efi/Pi/PiFirmwareFile.h b/src/include/ipxe/efi/Pi/PiFirmwareFile.h index 6909018b..f6cf9574 100644 --- a/src/include/ipxe/efi/Pi/PiFirmwareFile.h +++ b/src/include/ipxe/efi/Pi/PiFirmwareFile.h @@ -1,7 +1,7 @@ /** @file The firmware file related definitions in PI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -36,8 +36,7 @@ typedef union { /// /// If the FFS_ATTRIB_CHECKSUM (see definition below) bit of the Attributes /// field is set to one, the IntegrityCheck.Checksum.File field is an 8-bit - /// checksum of the entire file The State field and the file tail are assumed to be zero - /// and the checksum is calculated such that the entire file sums to zero. + /// checksum of the file data. /// If the FFS_ATTRIB_CHECKSUM bit of the Attributes field is cleared to zero, /// the IntegrityCheck.Checksum.File field must be initialized with a value of /// 0xAA. The IntegrityCheck.Checksum.File field is valid any time the @@ -176,9 +175,18 @@ typedef struct { /// If FFS_ATTRIB_LARGE_FILE is set in Attributes, then ExtendedSize exists and Size must be set to zero. /// If FFS_ATTRIB_LARGE_FILE is not set then EFI_FFS_FILE_HEADER is used. /// - EFI_FFS_FILE_STATE ExtendedSize; + UINT32 ExtendedSize; } EFI_FFS_FILE_HEADER2; +#define IS_FFS_FILE2(FfsFileHeaderPtr) \ + (((((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Attributes) & FFS_ATTRIB_LARGE_FILE) == FFS_ATTRIB_LARGE_FILE) + +#define FFS_FILE_SIZE(FfsFileHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_FFS_FILE_HEADER *) (UINTN) FfsFileHeaderPtr)->Size) & 0x00ffffff)) + +#define FFS_FILE2_SIZE(FfsFileHeaderPtr) \ + (((EFI_FFS_FILE_HEADER2 *) (UINTN) FfsFileHeaderPtr)->ExtendedSize) + typedef UINT8 EFI_SECTION_TYPE; /// @@ -473,8 +481,14 @@ typedef struct { CHAR16 VersionString[1]; } EFI_VERSION_SECTION2; +#define IS_SECTION2(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff) == 0x00ffffff) + #define SECTION_SIZE(SectionHeaderPtr) \ - ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff)) + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) (UINTN) SectionHeaderPtr)->Size) & 0x00ffffff)) + +#define SECTION2_SIZE(SectionHeaderPtr) \ + (((EFI_COMMON_SECTION_HEADER2 *) (UINTN) SectionHeaderPtr)->ExtendedSize) #pragma pack() diff --git a/src/include/ipxe/efi/Pi/PiFirmwareVolume.h b/src/include/ipxe/efi/Pi/PiFirmwareVolume.h index 813fab22..4863e146 100644 --- a/src/include/ipxe/efi/Pi/PiFirmwareVolume.h +++ b/src/include/ipxe/efi/Pi/PiFirmwareVolume.h @@ -11,7 +11,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. @par Revision Reference: - PI Version 1.2B + PI Version 1.2C **/ @@ -75,7 +75,7 @@ typedef UINT32 EFI_FVB_ATTRIBUTES_2; #define EFI_FVB2_ALIGNMENT_64K 0x00100000 #define EFI_FVB2_ALIGNMENT_128K 0x00110000 #define EFI_FVB2_ALIGNMENT_256K 0x00120000 -#define EFI_FVB2_ALIGNMNET_512K 0x00130000 +#define EFI_FVB2_ALIGNMENT_512K 0x00130000 #define EFI_FVB2_ALIGNMENT_1M 0x00140000 #define EFI_FVB2_ALIGNMENT_2M 0x00150000 #define EFI_FVB2_ALIGNMENT_4M 0x00160000 @@ -207,13 +207,15 @@ typedef struct { /// /// An array of GUIDs, each GUID representing an OEM file type. /// - EFI_GUID Types[1]; + /// EFI_GUID Types[1]; + /// } EFI_FIRMWARE_VOLUME_EXT_ENTRY_OEM_TYPE; #define EFI_FV_EXT_TYPE_GUID_TYPE 0x0002 /// -/// This extension header provides a mapping between a GUID and an OEM file type. +/// This extension header EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE provides a vendor specific +/// GUID FormatType type which includes a length and a successive series of data bytes. /// typedef struct { /// @@ -227,7 +229,8 @@ typedef struct { /// /// An arry of bytes of length Length. /// - UINT8 Data[1]; + /// UINT8 Data[1]; + /// } EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE; #endif diff --git a/src/include/ipxe/efi/Pi/PiHob.h b/src/include/ipxe/efi/Pi/PiHob.h index cd196cb3..c68ea300 100644 --- a/src/include/ipxe/efi/Pi/PiHob.h +++ b/src/include/ipxe/efi/Pi/PiHob.h @@ -1,7 +1,7 @@ /** @file HOB related definitions in PI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -251,21 +251,21 @@ typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; // // These types can be ORed together as needed. // -// The first three enumerations describe settings +// The following attributes are used to describe settings // -#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 -#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 -#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 +#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 +#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 // -// The rest of the settings describe capabilities +// The rest of the attributes are used to describe capabilities // #define EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008 #define EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010 #define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020 #define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040 -#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 -#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 -#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 #define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400 #define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800 #define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000 @@ -274,6 +274,9 @@ typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; #define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000 #define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000 #define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE 0x00100000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE 0x00200000 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE 0x00400000 /// /// Describes the resource properties of all fixed, diff --git a/src/include/ipxe/efi/Pi/PiStatusCode.h b/src/include/ipxe/efi/Pi/PiStatusCode.h index 6133f00c..4c720529 100644 --- a/src/include/ipxe/efi/Pi/PiStatusCode.h +++ b/src/include/ipxe/efi/Pi/PiStatusCode.h @@ -22,7 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. FILE_LICENCE ( BSD3 ); // -// Required for IA32 and IPF defines for CPU exception types +// Required for IA32, X64, IPF, ARM and EBC defines for CPU exception types // #include @@ -713,6 +713,9 @@ typedef struct { #define EFI_SOFTWARE_EFI_BOOT_SERVICE (EFI_SOFTWARE | 0x00100000) #define EFI_SOFTWARE_EFI_RUNTIME_SERVICE (EFI_SOFTWARE | 0x00110000) #define EFI_SOFTWARE_EFI_DXE_SERVICE (EFI_SOFTWARE | 0x00120000) +#define EFI_SOFTWARE_X64_EXCEPTION (EFI_SOFTWARE | 0x00130000) +#define EFI_SOFTWARE_ARM_EXCEPTION (EFI_SOFTWARE | 0x00140000) + ///@} /// @@ -753,7 +756,6 @@ typedef struct { /// /// Software Class PEI Module Subclass Progress Code definitions. -/// Note: EFI_SW_PEI_PC_RECOVERY_BEGIN is different from PI 1.2 Specification. /// ///@{ #define EFI_SW_PEI_PC_RECOVERY_BEGIN (EFI_SUBCLASS_SPECIFIC | 0x00000000) @@ -808,6 +810,14 @@ typedef struct { #define EFI_SW_RT_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) ///@} +// +// Software Class X64 Exception Subclass Progress Code definitions. +// + +// +// Software Class ARM Exception Subclass Progress Code definitions. +// + // // Software Class EBC Exception Subclass Progress Code definitions. // @@ -987,7 +997,6 @@ typedef struct { /// /// Software Class PEI Module Subclass Error Code definitions. -/// Note: EFI_SW_PEI_EC_INVALID_CAPSULE_DESCRIPTOR is different from PI 1.2 Specification. /// ///@{ #define EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE (EFI_SUBCLASS_SPECIFIC | 0x00000000) @@ -1123,8 +1132,65 @@ typedef struct { // Software Class EFI Runtime Service Subclass Error Code definitions. // -// -// Software Class EFI DXE Service Subclass Error Code definitions. -// +/// +/// Software Class EFI DXE Service Subclass Error Code definitions. +/// +///@{ +#define EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_DXE_BS_PC_VERIFYING_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000006) +///@} + +/// +/// Software Class DXE RT Driver Subclass Progress Code definitions. +/// +///@{ +#define EFI_SW_DXE_RT_PC_S0 (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_RT_PC_S1 (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_RT_PC_S2 (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_RT_PC_S3 (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_RT_PC_S4 (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DXE_RT_PC_S5 (EFI_SUBCLASS_SPECIFIC | 0x00000005) +///@} + +/// +/// Software Class X64 Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol +/// definitions in the EFI specification. +/// +///@{ +#define EFI_SW_EC_X64_DIVIDE_ERROR EXCEPT_X64_DIVIDE_ERROR +#define EFI_SW_EC_X64_DEBUG EXCEPT_X64_DEBUG +#define EFI_SW_EC_X64_NMI EXCEPT_X64_NMI +#define EFI_SW_EC_X64_BREAKPOINT EXCEPT_X64_BREAKPOINT +#define EFI_SW_EC_X64_OVERFLOW EXCEPT_X64_OVERFLOW +#define EFI_SW_EC_X64_BOUND EXCEPT_X64_BOUND +#define EFI_SW_EC_X64_INVALID_OPCODE EXCEPT_X64_INVALID_OPCODE +#define EFI_SW_EC_X64_DOUBLE_FAULT EXCEPT_X64_DOUBLE_FAULT +#define EFI_SW_EC_X64_INVALID_TSS EXCEPT_X64_INVALID_TSS +#define EFI_SW_EC_X64_SEG_NOT_PRESENT EXCEPT_X64_SEG_NOT_PRESENT +#define EFI_SW_EC_X64_STACK_FAULT EXCEPT_X64_STACK_FAULT +#define EFI_SW_EC_X64_GP_FAULT EXCEPT_X64_GP_FAULT +#define EFI_SW_EC_X64_PAGE_FAULT EXCEPT_X64_PAGE_FAULT +#define EFI_SW_EC_X64_FP_ERROR EXCEPT_X64_FP_ERROR +#define EFI_SW_EC_X64_ALIGNMENT_CHECK EXCEPT_X64_ALIGNMENT_CHECK +#define EFI_SW_EC_X64_MACHINE_CHECK EXCEPT_X64_MACHINE_CHECK +#define EFI_SW_EC_X64_SIMD EXCEPT_X64_SIMD +///@} + +/// +/// Software Class ARM Exception Subclass Error Code definitions. +/// These exceptions are derived from the debug protocol +/// definitions in the EFI specification. +/// +///@{ +#define EFI_SW_EC_ARM_RESET EXCEPT_ARM_RESET +#define EFI_SW_EC_ARM_UNDEFINED_INSTRUCTION EXCEPT_ARM_UNDEFINED_INSTRUCTION +#define EFI_SW_EC_ARM_SOFTWARE_INTERRUPT EXCEPT_ARM_SOFTWARE_INTERRUPT +#define EFI_SW_EC_ARM_PREFETCH_ABORT EXCEPT_ARM_PREFETCH_ABORT +#define EFI_SW_EC_ARM_DATA_ABORT EXCEPT_ARM_DATA_ABORT +#define EFI_SW_EC_ARM_RESERVED EXCEPT_ARM_RESERVED +#define EFI_SW_EC_ARM_IRQ EXCEPT_ARM_IRQ +#define EFI_SW_EC_ARM_FIQ EXCEPT_ARM_FIQ +///@} #endif diff --git a/src/include/ipxe/efi/Protocol/ComponentName2.h b/src/include/ipxe/efi/Protocol/ComponentName2.h index 978ede5a..82d8b256 100644 --- a/src/include/ipxe/efi/Protocol/ComponentName2.h +++ b/src/include/ipxe/efi/Protocol/ComponentName2.h @@ -3,7 +3,7 @@ This protocol is used to retrieve user readable names of drivers and controllers managed by UEFI Drivers. - Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -121,8 +121,7 @@ EFI_STATUS driver specified by This was returned in DriverName. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid - EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. diff --git a/src/include/ipxe/efi/Protocol/Cpu.h b/src/include/ipxe/efi/Protocol/Cpu.h index ebcaf5f1..665924e8 100644 --- a/src/include/ipxe/efi/Protocol/Cpu.h +++ b/src/include/ipxe/efi/Protocol/Cpu.h @@ -3,7 +3,7 @@ This code abstracts the DXE core from processor implementation details. - Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -246,6 +246,8 @@ EFI_STATUS @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by BaseAddress and Length cannot be modified. @retval EFI_INVALID_PARAMETER Length is zero. + Attributes specified an illegal combination of attributes that + cannot be set together. @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of the memory resource range. @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory diff --git a/src/include/ipxe/efi/Protocol/DevicePath.h b/src/include/ipxe/efi/Protocol/DevicePath.h index 5c678708..cc4c927d 100644 --- a/src/include/ipxe/efi/Protocol/DevicePath.h +++ b/src/include/ipxe/efi/Protocol/DevicePath.h @@ -5,7 +5,7 @@ from a software point of view. The path must persist from boot to boot, so it can not contain things like PCI bus numbers that change from boot to boot. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -348,6 +348,26 @@ typedef struct { UINT64 Lun; } FIBRECHANNEL_DEVICE_PATH; +/// +/// Fibre Channel Ex SubType. +/// +#define MSG_FIBRECHANNELEX_DP 0x15 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 8 byte array containing Fibre Channel End Device Port Name. + /// + UINT8 WWN[8]; + /// + /// 8 byte array containing Fibre Channel Logical Unit Number. + /// + UINT8 Lun[8]; +} FIBRECHANNELEX_DEVICE_PATH; + /// /// 1394 Device Path SubType /// @@ -543,6 +563,14 @@ typedef struct { /// 0x01 - The Source IP Address is statically bound. /// BOOLEAN StaticIpAddress; + /// + /// The gateway IP address + /// + EFI_IPv4_ADDRESS GatewayIpAddress; + /// + /// The subnet mask + /// + EFI_IPv4_ADDRESS SubnetMask; } IPv4_DEVICE_PATH; /// @@ -572,10 +600,21 @@ typedef struct { /// UINT16 Protocol; /// - /// 0x00 - The Source IP Address was assigned though DHCP. - /// 0x01 - The Source IP Address is statically bound. + /// 0x00 - The Local IP Address was manually configured. + /// 0x01 - The Local IP Address is assigned through IPv6 + /// stateless auto-configuration. + /// 0x02 - The Local IP Address is assigned through IPv6 + /// stateful configuration. /// - BOOLEAN StaticIpAddress; + UINT8 IpAddressOrigin; + /// + /// The prefix length + /// + UINT8 PrefixLength; + /// + /// The gateway IP address + /// + EFI_IPv6_ADDRESS GatewayIpAddress; } IPv6_DEVICE_PATH; /// @@ -692,9 +731,9 @@ typedef struct { #define UART_FLOW_CONTROL_HARDWARE 0x00000001 #define UART_FLOW_CONTROL_XON_XOFF 0x00000010 -#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID /// -/// Serial Attached SCSI (SAS) devices. +/// Serial Attached SCSI (SAS) Device Path. /// typedef struct { EFI_DEVICE_PATH_PROTOCOL Header; @@ -724,6 +763,30 @@ typedef struct { UINT16 RelativeTargetPort; } SAS_DEVICE_PATH; +/// +/// Serial Attached SCSI (SAS) Ex Device Path SubType +/// +#define MSG_SASEX_DP 0x16 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// 8-byte array of the SAS Address for Serial Attached SCSI Target Port. + /// + UINT8 SasAddress[8]; + /// + /// 8-byte array of the SAS Logical Unit Number. + /// + UINT8 Lun[8]; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SASEX_DEVICE_PATH; + /// /// iSCSI Device Path SubType /// @@ -897,7 +960,7 @@ typedef struct { } MEDIA_PROTOCOL_DEVICE_PATH; /// -/// PIWG Firmware Volume Device Path SubType. +/// PIWG Firmware File SubType. /// #define MEDIA_PIWG_FW_FILE_DP 0x06 @@ -967,7 +1030,7 @@ typedef struct { /// UINT16 StatusFlag; /// - /// ASCIIZ string that describes the boot device to a user. + /// Null-terminated ASCII string that describes the boot device to a user. /// CHAR8 String[1]; } BBS_BBS_DEVICE_PATH; @@ -989,78 +1052,100 @@ typedef struct { /// Union of all possible Device Paths and pointers to Device Paths. /// typedef union { - EFI_DEVICE_PATH_PROTOCOL DevPath; - PCI_DEVICE_PATH Pci; - PCCARD_DEVICE_PATH PcCard; - MEMMAP_DEVICE_PATH MemMap; - VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; - CONTROLLER_DEVICE_PATH Controller; - ACPI_HID_DEVICE_PATH Acpi; + CONTROLLER_DEVICE_PATH Controller; + ACPI_HID_DEVICE_PATH Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH ExtendedAcpi; + ACPI_ADR_DEVICE_PATH AcpiAdr; - ATAPI_DEVICE_PATH Atapi; - SCSI_DEVICE_PATH Scsi; - ISCSI_DEVICE_PATH Iscsi; - FIBRECHANNEL_DEVICE_PATH FibreChannel; + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + ISCSI_DEVICE_PATH Iscsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + FIBRECHANNELEX_DEVICE_PATH FibreChannelEx; - F1394_DEVICE_PATH F1394; - USB_DEVICE_PATH Usb; - SATA_DEVICE_PATH Sata; - USB_CLASS_DEVICE_PATH UsbClass; - I2O_DEVICE_PATH I2O; - MAC_ADDR_DEVICE_PATH MacAddr; - IPv4_DEVICE_PATH Ipv4; - IPv6_DEVICE_PATH Ipv6; - INFINIBAND_DEVICE_PATH InfiniBand; - UART_DEVICE_PATH Uart; + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + SATA_DEVICE_PATH Sata; + USB_CLASS_DEVICE_PATH UsbClass; + USB_WWID_DEVICE_PATH UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH LogicUnit; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + VLAN_DEVICE_PATH Vlan; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + UART_FLOW_CONTROL_DEVICE_PATH UartFlowControl; + SAS_DEVICE_PATH Sas; + SASEX_DEVICE_PATH SasEx; + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; - HARDDRIVE_DEVICE_PATH HardDrive; - CDROM_DEVICE_PATH CD; + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; - FILEPATH_DEVICE_PATH FilePath; - MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; - MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH Offset; + MEDIA_FW_VOL_DEVICE_PATH FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH Offset; - BBS_BBS_DEVICE_PATH Bbs; + BBS_BBS_DEVICE_PATH Bbs; } EFI_DEV_PATH; typedef union { - EFI_DEVICE_PATH_PROTOCOL *DevPath; - PCI_DEVICE_PATH *Pci; - PCCARD_DEVICE_PATH *PcCard; - MEMMAP_DEVICE_PATH *MemMap; - VENDOR_DEVICE_PATH *Vendor; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + PCI_DEVICE_PATH *Pci; + PCCARD_DEVICE_PATH *PcCard; + MEMMAP_DEVICE_PATH *MemMap; + VENDOR_DEVICE_PATH *Vendor; - CONTROLLER_DEVICE_PATH *Controller; - ACPI_HID_DEVICE_PATH *Acpi; - ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + CONTROLLER_DEVICE_PATH *Controller; + ACPI_HID_DEVICE_PATH *Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + ACPI_ADR_DEVICE_PATH *AcpiAdr; - ATAPI_DEVICE_PATH *Atapi; - SCSI_DEVICE_PATH *Scsi; - FIBRECHANNEL_DEVICE_PATH *FibreChannel; + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + ISCSI_DEVICE_PATH *Iscsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + FIBRECHANNELEX_DEVICE_PATH *FibreChannelEx; - F1394_DEVICE_PATH *F1394; - USB_DEVICE_PATH *Usb; - SATA_DEVICE_PATH *Sata; - USB_CLASS_DEVICE_PATH *UsbClass; - I2O_DEVICE_PATH *I2O; - MAC_ADDR_DEVICE_PATH *MacAddr; - IPv4_DEVICE_PATH *Ipv4; - IPv6_DEVICE_PATH *Ipv6; - INFINIBAND_DEVICE_PATH *InfiniBand; - UART_DEVICE_PATH *Uart; + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + SATA_DEVICE_PATH *Sata; + USB_CLASS_DEVICE_PATH *UsbClass; + USB_WWID_DEVICE_PATH *UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicUnit; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + VLAN_DEVICE_PATH *Vlan; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + SAS_DEVICE_PATH *Sas; + SASEX_DEVICE_PATH *SasEx; + HARDDRIVE_DEVICE_PATH *HardDrive; + CDROM_DEVICE_PATH *CD; - HARDDRIVE_DEVICE_PATH *HardDrive; - CDROM_DEVICE_PATH *CD; + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; - FILEPATH_DEVICE_PATH *FilePath; - MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; - MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + MEDIA_FW_VOL_DEVICE_PATH *FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; - BBS_BBS_DEVICE_PATH *Bbs; - UINT8 *Raw; + BBS_BBS_DEVICE_PATH *Bbs; + UINT8 *Raw; } EFI_DEV_PATH_PTR; #pragma pack() diff --git a/src/include/ipxe/efi/Protocol/FormBrowser2.h b/src/include/ipxe/efi/Protocol/FormBrowser2.h index 6befec63..12873c31 100644 --- a/src/include/ipxe/efi/Protocol/FormBrowser2.h +++ b/src/include/ipxe/efi/Protocol/FormBrowser2.h @@ -61,6 +61,10 @@ typedef UINTN EFI_BROWSER_ACTION_REQUEST; #define EFI_BROWSER_ACTION_REQUEST_RESET 1 #define EFI_BROWSER_ACTION_REQUEST_SUBMIT 2 #define EFI_BROWSER_ACTION_REQUEST_EXIT 3 +#define EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT 4 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT 5 +#define EFI_BROWSER_ACTION_REQUEST_FORM_APPLY 6 +#define EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD 7 /** diff --git a/src/include/ipxe/efi/Protocol/HiiConfigAccess.h b/src/include/ipxe/efi/Protocol/HiiConfigAccess.h index 2bef5cbc..929d9cd2 100644 --- a/src/include/ipxe/efi/Protocol/HiiConfigAccess.h +++ b/src/include/ipxe/efi/Protocol/HiiConfigAccess.h @@ -36,6 +36,12 @@ typedef UINTN EFI_BROWSER_ACTION; #define EFI_BROWSER_ACTION_RETRIEVE 2 #define EFI_BROWSER_ACTION_FORM_OPEN 3 #define EFI_BROWSER_ACTION_FORM_CLOSE 4 +#define EFI_BROWSER_ACTION_DEFAULT_STANDARD 0x1000 +#define EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING 0x1001 +#define EFI_BROWSER_ACTION_DEFAULT_SAFE 0x1002 +#define EFI_BROWSER_ACTION_DEFAULT_PLATFORM 0x2000 +#define EFI_BROWSER_ACTION_DEFAULT_HARDWARE 0x3000 +#define EFI_BROWSER_ACTION_DEFAULT_FIRMWARE 0x4000 /** diff --git a/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h b/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h index ac86e972..29319069 100644 --- a/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h +++ b/src/include/ipxe/efi/Protocol/NetworkInterfaceIdentifier.h @@ -1,7 +1,7 @@ /** @file EFI Network Interface Identifier Protocol. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -87,6 +87,29 @@ typedef enum { EfiNetworkInterfaceUndi = 1 } EFI_NETWORK_INTERFACE_TYPE; +/// +/// Forward reference for pure ANSI compatability. +/// +typedef struct undiconfig_table UNDI_CONFIG_TABLE; + +/// +/// The format of the configuration table for UNDI +/// +struct undiconfig_table { + UINT32 NumberOfInterfaces; ///< The number of NIC devices + ///< that this UNDI controls. + UINT32 reserved; + UNDI_CONFIG_TABLE *nextlink; ///< A pointer to the next UNDI + ///< configuration table. + /// + /// The length of this array is given in the NumberOfInterfaces field. + /// + struct { + VOID *NII_InterfacePointer; ///< Pointer to the NII interface structure. + VOID *DevicePathPointer; ///< Pointer to the device path for this NIC. + } NII_entry[1]; +}; + extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid; extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid_31; diff --git a/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h b/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h index e8feea0c..b9c80f58 100644 --- a/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h +++ b/src/include/ipxe/efi/Protocol/PciRootBridgeIo.h @@ -5,7 +5,7 @@ and PCI Configuration cycles on a PCI Root Bridge. It also provides services to perform defferent types of bus mastering DMA. - Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -21,6 +21,8 @@ FILE_LICENCE ( BSD3 ); +#include + #define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ { \ 0x2f707ebb, 0x4a1a, 0x11d4, {0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ @@ -108,7 +110,11 @@ typedef enum { #define EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER (~EFI_PCI_ATTRIBUTE_VALID_FOR_ALLOCATE_BUFFER) #define EFI_PCI_ADDRESS(bus, dev, func, reg) \ - ((UINT64) ((((UINTN) bus) << 24) + (((UINTN) dev) << 16) + (((UINTN) func) << 8) + ((UINTN) reg))) + (UINT64) ( \ + (((UINTN) bus) << 24) | \ + (((UINTN) dev) << 16) | \ + (((UINTN) func) << 8) | \ + (((UINTN) (reg)) < 256 ? ((UINTN) (reg)) : (UINT64) (LShiftU64 ((UINT64) (reg), 32)))) typedef struct { UINT8 Register; diff --git a/src/include/ipxe/efi/Protocol/SimpleTextIn.h b/src/include/ipxe/efi/Protocol/SimpleTextIn.h index a89a9b4f..571ecaf3 100644 --- a/src/include/ipxe/efi/Protocol/SimpleTextIn.h +++ b/src/include/ipxe/efi/Protocol/SimpleTextIn.h @@ -4,7 +4,7 @@ Abstraction of a very simple input device like a keyboard or serial terminal. - Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -78,8 +78,6 @@ typedef struct { #define SCAN_F8 0x0012 #define SCAN_F9 0x0013 #define SCAN_F10 0x0014 -#define SCAN_F11 0x0015 -#define SCAN_F12 0x0016 #define SCAN_ESC 0x0017 /** diff --git a/src/include/ipxe/efi/Protocol/SimpleTextInEx.h b/src/include/ipxe/efi/Protocol/SimpleTextInEx.h new file mode 100644 index 00000000..71d3463b --- /dev/null +++ b/src/include/ipxe/efi/Protocol/SimpleTextInEx.h @@ -0,0 +1,327 @@ +/** @file + Simple Text Input Ex protocol from the UEFI 2.0 specification. + + This protocol defines an extension to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL + which exposes much more state and modifier information from the input device, + also allows one to register a notification for a particular keystroke. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SIMPLE_TEXT_IN_EX_H__ +#define __SIMPLE_TEXT_IN_EX_H__ + +FILE_LICENCE ( BSD3 ); + +#include + +#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + {0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } + + +typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; + +/** + The Reset() function resets the input device hardware. As part + of initialization process, the firmware/device will make a quick + but reasonable attempt to verify that the device is functioning. + If the ExtendedVerification flag is TRUE the firmware may take + an extended amount of time to verify the device is operating on + reset. Otherwise the reset operation is to occur as quickly as + possible. The hardware verification process is not defined by + this specification and is left up to the platform firmware or + driver to implement. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param ExtendedVerification Indicates that the driver may + perform a more exhaustive + verification operation of the + device during reset. + + + @retval EFI_SUCCESS The device was reset. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_RESET_EX)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + + +/// +/// EFI_KEY_TOGGLE_STATE. The toggle states are defined. +/// They are: EFI_TOGGLE_STATE_VALID, EFI_SCROLL_LOCK_ACTIVE +/// EFI_NUM_LOCK_ACTIVE, EFI_CAPS_LOCK_ACTIVE +/// +typedef UINT8 EFI_KEY_TOGGLE_STATE; + +typedef struct _EFI_KEY_STATE { + /// + /// Reflects the currently pressed shift + /// modifiers for the input device. The + /// returned value is valid only if the high + /// order bit has been set. + /// + UINT32 KeyShiftState; + /// + /// Reflects the current internal state of + /// various toggled attributes. The returned + /// value is valid only if the high order + /// bit has been set. + /// + EFI_KEY_TOGGLE_STATE KeyToggleState; +} EFI_KEY_STATE; + +typedef struct { + /// + /// The EFI scan code and Unicode value returned from the input device. + /// + EFI_INPUT_KEY Key; + /// + /// The current state of various toggled attributes as well as input modifier values. + /// + EFI_KEY_STATE KeyState; +} EFI_KEY_DATA; + +// +// Any Shift or Toggle State that is valid should have +// high order bit set. +// +// Shift state +// +#define EFI_SHIFT_STATE_VALID 0x80000000 +#define EFI_RIGHT_SHIFT_PRESSED 0x00000001 +#define EFI_LEFT_SHIFT_PRESSED 0x00000002 +#define EFI_RIGHT_CONTROL_PRESSED 0x00000004 +#define EFI_LEFT_CONTROL_PRESSED 0x00000008 +#define EFI_RIGHT_ALT_PRESSED 0x00000010 +#define EFI_LEFT_ALT_PRESSED 0x00000020 +#define EFI_RIGHT_LOGO_PRESSED 0x00000040 +#define EFI_LEFT_LOGO_PRESSED 0x00000080 +#define EFI_MENU_KEY_PRESSED 0x00000100 +#define EFI_SYS_REQ_PRESSED 0x00000200 + +// +// Toggle state +// +#define EFI_TOGGLE_STATE_VALID 0x80 +#define EFI_KEY_STATE_EXPOSED 0x40 +#define EFI_SCROLL_LOCK_ACTIVE 0x01 +#define EFI_NUM_LOCK_ACTIVE 0x02 +#define EFI_CAPS_LOCK_ACTIVE 0x04 + +// +// EFI Scan codes +// +#define SCAN_F11 0x0015 +#define SCAN_F12 0x0016 +#define SCAN_PAUSE 0x0048 +#define SCAN_F13 0x0068 +#define SCAN_F14 0x0069 +#define SCAN_F15 0x006A +#define SCAN_F16 0x006B +#define SCAN_F17 0x006C +#define SCAN_F18 0x006D +#define SCAN_F19 0x006E +#define SCAN_F20 0x006F +#define SCAN_F21 0x0070 +#define SCAN_F22 0x0071 +#define SCAN_F23 0x0072 +#define SCAN_F24 0x0073 +#define SCAN_MUTE 0x007F +#define SCAN_VOLUME_UP 0x0080 +#define SCAN_VOLUME_DOWN 0x0081 +#define SCAN_BRIGHTNESS_UP 0x0100 +#define SCAN_BRIGHTNESS_DOWN 0x0101 +#define SCAN_SUSPEND 0x0102 +#define SCAN_HIBERNATE 0x0103 +#define SCAN_TOGGLE_DISPLAY 0x0104 +#define SCAN_RECOVERY 0x0105 +#define SCAN_EJECT 0x0106 + +/** + The function reads the next keystroke from the input device. If + there is no pending keystroke the function returns + EFI_NOT_READY. If there is a pending keystroke, then + KeyData.Key.ScanCode is the EFI scan code defined in Error! + Reference source not found. The KeyData.Key.UnicodeChar is the + actual printable character or is zero if the key does not + represent a printable character (control key, function key, + etc.). The KeyData.KeyState is shift state for the character + reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode . + When interpreting the data from this function, it should be + noted that if a class of printable characters that are + normally adjusted by shift modifiers (e.g. Shift Key + "f" + key) would be presented solely as a KeyData.Key.UnicodeChar + without the associated shift state. So in the previous example + of a Shift Key + "f" key being pressed, the only pertinent + data returned would be KeyData.Key.UnicodeChar with the value + of "F". This of course would not typically be the case for + non-printable characters such as the pressing of the Right + Shift Key + F10 key since the corresponding returned data + would be reflected both in the KeyData.KeyState.KeyShiftState + and KeyData.Key.ScanCode values. UEFI drivers which implement + the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return + KeyData.Key and KeyData.KeyState values. These drivers must + always return the most current state of + KeyData.KeyState.KeyShiftState and + KeyData.KeyState.KeyToggleState. It should also be noted that + certain input devices may not be able to produce shift or toggle + state information, and in those cases the high order bit in the + respective Toggle and Shift state fields should not be active. + + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke state data for the key that was + pressed. + + + @retval EFI_SUCCESS The keystroke information was + returned. + + @retval EFI_NOT_READY There was no keystroke data available. + EFI_DEVICE_ERROR The keystroke + information was not returned due to + hardware errors. + + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_READ_KEY_EX)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData +); + +/** + The SetState() function allows the input device hardware to + have state settings adjusted. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to + set the state for the input device. + + + @retval EFI_SUCCESS The device state was set appropriately. + + @retval EFI_DEVICE_ERROR The device is not functioning + correctly and could not have the + setting adjusted. + + @retval EFI_UNSUPPORTED The device does not support the + ability to have its state set. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_STATE)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState +); + +/// +/// The function will be called when the key sequence is typed specified by KeyData. +/// +typedef +EFI_STATUS +(EFIAPI *EFI_KEY_NOTIFY_FUNCTION)( + IN EFI_KEY_DATA *KeyData +); + +/** + The RegisterKeystrokeNotify() function registers a function + which will be called when a specified keystroke will occur. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke information for the key that was + pressed. + + @param KeyNotificationFunction Points to the function to be + called when the key sequence + is typed specified by KeyData. + + + @param NotifyHandle Points to the unique handle assigned to + the registered notification. + + @retval EFI_SUCCESS The device state was set + appropriately. + + @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary + data structures. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_KEYSTROKE_NOTIFY)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT EFI_HANDLE *NotifyHandle +); + +/** + The UnregisterKeystrokeNotify() function removes the + notification which was previously registered. + + @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance. + + @param NotificationHandle The handle of the notification + function being unregistered. + + @retval EFI_SUCCESS The device state was set appropriately. + + @retval EFI_INVALID_PARAMETER The NotificationHandle is + invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_HANDLE NotificationHandle +); + + +/// +/// The EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL is used on the ConsoleIn +/// device. It is an extension to the Simple Text Input protocol +/// which allows a variety of extended shift state information to be +/// returned. +/// +struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL{ + EFI_INPUT_RESET_EX Reset; + EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; + /// + /// Event to use with WaitForEvent() to wait for a key to be available. + /// + EFI_EVENT WaitForKeyEx; + EFI_SET_STATE SetState; + EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; + EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; +}; + + +extern EFI_GUID gEfiSimpleTextInputExProtocolGuid; + +#endif + diff --git a/src/include/ipxe/efi/Uefi/UefiBaseType.h b/src/include/ipxe/efi/Uefi/UefiBaseType.h index 2c63aa6f..c56f3757 100644 --- a/src/include/ipxe/efi/Uefi/UefiBaseType.h +++ b/src/include/ipxe/efi/Uefi/UefiBaseType.h @@ -1,7 +1,7 @@ /** @file Defines data types and constants introduced in UEFI. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -150,11 +150,13 @@ typedef union { #define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA #define EFI_END_OF_FILE RETURN_END_OF_FILE #define EFI_INVALID_LANGUAGE RETURN_INVALID_LANGUAGE +#define EFI_COMPROMISED_DATA RETURN_COMPROMISED_DATA #define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH #define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE #define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE #define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL +#define EFI_WARN_STALE_DATA RETURN_WARN_STALE_DATA ///@} /// diff --git a/src/include/ipxe/efi/Uefi/UefiGpt.h b/src/include/ipxe/efi/Uefi/UefiGpt.h index 26af39f5..19acf55d 100644 --- a/src/include/ipxe/efi/Uefi/UefiGpt.h +++ b/src/include/ipxe/efi/Uefi/UefiGpt.h @@ -71,7 +71,8 @@ typedef struct { /// /// The size, in bytes, of each the GUID Partition /// Entry structures in the GUID Partition Entry - /// array. Must be a multiple of 8. + /// array. This field shall be set to a value of 128 x 2^n where n is + /// an integer greater than or equal to zero (e.g., 128, 256, 512, etc.). /// UINT32 SizeOfPartitionEntry; /// diff --git a/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h b/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h index 6b6d1e06..fb20d763 100644 --- a/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h +++ b/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h @@ -3,7 +3,7 @@ IFR is primarily consumed by the EFI presentation engine, and produced by EFI internal application and drivers as well as all add-in card option-ROM drivers -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -660,6 +660,13 @@ typedef struct { UINT8 Day; } EFI_HII_DATE; +typedef struct { + EFI_QUESTION_ID QuestionId; + EFI_FORM_ID FormId; + EFI_GUID FormSetGuid; + EFI_STRING_ID DevicePath; +} EFI_HII_REF; + typedef union { UINT8 u8; UINT16 u16; @@ -669,7 +676,8 @@ typedef union { EFI_HII_TIME time; EFI_HII_DATE date; EFI_STRING_ID string; ///< EFI_IFR_TYPE_STRING, EFI_IFR_TYPE_ACTION - // UINT8 buffer[]; ///< EFI_IFR_TYPE_ORDERED_LIST + EFI_HII_REF ref; ///< EFI_IFR_TYPE_REF + // UINT8 buffer[]; ///< EFI_IFR_TYPE_BUFFER } EFI_IFR_TYPE_VALUE; // @@ -694,7 +702,7 @@ typedef union { #define EFI_IFR_INCONSISTENT_IF_OP 0x11 #define EFI_IFR_EQ_ID_VAL_OP 0x12 #define EFI_IFR_EQ_ID_ID_OP 0x13 -#define EFI_IFR_EQ_ID_LIST_OP 0x14 +#define EFI_IFR_EQ_ID_VAL_LIST_OP 0x14 #define EFI_IFR_AND_OP 0x15 #define EFI_IFR_OR_OP 0x16 #define EFI_IFR_NOT_OP 0x17 @@ -771,6 +779,8 @@ typedef union { #define EFI_IFR_CATENATE_OP 0x5E #define EFI_IFR_GUID_OP 0x5F #define EFI_IFR_SECURITY_OP 0x60 +#define EFI_IFR_MODAL_TAG_OP 0x61 +#define EFI_IFR_REFRESH_ID_OP 0x62 // // Definitions of IFR Standard Headers @@ -843,6 +853,8 @@ typedef struct _EFI_IFR_VARSTORE_EFI { EFI_VARSTORE_ID VarStoreId; EFI_GUID Guid; UINT32 Attributes; + UINT16 Size; + UINT8 Name[1]; } EFI_IFR_VARSTORE_EFI; typedef struct _EFI_IFR_VARSTORE_NAME_VALUE { @@ -875,6 +887,10 @@ typedef struct _EFI_IFR_IMAGE { EFI_IMAGE_ID Id; } EFI_IFR_IMAGE; +typedef struct _EFI_IFR_MODAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODAL; + typedef struct _EFI_IFR_LOCKED { EFI_IFR_OP_HEADER Header; } EFI_IFR_LOCKED; @@ -948,6 +964,11 @@ typedef struct _EFI_IFR_REF4 { EFI_STRING_ID DevicePath; } EFI_IFR_REF4; +typedef struct _EFI_IFR_REF5 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_REF5; + typedef struct _EFI_IFR_RESET_BUTTON { EFI_IFR_OP_HEADER Header; EFI_IFR_STATEMENT_HEADER Statement; @@ -1134,6 +1155,7 @@ typedef struct _EFI_IFR_ONE_OF_OPTION { #define EFI_IFR_TYPE_UNDEFINED 0x09 #define EFI_IFR_TYPE_ACTION 0x0A #define EFI_IFR_TYPE_BUFFER 0x0B +#define EFI_IFR_TYPE_REF 0x0C #define EFI_IFR_OPTION_DEFAULT 0x10 #define EFI_IFR_OPTION_DEFAULT_MFG 0x20 @@ -1144,6 +1166,11 @@ typedef struct _EFI_IFR_GUID { //Optional Data Follows } EFI_IFR_GUID; +typedef struct _EFI_IFR_REFRESH_ID { + EFI_IFR_OP_HEADER Header; + EFI_GUID RefreshEventGroupId; +} EFI_IFR_REFRESH_ID; + typedef struct _EFI_IFR_DUP { EFI_IFR_OP_HEADER Header; } EFI_IFR_DUP; diff --git a/src/include/ipxe/efi/Uefi/UefiMultiPhase.h b/src/include/ipxe/efi/Uefi/UefiMultiPhase.h index 6ecbcf11..678f3ebd 100644 --- a/src/include/ipxe/efi/Uefi/UefiMultiPhase.h +++ b/src/include/ipxe/efi/Uefi/UefiMultiPhase.h @@ -1,7 +1,7 @@ /** @file This includes some definitions introduced in UEFI that will be used in both PEI and DXE phases. -Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -122,21 +122,26 @@ typedef struct { /// /// Attributes of variable. /// -#define EFI_VARIABLE_NON_VOLATILE 0x00000001 -#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 -#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 -#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 - +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 /// /// This attribute is identified by the mnemonic 'HR' /// elsewhere in this specification. /// -#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 +/// +/// Attributes of Authenticated Variable +/// +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 +#define EFI_VARIABLE_APPEND_WRITE 0x00000040 + /// /// AuthInfo is a WIN_CERTIFICATE using the wCertificateType /// WIN_CERTIFICATE_UEFI_GUID and the CertType -/// EFI_CERT_TYPE_RSA2048_SHA256. If the attribute specifies +/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies /// authenticated access, then the Data buffer should begin with an /// authentication descriptor prior to the data payload and DataSize /// should reflect the the data.and descriptor size. The caller @@ -167,5 +172,24 @@ typedef struct { WIN_CERTIFICATE_UEFI_GUID AuthInfo; } EFI_VARIABLE_AUTHENTICATION; -#endif +/// +/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is +/// set, then the Data buffer shall begin with an instance of a complete (and serialized) +/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new +/// variable value and DataSize shall reflect the combined size of the descriptor and the new +/// variable value. The authentication descriptor is not part of the variable data and is not +/// returned by subsequent calls to GetVariable(). +/// +typedef struct { + /// + /// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and + /// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT. + /// + EFI_TIME TimeStamp; + /// + /// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted. + /// + WIN_CERTIFICATE_UEFI_GUID AuthInfo; + } EFI_VARIABLE_AUTHENTICATION_2; +#endif diff --git a/src/include/ipxe/efi/Uefi/UefiSpec.h b/src/include/ipxe/efi/Uefi/UefiSpec.h index 1f125d4f..4887157c 100644 --- a/src/include/ipxe/efi/Uefi/UefiSpec.h +++ b/src/include/ipxe/efi/Uefi/UefiSpec.h @@ -5,7 +5,7 @@ If a code construct is defined in the UEFI 2.3 specification it must be included by this include file. -Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -25,6 +25,7 @@ FILE_LICENCE ( BSD3 ); #include #include +#include #include /// @@ -128,6 +129,7 @@ typedef struct { @retval EFI_INVALID_PARAMETER 1) Type is not AllocateAnyPages or AllocateMaxAddress or AllocateAddress. 2) MemoryType is in the range + 3) Memory is NULL. EfiMaxMemoryType..0x7FFFFFFF. @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. @retval EFI_NOT_FOUND The requested pages could not be found. @@ -206,7 +208,7 @@ EFI_STATUS @retval EFI_SUCCESS The requested number of bytes was allocated. @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated. - @retval EFI_INVALID_PARAMETER PoolType was invalid. + @retval EFI_INVALID_PARAMETER PoolType was invalid or Buffer is NULL. **/ typedef @@ -277,7 +279,7 @@ EFI_STATUS 2) No drivers were connected to ControllerHandle, but RemainingDevicePath is not NULL, and it is an End Device Path Node. - @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances present in the system. 2) No drivers were connected to ControllerHandle. @@ -307,7 +309,7 @@ EFI_STATUS 2) On entry, no drivers are managing ControllerHandle. 3) DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle. - @retval EFI_INVALID_PARAMETER 1) ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER 1) ControllerHandle is NULL. 2) DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE. 3) ChildHandle is not NULL, and it is not a valid EFI_HANDLE. 4) DriverImageHandle does not support the EFI_DRIVER_BINDING_PROTOCOL. @@ -1168,7 +1170,7 @@ EFI_STATUS @retval EFI_ACCESS_DENIED The protocol interface could not be reinstalled, because OldInterface is still being used by a driver that will not release it. - @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. **/ @@ -1194,7 +1196,7 @@ EFI_STATUS @retval EFI_NOT_FOUND The interface was not found. @retval EFI_ACCESS_DENIED The interface was not removed because the interface is still being used by a driver. - @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. **/ @@ -1234,7 +1236,7 @@ EFI_STATUS @retval EFI_SUCCESS The interface information for the specified protocol was returned. @retval EFI_UNSUPPORTED The device does not support the specified protocol. - @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Handle is NULL. @retval EFI_INVALID_PARAMETER Protocol is NULL. @retval EFI_INVALID_PARAMETER Interface is NULL. @@ -1305,8 +1307,8 @@ EFI_STATUS that required the protocol interface. @retval EFI_SUCCESS The protocol instance was closed. - @retval EFI_INVALID_PARAMETER 1) Handle is not a valid EFI_HANDLE. - 2) AgentHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER 1) Handle is NULL. + 2) AgentHandle is NULL. 3) ControllerHandle is not NULL and ControllerHandle is not a valid EFI_HANDLE. 4) Protocol is NULL. @retval EFI_NOT_FOUND 1) Handle does not support the protocol specified by Protocol. @@ -1493,7 +1495,7 @@ EFI_STATUS @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. @retval EFI_NOT_FOUND An attempt was made to delete a nonexistent entry. - @retval EFI_INVALID_PARAMETER Guid is not valid. + @retval EFI_INVALID_PARAMETER Guid is NULL. @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. **/ @@ -1725,16 +1727,17 @@ EFI_STATUS // EFI Runtime Services Table // #define EFI_SYSTEM_TABLE_SIGNATURE SIGNATURE_64 ('I','B','I',' ','S','Y','S','T') +#define EFI_2_31_SYSTEM_TABLE_REVISION ((2 << 16) | (31)) #define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) #define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) #define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) #define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00)) #define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10)) #define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02)) -#define EFI_SYSTEM_TABLE_REVISION EFI_2_30_SYSTEM_TABLE_REVISION +#define EFI_SYSTEM_TABLE_REVISION EFI_2_31_SYSTEM_TABLE_REVISION #define EFI_RUNTIME_SERVICES_SIGNATURE SIGNATURE_64 ('R','U','N','T','S','E','R','V') -#define EFI_RUNTIME_SERVICES_REVISION EFI_2_30_SYSTEM_TABLE_REVISION +#define EFI_RUNTIME_SERVICES_REVISION EFI_2_31_SYSTEM_TABLE_REVISION /// /// EFI Runtime Services Table. @@ -1786,7 +1789,7 @@ typedef struct { #define EFI_BOOT_SERVICES_SIGNATURE SIGNATURE_64 ('B','O','O','T','S','E','R','V') -#define EFI_BOOT_SERVICES_REVISION EFI_2_30_SYSTEM_TABLE_REVISION +#define EFI_BOOT_SERVICES_REVISION EFI_2_31_SYSTEM_TABLE_REVISION /// /// EFI Boot Services Table. diff --git a/src/include/ipxe/efi/X64/ProcessorBind.h b/src/include/ipxe/efi/X64/ProcessorBind.h index 0b1a3e11..e10e3b54 100644 --- a/src/include/ipxe/efi/X64/ProcessorBind.h +++ b/src/include/ipxe/efi/X64/ProcessorBind.h @@ -1,7 +1,7 @@ /** @file Processor or Compiler specific defines and types x64 (Intel 64, AMD64). - Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -149,7 +149,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value /// - typedef char INT8; + typedef signed char INT8; #else /// /// 8-byte unsigned value @@ -196,7 +196,7 @@ FILE_LICENCE ( BSD3 ); /// /// 1-byte signed value /// - typedef char INT8; + typedef signed char INT8; #endif /// diff --git a/src/include/ipxe/efi/efi_pci.h b/src/include/ipxe/efi/efi_pci.h index 24890eb4..6429f210 100644 --- a/src/include/ipxe/efi/efi_pci.h +++ b/src/include/ipxe/efi/efi_pci.h @@ -12,6 +12,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +/* PciRootBridgeIo.h uses LShiftU64(), which isn't defined anywhere else */ +static inline EFIAPI uint64_t LShiftU64 ( UINT64 value, UINTN shift ) { + return ( value << shift ); +} + struct efi_driver; struct device; From 7ad6caf29f861bbf8214b9b575d51632e17af86f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 10:21:50 +0100 Subject: [PATCH 090/250] [efi] Add EFI_LOAD_FILE_PROTOCOL header Signed-off-by: Michael Brown --- src/include/ipxe/efi/Protocol/LoadFile.h | 90 ++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/include/ipxe/efi/Protocol/LoadFile.h diff --git a/src/include/ipxe/efi/Protocol/LoadFile.h b/src/include/ipxe/efi/Protocol/LoadFile.h new file mode 100644 index 00000000..99387e89 --- /dev/null +++ b/src/include/ipxe/efi/Protocol/LoadFile.h @@ -0,0 +1,90 @@ +/** @file + Load File protocol as defined in the UEFI 2.0 specification. + + The load file protocol exists to supports the addition of new boot devices, + and to support booting from devices that do not map well to file system. + Network boot is done via a LoadFile protocol. + + UEFI 2.0 can boot from any device that produces a LoadFile protocol. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_LOAD_FILE_PROTOCOL_H__ +#define __EFI_LOAD_FILE_PROTOCOL_H__ + +FILE_LICENCE ( BSD3 ); + +#define EFI_LOAD_FILE_PROTOCOL_GUID \ + { \ + 0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } + +/// +/// Protocol Guid defined by EFI1.1. +/// +#define LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL_GUID + +typedef struct _EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL; + +/// +/// Backward-compatible with EFI1.1 +/// +typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_INTERFACE; + +/** + Causes the driver to load a specified file. + + @param This Protocol instance pointer. + @param FilePath The device specific path of the file to load. + @param BootPolicy If TRUE, indicates that the request originates from the + boot manager is attempting to load FilePath as a boot + selection. If FALSE, then FilePath must match as exact file + to be loaded. + @param BufferSize On input the size of Buffer in bytes. On output with a return + code of EFI_SUCCESS, the amount of data transferred to + Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested file. + @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL, + then the size of the requested file is returned in + BufferSize. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or + BufferSize is NULL. + @retval EFI_NO_MEDIA No medium was present to load the file. + @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. + @retval EFI_NO_RESPONSE The remote system did not respond. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_ABORTED The file load process was manually cancelled. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOAD_FILE)( + IN EFI_LOAD_FILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ); + +/// +/// The EFI_LOAD_FILE_PROTOCOL is a simple protocol used to obtain files from arbitrary devices. +/// +struct _EFI_LOAD_FILE_PROTOCOL { + EFI_LOAD_FILE LoadFile; +}; + +extern EFI_GUID gEfiLoadFileProtocolGuid; + +#endif From 58ed3b1ceec8a62ba33bb4055348df58ae49d30d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 13:57:17 +0100 Subject: [PATCH 091/250] [libc] Add support for "%lc" and "%ls" format specifiers Signed-off-by: Michael Brown --- src/core/vsprintf.c | 36 +++++++++++++++++++++++++++++++----- src/include/stddef.h | 1 + 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/core/vsprintf.c b/src/core/vsprintf.c index b721b024..dd1a101d 100644 --- a/src/core/vsprintf.c +++ b/src/core/vsprintf.c @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file */ @@ -185,6 +186,7 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { char *ptr; char tmp_buf[32]; /* 32 is enough for all numerical formats. * Insane width fields could overflow this buffer. */ + wchar_t *wptr; /* Initialise context */ ctx->len = 0; @@ -234,11 +236,26 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { /* Process conversion specifier */ ptr = tmp_buf + sizeof ( tmp_buf ) - 1; *ptr = '\0'; + wptr = NULL; if ( *fmt == 'c' ) { - cputchar ( ctx, va_arg ( args, unsigned int ) ); + if ( length < &type_sizes[LONG_LEN] ) { + cputchar ( ctx, va_arg ( args, unsigned int ) ); + } else { + wchar_t wc; + size_t len; + + wc = va_arg ( args, wint_t ); + len = wcrtomb ( tmp_buf, wc, NULL ); + tmp_buf[len] = '\0'; + ptr = tmp_buf; + } } else if ( *fmt == 's' ) { - ptr = va_arg ( args, char * ); - if ( ! ptr ) + if ( length < &type_sizes[LONG_LEN] ) { + ptr = va_arg ( args, char * ); + } else { + wptr = va_arg ( args, wchar_t * ); + } + if ( ( ptr == NULL ) && ( wptr == NULL ) ) ptr = ""; } else if ( *fmt == 'p' ) { intptr_t ptrval; @@ -271,8 +288,17 @@ size_t vcprintf ( struct printf_context *ctx, const char *fmt, va_list args ) { *(--ptr) = *fmt; } /* Write out conversion result */ - for ( ; *ptr ; ptr++ ) { - cputchar ( ctx, *ptr ); + if ( wptr == NULL ) { + for ( ; *ptr ; ptr++ ) { + cputchar ( ctx, *ptr ); + } + } else { + for ( ; *wptr ; wptr++ ) { + size_t len = wcrtomb ( tmp_buf, *wptr, NULL ); + for ( ptr = tmp_buf ; len-- ; ptr++ ) { + cputchar ( ctx, *ptr ); + } + } } } diff --git a/src/include/stddef.h b/src/include/stddef.h index c91a103f..83a0f0ed 100644 --- a/src/include/stddef.h +++ b/src/include/stddef.h @@ -26,5 +26,6 @@ FILE_LICENCE ( GPL2_ONLY ); #define __WCHAR_TYPE__ long int #endif typedef __WCHAR_TYPE__ wchar_t; +typedef __WINT_TYPE__ wint_t; #endif /* STDDEF_H */ From ac8107854fb4ad2c90ab9c04e562d2a65b5e8f72 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 17:10:28 +0100 Subject: [PATCH 092/250] [intel] Add missing iounmap() Reported-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 1fdce1cb..353fc971 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -799,6 +799,7 @@ static int intel_probe ( struct pci_device *pci ) { err_fetch_mac: intel_reset ( intel ); err_reset: + iounmap ( intel->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: @@ -821,6 +822,7 @@ static void intel_remove ( struct pci_device *pci ) { intel_reset ( intel ); /* Free network device */ + iounmap ( intel->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); } From e982a7e3c46d109e5d68b5c875ebbbf03bcaf2c4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 17:10:28 +0100 Subject: [PATCH 093/250] [realtek] Add missing iounmap() Reported-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 104ff76e..3c7b1f85 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -987,6 +987,7 @@ static int realtek_probe ( struct pci_device *pci ) { err_nvs_read: realtek_reset ( rtl ); err_reset: + iounmap ( rtl->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: @@ -1013,6 +1014,7 @@ static void realtek_remove ( struct pci_device *pci ) { realtek_reset ( rtl ); /* Free network device */ + iounmap ( rtl->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); } From 93f1d69a779b1999fbe3a8b62caffde3fe3edf3f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 17:10:28 +0100 Subject: [PATCH 094/250] [natsemi] Add missing iounmap() Reported-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/natsemi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/net/natsemi.c b/src/drivers/net/natsemi.c index fb1eb822..669fb877 100644 --- a/src/drivers/net/natsemi.c +++ b/src/drivers/net/natsemi.c @@ -880,6 +880,7 @@ static int natsemi_probe ( struct pci_device *pci ) { err_hwaddr: natsemi_reset ( natsemi ); err_reset: + iounmap ( natsemi->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: @@ -902,6 +903,7 @@ static void natsemi_remove ( struct pci_device *pci ) { natsemi_reset ( natsemi ); /* Free network device */ + iounmap ( natsemi->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); } From 76b4323b4da6f470bf75180562bb03a78ea58d31 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 17:10:28 +0100 Subject: [PATCH 095/250] [myson] Add missing iounmap() Reported-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/myson.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/net/myson.c b/src/drivers/net/myson.c index 25f1a270..237f8721 100644 --- a/src/drivers/net/myson.c +++ b/src/drivers/net/myson.c @@ -626,6 +626,7 @@ static int myson_probe ( struct pci_device *pci ) { err_register_netdev: myson_reset ( myson ); err_reset: + iounmap ( myson->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: @@ -648,6 +649,7 @@ static void myson_remove ( struct pci_device *pci ) { myson_reset ( myson ); /* Free network device */ + iounmap ( myson->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); } From d32aac88efa05df8f70848befe64da827f94276b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 17:10:28 +0100 Subject: [PATCH 096/250] [skel] Add missing iounmap() Reported-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/skeleton.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/net/skeleton.c b/src/drivers/net/skeleton.c index 3e1e2d54..e50b778a 100644 --- a/src/drivers/net/skeleton.c +++ b/src/drivers/net/skeleton.c @@ -268,6 +268,7 @@ static int skeleton_probe ( struct pci_device *pci ) { err_mii_reset: skeleton_reset ( skel ); err_reset: + iounmap ( skel->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: @@ -290,6 +291,7 @@ static void skeleton_remove ( struct pci_device *pci ) { skeleton_reset ( skel ); /* Free network device */ + iounmap ( skel->regs ); netdev_nullify ( netdev ); netdev_put ( netdev ); } From 23b70323c7d91b941344df6a27ddd035d0fea934 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 19 Jul 2012 17:19:26 +0100 Subject: [PATCH 097/250] [libc] Add missing wchar.h header Commit 58ed3b1 ("[libc] Add support for "%lc" and "%ls" format specifiers") was missing a file. Signed-off-by: Michael Brown --- src/include/wchar.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/include/wchar.h diff --git a/src/include/wchar.h b/src/include/wchar.h new file mode 100644 index 00000000..84312c70 --- /dev/null +++ b/src/include/wchar.h @@ -0,0 +1,27 @@ +#ifndef WCHAR_H +#define WCHAR_H + +FILE_LICENCE ( GPL2_ONLY ); + +#include + +typedef void mbstate_t; + +/** + * Convert wide character to multibyte sequence + * + * @v buf Buffer + * @v wc Wide character + * @v ps Shift state + * @ret len Number of characters written + * + * This is a stub implementation, sufficient to handle basic ASCII + * characters. + */ +static inline __attribute__ (( always_inline )) +size_t wcrtomb ( char *buf, wchar_t wc, mbstate_t *ps __unused ) { + *buf = wc; + return 1; +} + +#endif /* WCHAR_H */ From d3c660b6718c8d85b34d5c7ca8c4ed12659e1cc7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 20 Jul 2012 10:37:24 +0100 Subject: [PATCH 098/250] [image] Add "--autofree" option Allow images to be automatically freed after execution completes (successfully or otherwise). Signed-off-by: Michael Brown --- src/core/image.c | 32 +++++++++++++++++++++----------- src/hci/commands/image_cmd.c | 15 ++++++++++++--- src/include/ipxe/image.h | 3 +++ src/usr/imgmgmt.c | 2 ++ 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/core/image.c b/src/core/image.c index bf9bb7fa..666ee3de 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -194,6 +194,10 @@ int register_image ( struct image *image ) { */ void unregister_image ( struct image *image ) { + /* Do nothing unless image is registered */ + if ( ! ( image->flags & IMAGE_REGISTERED ) ) + return; + DBGC ( image, "IMAGE %s unregistered\n", image->name ); list_del ( &image->list ); image->flags &= ~IMAGE_REGISTERED; @@ -259,23 +263,13 @@ int image_probe ( struct image *image ) { */ int image_exec ( struct image *image ) { struct image *saved_current_image; - struct image *replacement; + struct image *replacement = NULL; struct uri *old_cwuri; int rc; /* Sanity check */ assert ( image->flags & IMAGE_REGISTERED ); - /* Check that this image can be selected for execution */ - if ( ( rc = image_select ( image ) ) != 0 ) - return rc; - - /* Check that image is trusted (if applicable) */ - if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) { - DBGC ( image, "IMAGE %s is not trusted\n", image->name ); - return -EACCES_UNTRUSTED; - } - /* Switch current working directory to be that of the image itself */ old_cwuri = uri_get ( cwuri ); churi ( image->uri ); @@ -289,6 +283,17 @@ int image_exec ( struct image *image ) { */ current_image = image_get ( image ); + /* Check that this image can be selected for execution */ + if ( ( rc = image_select ( image ) ) != 0 ) + goto err; + + /* Check that image is trusted (if applicable) */ + if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) { + DBGC ( image, "IMAGE %s is not trusted\n", image->name ); + rc = -EACCES_UNTRUSTED; + goto err; + } + /* Record boot attempt */ syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name ); @@ -317,6 +322,11 @@ int image_exec ( struct image *image ) { if ( replacement ) assert ( replacement->flags & IMAGE_REGISTERED ); + err: + /* Unregister image if applicable */ + if ( image->flags & IMAGE_AUTO_UNREGISTER ) + unregister_image ( image ); + /* Drop temporary reference to the original image */ image_put ( image ); diff --git a/src/hci/commands/image_cmd.c b/src/hci/commands/image_cmd.c index 1ae33074..38d814cd 100644 --- a/src/hci/commands/image_cmd.c +++ b/src/hci/commands/image_cmd.c @@ -38,19 +38,24 @@ FILE_LICENCE ( GPL2_OR_LATER ); struct imgsingle_options { /** Image name */ const char *name; + /** Free image after execution */ + int autofree; }; /** "img{single}" option list */ static struct option_descriptor imgsingle_opts[] = { OPTION_DESC ( "name", 'n', required_argument, struct imgsingle_options, name, parse_string ), + OPTION_DESC ( "autofree", 'a', no_argument, + struct imgsingle_options, autofree, parse_flag ), }; /** "img{single}" command descriptor */ static struct command_descriptor imgsingle_cmd = COMMAND_DESC ( struct imgsingle_options, imgsingle_opts, 1, MAX_ARGUMENTS, - "[--name ] [...]" ); + "[--name ] [--autofree] " + " [...]" ); /** An "img{single}" family command descriptor */ struct imgsingle_descriptor { @@ -134,6 +139,10 @@ static int imgsingle_exec ( int argc, char **argv, } } + /* Set the auto-unregister flag, if applicable */ + if ( opts.autofree ) + image->flags |= IMAGE_AUTO_UNREGISTER; + /* Carry out command action, if applicable */ if ( desc->action ) { if ( ( rc = desc->action ( image ) ) != 0 ) { @@ -160,7 +169,7 @@ static int imgsingle_exec ( int argc, char **argv, static struct command_descriptor imgfetch_cmd = COMMAND_DESC ( struct imgsingle_options, imgsingle_opts, 1, MAX_ARGUMENTS, - "[--name ] [...]" ); + "[--name ] [--autofree] [...]" ); /** "imgfetch" family command descriptor */ struct imgsingle_descriptor imgfetch_desc = { @@ -202,7 +211,7 @@ static int imgselect_exec ( int argc, char **argv ) { static struct command_descriptor imgexec_cmd = COMMAND_DESC ( struct imgsingle_options, imgsingle_opts, 0, MAX_ARGUMENTS, - "[--name ] [ [...]]" ); + "[--autofree] [ [...]]" ); /** "imgexec" family command descriptor */ struct imgsingle_descriptor imgexec_desc = { diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h index ac97137b..6022dce6 100644 --- a/src/include/ipxe/image.h +++ b/src/include/ipxe/image.h @@ -67,6 +67,9 @@ struct image { /** Image is trusted */ #define IMAGE_TRUSTED 0x0004 +/** Image will be automatically unregistered after execution */ +#define IMAGE_AUTO_UNREGISTER 0x0008 + /** An executable image type */ struct image_type { /** Name of this image type */ diff --git a/src/usr/imgmgmt.c b/src/usr/imgmgmt.c index 2c74f486..ce3bc90f 100644 --- a/src/usr/imgmgmt.c +++ b/src/usr/imgmgmt.c @@ -146,6 +146,8 @@ void imgstat ( struct image *image ) { printf ( " [TRUSTED]" ); if ( image->flags & IMAGE_SELECTED ) printf ( " [SELECTED]" ); + if ( image->flags & IMAGE_AUTO_UNREGISTER ) + printf ( " [AUTOFREE]" ); if ( image->cmdline ) printf ( " \"%s\"", image->cmdline ); printf ( "\n" ); From 5d3c368efbc23d0e85e7bb3fa20c3766bfafd88a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 20 Jul 2012 12:36:41 +0100 Subject: [PATCH 099/250] [image] Add "--replace" option Expose image tail-recursion to iPXE scripts via the "--replace" option. This functions similarly to exec() under Unix: the currently-executing script is replaced with the new image (as opposed to running the new image as a subroutine). Signed-off-by: Michael Brown --- src/core/image.c | 16 ++++++---- src/hci/commands/image_cmd.c | 59 +++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/core/image.c b/src/core/image.c index 666ee3de..1bf5447f 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -327,6 +327,14 @@ int image_exec ( struct image *image ) { if ( image->flags & IMAGE_AUTO_UNREGISTER ) unregister_image ( image ); + /* Debug message for tail-recursion. Placed here because the + * image_put() may end up freeing the image. + */ + if ( replacement ) { + DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n", + image->name, replacement->name ); + } + /* Drop temporary reference to the original image */ image_put ( image ); @@ -338,12 +346,8 @@ int image_exec ( struct image *image ) { uri_put ( old_cwuri ); /* Tail-recurse into replacement image, if one exists */ - if ( replacement ) { - DBGC ( image, "IMAGE replacing self with IMAGE %s\n", - replacement->name ); - if ( ( rc = image_exec ( replacement ) ) != 0 ) - return rc; - } + if ( replacement ) + return image_exec ( replacement ); return rc; } diff --git a/src/hci/commands/image_cmd.c b/src/hci/commands/image_cmd.c index 38d814cd..0a4232f2 100644 --- a/src/hci/commands/image_cmd.c +++ b/src/hci/commands/image_cmd.c @@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -38,6 +39,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); struct imgsingle_options { /** Image name */ const char *name; + /** Replace image */ + int replace; /** Free image after execution */ int autofree; }; @@ -46,6 +49,8 @@ struct imgsingle_options { static struct option_descriptor imgsingle_opts[] = { OPTION_DESC ( "name", 'n', required_argument, struct imgsingle_options, name, parse_string ), + OPTION_DESC ( "replace", 'r', no_argument, + struct imgsingle_options, replace, parse_flag ), OPTION_DESC ( "autofree", 'a', no_argument, struct imgsingle_options, autofree, parse_flag ), }; @@ -66,7 +71,8 @@ struct imgsingle_descriptor { /** Pre-action to take upon image, or NULL */ void ( * preaction ) ( struct image *image ); /** Action to take upon image, or NULL */ - int ( * action ) ( struct image *image ); + int ( * action ) ( struct image *image, + struct imgsingle_options *opts ); /** Verb to describe action */ const char *verb; }; @@ -145,7 +151,7 @@ static int imgsingle_exec ( int argc, char **argv, /* Carry out command action, if applicable */ if ( desc->action ) { - if ( ( rc = desc->action ( image ) ) != 0 ) { + if ( ( rc = desc->action ( image, &opts ) ) != 0 ) { printf ( "Could not %s: %s\n", desc->verb, strerror ( rc ) ); goto err_action; @@ -188,11 +194,23 @@ static int imgfetch_exec ( int argc, char **argv ) { return imgsingle_exec ( argc, argv, &imgfetch_desc ); } +/** + * "imgselect" command action + * + * @v image Image + * @v opts Options + * @ret rc Return status code + */ +static int imgselect ( struct image *image, + struct imgsingle_options *opts __unused ) { + return image_select ( image ); +} + /** "imgselect" family command descriptor */ struct imgsingle_descriptor imgselect_desc = { .cmd = &imgsingle_cmd, .acquire = imgacquire, - .action = image_select, + .action = imgselect, .verb = "select", }; @@ -211,13 +229,44 @@ static int imgselect_exec ( int argc, char **argv ) { static struct command_descriptor imgexec_cmd = COMMAND_DESC ( struct imgsingle_options, imgsingle_opts, 0, MAX_ARGUMENTS, - "[--autofree] [ [...]]" ); + "[--autofree] [--replace] " + "[ [...]]" ); + +/** + * "imgexec" command action + * + * @v image Image + * @v opts Options + * @ret rc Return status code + */ +static int imgexec ( struct image *image, struct imgsingle_options *opts ) { + int rc; + + /* Perform replacement or execution as applicable */ + if ( opts->replace ) { + + /* Try to replace image */ + if ( ( rc = image_replace ( image ) ) != 0 ) + return rc; + + /* Stop script and tail-recurse into replacement image */ + shell_stop ( SHELL_STOP_COMMAND_SEQUENCE ); + + } else { + + /* Try to execute image */ + if ( ( rc = image_exec ( image ) ) != 0 ) + return rc; + } + + return 0; +} /** "imgexec" family command descriptor */ struct imgsingle_descriptor imgexec_desc = { .cmd = &imgexec_cmd, .acquire = imgacquire, - .action = image_exec, + .action = imgexec, .verb = "boot", }; From b3b939c6ff67eb108a331d48320ea1720a291937 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 20 Jul 2012 12:37:16 +0100 Subject: [PATCH 100/250] [image] Automatically free autobooted images Simplify the process of booting by ensuring that old images are not left registered after an unsuccessful autoboot attempt. Signed-off-by: Michael Brown --- src/usr/autoboot.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index da82f5e8..53f246ae 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -160,6 +160,7 @@ int uriboot ( struct uri *filename, struct uri *root_path, int drive, if ( filename ) { if ( ( rc = imgdownload ( filename, &image ) ) != 0 ) goto err_download; + image->flags |= IMAGE_AUTO_UNREGISTER; if ( ( rc = image_exec ( image ) ) != 0 ) { printf ( "Could not boot image: %s\n", strerror ( rc ) ); From 348ec33aee6b34edcec8e7273cf2435b4e8910b8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 20 Jul 2012 18:06:15 +0100 Subject: [PATCH 101/250] [build] Include git commit within version string when available Originally-implemented-by: Christian Hesse Signed-off-by: Michael Brown --- src/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 6537ecb4..a061f834 100644 --- a/src/Makefile +++ b/src/Makefile @@ -165,13 +165,17 @@ VERSION_PATCH = 0 EXTRAVERSION = + MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR) VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION) +GITVERSION := $(shell git describe --always --abbrev=1 --match "" 2>/dev/null) +ifneq ($(GITVERSION),) +VERSION += ($(GITVERSION)) +endif CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) \ -DVERSION_MINOR=$(VERSION_MINOR) \ -DVERSION_PATCH=$(VERSION_PATCH) \ - -DVERSION=\"$(VERSION)\" + -DVERSION="\"$(VERSION)\"" IDENT = '$(@F) $(VERSION) (GPL) ipxe.org' version : - @$(ECHO) $(VERSION) + @$(ECHO) "$(VERSION)" ############################################################################### # From a87c0c4f0f47f5dc4b4d7050b15713a9f7a52757 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 20 Jul 2012 18:32:58 +0100 Subject: [PATCH 102/250] [isa] Avoid spurious compiler warning on gcc 4.7 gcc 4.7 produces a spurious warning about an array subscript being out of bounds. Use a pointer dereference instead of an array lookup to inhibit this spurious warning. Signed-off-by: Michael Brown --- src/drivers/bus/isa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/drivers/bus/isa.c b/src/drivers/bus/isa.c index 9b562c66..da0c43c6 100644 --- a/src/drivers/bus/isa.c +++ b/src/drivers/bus/isa.c @@ -46,9 +46,9 @@ static isa_probe_addr_t isa_extra_probe_addrs[] = { #endif #define ISA_IOADDR( driver, ioidx ) \ - ( ( (ioidx) < 0 ) ? \ - isa_extra_probe_addrs[ (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ] : \ - (driver)->probe_addrs[(ioidx)] ) + ( ( (ioidx) >= 0 ) ? \ + (driver)->probe_addrs[(ioidx)] : \ + *( isa_extra_probe_addrs + (ioidx) + ISA_EXTRA_PROBE_ADDR_COUNT ) ) static void isabus_remove ( struct root_device *rootdev ); From 1ac62b914ec9f478cc0ed63a45a87196a583b073 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 20 Jul 2012 19:18:50 +0100 Subject: [PATCH 103/250] [qib7322] Fix compiler warning on gcc 4.7 Originally-fixed-by: Christian Hesse Signed-off-by: Michael Brown --- src/drivers/infiniband/qib7322.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/infiniband/qib7322.c b/src/drivers/infiniband/qib7322.c index b66f8eff..8b61b8dc 100644 --- a/src/drivers/infiniband/qib7322.c +++ b/src/drivers/infiniband/qib7322.c @@ -2062,6 +2062,9 @@ static int qib7322_ahb_read ( struct qib7322 *qib7322, unsigned int location, struct QIB_7322_ahb_transaction_reg xact; int rc; + /* Avoid returning uninitialised data on error */ + *data = 0; + /* Initiate transaction */ memset ( &xact, 0, sizeof ( xact ) ); BIT_FILL_2 ( &xact, From c3b4860ce3fb25b907a2ca3e46955df34c0ae9fd Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 20 Jul 2012 19:55:45 +0100 Subject: [PATCH 104/250] [legal] Update FSF mailing address in GPL licence texts Suggested-by: Daniel P. Berrange Signed-off-by: Michael Brown --- src/arch/i386/core/basemem_packet.c | 3 ++- src/arch/i386/core/gdbmach.c | 3 ++- src/arch/i386/core/pic8259.c | 3 ++- src/arch/i386/core/rdtsc_timer.c | 3 ++- src/arch/i386/core/runtime.c | 3 ++- src/arch/i386/drivers/net/undi.c | 3 ++- src/arch/i386/drivers/net/undiload.c | 3 ++- src/arch/i386/drivers/net/undinet.c | 3 ++- src/arch/i386/drivers/net/undionly.c | 3 ++- src/arch/i386/drivers/net/undipreload.c | 3 ++- src/arch/i386/drivers/net/undirom.c | 3 ++- src/arch/i386/firmware/pcbios/basemem.c | 3 ++- src/arch/i386/firmware/pcbios/bios_console.c | 3 ++- src/arch/i386/firmware/pcbios/e820mangler.S | 3 ++- src/arch/i386/firmware/pcbios/fakee820.c | 3 ++- src/arch/i386/firmware/pcbios/hidemem.c | 3 ++- src/arch/i386/firmware/pcbios/memmap.c | 3 ++- src/arch/i386/firmware/pcbios/pnpbios.c | 3 ++- src/arch/i386/hci/commands/pxe_cmd.c | 3 ++- src/arch/i386/hci/commands/reboot_cmd.c | 3 ++- src/arch/i386/image/bootsector.c | 3 ++- src/arch/i386/image/bzimage.c | 3 ++- src/arch/i386/image/com32.c | 3 ++- src/arch/i386/image/comboot.c | 3 ++- src/arch/i386/image/elfboot.c | 3 ++- src/arch/i386/image/multiboot.c | 3 ++- src/arch/i386/image/pxe_image.c | 3 ++- src/arch/i386/include/pxe_api.h | 3 ++- src/arch/i386/interface/pcbios/bios_smbios.c | 3 ++- src/arch/i386/interface/pcbios/bios_timer.c | 3 ++- src/arch/i386/interface/pcbios/int13.c | 3 ++- src/arch/i386/interface/pcbios/memtop_umalloc.c | 3 ++- src/arch/i386/interface/pcbios/pcibios.c | 3 ++- src/arch/i386/interface/pcbios/rtc_entropy.c | 3 ++- src/arch/i386/interface/pcbios/rtc_time.c | 3 ++- src/arch/i386/interface/pxe/pxe_call.c | 3 ++- src/arch/i386/interface/pxe/pxe_entry.S | 3 ++- src/arch/i386/interface/pxe/pxe_exit_hook.c | 3 ++- src/arch/i386/interface/pxe/pxe_file.c | 3 ++- src/arch/i386/interface/pxe/pxe_loader.c | 3 ++- src/arch/i386/interface/pxe/pxe_preboot.c | 3 ++- src/arch/i386/interface/pxe/pxe_tftp.c | 3 ++- src/arch/i386/interface/pxe/pxe_udp.c | 3 ++- src/arch/i386/interface/pxe/pxe_undi.c | 3 ++- src/arch/i386/interface/pxeparent/pxeparent.c | 3 ++- src/arch/i386/interface/pxeparent/pxeparent_dhcp.c | 3 ++- src/arch/i386/interface/syslinux/com32_call.c | 3 ++- src/arch/i386/interface/syslinux/com32_wrapper.S | 3 ++- src/arch/i386/interface/syslinux/comboot_call.c | 3 ++- src/arch/i386/interface/vmware/guestinfo.c | 3 ++- src/arch/i386/interface/vmware/guestrpc.c | 3 ++- src/arch/i386/interface/vmware/vmconsole.c | 3 ++- src/arch/i386/interface/vmware/vmware.c | 3 ++- src/arch/i386/prefix/exeprefix.S | 3 ++- src/arch/i386/prefix/libprefix.S | 3 ++- src/arch/i386/prefix/mromprefix.S | 3 ++- src/arch/i386/transitions/liba20.S | 3 ++- src/arch/x86/core/cpuid.c | 3 ++- src/arch/x86/core/pcidirect.c | 3 ++- src/arch/x86/core/x86_bigint.c | 3 ++- src/arch/x86/core/x86_io.c | 3 ++- src/arch/x86/core/x86_string.c | 3 ++- src/arch/x86/hci/commands/cpuid_cmd.c | 3 ++- src/arch/x86/interface/efi/efix86_nap.c | 3 ++- src/arch/x86/prefix/efidrvprefix.c | 3 ++- src/arch/x86/prefix/efiprefix.c | 3 ++- src/core/acpi.c | 3 ++- src/core/ansiesc.c | 3 ++- src/core/assert.c | 3 ++- src/core/base16.c | 3 ++- src/core/base64.c | 3 ++- src/core/basename.c | 3 ++- src/core/bitmap.c | 3 ++- src/core/blockdev.c | 3 ++- src/core/cpio.c | 3 ++- src/core/ctype.c | 3 ++- src/core/cwuri.c | 3 ++- src/core/debug.c | 3 ++- src/core/debug_md5.c | 3 ++- src/core/device.c | 3 ++- src/core/downloader.c | 3 ++- src/core/edd.c | 3 ++- src/core/exec.c | 3 ++- src/core/fnrec.c | 3 ++- src/core/gdbserial.c | 3 ++- src/core/gdbstub.c | 3 ++- src/core/gdbudp.c | 3 ++- src/core/getkey.c | 3 ++- src/core/getopt.c | 3 ++- src/core/image.c | 3 ++- src/core/init.c | 3 ++- src/core/interface.c | 3 ++- src/core/iobuf.c | 3 ++- src/core/job.c | 3 ++- src/core/linebuf.c | 3 ++- src/core/lineconsole.c | 3 ++- src/core/log.c | 3 ++- src/core/malloc.c | 3 ++- src/core/menu.c | 3 ++- src/core/monojob.c | 3 ++- src/core/null_sanboot.c | 3 ++- src/core/null_time.c | 3 ++- src/core/nvo.c | 3 ++- src/core/open.c | 3 ++- src/core/parseopt.c | 3 ++- src/core/pending.c | 3 ++- src/core/posix_io.c | 3 ++- src/core/process.c | 3 ++- src/core/refcnt.c | 3 ++- src/core/resolv.c | 3 ++- src/core/settings.c | 3 ++- src/core/time.c | 3 ++- src/core/timer.c | 3 ++- src/core/uri.c | 3 ++- src/core/uuid.c | 3 ++- src/core/vsprintf.c | 3 ++- src/core/xfer.c | 3 ++- src/crypto/aes_wrap.c | 3 ++- src/crypto/arc4.c | 3 ++- src/crypto/asn1.c | 3 ++- src/crypto/axtls_aes.c | 3 ++- src/crypto/bigint.c | 3 ++- src/crypto/cbc.c | 3 ++- src/crypto/chap.c | 3 ++- src/crypto/clientcert.c | 3 ++- src/crypto/cms.c | 3 ++- src/crypto/crc32.c | 3 ++- src/crypto/crypto_null.c | 3 ++- src/crypto/drbg.c | 3 ++- src/crypto/entropy.c | 3 ++- src/crypto/hash_df.c | 3 ++- src/crypto/hmac.c | 3 ++- src/crypto/hmac_drbg.c | 3 ++- src/crypto/md5.c | 3 ++- src/crypto/null_entropy.c | 3 ++- src/crypto/random_nz.c | 3 ++- src/crypto/rbg.c | 3 ++- src/crypto/rootcert.c | 3 ++- src/crypto/rsa.c | 3 ++- src/crypto/sha1.c | 3 ++- src/crypto/sha1extra.c | 3 ++- src/crypto/sha256.c | 3 ++- src/crypto/x509.c | 3 ++- src/drivers/bitbash/bitbash.c | 3 ++- src/drivers/bitbash/i2c_bit.c | 3 ++- src/drivers/bitbash/spi_bit.c | 3 ++- src/drivers/block/ata.c | 3 ++- src/drivers/block/scsi.c | 3 ++- src/drivers/bus/isapnp.c | 3 ++- src/drivers/bus/pci.c | 3 ++- src/drivers/bus/pcibackup.c | 3 ++- src/drivers/bus/pcivpd.c | 3 ++- src/drivers/infiniband/arbel.c | 3 ++- src/drivers/infiniband/hermon.c | 3 ++- src/drivers/infiniband/linda.c | 3 ++- src/drivers/infiniband/linda.h | 3 ++- src/drivers/infiniband/mlx_bitops.h | 3 ++- src/drivers/infiniband/qib7322.c | 3 ++- src/drivers/infiniband/qib7322.h | 3 ++- src/drivers/infiniband/qib_genbits.pl | 3 ++- src/drivers/net/3c515.c | 3 ++- src/drivers/net/amd8111e.c | 3 ++- src/drivers/net/amd8111e.h | 3 ++- src/drivers/net/atl1e.c | 4 ++-- src/drivers/net/atl1e.h | 4 ++-- src/drivers/net/b44.c | 3 ++- src/drivers/net/b44.h | 3 ++- src/drivers/net/cs89x0.h | 3 ++- src/drivers/net/dmfe.c | 3 ++- src/drivers/net/eepro100.c | 3 ++- src/drivers/net/forcedeth.c | 3 ++- src/drivers/net/forcedeth.h | 3 ++- src/drivers/net/ipoib.c | 3 ++- src/drivers/net/jme.c | 3 ++- src/drivers/net/jme.h | 3 ++- src/drivers/net/myri10ge.c | 3 ++- src/drivers/net/myri10ge_mcp.h | 3 ++- src/drivers/net/pcnet32.c | 3 ++- src/drivers/net/pcnet32.h | 3 ++- src/drivers/net/phantom/nx_bitops.h | 3 ++- src/drivers/net/phantom/phantom.c | 3 ++- src/drivers/net/phantom/phantom.h | 3 ++- src/drivers/net/phantom/phantom_hw.h | 3 ++- src/drivers/net/skge.c | 3 ++- src/drivers/net/sky2.c | 3 ++- src/drivers/net/sundance.c | 3 ++- src/drivers/net/tlan.c | 3 ++- src/drivers/net/tlan.h | 3 ++- src/drivers/net/via-velocity.c | 3 ++- src/drivers/net/vmxnet3.c | 3 ++- src/drivers/net/vmxnet3.h | 3 ++- src/drivers/net/w89c840.c | 3 ++- src/drivers/nvs/nvs.c | 3 ++- src/drivers/nvs/nvsvpd.c | 3 ++- src/drivers/nvs/spi.c | 3 ++- src/drivers/nvs/threewire.c | 3 ++- src/hci/commands/autoboot_cmd.c | 3 ++- src/hci/commands/config_cmd.c | 3 ++- src/hci/commands/dhcp_cmd.c | 3 ++- src/hci/commands/digest_cmd.c | 3 ++- src/hci/commands/fcmgmt_cmd.c | 3 ++- src/hci/commands/gdbstub_cmd.c | 3 ++- src/hci/commands/ifmgmt_cmd.c | 3 ++- src/hci/commands/image_cmd.c | 3 ++- src/hci/commands/image_trust_cmd.c | 3 ++- src/hci/commands/iwmgmt_cmd.c | 3 ++- src/hci/commands/login_cmd.c | 3 ++- src/hci/commands/lotest_cmd.c | 3 ++- src/hci/commands/menu_cmd.c | 3 ++- src/hci/commands/nvo_cmd.c | 3 ++- src/hci/commands/route_cmd.c | 3 ++- src/hci/commands/sanboot_cmd.c | 3 ++- src/hci/commands/sync_cmd.c | 3 ++- src/hci/commands/time_cmd.c | 3 ++- src/hci/commands/vlan_cmd.c | 3 ++- src/hci/editstring.c | 3 ++- src/hci/mucurses/widgets/editbox.c | 3 ++- src/hci/readline.c | 3 ++- src/hci/shell.c | 3 ++- src/hci/tui/login_ui.c | 3 ++- src/hci/tui/menu_ui.c | 3 ++- src/hci/tui/settings_ui.c | 3 ++- src/hci/wireless_errors.c | 3 ++- src/image/efi_image.c | 3 ++- src/image/elf.c | 3 ++- src/image/script.c | 3 ++- src/image/segment.c | 3 ++- src/include/errno.h | 3 ++- src/include/hci/ifmgmt_cmd.h | 3 ++- src/include/ipxe/bitops.h | 3 ++- src/include/ipxe/eapol.h | 3 ++- src/include/ipxe/fip.h | 3 ++- src/include/ipxe/isapnp.h | 3 ++- src/include/ipxe/sec80211.h | 3 ++- src/include/ipxe/wpa.h | 3 ++- src/interface/bofm/bofm.c | 3 ++- src/interface/efi/efi_bofm.c | 3 ++- src/interface/efi/efi_console.c | 3 ++- src/interface/efi/efi_driver.c | 3 ++- src/interface/efi/efi_init.c | 3 ++- src/interface/efi/efi_io.c | 3 ++- src/interface/efi/efi_pci.c | 3 ++- src/interface/efi/efi_smbios.c | 3 ++- src/interface/efi/efi_snp.c | 3 ++- src/interface/efi/efi_strerror.c | 3 ++- src/interface/efi/efi_strings.c | 3 ++- src/interface/efi/efi_timer.c | 3 ++- src/interface/efi/efi_uaccess.c | 3 ++- src/interface/efi/efi_umalloc.c | 3 ++- src/interface/linux/linux_entropy.c | 3 ++- src/interface/linux/linux_nap.c | 3 ++- src/interface/linux/linux_uaccess.c | 3 ++- src/interface/smbios/smbios.c | 3 ++- src/interface/smbios/smbios_settings.c | 3 ++- src/net/80211/net80211.c | 3 ++- src/net/80211/rc80211.c | 3 ++- src/net/80211/sec80211.c | 3 ++- src/net/80211/wep.c | 3 ++- src/net/80211/wpa.c | 3 ++- src/net/80211/wpa_ccmp.c | 3 ++- src/net/80211/wpa_psk.c | 3 ++- src/net/80211/wpa_tkip.c | 3 ++- src/net/aoe.c | 3 ++- src/net/arp.c | 3 ++- src/net/cachedhcp.c | 3 ++- src/net/dhcpopts.c | 3 ++- src/net/dhcppkt.c | 3 ++- src/net/eapol.c | 3 ++- src/net/eth_slow.c | 3 ++- src/net/ethernet.c | 3 ++- src/net/fakedhcp.c | 3 ++- src/net/fc.c | 3 ++- src/net/fcels.c | 3 ++- src/net/fcns.c | 3 ++- src/net/fcoe.c | 3 ++- src/net/fcp.c | 3 ++- src/net/icmp.c | 3 ++- src/net/infiniband.c | 3 ++- src/net/infiniband/ib_cm.c | 3 ++- src/net/infiniband/ib_mcast.c | 3 ++- src/net/infiniband/ib_mi.c | 3 ++- src/net/infiniband/ib_packet.c | 3 ++- src/net/infiniband/ib_pathrec.c | 3 ++- src/net/infiniband/ib_sma.c | 3 ++- src/net/infiniband/ib_smc.c | 3 ++- src/net/iobpad.c | 3 ++- src/net/netdev_settings.c | 3 ++- src/net/netdevice.c | 3 ++- src/net/nullnet.c | 3 ++- src/net/rarp.c | 3 ++- src/net/retry.c | 3 ++- src/net/tcp/http.c | 3 ++- src/net/tcp/httpcore.c | 3 ++- src/net/tcp/https.c | 3 ++- src/net/tcp/iscsi.c | 3 ++- src/net/tcp/syslogs.c | 3 ++- src/net/tls.c | 3 ++- src/net/udp/dhcp.c | 3 ++- src/net/udp/dns.c | 3 ++- src/net/udp/slam.c | 3 ++- src/net/udp/syslog.c | 3 ++- src/net/udp/tftp.c | 3 ++- src/net/vlan.c | 3 ++- src/tests/aes_cbc_test.c | 3 ++- src/tests/bigint_test.c | 3 ++- src/tests/bofm_test.c | 3 ++- src/tests/byteswap_test.c | 3 ++- src/tests/cbc_test.c | 3 ++- src/tests/cms_test.c | 3 ++- src/tests/digest_test.c | 3 ++- src/tests/entropy_sample.c | 3 ++- src/tests/hash_df_test.c | 3 ++- src/tests/hmac_drbg_test.c | 3 ++- src/tests/list_test.c | 3 ++- src/tests/md5_test.c | 3 ++- src/tests/rsa_test.c | 3 ++- src/tests/settings_test.c | 3 ++- src/tests/sha1_test.c | 3 ++- src/tests/sha256_test.c | 3 ++- src/tests/test.c | 3 ++- src/tests/tests.c | 3 ++- src/tests/time_test.c | 3 ++- src/tests/x509_test.c | 3 ++- src/usr/autoboot.c | 3 ++- src/usr/dhcpmgmt.c | 3 ++- src/usr/fcmgmt.c | 3 ++- src/usr/ifmgmt.c | 3 ++- src/usr/imgmgmt.c | 3 ++- src/usr/imgtrust.c | 3 ++- src/usr/iwmgmt.c | 3 ++- src/usr/lotest.c | 3 ++- src/usr/prompt.c | 3 ++- src/usr/pxemenu.c | 3 ++- src/usr/route.c | 3 ++- src/util/Option/ROM.pm | 3 ++- src/util/disrom.pl | 3 ++- src/util/efirom.c | 3 ++- src/util/einfo.c | 3 ++- src/util/elf2efi.c | 3 ++- src/util/fixrom.pl | 3 ++- src/util/fnrec.pl | 3 ++- src/util/genkeymap.pl | 3 ++- src/util/get-pci-ids | 3 ++- src/util/licence.pl | 3 ++- src/util/mergerom.pl | 3 ++- 345 files changed, 690 insertions(+), 347 deletions(-) diff --git a/src/arch/i386/core/basemem_packet.c b/src/arch/i386/core/basemem_packet.c index d487cce3..06ffa3bb 100644 --- a/src/arch/i386/core/basemem_packet.c +++ b/src/arch/i386/core/basemem_packet.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/core/gdbmach.c b/src/arch/i386/core/gdbmach.c index 68b37c04..4232c755 100644 --- a/src/arch/i386/core/gdbmach.c +++ b/src/arch/i386/core/gdbmach.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/core/pic8259.c b/src/arch/i386/core/pic8259.c index 0264c0c1..0a9ea2e0 100644 --- a/src/arch/i386/core/pic8259.c +++ b/src/arch/i386/core/pic8259.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/core/rdtsc_timer.c b/src/arch/i386/core/rdtsc_timer.c index d2a8cc84..2f31afc6 100644 --- a/src/arch/i386/core/rdtsc_timer.c +++ b/src/arch/i386/core/rdtsc_timer.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/core/runtime.c b/src/arch/i386/core/runtime.c index fcfec060..18ca7936 100644 --- a/src/arch/i386/core/runtime.c +++ b/src/arch/i386/core/runtime.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/drivers/net/undi.c b/src/arch/i386/drivers/net/undi.c index ad655620..2bc54824 100644 --- a/src/arch/i386/drivers/net/undi.c +++ b/src/arch/i386/drivers/net/undi.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/drivers/net/undiload.c b/src/arch/i386/drivers/net/undiload.c index c278db79..0edfa35d 100644 --- a/src/arch/i386/drivers/net/undiload.c +++ b/src/arch/i386/drivers/net/undiload.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index def44113..6205c809 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/drivers/net/undionly.c b/src/arch/i386/drivers/net/undionly.c index a0012c88..028fac5d 100644 --- a/src/arch/i386/drivers/net/undionly.c +++ b/src/arch/i386/drivers/net/undionly.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/drivers/net/undipreload.c b/src/arch/i386/drivers/net/undipreload.c index a4b2f4ac..81d7a80e 100644 --- a/src/arch/i386/drivers/net/undipreload.c +++ b/src/arch/i386/drivers/net/undipreload.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/drivers/net/undirom.c b/src/arch/i386/drivers/net/undirom.c index 2463d969..b54c6170 100644 --- a/src/arch/i386/drivers/net/undirom.c +++ b/src/arch/i386/drivers/net/undirom.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/firmware/pcbios/basemem.c b/src/arch/i386/firmware/pcbios/basemem.c index d18e8b80..b23f2c35 100644 --- a/src/arch/i386/firmware/pcbios/basemem.c +++ b/src/arch/i386/firmware/pcbios/basemem.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/firmware/pcbios/bios_console.c b/src/arch/i386/firmware/pcbios/bios_console.c index 7f9892fc..25c8dad2 100644 --- a/src/arch/i386/firmware/pcbios/bios_console.c +++ b/src/arch/i386/firmware/pcbios/bios_console.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/firmware/pcbios/e820mangler.S b/src/arch/i386/firmware/pcbios/e820mangler.S index eeed51f8..cea17ef8 100644 --- a/src/arch/i386/firmware/pcbios/e820mangler.S +++ b/src/arch/i386/firmware/pcbios/e820mangler.S @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ) diff --git a/src/arch/i386/firmware/pcbios/fakee820.c b/src/arch/i386/firmware/pcbios/fakee820.c index ea116fe5..e5f71372 100644 --- a/src/arch/i386/firmware/pcbios/fakee820.c +++ b/src/arch/i386/firmware/pcbios/fakee820.c @@ -12,7 +12,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/firmware/pcbios/hidemem.c b/src/arch/i386/firmware/pcbios/hidemem.c index cc5fc28f..c1788b3a 100644 --- a/src/arch/i386/firmware/pcbios/hidemem.c +++ b/src/arch/i386/firmware/pcbios/hidemem.c @@ -12,7 +12,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/firmware/pcbios/memmap.c b/src/arch/i386/firmware/pcbios/memmap.c index 493d2c20..cf659226 100644 --- a/src/arch/i386/firmware/pcbios/memmap.c +++ b/src/arch/i386/firmware/pcbios/memmap.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/firmware/pcbios/pnpbios.c b/src/arch/i386/firmware/pcbios/pnpbios.c index c572914f..5c74b043 100644 --- a/src/arch/i386/firmware/pcbios/pnpbios.c +++ b/src/arch/i386/firmware/pcbios/pnpbios.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/hci/commands/pxe_cmd.c b/src/arch/i386/hci/commands/pxe_cmd.c index 79585cde..f86f180c 100644 --- a/src/arch/i386/hci/commands/pxe_cmd.c +++ b/src/arch/i386/hci/commands/pxe_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/arch/i386/hci/commands/reboot_cmd.c b/src/arch/i386/hci/commands/reboot_cmd.c index d6a1d9a3..74c69c94 100644 --- a/src/arch/i386/hci/commands/reboot_cmd.c +++ b/src/arch/i386/hci/commands/reboot_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/arch/i386/image/bootsector.c b/src/arch/i386/image/bootsector.c index f96cf201..289be7d7 100644 --- a/src/arch/i386/image/bootsector.c +++ b/src/arch/i386/image/bootsector.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index 08eb4d34..67bd665f 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/image/com32.c b/src/arch/i386/image/com32.c index d6e48ebe..5cc9a447 100644 --- a/src/arch/i386/image/com32.c +++ b/src/arch/i386/image/com32.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** diff --git a/src/arch/i386/image/comboot.c b/src/arch/i386/image/comboot.c index 0b924cce..915ed2de 100644 --- a/src/arch/i386/image/comboot.c +++ b/src/arch/i386/image/comboot.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** diff --git a/src/arch/i386/image/elfboot.c b/src/arch/i386/image/elfboot.c index 21504b7a..a867a956 100644 --- a/src/arch/i386/image/elfboot.c +++ b/src/arch/i386/image/elfboot.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/image/multiboot.c b/src/arch/i386/image/multiboot.c index 004a01b1..8b8959e1 100644 --- a/src/arch/i386/image/multiboot.c +++ b/src/arch/i386/image/multiboot.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/image/pxe_image.c b/src/arch/i386/image/pxe_image.c index 722f6bbc..4a7d874b 100644 --- a/src/arch/i386/image/pxe_image.c +++ b/src/arch/i386/image/pxe_image.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/include/pxe_api.h b/src/arch/i386/include/pxe_api.h index fd179ddb..e4396efb 100644 --- a/src/arch/i386/include/pxe_api.h +++ b/src/arch/i386/include/pxe_api.h @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * As an alternative, at your option, you may use this file under the * following terms, known as the "MIT license": diff --git a/src/arch/i386/interface/pcbios/bios_smbios.c b/src/arch/i386/interface/pcbios/bios_smbios.c index cde3d060..2ecc24ea 100644 --- a/src/arch/i386/interface/pcbios/bios_smbios.c +++ b/src/arch/i386/interface/pcbios/bios_smbios.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pcbios/bios_timer.c b/src/arch/i386/interface/pcbios/bios_timer.c index 70c3986b..3cb8756f 100644 --- a/src/arch/i386/interface/pcbios/bios_timer.c +++ b/src/arch/i386/interface/pcbios/bios_timer.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pcbios/int13.c b/src/arch/i386/interface/pcbios/int13.c index 0a1e7748..191e7418 100644 --- a/src/arch/i386/interface/pcbios/int13.c +++ b/src/arch/i386/interface/pcbios/int13.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pcbios/memtop_umalloc.c b/src/arch/i386/interface/pcbios/memtop_umalloc.c index dba4a23a..1821faf2 100644 --- a/src/arch/i386/interface/pcbios/memtop_umalloc.c +++ b/src/arch/i386/interface/pcbios/memtop_umalloc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pcbios/pcibios.c b/src/arch/i386/interface/pcbios/pcibios.c index 511ec623..61873039 100644 --- a/src/arch/i386/interface/pcbios/pcibios.c +++ b/src/arch/i386/interface/pcbios/pcibios.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pcbios/rtc_entropy.c b/src/arch/i386/interface/pcbios/rtc_entropy.c index 3f2a7c78..fad421c2 100644 --- a/src/arch/i386/interface/pcbios/rtc_entropy.c +++ b/src/arch/i386/interface/pcbios/rtc_entropy.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pcbios/rtc_time.c b/src/arch/i386/interface/pcbios/rtc_time.c index b5b46ff4..67041d4c 100644 --- a/src/arch/i386/interface/pcbios/rtc_time.c +++ b/src/arch/i386/interface/pcbios/rtc_time.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c index 3e461d02..b8e73a06 100644 --- a/src/arch/i386/interface/pxe/pxe_call.c +++ b/src/arch/i386/interface/pxe/pxe_call.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_entry.S b/src/arch/i386/interface/pxe/pxe_entry.S index 0d3a57cd..6274264f 100644 --- a/src/arch/i386/interface/pxe/pxe_entry.S +++ b/src/arch/i386/interface/pxe/pxe_entry.S @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/src/arch/i386/interface/pxe/pxe_exit_hook.c b/src/arch/i386/interface/pxe/pxe_exit_hook.c index 507229d8..9d189650 100644 --- a/src/arch/i386/interface/pxe/pxe_exit_hook.c +++ b/src/arch/i386/interface/pxe/pxe_exit_hook.c @@ -19,7 +19,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_file.c b/src/arch/i386/interface/pxe/pxe_file.c index ffb27087..6e961029 100644 --- a/src/arch/i386/interface/pxe/pxe_file.c +++ b/src/arch/i386/interface/pxe/pxe_file.c @@ -29,7 +29,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_loader.c b/src/arch/i386/interface/pxe/pxe_loader.c index 63858be2..695af3b9 100644 --- a/src/arch/i386/interface/pxe/pxe_loader.c +++ b/src/arch/i386/interface/pxe/pxe_loader.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_preboot.c b/src/arch/i386/interface/pxe/pxe_preboot.c index 839e4faf..534352b2 100644 --- a/src/arch/i386/interface/pxe/pxe_preboot.c +++ b/src/arch/i386/interface/pxe/pxe_preboot.c @@ -20,7 +20,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_tftp.c b/src/arch/i386/interface/pxe/pxe_tftp.c index 2249fc83..aab376e8 100644 --- a/src/arch/i386/interface/pxe/pxe_tftp.c +++ b/src/arch/i386/interface/pxe/pxe_tftp.c @@ -19,7 +19,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_udp.c b/src/arch/i386/interface/pxe/pxe_udp.c index a127f453..32bc39c8 100644 --- a/src/arch/i386/interface/pxe/pxe_udp.c +++ b/src/arch/i386/interface/pxe/pxe_udp.c @@ -28,7 +28,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxe/pxe_undi.c b/src/arch/i386/interface/pxe/pxe_undi.c index d605c82f..f9282db1 100644 --- a/src/arch/i386/interface/pxe/pxe_undi.c +++ b/src/arch/i386/interface/pxe/pxe_undi.c @@ -19,7 +19,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxeparent/pxeparent.c b/src/arch/i386/interface/pxeparent/pxeparent.c index e9330744..8b2a2c88 100644 --- a/src/arch/i386/interface/pxeparent/pxeparent.c +++ b/src/arch/i386/interface/pxeparent/pxeparent.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c b/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c index 8fe1572f..f3728633 100644 --- a/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c +++ b/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/syslinux/com32_call.c b/src/arch/i386/interface/syslinux/com32_call.c index 47df64cb..8fffd069 100644 --- a/src/arch/i386/interface/syslinux/com32_call.c +++ b/src/arch/i386/interface/syslinux/com32_call.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** diff --git a/src/arch/i386/interface/syslinux/com32_wrapper.S b/src/arch/i386/interface/syslinux/com32_wrapper.S index 4cd88221..69cea02e 100644 --- a/src/arch/i386/interface/syslinux/com32_wrapper.S +++ b/src/arch/i386/interface/syslinux/com32_wrapper.S @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ) diff --git a/src/arch/i386/interface/syslinux/comboot_call.c b/src/arch/i386/interface/syslinux/comboot_call.c index 7ee5f61b..3eee584c 100644 --- a/src/arch/i386/interface/syslinux/comboot_call.c +++ b/src/arch/i386/interface/syslinux/comboot_call.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** diff --git a/src/arch/i386/interface/vmware/guestinfo.c b/src/arch/i386/interface/vmware/guestinfo.c index 5f73e949..3e20b8ed 100644 --- a/src/arch/i386/interface/vmware/guestinfo.c +++ b/src/arch/i386/interface/vmware/guestinfo.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/vmware/guestrpc.c b/src/arch/i386/interface/vmware/guestrpc.c index a19e5bff..390fc554 100644 --- a/src/arch/i386/interface/vmware/guestrpc.c +++ b/src/arch/i386/interface/vmware/guestrpc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/vmware/vmconsole.c b/src/arch/i386/interface/vmware/vmconsole.c index 7f02c50e..48510520 100644 --- a/src/arch/i386/interface/vmware/vmconsole.c +++ b/src/arch/i386/interface/vmware/vmconsole.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/interface/vmware/vmware.c b/src/arch/i386/interface/vmware/vmware.c index 8cc26c94..8074e611 100644 --- a/src/arch/i386/interface/vmware/vmware.c +++ b/src/arch/i386/interface/vmware/vmware.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/i386/prefix/exeprefix.S b/src/arch/i386/prefix/exeprefix.S index 5ba0239a..acd3f83c 100644 --- a/src/arch/i386/prefix/exeprefix.S +++ b/src/arch/i386/prefix/exeprefix.S @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S index e5bc7bb1..2f8fc4e1 100644 --- a/src/arch/i386/prefix/libprefix.S +++ b/src/arch/i386/prefix/libprefix.S @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/src/arch/i386/prefix/mromprefix.S b/src/arch/i386/prefix/mromprefix.S index abe1c9e3..058663c4 100644 --- a/src/arch/i386/prefix/mromprefix.S +++ b/src/arch/i386/prefix/mromprefix.S @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/src/arch/i386/transitions/liba20.S b/src/arch/i386/transitions/liba20.S index a60f1a54..68469752 100644 --- a/src/arch/i386/transitions/liba20.S +++ b/src/arch/i386/transitions/liba20.S @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/src/arch/x86/core/cpuid.c b/src/arch/x86/core/cpuid.c index cf9dd6dd..96f79409 100644 --- a/src/arch/x86/core/cpuid.c +++ b/src/arch/x86/core/cpuid.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/x86/core/pcidirect.c b/src/arch/x86/core/pcidirect.c index a07f7d4b..dbc8317b 100644 --- a/src/arch/x86/core/pcidirect.c +++ b/src/arch/x86/core/pcidirect.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/x86/core/x86_bigint.c b/src/arch/x86/core/x86_bigint.c index cb6c67b1..418ac230 100644 --- a/src/arch/x86/core/x86_bigint.c +++ b/src/arch/x86/core/x86_bigint.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/x86/core/x86_io.c b/src/arch/x86/core/x86_io.c index f1c3eb03..9b2d2d93 100644 --- a/src/arch/x86/core/x86_io.c +++ b/src/arch/x86/core/x86_io.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 8c3a4d2a..698dbe2e 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ /** @file diff --git a/src/arch/x86/hci/commands/cpuid_cmd.c b/src/arch/x86/hci/commands/cpuid_cmd.c index 6659bf60..98114330 100644 --- a/src/arch/x86/hci/commands/cpuid_cmd.c +++ b/src/arch/x86/hci/commands/cpuid_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/x86/interface/efi/efix86_nap.c b/src/arch/x86/interface/efi/efix86_nap.c index b6bee627..b05421fa 100644 --- a/src/arch/x86/interface/efi/efix86_nap.c +++ b/src/arch/x86/interface/efi/efix86_nap.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/x86/prefix/efidrvprefix.c b/src/arch/x86/prefix/efidrvprefix.c index a96c5c43..8a31df56 100644 --- a/src/arch/x86/prefix/efidrvprefix.c +++ b/src/arch/x86/prefix/efidrvprefix.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/arch/x86/prefix/efiprefix.c b/src/arch/x86/prefix/efiprefix.c index 1515c6fc..bfa94d40 100644 --- a/src/arch/x86/prefix/efiprefix.c +++ b/src/arch/x86/prefix/efiprefix.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/acpi.c b/src/core/acpi.c index 223765f7..330f5063 100644 --- a/src/core/acpi.c +++ b/src/core/acpi.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/ansiesc.c b/src/core/ansiesc.c index 05bbb869..32e9d7c9 100644 --- a/src/core/ansiesc.c +++ b/src/core/ansiesc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/assert.c b/src/core/assert.c index 45d3b9b7..0791ea7b 100644 --- a/src/core/assert.c +++ b/src/core/assert.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/base16.c b/src/core/base16.c index 14de7957..1f0e536c 100644 --- a/src/core/base16.c +++ b/src/core/base16.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/base64.c b/src/core/base64.c index 761b42f2..bdaf7095 100644 --- a/src/core/base64.c +++ b/src/core/base64.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/basename.c b/src/core/basename.c index a481c54f..b534a788 100644 --- a/src/core/basename.c +++ b/src/core/basename.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/bitmap.c b/src/core/bitmap.c index e9b6d904..0d115232 100644 --- a/src/core/bitmap.c +++ b/src/core/bitmap.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/blockdev.c b/src/core/blockdev.c index 182765e3..9d118cb2 100644 --- a/src/core/blockdev.c +++ b/src/core/blockdev.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/cpio.c b/src/core/cpio.c index 5b7b3aa1..3a5f4d2b 100644 --- a/src/core/cpio.c +++ b/src/core/cpio.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/ctype.c b/src/core/ctype.c index 6185bb2f..c812346a 100644 --- a/src/core/ctype.c +++ b/src/core/ctype.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/cwuri.c b/src/core/cwuri.c index 893e2050..5865552a 100644 --- a/src/core/cwuri.c +++ b/src/core/cwuri.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/debug.c b/src/core/debug.c index fc90c64a..627d5d9a 100644 --- a/src/core/debug.c +++ b/src/core/debug.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/debug_md5.c b/src/core/debug_md5.c index 6214f611..f049ac75 100644 --- a/src/core/debug_md5.c +++ b/src/core/debug_md5.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/device.c b/src/core/device.c index dc182e03..330f95c5 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/downloader.c b/src/core/downloader.c index b4c5a5a7..4f3fc2c8 100644 --- a/src/core/downloader.c +++ b/src/core/downloader.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/edd.c b/src/core/edd.c index 8ba24b17..d574ea6c 100644 --- a/src/core/edd.c +++ b/src/core/edd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/exec.c b/src/core/exec.c index 5b3d1489..843a51db 100644 --- a/src/core/exec.c +++ b/src/core/exec.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/fnrec.c b/src/core/fnrec.c index 05d63aaa..3453c8b6 100644 --- a/src/core/fnrec.c +++ b/src/core/fnrec.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/gdbserial.c b/src/core/gdbserial.c index ed217add..6f78c88b 100644 --- a/src/core/gdbserial.c +++ b/src/core/gdbserial.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/gdbstub.c b/src/core/gdbstub.c index 34e6a037..cbe328f9 100644 --- a/src/core/gdbstub.c +++ b/src/core/gdbstub.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/gdbudp.c b/src/core/gdbudp.c index 9cb6572b..5977547c 100644 --- a/src/core/gdbudp.c +++ b/src/core/gdbudp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/getkey.c b/src/core/getkey.c index d692b1bc..f16cafa4 100644 --- a/src/core/getkey.c +++ b/src/core/getkey.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/getopt.c b/src/core/getopt.c index 8a0fa2d0..abc1edd6 100644 --- a/src/core/getopt.c +++ b/src/core/getopt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/image.c b/src/core/image.c index 1bf5447f..4101ff3b 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/init.c b/src/core/init.c index 4dc706f6..56274419 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/interface.c b/src/core/interface.c index c69875ea..97caac80 100644 --- a/src/core/interface.c +++ b/src/core/interface.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/iobuf.c b/src/core/iobuf.c index 0c61306e..c0491181 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/job.c b/src/core/job.c index ac4e43e7..64d184ec 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/linebuf.c b/src/core/linebuf.c index f152bccb..8fb2f86a 100644 --- a/src/core/linebuf.c +++ b/src/core/linebuf.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/lineconsole.c b/src/core/lineconsole.c index 71bc1f8b..1b6791cf 100644 --- a/src/core/lineconsole.c +++ b/src/core/lineconsole.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/log.c b/src/core/log.c index c0c3656c..f160b4fc 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/malloc.c b/src/core/malloc.c index 1b8ac17e..9d81ca5c 100644 --- a/src/core/malloc.c +++ b/src/core/malloc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/menu.c b/src/core/menu.c index 1d1678f3..8d42e1f8 100644 --- a/src/core/menu.c +++ b/src/core/menu.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/monojob.c b/src/core/monojob.c index d2161b3c..d262f70b 100644 --- a/src/core/monojob.c +++ b/src/core/monojob.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/null_sanboot.c b/src/core/null_sanboot.c index 6584e7a1..18c0dea8 100644 --- a/src/core/null_sanboot.c +++ b/src/core/null_sanboot.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/null_time.c b/src/core/null_time.c index f9c48a95..506c70b5 100644 --- a/src/core/null_time.c +++ b/src/core/null_time.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/nvo.c b/src/core/nvo.c index ea58bade..ffa30b89 100644 --- a/src/core/nvo.c +++ b/src/core/nvo.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/open.c b/src/core/open.c index b026efcd..b479c297 100644 --- a/src/core/open.c +++ b/src/core/open.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/parseopt.c b/src/core/parseopt.c index 432e856d..659d20ee 100644 --- a/src/core/parseopt.c +++ b/src/core/parseopt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/pending.c b/src/core/pending.c index da540fec..c2671a68 100644 --- a/src/core/pending.c +++ b/src/core/pending.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/posix_io.c b/src/core/posix_io.c index 38bd727b..8460d0f5 100644 --- a/src/core/posix_io.c +++ b/src/core/posix_io.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/process.c b/src/core/process.c index 4a705ef6..d341a2c3 100644 --- a/src/core/process.c +++ b/src/core/process.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/refcnt.c b/src/core/refcnt.c index 6117d741..68a86120 100644 --- a/src/core/refcnt.c +++ b/src/core/refcnt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/resolv.c b/src/core/resolv.c index 31e80aab..86f19ee2 100644 --- a/src/core/resolv.c +++ b/src/core/resolv.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/settings.c b/src/core/settings.c index 02dd07e3..392f598d 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/time.c b/src/core/time.c index 52ae3ee9..f70e1981 100644 --- a/src/core/time.c +++ b/src/core/time.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/timer.c b/src/core/timer.c index 096d07ec..18c2b284 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/uri.c b/src/core/uri.c index ff49e47a..e9526882 100644 --- a/src/core/uri.c +++ b/src/core/uri.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/uuid.c b/src/core/uuid.c index cc41afda..27a249da 100644 --- a/src/core/uuid.c +++ b/src/core/uuid.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/vsprintf.c b/src/core/vsprintf.c index dd1a101d..5cc72310 100644 --- a/src/core/vsprintf.c +++ b/src/core/vsprintf.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/core/xfer.c b/src/core/xfer.c index 037c089a..8d4bc9f5 100644 --- a/src/core/xfer.c +++ b/src/core/xfer.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/aes_wrap.c b/src/crypto/aes_wrap.c index f59fbf91..c09480e5 100644 --- a/src/crypto/aes_wrap.c +++ b/src/crypto/aes_wrap.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/arc4.c b/src/crypto/arc4.c index ab3325c8..91a73201 100644 --- a/src/crypto/arc4.c +++ b/src/crypto/arc4.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/asn1.c b/src/crypto/asn1.c index 462885f3..6d880704 100644 --- a/src/crypto/asn1.c +++ b/src/crypto/asn1.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/axtls_aes.c b/src/crypto/axtls_aes.c index 3f1d668a..7f93c0ed 100644 --- a/src/crypto/axtls_aes.c +++ b/src/crypto/axtls_aes.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/bigint.c b/src/crypto/bigint.c index b13b0ac6..340128e2 100644 --- a/src/crypto/bigint.c +++ b/src/crypto/bigint.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/cbc.c b/src/crypto/cbc.c index c00ebb0a..28d38b2d 100644 --- a/src/crypto/cbc.c +++ b/src/crypto/cbc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/chap.c b/src/crypto/chap.c index 492d2216..db64371c 100644 --- a/src/crypto/chap.c +++ b/src/crypto/chap.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/clientcert.c b/src/crypto/clientcert.c index 01ab2e38..5ce1f6c1 100644 --- a/src/crypto/clientcert.c +++ b/src/crypto/clientcert.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/cms.c b/src/crypto/cms.c index 2083433e..c0c8d144 100644 --- a/src/crypto/cms.c +++ b/src/crypto/cms.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/crc32.c b/src/crypto/crc32.c index 71ec1d66..cfef68c0 100644 --- a/src/crypto/crc32.c +++ b/src/crypto/crc32.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/crypto_null.c b/src/crypto/crypto_null.c index 590ac560..ba05f726 100644 --- a/src/crypto/crypto_null.c +++ b/src/crypto/crypto_null.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/drbg.c b/src/crypto/drbg.c index 809de372..9e0175d2 100644 --- a/src/crypto/drbg.c +++ b/src/crypto/drbg.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/entropy.c b/src/crypto/entropy.c index 03e7290a..c7045840 100644 --- a/src/crypto/entropy.c +++ b/src/crypto/entropy.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/hash_df.c b/src/crypto/hash_df.c index 250c2ffc..adf1d87e 100644 --- a/src/crypto/hash_df.c +++ b/src/crypto/hash_df.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/hmac.c b/src/crypto/hmac.c index 6b61dc44..e9459198 100644 --- a/src/crypto/hmac.c +++ b/src/crypto/hmac.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/hmac_drbg.c b/src/crypto/hmac_drbg.c index 3f56e1b7..1e5f732e 100644 --- a/src/crypto/hmac_drbg.c +++ b/src/crypto/hmac_drbg.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/md5.c b/src/crypto/md5.c index b8b7b43d..122c7d59 100644 --- a/src/crypto/md5.c +++ b/src/crypto/md5.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/null_entropy.c b/src/crypto/null_entropy.c index be2acae3..c56d5e76 100644 --- a/src/crypto/null_entropy.c +++ b/src/crypto/null_entropy.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/random_nz.c b/src/crypto/random_nz.c index 7b54aad7..f1d2e187 100644 --- a/src/crypto/random_nz.c +++ b/src/crypto/random_nz.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/rbg.c b/src/crypto/rbg.c index da0ad5df..e2d06978 100644 --- a/src/crypto/rbg.c +++ b/src/crypto/rbg.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/rootcert.c b/src/crypto/rootcert.c index ee2a3454..30ca170f 100644 --- a/src/crypto/rootcert.c +++ b/src/crypto/rootcert.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/rsa.c b/src/crypto/rsa.c index 563d6b9b..1a5cf6cd 100644 --- a/src/crypto/rsa.c +++ b/src/crypto/rsa.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/sha1.c b/src/crypto/sha1.c index 7f287d3c..e1bef669 100644 --- a/src/crypto/sha1.c +++ b/src/crypto/sha1.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/sha1extra.c b/src/crypto/sha1extra.c index 01d5f89c..cec0d35e 100644 --- a/src/crypto/sha1extra.c +++ b/src/crypto/sha1extra.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/sha256.c b/src/crypto/sha256.c index e85d2006..36e02b3c 100644 --- a/src/crypto/sha256.c +++ b/src/crypto/sha256.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/crypto/x509.c b/src/crypto/x509.c index a3a17991..df3c5c0d 100644 --- a/src/crypto/x509.c +++ b/src/crypto/x509.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/bitbash/bitbash.c b/src/drivers/bitbash/bitbash.c index ac914075..23ca3035 100644 --- a/src/drivers/bitbash/bitbash.c +++ b/src/drivers/bitbash/bitbash.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/bitbash/i2c_bit.c b/src/drivers/bitbash/i2c_bit.c index ccf82db8..a72d1459 100644 --- a/src/drivers/bitbash/i2c_bit.c +++ b/src/drivers/bitbash/i2c_bit.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/bitbash/spi_bit.c b/src/drivers/bitbash/spi_bit.c index b64ffb82..4a9af0a3 100644 --- a/src/drivers/bitbash/spi_bit.c +++ b/src/drivers/bitbash/spi_bit.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/block/ata.c b/src/drivers/block/ata.c index 56740012..c9b87c20 100644 --- a/src/drivers/block/ata.c +++ b/src/drivers/block/ata.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/block/scsi.c b/src/drivers/block/scsi.c index fb90fbce..b45ae630 100644 --- a/src/drivers/block/scsi.c +++ b/src/drivers/block/scsi.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/bus/isapnp.c b/src/drivers/bus/isapnp.c index f7845d3f..6417c74a 100644 --- a/src/drivers/bus/isapnp.c +++ b/src/drivers/bus/isapnp.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code: * Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c index 3ae17e5c..7bd353d8 100644 --- a/src/drivers/bus/pci.c +++ b/src/drivers/bus/pci.c @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/bus/pcibackup.c b/src/drivers/bus/pcibackup.c index 6719c53c..6b592e89 100644 --- a/src/drivers/bus/pcibackup.c +++ b/src/drivers/bus/pcibackup.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/bus/pcivpd.c b/src/drivers/bus/pcivpd.c index 15cf9059..0b7a879f 100644 --- a/src/drivers/bus/pcivpd.c +++ b/src/drivers/bus/pcivpd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/arbel.c b/src/drivers/infiniband/arbel.c index 0a801856..95957d68 100644 --- a/src/drivers/infiniband/arbel.c +++ b/src/drivers/infiniband/arbel.c @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index dc3d413b..e7db0359 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/linda.c b/src/drivers/infiniband/linda.c index 6a6a2ec9..ae0a3039 100644 --- a/src/drivers/infiniband/linda.c +++ b/src/drivers/infiniband/linda.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/linda.h b/src/drivers/infiniband/linda.h index 1450a6ad..72ce7086 100644 --- a/src/drivers/infiniband/linda.h +++ b/src/drivers/infiniband/linda.h @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/mlx_bitops.h b/src/drivers/infiniband/mlx_bitops.h index 490d5e3c..b6ca9f63 100644 --- a/src/drivers/infiniband/mlx_bitops.h +++ b/src/drivers/infiniband/mlx_bitops.h @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/qib7322.c b/src/drivers/infiniband/qib7322.c index 8b61b8dc..d9baf46d 100644 --- a/src/drivers/infiniband/qib7322.c +++ b/src/drivers/infiniband/qib7322.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/qib7322.h b/src/drivers/infiniband/qib7322.h index 0dac09ef..63abe221 100644 --- a/src/drivers/infiniband/qib7322.h +++ b/src/drivers/infiniband/qib7322.h @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/infiniband/qib_genbits.pl b/src/drivers/infiniband/qib_genbits.pl index 1d5eeded..586f7b6b 100755 --- a/src/drivers/infiniband/qib_genbits.pl +++ b/src/drivers/infiniband/qib_genbits.pl @@ -14,7 +14,8 @@ # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; diff --git a/src/drivers/net/3c515.c b/src/drivers/net/3c515.c index 2b860690..f345bb96 100644 --- a/src/drivers/net/3c515.c +++ b/src/drivers/net/3c515.c @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code: * Copyright (C) 1997-2002 Donald Becker 3c515.c: A 3Com ISA EtherLink XL "Corkscrew" ethernet driver for linux. diff --git a/src/drivers/net/amd8111e.c b/src/drivers/net/amd8111e.c index 476d5306..693d77d1 100644 --- a/src/drivers/net/amd8111e.c +++ b/src/drivers/net/amd8111e.c @@ -24,7 +24,8 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * USA */ diff --git a/src/drivers/net/amd8111e.h b/src/drivers/net/amd8111e.h index a402a63e..7898deb6 100644 --- a/src/drivers/net/amd8111e.h +++ b/src/drivers/net/amd8111e.h @@ -14,7 +14,8 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * USA Module Name: diff --git a/src/drivers/net/atl1e.c b/src/drivers/net/atl1e.c index e4dd5c97..1ff0f0d1 100644 --- a/src/drivers/net/atl1e.c +++ b/src/drivers/net/atl1e.c @@ -17,8 +17,8 @@ * 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., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/atl1e.h b/src/drivers/net/atl1e.h index e759ea49..2c972ea1 100644 --- a/src/drivers/net/atl1e.h +++ b/src/drivers/net/atl1e.h @@ -18,8 +18,8 @@ * 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., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * this program; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/b44.c b/src/drivers/net/b44.c index f9e47980..d9aeb1b4 100644 --- a/src/drivers/net/b44.c +++ b/src/drivers/net/b44.c @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * This driver is a port of the b44 linux driver version 1.01 * diff --git a/src/drivers/net/b44.h b/src/drivers/net/b44.h index 2d1f206e..08958092 100644 --- a/src/drivers/net/b44.h +++ b/src/drivers/net/b44.h @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * This driver is a port of the b44 linux driver version 1.01 * diff --git a/src/drivers/net/cs89x0.h b/src/drivers/net/cs89x0.h index a36b907c..432fe94e 100644 --- a/src/drivers/net/cs89x0.h +++ b/src/drivers/net/cs89x0.h @@ -31,7 +31,8 @@ FILE_LICENCE ( GPL2_ONLY ); 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */ /* offset 2h -> Model/Product Number */ diff --git a/src/drivers/net/dmfe.c b/src/drivers/net/dmfe.c index dd6c1dec..edc15941 100644 --- a/src/drivers/net/dmfe.c +++ b/src/drivers/net/dmfe.c @@ -17,7 +17,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code based on: * diff --git a/src/drivers/net/eepro100.c b/src/drivers/net/eepro100.c index 99dfb180..b98b745d 100644 --- a/src/drivers/net/eepro100.c +++ b/src/drivers/net/eepro100.c @@ -25,7 +25,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * * date version by what diff --git a/src/drivers/net/forcedeth.c b/src/drivers/net/forcedeth.c index 34c59223..47e2c5e8 100644 --- a/src/drivers/net/forcedeth.c +++ b/src/drivers/net/forcedeth.c @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * Portions of this code are taken from the Linux forcedeth driver that was * based on a cleanroom reimplementation which was based on reverse engineered diff --git a/src/drivers/net/forcedeth.h b/src/drivers/net/forcedeth.h index 70686d15..8a095eab 100644 --- a/src/drivers/net/forcedeth.h +++ b/src/drivers/net/forcedeth.h @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * Portions of this code are taken from the Linux forcedeth driver that was * based on a cleanroom reimplementation which was based on reverse engineered diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 30ba10c7..44afa2b6 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/jme.c b/src/drivers/net/jme.c index 54540265..29694b69 100644 --- a/src/drivers/net/jme.c +++ b/src/drivers/net/jme.c @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/jme.h b/src/drivers/net/jme.h index 7e225430..42db01ed 100644 --- a/src/drivers/net/jme.h +++ b/src/drivers/net/jme.h @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/myri10ge.c b/src/drivers/net/myri10ge.c index 2c9bf960..1b6835de 100644 --- a/src/drivers/net/myri10ge.c +++ b/src/drivers/net/myri10ge.c @@ -13,7 +13,8 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. ****************************************************************/ FILE_LICENCE ( GPL2_ONLY ); diff --git a/src/drivers/net/myri10ge_mcp.h b/src/drivers/net/myri10ge_mcp.h index 391dab37..6c82b3c7 100644 --- a/src/drivers/net/myri10ge_mcp.h +++ b/src/drivers/net/myri10ge_mcp.h @@ -13,7 +13,8 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. ****************************************************************/ FILE_LICENCE ( GPL2_ONLY ); diff --git a/src/drivers/net/pcnet32.c b/src/drivers/net/pcnet32.c index d6da3c5e..28fd583d 100644 --- a/src/drivers/net/pcnet32.c +++ b/src/drivers/net/pcnet32.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/src/drivers/net/pcnet32.h b/src/drivers/net/pcnet32.h index bd03cbc0..5e4492ef 100644 --- a/src/drivers/net/pcnet32.h +++ b/src/drivers/net/pcnet32.h @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * */ diff --git a/src/drivers/net/phantom/nx_bitops.h b/src/drivers/net/phantom/nx_bitops.h index 40686326..15f3d376 100644 --- a/src/drivers/net/phantom/nx_bitops.h +++ b/src/drivers/net/phantom/nx_bitops.h @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/phantom/phantom.c b/src/drivers/net/phantom/phantom.c index a55319ea..1c798e04 100644 --- a/src/drivers/net/phantom/phantom.c +++ b/src/drivers/net/phantom/phantom.c @@ -14,7 +14,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/phantom/phantom.h b/src/drivers/net/phantom/phantom.h index a55f32fb..1647168b 100644 --- a/src/drivers/net/phantom/phantom.h +++ b/src/drivers/net/phantom/phantom.h @@ -17,7 +17,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/phantom/phantom_hw.h b/src/drivers/net/phantom/phantom_hw.h index 950f36a4..7dfff52b 100644 --- a/src/drivers/net/phantom/phantom_hw.h +++ b/src/drivers/net/phantom/phantom_hw.h @@ -17,7 +17,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/skge.c b/src/drivers/net/skge.c index fea33841..6384e764 100755 --- a/src/drivers/net/skge.c +++ b/src/drivers/net/skge.c @@ -24,7 +24,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_ONLY ); diff --git a/src/drivers/net/sky2.c b/src/drivers/net/sky2.c index d60ef113..eed9b5cb 100644 --- a/src/drivers/net/sky2.c +++ b/src/drivers/net/sky2.c @@ -21,7 +21,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_ONLY ); diff --git a/src/drivers/net/sundance.c b/src/drivers/net/sundance.c index 63a9ea5f..4d276105 100644 --- a/src/drivers/net/sundance.c +++ b/src/drivers/net/sundance.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code based on: * sundance.c: A Linux device driver for the Sundance ST201 "Alta" diff --git a/src/drivers/net/tlan.c b/src/drivers/net/tlan.c index b1a09d18..927bfce8 100644 --- a/src/drivers/net/tlan.c +++ b/src/drivers/net/tlan.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code based on: * lan.c: Linux ThunderLan Driver: diff --git a/src/drivers/net/tlan.h b/src/drivers/net/tlan.h index 31b3c8f4..b787532b 100644 --- a/src/drivers/net/tlan.h +++ b/src/drivers/net/tlan.h @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code (almost all) based on: * tlan.c: Linux ThunderLan Driver: diff --git a/src/drivers/net/via-velocity.c b/src/drivers/net/via-velocity.c index fa90f9b3..f50b1590 100644 --- a/src/drivers/net/via-velocity.c +++ b/src/drivers/net/via-velocity.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * This driver is based on: * via-velocity.c: VIA Velocity VT6120, VT6122 Ethernet driver diff --git a/src/drivers/net/vmxnet3.c b/src/drivers/net/vmxnet3.c index 79cf1d80..9401c110 100644 --- a/src/drivers/net/vmxnet3.c +++ b/src/drivers/net/vmxnet3.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/vmxnet3.h b/src/drivers/net/vmxnet3.h index 22a93539..db313d4b 100644 --- a/src/drivers/net/vmxnet3.h +++ b/src/drivers/net/vmxnet3.h @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/net/w89c840.c b/src/drivers/net/w89c840.c index b3149550..ce638ab9 100644 --- a/src/drivers/net/w89c840.c +++ b/src/drivers/net/w89c840.c @@ -26,7 +26,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/nvs/nvs.c b/src/drivers/nvs/nvs.c index a4a06ccf..ccb2145b 100644 --- a/src/drivers/nvs/nvs.c +++ b/src/drivers/nvs/nvs.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/nvs/nvsvpd.c b/src/drivers/nvs/nvsvpd.c index a22ec825..33148d5b 100644 --- a/src/drivers/nvs/nvsvpd.c +++ b/src/drivers/nvs/nvsvpd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/nvs/spi.c b/src/drivers/nvs/spi.c index e12aeff6..84613b9d 100644 --- a/src/drivers/nvs/spi.c +++ b/src/drivers/nvs/spi.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/drivers/nvs/threewire.c b/src/drivers/nvs/threewire.c index 047091fd..53f1ad8d 100644 --- a/src/drivers/nvs/threewire.c +++ b/src/drivers/nvs/threewire.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/autoboot_cmd.c b/src/hci/commands/autoboot_cmd.c index 0917f6fa..f3886b1f 100644 --- a/src/hci/commands/autoboot_cmd.c +++ b/src/hci/commands/autoboot_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/hci/commands/config_cmd.c b/src/hci/commands/config_cmd.c index e447d6af..f1fb567c 100644 --- a/src/hci/commands/config_cmd.c +++ b/src/hci/commands/config_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/hci/commands/dhcp_cmd.c b/src/hci/commands/dhcp_cmd.c index acf3cfda..279620c3 100644 --- a/src/hci/commands/dhcp_cmd.c +++ b/src/hci/commands/dhcp_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/digest_cmd.c b/src/hci/commands/digest_cmd.c index fac49765..3cf2f102 100644 --- a/src/hci/commands/digest_cmd.c +++ b/src/hci/commands/digest_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/fcmgmt_cmd.c b/src/hci/commands/fcmgmt_cmd.c index a2b818ec..b7e38040 100644 --- a/src/hci/commands/fcmgmt_cmd.c +++ b/src/hci/commands/fcmgmt_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/gdbstub_cmd.c b/src/hci/commands/gdbstub_cmd.c index f35f0140..33890aeb 100644 --- a/src/hci/commands/gdbstub_cmd.c +++ b/src/hci/commands/gdbstub_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/ifmgmt_cmd.c b/src/hci/commands/ifmgmt_cmd.c index 29691d4e..3f3f6b51 100644 --- a/src/hci/commands/ifmgmt_cmd.c +++ b/src/hci/commands/ifmgmt_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/image_cmd.c b/src/hci/commands/image_cmd.c index 0a4232f2..6f51a6ba 100644 --- a/src/hci/commands/image_cmd.c +++ b/src/hci/commands/image_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/image_trust_cmd.c b/src/hci/commands/image_trust_cmd.c index 25e77dde..e7a2bf12 100644 --- a/src/hci/commands/image_trust_cmd.c +++ b/src/hci/commands/image_trust_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/iwmgmt_cmd.c b/src/hci/commands/iwmgmt_cmd.c index 00a8360d..d91ad1e3 100644 --- a/src/hci/commands/iwmgmt_cmd.c +++ b/src/hci/commands/iwmgmt_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/login_cmd.c b/src/hci/commands/login_cmd.c index 3286932d..bc23e6ff 100644 --- a/src/hci/commands/login_cmd.c +++ b/src/hci/commands/login_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/hci/commands/lotest_cmd.c b/src/hci/commands/lotest_cmd.c index 172be2d8..92f08887 100644 --- a/src/hci/commands/lotest_cmd.c +++ b/src/hci/commands/lotest_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/menu_cmd.c b/src/hci/commands/menu_cmd.c index ff3b76fa..c11baea7 100644 --- a/src/hci/commands/menu_cmd.c +++ b/src/hci/commands/menu_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/nvo_cmd.c b/src/hci/commands/nvo_cmd.c index a7e0f4a0..4bb7f457 100644 --- a/src/hci/commands/nvo_cmd.c +++ b/src/hci/commands/nvo_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/hci/commands/route_cmd.c b/src/hci/commands/route_cmd.c index f839d53f..3b51f06b 100644 --- a/src/hci/commands/route_cmd.c +++ b/src/hci/commands/route_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/sanboot_cmd.c b/src/hci/commands/sanboot_cmd.c index b4937104..14055a8c 100644 --- a/src/hci/commands/sanboot_cmd.c +++ b/src/hci/commands/sanboot_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/hci/commands/sync_cmd.c b/src/hci/commands/sync_cmd.c index f0845133..221e8739 100644 --- a/src/hci/commands/sync_cmd.c +++ b/src/hci/commands/sync_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/commands/time_cmd.c b/src/hci/commands/time_cmd.c index ce26f9d2..d1dd49ca 100644 --- a/src/hci/commands/time_cmd.c +++ b/src/hci/commands/time_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. * * March-19-2009 @ 02:44: Added sleep command. * Shao Miller . diff --git a/src/hci/commands/vlan_cmd.c b/src/hci/commands/vlan_cmd.c index 28638ae6..822e5dcf 100644 --- a/src/hci/commands/vlan_cmd.c +++ b/src/hci/commands/vlan_cmd.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/editstring.c b/src/hci/editstring.c index 35a5b2c1..8c56d233 100644 --- a/src/hci/editstring.c +++ b/src/hci/editstring.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/mucurses/widgets/editbox.c b/src/hci/mucurses/widgets/editbox.c index 5d2ba56c..630a66e0 100644 --- a/src/hci/mucurses/widgets/editbox.c +++ b/src/hci/mucurses/widgets/editbox.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/readline.c b/src/hci/readline.c index 32793abe..2ecb8f27 100644 --- a/src/hci/readline.c +++ b/src/hci/readline.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/shell.c b/src/hci/shell.c index e426ba94..33438da0 100644 --- a/src/hci/shell.c +++ b/src/hci/shell.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/tui/login_ui.c b/src/hci/tui/login_ui.c index c33cbcf2..52ab0e36 100644 --- a/src/hci/tui/login_ui.c +++ b/src/hci/tui/login_ui.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c index e9250099..dfa1d2e7 100644 --- a/src/hci/tui/menu_ui.c +++ b/src/hci/tui/menu_ui.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/tui/settings_ui.c b/src/hci/tui/settings_ui.c index 258f0cf9..403d1245 100644 --- a/src/hci/tui/settings_ui.c +++ b/src/hci/tui/settings_ui.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/hci/wireless_errors.c b/src/hci/wireless_errors.c index 63c6251c..7154df55 100644 --- a/src/hci/wireless_errors.c +++ b/src/hci/wireless_errors.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 9b9e7600..bee966e7 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/image/elf.c b/src/image/elf.c index 26666ec5..51636a8e 100644 --- a/src/image/elf.c +++ b/src/image/elf.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/image/script.c b/src/image/script.c index b032d18f..e83180ab 100644 --- a/src/image/script.c +++ b/src/image/script.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/image/segment.c b/src/image/segment.c index 97f6a995..86fe4266 100644 --- a/src/image/segment.c +++ b/src/image/segment.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/include/errno.h b/src/include/errno.h index a86573fc..bd4ddaf4 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef ERRNO_H diff --git a/src/include/hci/ifmgmt_cmd.h b/src/include/hci/ifmgmt_cmd.h index a7751cb2..abdb27f4 100644 --- a/src/include/hci/ifmgmt_cmd.h +++ b/src/include/hci/ifmgmt_cmd.h @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IFMGMT_CMD_H diff --git a/src/include/ipxe/bitops.h b/src/include/ipxe/bitops.h index 4118ef81..73e859f4 100644 --- a/src/include/ipxe/bitops.h +++ b/src/include/ipxe/bitops.h @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/include/ipxe/eapol.h b/src/include/ipxe/eapol.h index 3fad4428..5ca9c281 100644 --- a/src/include/ipxe/eapol.h +++ b/src/include/ipxe/eapol.h @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IPXE_EAPOL_H diff --git a/src/include/ipxe/fip.h b/src/include/ipxe/fip.h index b81e8604..87292337 100644 --- a/src/include/ipxe/fip.h +++ b/src/include/ipxe/fip.h @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/include/ipxe/isapnp.h b/src/include/ipxe/isapnp.h index 47a47025..b0b0e98d 100644 --- a/src/include/ipxe/isapnp.h +++ b/src/include/ipxe/isapnp.h @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +* 02110-1301, USA. * * Portions of this code: * Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk) diff --git a/src/include/ipxe/sec80211.h b/src/include/ipxe/sec80211.h index 59ca3eb8..3ca3d84f 100644 --- a/src/include/ipxe/sec80211.h +++ b/src/include/ipxe/sec80211.h @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IPXE_SEC80211_H diff --git a/src/include/ipxe/wpa.h b/src/include/ipxe/wpa.h index 29342282..44934b3b 100644 --- a/src/include/ipxe/wpa.h +++ b/src/include/ipxe/wpa.h @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #ifndef _IPXE_WPA_H diff --git a/src/interface/bofm/bofm.c b/src/interface/bofm/bofm.c index 63b25a55..b0e92b27 100644 --- a/src/interface/bofm/bofm.c +++ b/src/interface/bofm/bofm.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_bofm.c b/src/interface/efi/efi_bofm.c index bf38d88b..c313d2e9 100644 --- a/src/interface/efi/efi_bofm.c +++ b/src/interface/efi/efi_bofm.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_console.c b/src/interface/efi/efi_console.c index 6b612438..a30ca301 100644 --- a/src/interface/efi/efi_console.c +++ b/src/interface/efi/efi_console.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c index 4aa976f9..476b3c32 100644 --- a/src/interface/efi/efi_driver.c +++ b/src/interface/efi/efi_driver.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index 6c7b4955..aaf89471 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_io.c b/src/interface/efi/efi_io.c index 9a9aad31..a620d6e4 100644 --- a/src/interface/efi/efi_io.c +++ b/src/interface/efi/efi_io.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_pci.c b/src/interface/efi/efi_pci.c index 0a2da2e4..0288cf32 100644 --- a/src/interface/efi/efi_pci.c +++ b/src/interface/efi/efi_pci.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_smbios.c b/src/interface/efi/efi_smbios.c index 4b58d846..506b04e7 100644 --- a/src/interface/efi/efi_smbios.c +++ b/src/interface/efi/efi_smbios.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 4df221c5..88072aa6 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_strerror.c b/src/interface/efi/efi_strerror.c index 430758f8..46bfbbb5 100644 --- a/src/interface/efi/efi_strerror.c +++ b/src/interface/efi/efi_strerror.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_strings.c b/src/interface/efi/efi_strings.c index 0fbc4538..751589b4 100644 --- a/src/interface/efi/efi_strings.c +++ b/src/interface/efi/efi_strings.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_timer.c b/src/interface/efi/efi_timer.c index 1f8ad150..b110cae2 100644 --- a/src/interface/efi/efi_timer.c +++ b/src/interface/efi/efi_timer.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_uaccess.c b/src/interface/efi/efi_uaccess.c index d80ca7a7..8b429b9e 100644 --- a/src/interface/efi/efi_uaccess.c +++ b/src/interface/efi/efi_uaccess.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/efi/efi_umalloc.c b/src/interface/efi/efi_umalloc.c index d1d689ea..b4994932 100644 --- a/src/interface/efi/efi_umalloc.c +++ b/src/interface/efi/efi_umalloc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/linux/linux_entropy.c b/src/interface/linux/linux_entropy.c index d82aabaa..4671a48d 100644 --- a/src/interface/linux/linux_entropy.c +++ b/src/interface/linux/linux_entropy.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/linux/linux_nap.c b/src/interface/linux/linux_nap.c index 98642bad..f1d3cd96 100644 --- a/src/interface/linux/linux_nap.c +++ b/src/interface/linux/linux_nap.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE(GPL2_OR_LATER); diff --git a/src/interface/linux/linux_uaccess.c b/src/interface/linux/linux_uaccess.c index d4e52d09..5ab0b6b6 100644 --- a/src/interface/linux/linux_uaccess.c +++ b/src/interface/linux/linux_uaccess.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE(GPL2_OR_LATER); diff --git a/src/interface/smbios/smbios.c b/src/interface/smbios/smbios.c index b60e10f7..8ed24dd6 100644 --- a/src/interface/smbios/smbios.c +++ b/src/interface/smbios/smbios.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 92dc4127..727970e9 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c index c00363cd..a3d3e76e 100644 --- a/src/net/80211/net80211.c +++ b/src/net/80211/net80211.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/rc80211.c b/src/net/80211/rc80211.c index 56bbc8a0..eea3bc90 100644 --- a/src/net/80211/rc80211.c +++ b/src/net/80211/rc80211.c @@ -15,7 +15,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/sec80211.c b/src/net/80211/sec80211.c index 82b1ce94..d159edbd 100644 --- a/src/net/80211/sec80211.c +++ b/src/net/80211/sec80211.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/wep.c b/src/net/80211/wep.c index 3b104552..37b27f71 100644 --- a/src/net/80211/wep.c +++ b/src/net/80211/wep.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/wpa.c b/src/net/80211/wpa.c index 45def8c1..e2c4945f 100644 --- a/src/net/80211/wpa.c +++ b/src/net/80211/wpa.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/wpa_ccmp.c b/src/net/80211/wpa_ccmp.c index 38fd199f..f98ebea2 100644 --- a/src/net/80211/wpa_ccmp.c +++ b/src/net/80211/wpa_ccmp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/wpa_psk.c b/src/net/80211/wpa_psk.c index c88f556e..71190b13 100644 --- a/src/net/80211/wpa_psk.c +++ b/src/net/80211/wpa_psk.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/80211/wpa_tkip.c b/src/net/80211/wpa_tkip.c index 871666ee..fa3e0763 100644 --- a/src/net/80211/wpa_tkip.c +++ b/src/net/80211/wpa_tkip.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/aoe.c b/src/net/aoe.c index 1016b250..a6d7b3e7 100644 --- a/src/net/aoe.c +++ b/src/net/aoe.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/arp.c b/src/net/arp.c index 7cec73d5..d96cb4cc 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/cachedhcp.c b/src/net/cachedhcp.c index 36f480a9..fc7dabc9 100644 --- a/src/net/cachedhcp.c +++ b/src/net/cachedhcp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/dhcpopts.c b/src/net/dhcpopts.c index 249fde15..6d29a7b5 100644 --- a/src/net/dhcpopts.c +++ b/src/net/dhcpopts.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/dhcppkt.c b/src/net/dhcppkt.c index 0a0e458f..528f9003 100644 --- a/src/net/dhcppkt.c +++ b/src/net/dhcppkt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/eapol.c b/src/net/eapol.c index dd042083..eb036299 100644 --- a/src/net/eapol.c +++ b/src/net/eapol.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/eth_slow.c b/src/net/eth_slow.c index 593e45bc..69c38f30 100644 --- a/src/net/eth_slow.c +++ b/src/net/eth_slow.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/ethernet.c b/src/net/ethernet.c index a842bc11..ed1bb7a0 100644 --- a/src/net/ethernet.c +++ b/src/net/ethernet.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/fakedhcp.c b/src/net/fakedhcp.c index b182ab6f..d67501ed 100644 --- a/src/net/fakedhcp.c +++ b/src/net/fakedhcp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/fc.c b/src/net/fc.c index f76cfe92..58008995 100644 --- a/src/net/fc.c +++ b/src/net/fc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/fcels.c b/src/net/fcels.c index 2106cbd5..1cfe9072 100644 --- a/src/net/fcels.c +++ b/src/net/fcels.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/fcns.c b/src/net/fcns.c index 55bd29e5..3ca4ad55 100644 --- a/src/net/fcns.c +++ b/src/net/fcns.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/fcoe.c b/src/net/fcoe.c index c54d1b47..d1130425 100644 --- a/src/net/fcoe.c +++ b/src/net/fcoe.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/fcp.c b/src/net/fcp.c index bd1a0900..241b5463 100644 --- a/src/net/fcp.c +++ b/src/net/fcp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/icmp.c b/src/net/icmp.c index 84dad425..830d8292 100644 --- a/src/net/icmp.c +++ b/src/net/icmp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband.c b/src/net/infiniband.c index 147017fc..c17b6181 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband/ib_cm.c b/src/net/infiniband/ib_cm.c index 1a0646be..797639bc 100644 --- a/src/net/infiniband/ib_cm.c +++ b/src/net/infiniband/ib_cm.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband/ib_mcast.c b/src/net/infiniband/ib_mcast.c index 0f03b54a..0a5e72a3 100644 --- a/src/net/infiniband/ib_mcast.c +++ b/src/net/infiniband/ib_mcast.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband/ib_mi.c b/src/net/infiniband/ib_mi.c index d4cf58a6..ced2eea1 100644 --- a/src/net/infiniband/ib_mi.c +++ b/src/net/infiniband/ib_mi.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband/ib_packet.c b/src/net/infiniband/ib_packet.c index d58e0ad4..df883faf 100644 --- a/src/net/infiniband/ib_packet.c +++ b/src/net/infiniband/ib_packet.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband/ib_pathrec.c b/src/net/infiniband/ib_pathrec.c index 7b914654..1b95cbfa 100644 --- a/src/net/infiniband/ib_pathrec.c +++ b/src/net/infiniband/ib_pathrec.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband/ib_sma.c b/src/net/infiniband/ib_sma.c index 1f3c6d80..86553732 100644 --- a/src/net/infiniband/ib_sma.c +++ b/src/net/infiniband/ib_sma.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/infiniband/ib_smc.c b/src/net/infiniband/ib_smc.c index 8196cb7e..4d947d56 100644 --- a/src/net/infiniband/ib_smc.c +++ b/src/net/infiniband/ib_smc.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/iobpad.c b/src/net/iobpad.c index f83c76d8..9cc8328e 100644 --- a/src/net/iobpad.c +++ b/src/net/iobpad.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/netdev_settings.c b/src/net/netdev_settings.c index 2ef3984d..9efe6811 100644 --- a/src/net/netdev_settings.c +++ b/src/net/netdev_settings.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/netdevice.c b/src/net/netdevice.c index 6afe2d5f..5a4d8635 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/nullnet.c b/src/net/nullnet.c index 48849dfd..4ac50f64 100644 --- a/src/net/nullnet.c +++ b/src/net/nullnet.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/rarp.c b/src/net/rarp.c index 59cb1d07..37114501 100644 --- a/src/net/rarp.c +++ b/src/net/rarp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/retry.c b/src/net/retry.c index 7e20f0c8..4f43b76f 100644 --- a/src/net/retry.c +++ b/src/net/retry.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c index 0c038885..90bae9d7 100644 --- a/src/net/tcp/http.c +++ b/src/net/tcp/http.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 70f2a2a3..432c30d5 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/tcp/https.c b/src/net/tcp/https.c index 805d108b..6112acda 100644 --- a/src/net/tcp/https.c +++ b/src/net/tcp/https.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index 457ea731..c9daf1ff 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/tcp/syslogs.c b/src/net/tcp/syslogs.c index 854e2152..dae6ba18 100644 --- a/src/net/tcp/syslogs.c +++ b/src/net/tcp/syslogs.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/tls.c b/src/net/tls.c index a3433f92..05884df5 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 9a231840..a7206164 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index 6b4335d7..efe0d2e0 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -16,7 +16,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/udp/slam.c b/src/net/udp/slam.c index 0de138cd..e1b584fe 100644 --- a/src/net/udp/slam.c +++ b/src/net/udp/slam.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/udp/syslog.c b/src/net/udp/syslog.c index 9e55d211..00101008 100644 --- a/src/net/udp/syslog.c +++ b/src/net/udp/syslog.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c index a2d6473c..a6c64b4a 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/net/vlan.c b/src/net/vlan.c index 2147f91c..f7281f5d 100644 --- a/src/net/vlan.c +++ b/src/net/vlan.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/aes_cbc_test.c b/src/tests/aes_cbc_test.c index 371ec81b..09d38075 100644 --- a/src/tests/aes_cbc_test.c +++ b/src/tests/aes_cbc_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/bigint_test.c b/src/tests/bigint_test.c index 4052131f..75a80622 100644 --- a/src/tests/bigint_test.c +++ b/src/tests/bigint_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/bofm_test.c b/src/tests/bofm_test.c index 6f2e6c67..e430d12d 100644 --- a/src/tests/bofm_test.c +++ b/src/tests/bofm_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/byteswap_test.c b/src/tests/byteswap_test.c index 9bfe2659..a500218b 100644 --- a/src/tests/byteswap_test.c +++ b/src/tests/byteswap_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/cbc_test.c b/src/tests/cbc_test.c index ebff3268..7d755309 100644 --- a/src/tests/cbc_test.c +++ b/src/tests/cbc_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/cms_test.c b/src/tests/cms_test.c index 9de0228b..9899b06a 100644 --- a/src/tests/cms_test.c +++ b/src/tests/cms_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/digest_test.c b/src/tests/digest_test.c index 7c2b4a47..ccec0e9a 100644 --- a/src/tests/digest_test.c +++ b/src/tests/digest_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/entropy_sample.c b/src/tests/entropy_sample.c index 9e75b4e9..95a662e3 100644 --- a/src/tests/entropy_sample.c +++ b/src/tests/entropy_sample.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/hash_df_test.c b/src/tests/hash_df_test.c index ccbc86ea..74c8d0f4 100644 --- a/src/tests/hash_df_test.c +++ b/src/tests/hash_df_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/hmac_drbg_test.c b/src/tests/hmac_drbg_test.c index d03efef0..8cbf1cc8 100644 --- a/src/tests/hmac_drbg_test.c +++ b/src/tests/hmac_drbg_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/list_test.c b/src/tests/list_test.c index 5184b308..35cbd5e5 100644 --- a/src/tests/list_test.c +++ b/src/tests/list_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/md5_test.c b/src/tests/md5_test.c index 17972daa..e54296ac 100644 --- a/src/tests/md5_test.c +++ b/src/tests/md5_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/rsa_test.c b/src/tests/rsa_test.c index a451e38c..3b32c74b 100644 --- a/src/tests/rsa_test.c +++ b/src/tests/rsa_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c index ac4abee4..9e87a514 100644 --- a/src/tests/settings_test.c +++ b/src/tests/settings_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/sha1_test.c b/src/tests/sha1_test.c index 683409c9..3ff7e3c2 100644 --- a/src/tests/sha1_test.c +++ b/src/tests/sha1_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/sha256_test.c b/src/tests/sha256_test.c index 7599ba5d..77b6b10f 100644 --- a/src/tests/sha256_test.c +++ b/src/tests/sha256_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/test.c b/src/tests/test.c index 11dd2f5e..62f7c97d 100644 --- a/src/tests/test.c +++ b/src/tests/test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/tests.c b/src/tests/tests.c index c0d9df5e..a8d77788 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/time_test.c b/src/tests/time_test.c index d12d3acf..28acebee 100644 --- a/src/tests/time_test.c +++ b/src/tests/time_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/tests/x509_test.c b/src/tests/x509_test.c index 3a3c9d00..c014bd2e 100644 --- a/src/tests/x509_test.c +++ b/src/tests/x509_test.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 53f246ae..0587f204 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/dhcpmgmt.c b/src/usr/dhcpmgmt.c index e651dfda..1bd9bff0 100644 --- a/src/usr/dhcpmgmt.c +++ b/src/usr/dhcpmgmt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/fcmgmt.c b/src/usr/fcmgmt.c index f46c7d6b..2657ba0c 100644 --- a/src/usr/fcmgmt.c +++ b/src/usr/fcmgmt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c index 8ee311c0..94e6e875 100644 --- a/src/usr/ifmgmt.c +++ b/src/usr/ifmgmt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/imgmgmt.c b/src/usr/imgmgmt.c index ce3bc90f..ef4e2c36 100644 --- a/src/usr/imgmgmt.c +++ b/src/usr/imgmgmt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/imgtrust.c b/src/usr/imgtrust.c index be0ca6ee..afb41529 100644 --- a/src/usr/imgtrust.c +++ b/src/usr/imgtrust.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/iwmgmt.c b/src/usr/iwmgmt.c index abcd63f4..a486bceb 100644 --- a/src/usr/iwmgmt.c +++ b/src/usr/iwmgmt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/lotest.c b/src/usr/lotest.c index 52525261..c4b0b441 100644 --- a/src/usr/lotest.c +++ b/src/usr/lotest.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/prompt.c b/src/usr/prompt.c index 3c353a68..ede03745 100644 --- a/src/usr/prompt.c +++ b/src/usr/prompt.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/pxemenu.c b/src/usr/pxemenu.c index bc176563..d50ee6ba 100644 --- a/src/usr/pxemenu.c +++ b/src/usr/pxemenu.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/usr/route.c b/src/usr/route.c index 1da7135b..e393e38d 100644 --- a/src/usr/route.c +++ b/src/usr/route.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ FILE_LICENCE ( GPL2_OR_LATER ); diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm index b2b94c3e..fdc5e4ae 100644 --- a/src/util/Option/ROM.pm +++ b/src/util/Option/ROM.pm @@ -14,7 +14,8 @@ package Option::ROM; # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. =head1 NAME diff --git a/src/util/disrom.pl b/src/util/disrom.pl index aff972ea..c133c26a 100755 --- a/src/util/disrom.pl +++ b/src/util/disrom.pl @@ -14,7 +14,8 @@ # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; diff --git a/src/util/efirom.c b/src/util/efirom.c index a65abfee..abee496d 100644 --- a/src/util/efirom.c +++ b/src/util/efirom.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/util/einfo.c b/src/util/einfo.c index 15f920d0..d83828df 100644 --- a/src/util/einfo.c +++ b/src/util/einfo.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #include diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c index fc6bef37..007453e2 100644 --- a/src/util/elf2efi.c +++ b/src/util/elf2efi.c @@ -13,7 +13,8 @@ * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ #define _GNU_SOURCE diff --git a/src/util/fixrom.pl b/src/util/fixrom.pl index 88f8cb83..c84e2cf2 100755 --- a/src/util/fixrom.pl +++ b/src/util/fixrom.pl @@ -14,7 +14,8 @@ # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; diff --git a/src/util/fnrec.pl b/src/util/fnrec.pl index 9a2b3d81..cc7312b6 100755 --- a/src/util/fnrec.pl +++ b/src/util/fnrec.pl @@ -14,7 +14,8 @@ # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. =head1 NAME diff --git a/src/util/genkeymap.pl b/src/util/genkeymap.pl index 6487cd79..7a5024bf 100755 --- a/src/util/genkeymap.pl +++ b/src/util/genkeymap.pl @@ -14,7 +14,8 @@ # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. =head1 NAME diff --git a/src/util/get-pci-ids b/src/util/get-pci-ids index 6501a7f7..42466221 100755 --- a/src/util/get-pci-ids +++ b/src/util/get-pci-ids @@ -16,7 +16,8 @@ # 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. # Known bugs/limitations: diff --git a/src/util/licence.pl b/src/util/licence.pl index c37685d3..0e43c7b4 100755 --- a/src/util/licence.pl +++ b/src/util/licence.pl @@ -14,7 +14,8 @@ # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; diff --git a/src/util/mergerom.pl b/src/util/mergerom.pl index a1b456e2..815ac747 100755 --- a/src/util/mergerom.pl +++ b/src/util/mergerom.pl @@ -14,7 +14,8 @@ # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. use strict; use warnings; From 8f17955c03c139ca8a1b728d86d7b36a992941a8 Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 24 May 2012 22:41:40 +0300 Subject: [PATCH 105/250] [epic100] Fix wrong field used as rx packet length Datasheet pp. 41-42 defines 'rx packet length' as upper word of 'status' dword field of the receive descriptor table. http://www.smsc.com/media/Downloads_Archive/discontinued/83c171.pdf Tested on SMC EtherPower II. Signed-off-by: Alexey Smazhenko Signed-off-by: Michael Brown --- src/drivers/net/epic100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/net/epic100.c b/src/drivers/net/epic100.c index b478fab5..884eb722 100644 --- a/src/drivers/net/epic100.c +++ b/src/drivers/net/epic100.c @@ -376,7 +376,7 @@ epic100_poll(struct nic *nic, int retrieve) { int entry; int retcode; - int status; + unsigned long status; entry = cur_rx % RX_RING_SIZE; if ((rx_ring[entry].status & cpu_to_le32(RRING_OWN)) == RRING_OWN) @@ -401,7 +401,7 @@ epic100_poll(struct nic *nic, int retrieve) retcode = 0; } else { /* Omit the four octet CRC from the length. */ - nic->packetlen = le32_to_cpu((rx_ring[entry].buflength))- 4; + nic->packetlen = (status >> 16) - 4; memcpy(nic->packet, &rx_packet[entry * PKT_BUF_SZ], nic->packetlen); retcode = 1; } From def7f57eb28e24c3d5806a892feb6dc16d3f4451 Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Mon, 23 Jul 2012 02:39:44 +0200 Subject: [PATCH 106/250] [contrib] Fix rom-o-matic build (add new LOG_LEVEL constant) Signed-off-by: Michael Brown --- contrib/rom-o-matic/flag-table.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/contrib/rom-o-matic/flag-table.php b/contrib/rom-o-matic/flag-table.php index 0eee0c3f..fe81c802 100644 --- a/contrib/rom-o-matic/flag-table.php +++ b/contrib/rom-o-matic/flag-table.php @@ -109,6 +109,16 @@ $flag_table = array ( "cfgsec" => "console" ), + "LOG_LEVEL" + => array ( + "flag" => "LOG_LEVEL", + "type" => "choice", + "options" => array("LOG_NONE","LOG_EMERG","LOG_ALERT","LOG_CRIT","LOG_ERR", + "LOG_WARNING","LOG_NOTICE","LOG_INFO","LOG_DEBUG","LOG_ALL"), + "value" => "LOG_NONE", + "cfgsec" => "console" + ), + // End Console Options // Begin Network Protocol Options: From ee3636370d901bca306cf85241491f23e0f5034a Mon Sep 17 00:00:00 2001 From: Floris Bos Date: Mon, 23 Jul 2012 15:09:21 +0200 Subject: [PATCH 107/250] [contrib] Fix rom-o-matic git version number issues Fixes issue in which git version number is not displayed on startup when iPXE is built through rom-o-matic. Remove special characters from filename generated by rom-o-matic (so that you get "ipxe-1.0.0+c3b4-undionly.kkpxe" instead of "ipxe-1.0.0+ (c3b4)-undionly.kkpxe") Signed-off-by: Michael Brown --- contrib/rom-o-matic/build.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/contrib/rom-o-matic/build.php b/contrib/rom-o-matic/build.php index b9bc5951..b2b5bb45 100644 --- a/contrib/rom-o-matic/build.php +++ b/contrib/rom-o-matic/build.php @@ -179,7 +179,12 @@ if ( $embedded_script != "" ) { // Make the requested image. $status is set to 0 on success $make_target = "bin/${nic}.${fmt_extension}"; -$make_cmd = "make -C '$build_dir' '$make_target' $emb_script_cmd 2>&1"; +$gitversion = exec('git describe --always --abbrev=1 --match "" 2>/dev/null'); +if ($gitversion) { + $gitversion = "GITVERSION=$gitversion"; +} + +$make_cmd = "make -C '$build_dir' '$make_target' $gitversion $emb_script_cmd 2>&1"; exec ( $make_cmd, $maketxt, $status ); @@ -239,7 +244,7 @@ if ( $status == 0 ) { // Delete build directory as soon as it is not needed rm_build_dir (); - $output_filename = "ipxe-${version}-${nic}.${fmt_extension}"; + $output_filename = preg_replace('/[^a-z0-9\+\.\-]/i', '', "ipxe-${version}-${nic}.${fmt_extension}"); // Try to force IE to handle downloading right. Header ( "Cache-control: private"); From 5de45cd3da2308a6db37fb7c0822c9fdadf00d96 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 23 Jul 2012 17:41:38 +0100 Subject: [PATCH 108/250] [romprefix] Report a pessimistic runtime size estimate PCI3.0 allows us to report a "runtime size" which can be smaller than the actual ROM size. On systems that support PMM our runtime size will be small (~2.5kB), which helps to conserve the limited option ROM space. However, there is no guarantee that the PMM allocation will succeed, and so we need to report the worst-case runtime size in the PCI header. Move the "shrunk ROM size" field from the PCI header to a new "iPXE ROM header", allowing it to be accessed by ROM-manipulation utilities such as disrom.pl. Reported-by: Anton D. Kachalov Signed-off-by: Michael Brown --- src/arch/i386/prefix/romprefix.S | 28 +++++++++--- src/util/Option/ROM.pm | 77 +++++++++++++++++++++++++++++++- src/util/disrom.pl | 11 +++++ src/util/fixrom.pl | 1 + 4 files changed, 111 insertions(+), 6 deletions(-) diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 2719a70a..2b4c20b8 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -63,6 +63,8 @@ romheader_size: .byte 0 /* Size in 512-byte blocks */ jmp init /* Initialisation vector */ checksum: .byte 0 + .org 0x10 + .word ipxeheader .org 0x16 .word undiheader .org 0x18 @@ -78,9 +80,6 @@ checksum: .long 0 .previous -build_id: - .long _build_id /* Randomly-generated build ID */ - pciheader: .ascii "PCIR" /* Signature */ .word pci_vendor_id /* Vendor identification */ @@ -106,7 +105,7 @@ pciheader_runtime_length: .long pciheader_image_length .long 512 .long 0 - .ascii "ADHW" + .ascii ZINFO_TYPE_ADxW .long pciheader_runtime_length .long 512 .long 0 @@ -175,6 +174,25 @@ undiheader: .equ undiheader_len, . - undiheader .size undiheader, . - undiheader +ipxeheader: + .ascii "iPXE" /* Signature */ + .byte ipxeheader_len /* Length of structure */ + .byte 0 /* Checksum */ +shrunk_rom_size: + .byte 0 /* Shrunk size (in 512-byte blocks) */ + .byte 0 /* Reserved */ +build_id: + .long _build_id /* Randomly-generated build ID */ + .equ ipxeheader_len, . - ipxeheader + .size ipxeheader, . - ipxeheader + + .section ".zinfo.fixup", "a", @progbits /* Compressor fixups */ + .ascii "ADHB" + .long shrunk_rom_size + .long 512 + .long 0 + .previous + /* Initialisation (called once during POST) * * Determine whether or not this is a PnP system via a signature @@ -354,7 +372,7 @@ pmm_scan: addr32 rep movsl /* PMM presence implies flat real mode */ popw %es /* Shrink ROM */ - movw pciheader_runtime_length, %ax + movb shrunk_rom_size, %al movb %al, romheader_size 1: /* Allocate decompression PMM block. Round up the size to the * nearest 128kB and use the size within the PMM handle; this diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm index fdc5e4ae..82d65426 100644 --- a/src/util/Option/ROM.pm +++ b/src/util/Option/ROM.pm @@ -172,9 +172,10 @@ use constant ROM_SIGNATURE => 0xaa55; use constant PCI_SIGNATURE => 'PCIR'; use constant PCI_LAST_IMAGE => 0x80; use constant PNP_SIGNATURE => '$PnP'; +use constant IPXE_SIGNATURE => 'iPXE'; our @EXPORT_OK = qw ( ROM_SIGNATURE PCI_SIGNATURE PCI_LAST_IMAGE - PNP_SIGNATURE ); + PNP_SIGNATURE IPXE_SIGNATURE ); our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); use constant JMP_SHORT => 0xeb; @@ -232,6 +233,7 @@ sub new { init => { offset => 0x03, length => 0x03, pack => \&pack_init, unpack => \&unpack_init }, checksum => { offset => 0x06, length => 0x01, pack => "C" }, + ipxe_header => { offset => 0x10, length => 0x02, pack => "S" }, bofm_header => { offset => 0x14, length => 0x02, pack => "S" }, undi_header => { offset => 0x16, length => 0x02, pack => "S" }, pci_header => { offset => 0x18, length => 0x02, pack => "S" }, @@ -390,6 +392,25 @@ sub pnp_header { =pod +=item C<< ipxe_header () >> + +Return a C object representing the ROM's iPXE +header, if present. + +=cut + +sub ipxe_header { + my $hash = shift; + my $self = tied(%$hash); + + my $offset = $hash->{ipxe_header}; + return undef unless $offset != 0; + + return Option::ROM::iPXE->new ( $self->{data}, $offset ); +} + +=pod + =item C<< next_image () >> Return a C object representing the next image within the @@ -566,4 +587,58 @@ sub product { return unpack ( "Z*", $raw ); } +############################################################################## +# +# Option::ROM::iPXE +# +############################################################################## + +package Option::ROM::iPXE; + +use strict; +use warnings; +use Carp; +use bytes; + +sub new { + my $class = shift; + my $data = shift; + my $offset = shift; + + my $hash = {}; + tie %$hash, "Option::ROM::Fields", { + data => $data, + offset => $offset, + length => 0x06, + fields => { + signature => { offset => 0x00, length => 0x04, pack => "a4" }, + struct_length => { offset => 0x04, length => 0x01, pack => "C" }, + checksum => { offset => 0x05, length => 0x01, pack => "C" }, + shrunk_length => { offset => 0x06, length => 0x01, pack => "C" }, + build_id => { offset => 0x08, length => 0x04, pack => "L" }, + }, + }; + bless $hash, $class; + + # Retrieve true length of structure + my $self = tied ( %$hash ); + $self->{length} = $hash->{struct_length}; + + return $hash; +} + +sub checksum { + my $hash = shift; + my $self = tied(%$hash); + + return $self->checksum(); +} + +sub fix_checksum { + my $hash = shift; + my $self = tied(%$hash); + + $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff ); +} + 1; diff --git a/src/util/disrom.pl b/src/util/disrom.pl index c133c26a..87138686 100755 --- a/src/util/disrom.pl +++ b/src/util/disrom.pl @@ -85,4 +85,15 @@ do { printf "\n"; } + my $ipxe = $rom->ipxe_header(); + if ( $ipxe ) { + printf "iPXE header:\n\n"; + printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $ipxe->{checksum}, + ( ( $ipxe->checksum == 0 ) ? "" : "INCORRECT: " ), $ipxe->checksum; + printf " %-16s 0x%02x (%d)\n", "Shrunk length:", + $ipxe->{shrunk_length}, ( $ipxe->{shrunk_length} * 512 ); + printf " %-16s 0x%08x\n", "Build ID:", $ipxe->{build_id}; + printf "\n"; + } + } while ( $rom = $rom->next_image ); diff --git a/src/util/fixrom.pl b/src/util/fixrom.pl index c84e2cf2..8987b512 100755 --- a/src/util/fixrom.pl +++ b/src/util/fixrom.pl @@ -32,6 +32,7 @@ foreach my $romfile ( @romfiles ) { my $image = $rom; while ( $image ) { $image->pnp_header->fix_checksum() if $image->pnp_header; + $image->ipxe_header->fix_checksum() if $image->ipxe_header; $image->fix_checksum(); $image = $image->next_image(); } From 8cac5c0c9299b8fd176561d8672a87f07de38f88 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 23 Jul 2012 18:05:01 +0100 Subject: [PATCH 109/250] [util] Update mergerom.pl to handle iPXE ROM header Signed-off-by: Michael Brown --- src/util/mergerom.pl | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/util/mergerom.pl b/src/util/mergerom.pl index 815ac747..f5c1632b 100755 --- a/src/util/mergerom.pl +++ b/src/util/mergerom.pl @@ -44,9 +44,6 @@ my $offset = $baserom->length; foreach my $rom ( @roms ) { - # Update base length - $baserom->{length} += $rom->{length}; - # Merge initialisation entry point merge_entry_points ( $baserom->{init}, $rom->{init}, $offset ); @@ -85,6 +82,24 @@ foreach my $rom ( @roms ) { merge_entry_points ( $baserom_pnp->{bev}, $rom_pnp->{bev}, $offset ); } + # Update iPXE header, if present + my $baserom_ipxe = $baserom->ipxe_header; + my $rom_ipxe = $rom->ipxe_header; + if ( $baserom_ipxe ) { + + # Update shrunk length + $baserom_ipxe->{shrunk_length} = ( $baserom->{length} + + ( $rom_ipxe ? + $rom_ipxe->{shrunk_length} : + $rom->{length} ) ); + + # Fix checksum + $baserom_ipxe->fix_checksum(); + } + + # Update base length + $baserom->{length} += $rom->{length}; + # Fix checksum for this ROM segment $rom->fix_checksum(); From acd74089f59fbc24f2b7cfeb5432b3a8464aff0d Mon Sep 17 00:00:00 2001 From: Thomas Miletich Date: Mon, 23 Jul 2012 22:53:13 +0100 Subject: [PATCH 110/250] [vmware] Fix compilation under OpenBSD Reported-by: Jiri B Signed-off-by: Michael Brown --- src/arch/i386/interface/vmware/guestinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/i386/interface/vmware/guestinfo.c b/src/arch/i386/interface/vmware/guestinfo.c index 3e20b8ed..5e08d947 100644 --- a/src/arch/i386/interface/vmware/guestinfo.c +++ b/src/arch/i386/interface/vmware/guestinfo.c @@ -91,7 +91,7 @@ static int guestinfo_fetch_type ( struct settings *settings, /* Allocate temporary block to hold GuestInfo value */ info = zalloc ( info_len + 1 /* NUL */ ); if ( ! info ) { - DBGC ( settings, "GuestInfo %p could not allocate %zd bytes\n", + DBGC ( settings, "GuestInfo %p could not allocate %d bytes\n", settings, info_len ); ret = -ENOMEM; goto err_alloc; From c70586f6e93b975c68af14b108d5114636af6ba0 Mon Sep 17 00:00:00 2001 From: Thomas Miletich Date: Mon, 23 Jul 2012 23:03:05 +0100 Subject: [PATCH 111/250] [build] Fix building under OpenBSD Similarly to FreeBSD, OpenBSD requires the object format to be specified as elf_i386_obsd rather than elf_i386. Reported-by: Jiri B Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/arch/i386/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/arch/i386/Makefile b/src/arch/i386/Makefile index ca258330..8314f26d 100644 --- a/src/arch/i386/Makefile +++ b/src/arch/i386/Makefile @@ -54,6 +54,8 @@ CFLAGS += -m32 ASFLAGS += --32 ifeq ($(HOST_OS),FreeBSD) LDFLAGS += -m elf_i386_fbsd +else ifeq ($(HOST_OS),OpenBSD) +LDFLAGS += -m elf_i386_obsd else LDFLAGS += -m elf_i386 endif From fb7c022c2c72c4e3a549cb7a9157e60ef2e42b09 Mon Sep 17 00:00:00 2001 From: Joshua Oreman Date: Mon, 23 Jul 2012 23:07:52 +0100 Subject: [PATCH 112/250] [tcpip] Fix building under Cygwin Cygwin's assembler treats '/' as a comment character. Reported-by: Steve Goodrich Signed-off-by: Michael Brown --- src/arch/x86/core/x86_tcpip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86/core/x86_tcpip.c b/src/arch/x86/core/x86_tcpip.c index b4e7c3b8..8a4ce515 100644 --- a/src/arch/x86/core/x86_tcpip.c +++ b/src/arch/x86/core/x86_tcpip.c @@ -123,7 +123,7 @@ uint16_t x86_tcpip_continue_chksum ( uint16_t partial, "\nx86_tcpip_loop_end:\n\t" "loop x86_tcpip_loop_start\n\t" ".equ x86_tcpip_loop_step_size, " - " ( ( x86_tcpip_loop_end - x86_tcpip_loop_start ) / 16 )\n\t" + " ( ( x86_tcpip_loop_end - x86_tcpip_loop_start ) >> 4 )\n\t" /* Checksum remaining whole words */ "mov %13, %3\n\t" From 183a70e8b783ec143e8c30296f1a7c3c7de193d7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 24 Jul 2012 09:52:45 +0100 Subject: [PATCH 113/250] [console] Sleep while waiting for user input Reduce CPU usage while waiting for user input. This is particularly important for virtual machines, where CPU is a shared resource. Reported-by: Alessandro Salvatori Signed-off-by: Michael Brown --- src/core/getkey.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/getkey.c b/src/core/getkey.c index f16cafa4..d69cfb44 100644 --- a/src/core/getkey.c +++ b/src/core/getkey.c @@ -24,6 +24,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** @file * @@ -46,6 +47,7 @@ static int getchar_timeout ( unsigned long timeout ) { step(); if ( iskey() ) return getchar(); + cpu_nap(); } return -1; From ced1493c021133fe34066a0e430c82ec5a5d40ff Mon Sep 17 00:00:00 2001 From: Thomas Miletich Date: Tue, 24 Jul 2012 15:07:05 +0200 Subject: [PATCH 114/250] [tg3] Fix excessive DMA alignment. Change the DMA alignment from 4096 bytes to 16 bytes, to conserve available DMA memory. The hardware doesn't have any specific alignment requirements. Signed-off-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/tg3/tg3.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/drivers/net/tg3/tg3.h b/src/drivers/net/tg3/tg3.h index a56d7841..1913cb16 100644 --- a/src/drivers/net/tg3/tg3.h +++ b/src/drivers/net/tg3/tg3.h @@ -3277,8 +3277,7 @@ struct tg3 { #define TG3_TX_RING_SIZE 512 #define TG3_DEF_TX_RING_PENDING (TG3_TX_RING_SIZE - 1) -/* FIXME: look up alignment requirement in datasheet, page align for now */ -#define TG3_DMA_ALIGNMENT 4096 +#define TG3_DMA_ALIGNMENT 16 #define TG3_RX_STD_DMA_SZ (1536 + 64 + 2) From 1f88e9c8eaef91db510739b451a6837102a87f60 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 25 Jul 2012 14:32:37 +0100 Subject: [PATCH 115/250] [romprefix] Round up PMM allocation sizes to nearest 4kB Some AMI BIOSes apparently break in exciting ways when asked for PMM allocations for sizes that are not multiples of 4kB. Fix by rounding up the image source area to the nearest 4kB. (The temporary decompression area is already rounded up to the nearest 128kB, to facilitate sharing between multiple iPXE ROMs.) Reported-by: Itay Gazit Signed-off-by: Michael Brown --- src/arch/i386/prefix/romprefix.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 2b4c20b8..35d037ef 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -352,9 +352,13 @@ pmm_scan: call print_message /* We have PMM and so a 1kB stack: preserve whole registers */ pushal - /* Allocate image source PMM block */ + /* Allocate image source PMM block. Round up the size to the + * nearest 4kB (8 512-byte sectors) to work around AMI BIOS bugs. + */ movzbl romheader_size, %ecx addw extra_size, %cx + addw $0x0007, %cx /* Round up to multiple of 8 512-byte sectors */ + andw $0xfff8, %cx shll $5, %ecx movl $PMM_HANDLE_BASE_IMAGE_SOURCE, %ebx movw $get_pmm_image_source, %bp From d97c6a321e8c542877d5f702900929b267325851 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 3 Aug 2012 02:27:16 +0100 Subject: [PATCH 116/250] [bzimage] Allow file mode to be specified for standalone initrd files Allow the file mode to be specified using a "mode=" command line parameter. For example: initrd http://web/boot/bootlocal.sh /opt/bootlocal.sh mode=755 Requested-by: Bryce Zimmerman Signed-off-by: Michael Brown --- src/arch/i386/image/bzimage.c | 40 ++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index 67bd665f..9c22685b 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -322,6 +322,32 @@ static int bzimage_set_cmdline ( struct image *image, return 0; } +/** + * Parse standalone image command line for cpio parameters + * + * @v image bzImage file + * @v cpio CPIO header + * @v cmdline Command line + */ +static void bzimage_parse_cpio_cmdline ( struct image *image, + struct cpio_header *cpio, + const char *cmdline ) { + char *arg; + char *end; + unsigned int mode; + + /* Look for "mode=" */ + if ( ( arg = strstr ( cmdline, "mode=" ) ) ) { + arg += 5; + mode = strtoul ( arg, &end, 8 /* Octal for file mode */ ); + if ( *end && ( *end != ' ' ) ) { + DBGC ( image, "bzImage %p strange \"mode=\"" + "terminator '%c'\n", image, *end ); + } + cpio_set_field ( cpio->c_mode, ( 0100000 | mode ) ); + } +} + /** * Load initrd * @@ -334,8 +360,10 @@ static size_t bzimage_load_initrd ( struct image *image, struct image *initrd, userptr_t address ) { char *filename = initrd->cmdline; + char *cmdline; struct cpio_header cpio; size_t offset = 0; + size_t name_len; /* Do not include kernel image itself as an initrd */ if ( initrd == image ) @@ -343,24 +371,30 @@ static size_t bzimage_load_initrd ( struct image *image, /* Create cpio header before non-prebuilt images */ if ( filename && filename[0] ) { - size_t name_len = ( strlen ( filename ) + 1 ); - DBGC ( image, "bzImage %p inserting initrd %p as %s\n", image, initrd, filename ); + cmdline = strchr ( filename, ' ' ); + name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) ) + : strlen ( filename ) ) + 1 /* NUL */ ); memset ( &cpio, '0', sizeof ( cpio ) ); memcpy ( cpio.c_magic, CPIO_MAGIC, sizeof ( cpio.c_magic ) ); cpio_set_field ( cpio.c_mode, 0100644 ); cpio_set_field ( cpio.c_nlink, 1 ); cpio_set_field ( cpio.c_filesize, initrd->len ); cpio_set_field ( cpio.c_namesize, name_len ); + if ( cmdline ) { + bzimage_parse_cpio_cmdline ( image, &cpio, + ( cmdline + 1 /* ' ' */ )); + } if ( address ) { copy_to_user ( address, offset, &cpio, sizeof ( cpio ) ); } offset += sizeof ( cpio ); if ( address ) { + memset_user ( address, offset, 0, name_len ); copy_to_user ( address, offset, filename, - name_len ); + ( name_len - 1 /* NUL (or space) */ ) ); } offset += name_len; offset = ( ( offset + 0x03 ) & ~0x03 ); From d0bd3834633c1bb56b7cdbd7202db2925f3b5738 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 13 Aug 2012 22:14:57 +0100 Subject: [PATCH 117/250] [comboot] Accept only ".cbt" as an extension for COMBOOT images COMBOOT images are detected by looking for a ".com" or ".cbt" filename extension. There are widely-used files with a ".com" extension, such as "wdsnbp.com", which are PXE images rather than COMBOOT images. Avoid false detection of PXE images as COMBOOT images by accepting only a ".cbt" extension as indicating a COMBOOT image. Interestingly, this bug has been present for a long time but was frequently concealed because the filename was truncated to fit the fixed-length "name" field in struct image. (PXE binaries ending in ".com" tend to be related to Windows deployment products and so often use pathnames including backslashes, which iPXE doesn't recognise as a path separator and so treats as part of a very long filename.) Commit 1c127a6 ("[image] Simplify image management commands and internal API") made the image name a variable-length field, and so exposed this flaw in the COMBOOT image detection algorithm. Signed-off-by: Michael Brown --- src/arch/i386/image/comboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/i386/image/comboot.c b/src/arch/i386/image/comboot.c index 915ed2de..1ec02331 100644 --- a/src/arch/i386/image/comboot.c +++ b/src/arch/i386/image/comboot.c @@ -229,7 +229,7 @@ static int comboot_identify ( struct image *image ) { ++ext; - if ( strcasecmp( ext, "com" ) && strcasecmp( ext, "cbt" ) ) { + if ( strcasecmp( ext, "cbt" ) ) { DBGC ( image, "COMBOOT %p: unrecognized extension %s\n", image, ext ); return -ENOEXEC; From 37ac7a666fbb28f50cdd64e1df1428c266f60629 Mon Sep 17 00:00:00 2001 From: Daniel Wyatt Date: Wed, 15 Aug 2012 12:50:01 +0100 Subject: [PATCH 118/250] [util] Allow for CALL NEAR in the option ROM initialisation entry point Option::ROM currently understands only JMP NEAR and JMP SHORT instructions in the initialisation entry point. At least one Broadcom option ROM has been observed to use a CALL NEAR instruction. Signed-off-by: Michael Brown --- src/util/Option/ROM.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm index 82d65426..bf704cad 100644 --- a/src/util/Option/ROM.pm +++ b/src/util/Option/ROM.pm @@ -180,6 +180,7 @@ our %EXPORT_TAGS = ( all => [ @EXPORT_OK ] ); use constant JMP_SHORT => 0xeb; use constant JMP_NEAR => 0xe9; +use constant CALL_NEAR => 0xe8; sub pack_init { my $dest = shift; @@ -203,6 +204,9 @@ sub unpack_init { } elsif ( $jump == JMP_NEAR ) { my $offset = unpack ( "xS", $instr ); return ( $offset + 6 ); + } elsif ( $jump == CALL_NEAR ) { + my $offset = unpack ( "xS", $instr ); + return ( $offset + 6 ); } elsif ( $jump == 0 ) { return 0; } else { From 69fa49428088ccefd438a0e87b1111a727a8b702 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 15 Aug 2012 13:18:46 +0100 Subject: [PATCH 119/250] [util] Display UNDI ROM header in disrom.pl Requested-by: Daniel Wyatt Signed-off-by: Michael Brown --- src/util/Option/ROM.pm | 80 ++++++++++++++++++++++++++++++++++++++++++ src/util/disrom.pl | 16 +++++++++ 2 files changed, 96 insertions(+) diff --git a/src/util/Option/ROM.pm b/src/util/Option/ROM.pm index bf704cad..fb37ce4b 100644 --- a/src/util/Option/ROM.pm +++ b/src/util/Option/ROM.pm @@ -396,6 +396,25 @@ sub pnp_header { =pod +=item C<< undi_header () >> + +Return a C object representing the ROM's UNDI header, +if present. + +=cut + +sub undi_header { + my $hash = shift; + my $self = tied(%$hash); + + my $offset = $hash->{undi_header}; + return undef unless $offset != 0; + + return Option::ROM::UNDI->new ( $self->{data}, $offset ); +} + +=pod + =item C<< ipxe_header () >> Return a C object representing the ROM's iPXE @@ -591,6 +610,67 @@ sub product { return unpack ( "Z*", $raw ); } +############################################################################## +# +# Option::ROM::UNDI +# +############################################################################## + +package Option::ROM::UNDI; + +use strict; +use warnings; +use Carp; +use bytes; + +sub new { + my $class = shift; + my $data = shift; + my $offset = shift; + + my $hash = {}; + tie %$hash, "Option::ROM::Fields", { + data => $data, + offset => $offset, + length => 0x16, + fields => { + signature => { offset => 0x00, length => 0x04, pack => "a4" }, + struct_length => { offset => 0x04, length => 0x01, pack => "C" }, + checksum => { offset => 0x05, length => 0x01, pack => "C" }, + struct_revision =>{ offset => 0x06, length => 0x01, pack => "C" }, + version_revision =>{ offset => 0x07, length => 0x01, pack => "C" }, + version_minor => { offset => 0x08, length => 0x01, pack => "C" }, + version_major => { offset => 0x09, length => 0x01, pack => "C" }, + loader_entry => { offset => 0x0a, length => 0x02, pack => "S" }, + stack_size => { offset => 0x0c, length => 0x02, pack => "S" }, + data_size => { offset => 0x0e, length => 0x02, pack => "S" }, + code_size => { offset => 0x10, length => 0x02, pack => "S" }, + bus_type => { offset => 0x12, length => 0x04, pack => "a4" }, + }, + }; + bless $hash, $class; + + # Retrieve true length of structure + my $self = tied ( %$hash ); + $self->{length} = $hash->{struct_length}; + + return $hash; +} + +sub checksum { + my $hash = shift; + my $self = tied(%$hash); + + return $self->checksum(); +} + +sub fix_checksum { + my $hash = shift; + my $self = tied(%$hash); + + $hash->{checksum} = ( ( $hash->{checksum} - $hash->checksum() ) & 0xff ); +} + ############################################################################## # # Option::ROM::iPXE diff --git a/src/util/disrom.pl b/src/util/disrom.pl index 87138686..574957ac 100755 --- a/src/util/disrom.pl +++ b/src/util/disrom.pl @@ -85,6 +85,22 @@ do { printf "\n"; } + my $undi = $rom->undi_header(); + if ( $undi ) { + printf "UNDI header:\n\n"; + printf " %-16s %s\n", "Signature:", $undi->{signature}; + printf " %-16s 0x%02x (%s0x%02x)\n", "Checksum:", $undi->{checksum}, + ( ( $undi->checksum == 0 ) ? "" : "INCORRECT: " ), $undi->checksum; + printf " %-16s %d.%d.%d\n", "UNDI version:", $undi->{version_major}, + $undi->{version_minor}, $undi->{version_revision}; + printf " %-16s 0x%04x\n", "Loader entry:", $undi->{loader_entry}; + printf " %-16s 0x%04x\n", "Stack size:", $undi->{stack_size}; + printf " %-16s 0x%04x\n", "Data size:", $undi->{data_size}; + printf " %-16s 0x%04x\n", "Code size:", $undi->{code_size}; + printf " %-16s %s\n", "Bus type:", $undi->{bus_type}; + printf "\n"; + } + my $ipxe = $rom->ipxe_header(); if ( $ipxe ) { printf "iPXE header:\n\n"; From c7eea31ed8d2c138ff4ebe6e7c9ced3ba7341ab6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 15 Aug 2012 13:20:02 +0100 Subject: [PATCH 120/250] [util] Fix up checksum in UNDI ROM header, if present The UNDI ROM header does contain a checksum byte. Apparently no-one cares about this, since iPXE has left it as zero for years without anyone noticing. Since Option::ROM now understands the UNDI ROM header, we may as well fix up the checksum byte for the sake of completeness. Signed-off-by: Michael Brown --- src/util/fixrom.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/fixrom.pl b/src/util/fixrom.pl index 8987b512..dcc38fe4 100755 --- a/src/util/fixrom.pl +++ b/src/util/fixrom.pl @@ -32,6 +32,7 @@ foreach my $romfile ( @romfiles ) { my $image = $rom; while ( $image ) { $image->pnp_header->fix_checksum() if $image->pnp_header; + $image->undi_header->fix_checksum() if $image->undi_header; $image->ipxe_header->fix_checksum() if $image->ipxe_header; $image->fix_checksum(); $image = $image->next_image(); From 501527daab88a2911f5309d5215decf7011a7fde Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 15 Aug 2012 16:29:22 +0100 Subject: [PATCH 121/250] [http] Treat any unexpected connection close as an error iPXE currently checks that the server has not closed the connection mid-stream (i.e. in the middle of a chunked transfer, or before the specified Content-Length has been received), but does not check that the server got as far as starting to send data. Consequently, if the server closes the connection before any data is transferred (e.g. if the server gives up waiting while iPXE performs the validation steps for TLS), then iPXE will treat this as a successful transfer of a zero-length file. Fix by checking the RX connection state, and forcing an error if the server has closed the connection at an unexpected point. Originally-fixed-by: Marin Hannache Signed-off-by: Michael Brown --- src/net/tcp/httpcore.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 432c30d5..534e5a78 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -60,9 +60,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EIO_CONTENT_LENGTH __einfo_error ( EINFO_EIO_CONTENT_LENGTH ) #define EINFO_EIO_CONTENT_LENGTH \ __einfo_uniqify ( EINFO_EIO, 0x02, "Content length mismatch" ) -#define EIO_CHUNK __einfo_error ( EINFO_EIO_CHUNK ) -#define EINFO_EIO_CHUNK \ - __einfo_uniqify ( EINFO_EIO, 0x03, "Terminated mid-chunk" ) #define EINVAL_RESPONSE __einfo_error ( EINFO_EINVAL_RESPONSE ) #define EINFO_EINVAL_RESPONSE \ __einfo_uniqify ( EINFO_EINVAL, 0x01, "Invalid content length" ) @@ -111,7 +108,14 @@ enum http_rx_state { HTTP_RX_RESPONSE = 0, HTTP_RX_HEADER, HTTP_RX_CHUNK_LEN, + /* In HTTP_RX_DATA, it is acceptable for the server to close + * the connection (unless we are in the middle of a chunked + * transfer). + */ HTTP_RX_DATA, + /* In the following states, it is acceptable for the server to + * close the connection. + */ HTTP_RX_TRAILER, HTTP_RX_IDLE, HTTP_RX_DEAD, @@ -251,10 +255,14 @@ static int http_socket_open ( struct http_request *http ) { static void http_done ( struct http_request *http ) { int rc; - /* If we are in the middle of a chunked transfer, force an error */ - if ( http->chunked ) { - DBGC ( http, "HTTP %p terminated mid-chunk\n", http ); - http_close ( http, -EIO_CHUNK ); + /* If we are not at an appropriate stage of the protocol + * (including being in the middle of a chunked transfer), + * force an error. + */ + if ( ( http->rx_state < HTTP_RX_DATA ) || ( http->chunked != 0 ) ) { + DBGC ( http, "HTTP %p connection closed unexpectedly\n", + http ); + http_close ( http, -ECONNRESET ); return; } From 1170a36e6bb8091a638c815a17c2ec43715ad0a3 Mon Sep 17 00:00:00 2001 From: Marin Hannache Date: Wed, 15 Aug 2012 17:04:41 +0100 Subject: [PATCH 122/250] [ftp] Add support for the FTP SIZE command The FTP SIZE command allows us to get the size of a particular file, as a consequence, we can now show proper transfer progression while fetching a file using the FTP protocol. Signed-off-by: Marin Hannache Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/net/tcp/ftp.c | 71 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/src/net/tcp/ftp.c b/src/net/tcp/ftp.c index e5bc8e9f..9f93fb66 100644 --- a/src/net/tcp/ftp.c +++ b/src/net/tcp/ftp.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2007 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + #include #include #include @@ -34,6 +53,7 @@ enum ftp_state { FTP_USER, FTP_PASS, FTP_TYPE, + FTP_SIZE, FTP_PASV, FTP_RETR, FTP_WAIT, @@ -68,6 +88,8 @@ struct ftp_request { char status_text[5]; /** Passive-mode parameters, as text */ char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */ + /** File size, as text */ + char filesize[20]; }; /** @@ -157,6 +179,7 @@ static struct ftp_control_string ftp_strings[] = { [FTP_USER] = { "USER ", ftp_user }, [FTP_PASS] = { "PASS ", ftp_password }, [FTP_TYPE] = { "TYPE I", NULL }, + [FTP_SIZE] = { "SIZE ", ftp_uri_path }, [FTP_PASV] = { "PASV", NULL }, [FTP_RETR] = { "RETR ", ftp_uri_path }, [FTP_WAIT] = { NULL, NULL }, @@ -234,6 +257,14 @@ static void ftp_reply ( struct ftp_request *ftp ) { if ( status_major == '1' ) return; + /* If the SIZE command is not supported by the server, we go to + * the next step. + */ + if ( ( status_major == '5' ) && ( ftp->state == FTP_SIZE ) ) { + ftp_next_state ( ftp ); + return; + } + /* Anything other than success (2xx) or, in the case of a * repsonse to a "USER" command, a password prompt (3xx), is a * fatal error. @@ -245,6 +276,26 @@ static void ftp_reply ( struct ftp_request *ftp ) { return; } + /* Parse file size */ + if ( ftp->state == FTP_SIZE ) { + size_t filesize; + char *endptr; + + /* Parse size */ + filesize = strtoul ( ftp->filesize, &endptr, 10 ); + if ( *endptr != '\0' ) { + DBGC ( ftp, "FTP %p invalid SIZE \"%s\"\n", + ftp, ftp->filesize ); + ftp_done ( ftp, -EPROTO ); + return; + } + + /* Use seek() to notify recipient of filesize */ + DBGC ( ftp, "FTP %p file size is %zd bytes\n", ftp, filesize ); + xfer_seek ( &ftp->xfer, filesize ); + xfer_seek ( &ftp->xfer, 0 ); + } + /* Open passive connection when we get "PASV" response */ if ( ftp->state == FTP_PASV ) { char *ptr = ftp->passive_text; @@ -295,35 +346,33 @@ static int ftp_control_deliver ( struct ftp_request *ftp, while ( len-- ) { c = *(data++); - switch ( c ) { - case '\r' : - case '\n' : + if ( ( c == '\r' ) || ( c == '\n' ) ) { /* End of line: call ftp_reply() to handle * completed reply. Avoid calling ftp_reply() * twice if we receive both \r and \n. */ - if ( recvsize == 0 ) + if ( recvbuf != ftp->status_text ) ftp_reply ( ftp ); /* Start filling up the status code buffer */ recvbuf = ftp->status_text; recvsize = sizeof ( ftp->status_text ) - 1; - break; - case '(' : + } else if ( ( ftp->state == FTP_PASV ) && ( c == '(' ) ) { /* Start filling up the passive parameter buffer */ recvbuf = ftp->passive_text; recvsize = sizeof ( ftp->passive_text ) - 1; - break; - case ')' : + } else if ( ( ftp->state == FTP_PASV ) && ( c == ')' ) ) { /* Stop filling the passive parameter buffer */ recvsize = 0; - break; - default : + } else if ( ( ftp->state == FTP_SIZE ) && ( c == ' ' ) ) { + /* Start filling up the file size buffer */ + recvbuf = ftp->filesize; + recvsize = sizeof ( ftp->filesize ) - 1; + } else { /* Fill up buffer if applicable */ if ( recvsize > 0 ) { *(recvbuf++) = c; recvsize--; } - break; } } From 8f7cd88af543b0b95e4f6663251ba9d392389b8b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 17 Aug 2012 18:00:40 +0100 Subject: [PATCH 123/250] [http] Fix HTTP SAN booting Commit 501527d ("[http] Treat any unexpected connection close as an error") introduced a regression causing HTTP SAN booting to fail. At the end of the response to the HEAD request, the call to http_done() would erroneously believe that the server had disconnected in the middle of the HTTP headers. Fix by treating the header block from a HEAD request as a trailer block. This fixes the problem and also simplifies the logic in http_rx_header(). Reported-by: Shao Miller Signed-off-by: Michael Brown --- src/net/tcp/httpcore.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 534e5a78..7f178cc8 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -260,8 +260,8 @@ static void http_done ( struct http_request *http ) { * force an error. */ if ( ( http->rx_state < HTTP_RX_DATA ) || ( http->chunked != 0 ) ) { - DBGC ( http, "HTTP %p connection closed unexpectedly\n", - http ); + DBGC ( http, "HTTP %p connection closed unexpectedly in state " + "%d\n", http, http->rx_state ); http_close ( http, -ECONNRESET ); return; } @@ -362,8 +362,9 @@ static int http_rx_response ( struct http_request *http, char *response ) { return -EINVAL_RESPONSE; http->code = strtoul ( spc, NULL, 10 ); - /* Move to received headers */ - http->rx_state = HTTP_RX_HEADER; + /* Move to receive headers */ + http->rx_state = ( ( http->flags & HTTP_HEAD_ONLY ) ? + HTTP_RX_TRAILER : HTTP_RX_HEADER ); return 0; } @@ -697,8 +698,7 @@ static int http_rx_header ( struct http_request *http, char *header ) { } /* Move to next state */ - if ( ( http->rx_state == HTTP_RX_HEADER ) && - ( ! ( http->flags & HTTP_HEAD_ONLY ) ) ) { + if ( http->rx_state == HTTP_RX_HEADER ) { DBGC ( http, "HTTP %p start of data\n", http ); http->rx_state = ( http->chunked ? HTTP_RX_CHUNK_LEN : HTTP_RX_DATA ); From a05871d89ad9b94248049c66f238092fc896e9aa Mon Sep 17 00:00:00 2001 From: Kevin Tran Date: Mon, 20 Aug 2012 18:48:50 +0100 Subject: [PATCH 124/250] [tg3] Fix driver for BCM5719, BCM5720, BCM5764M, BCM57762 Signed-off-by: Michael Brown --- src/drivers/net/tg3/tg3.c | 24 ++++++++++++++---------- src/drivers/net/tg3/tg3.h | 2 ++ src/drivers/net/tg3/tg3_hw.c | 8 +++++++- src/drivers/net/tg3/tg3_phy.c | 14 ++++++-------- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/drivers/net/tg3/tg3.c b/src/drivers/net/tg3/tg3.c index b2cba72e..32ca1609 100644 --- a/src/drivers/net/tg3/tg3.c +++ b/src/drivers/net/tg3/tg3.c @@ -247,11 +247,12 @@ static int tg3_open(struct net_device *dev) return err; tpr->rx_std_iob_cnt = 0; - tg3_refill_prod_ring(tp); err = tg3_init_hw(tp, 1); if (err != 0) DBGC(tp->dev, "tg3_init_hw failed: %s\n", strerror(err)); + else + tg3_refill_prod_ring(tp); return err; } @@ -301,7 +302,6 @@ static int tg3_transmit(struct net_device *dev, struct io_buffer *iob) struct tg3 *tp = netdev_priv(dev); u32 len, entry; dma_addr_t mapping; - u32 bmsr; if (tg3_tx_avail(tp) < 1) { DBGC(dev, "Transmit ring full\n"); @@ -323,14 +323,10 @@ static int tg3_transmit(struct net_device *dev, struct io_buffer *iob) /* Packets are ready, update Tx producer idx local and on card. */ tw32_tx_mbox(tp->prodmbox, entry); - writel(entry, tp->regs + MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW); - tp->tx_prod = entry; mb(); - tg3_readphy(tp, MII_BMSR, &bmsr); - return 0; } @@ -422,8 +418,10 @@ static void tg3_refill_prod_ring(struct tg3 *tp) tpr->rx_std_iob_cnt++; } - tpr->rx_std_prod_idx = idx; - tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx); + if ((u32)idx != tpr->rx_std_prod_idx) { + tpr->rx_std_prod_idx = idx; + tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, idx); + } } static void tg3_rx_complete(struct net_device *dev) @@ -469,7 +467,10 @@ static void tg3_rx_complete(struct net_device *dev) tpr->rx_std_iob_cnt--; } - tp->rx_rcb_ptr = sw_idx; + if (tp->rx_rcb_ptr != sw_idx) { + tw32_rx_mbox(tp->consmbox, sw_idx); + tp->rx_rcb_ptr = sw_idx; + } tg3_refill_prod_ring(tp); } @@ -480,7 +481,9 @@ static void tg3_poll(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); /* ACK interrupts */ - tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00); + /* + *tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00); + */ tp->hw_status->status &= ~SD_STATUS_UPDATED; tg3_poll_link(tp); @@ -905,6 +908,7 @@ static struct pci_device_id tg3_nics[] = { PCI_ROM(0x14e4, 0x1684, "14e4-1684", "14e4-1684", 0), PCI_ROM(0x14e4, 0x165b, "14e4-165b", "14e4-165b", 0), PCI_ROM(0x14e4, 0x1681, "14e4-1681", "14e4-1681", 0), + PCI_ROM(0x14e4, 0x1682, "14e4-1682", "14e4-1682", 0), PCI_ROM(0x14e4, 0x1680, "14e4-1680", "14e4-1680", 0), PCI_ROM(0x14e4, 0x1688, "14e4-1688", "14e4-1688", 0), PCI_ROM(0x14e4, 0x1689, "14e4-1689", "14e4-1689", 0), diff --git a/src/drivers/net/tg3/tg3.h b/src/drivers/net/tg3/tg3.h index 1913cb16..e84eed87 100644 --- a/src/drivers/net/tg3/tg3.h +++ b/src/drivers/net/tg3/tg3.h @@ -153,6 +153,7 @@ #define TG3_BDINFO_NIC_ADDR 0xcUL /* 32-bit */ #define TG3_BDINFO_SIZE 0x10UL +#define RX_STD_MAX_SIZE 1536 #define TG3_RX_STD_MAX_SIZE_5700 512 #define TG3_RX_STD_MAX_SIZE_5717 2048 #define TG3_RX_JMB_MAX_SIZE_5700 256 @@ -182,6 +183,7 @@ #define TG3PCI_DEVICE_TIGON3_57781 0x16b1 #define TG3PCI_DEVICE_TIGON3_57785 0x16b5 #define TG3PCI_DEVICE_TIGON3_57761 0x16b0 +#define TG3PCI_DEVICE_TIGON3_57762 0x1682 #define TG3PCI_DEVICE_TIGON3_57765 0x16b4 #define TG3PCI_DEVICE_TIGON3_57791 0x16b2 #define TG3PCI_DEVICE_TIGON3_57795 0x16b6 diff --git a/src/drivers/net/tg3/tg3_hw.c b/src/drivers/net/tg3/tg3_hw.c index 13d5962c..9ae007c2 100644 --- a/src/drivers/net/tg3/tg3_hw.c +++ b/src/drivers/net/tg3/tg3_hw.c @@ -434,6 +434,7 @@ int tg3_get_invariants(struct tg3 *tp) else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_57781 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57785 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57761 || + tp->pdev->device == TG3PCI_DEVICE_TIGON3_57762 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57765 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 || tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795) @@ -2127,9 +2128,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) val = TG3_RX_STD_MAX_SIZE_5700 << BDINFO_FLAGS_MAXLEN_SHIFT; + if (tg3_flag(tp, 57765_PLUS)) + val |= (RX_STD_MAX_SIZE << 2); + tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val); - tpr->rx_std_prod_idx = TG3_DEF_RX_RING_PENDING; + tpr->rx_std_prod_idx = 0; /* std prod index is updated by tg3_refill_prod_ring() */ tw32_rx_mbox(TG3_RX_STD_PROD_IDX_REG, 0); @@ -2137,6 +2141,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_rings_reset(tp); + __tg3_set_mac_addr(tp,0); + #define TG3_MAX_MTU 1522 /* MTU + ethernet header + FCS + optional VLAN tag */ tw32(MAC_RX_MTU_SIZE, TG3_MAX_MTU); diff --git a/src/drivers/net/tg3/tg3_phy.c b/src/drivers/net/tg3/tg3_phy.c index f49c7f0b..65dea7e6 100644 --- a/src/drivers/net/tg3/tg3_phy.c +++ b/src/drivers/net/tg3/tg3_phy.c @@ -1008,12 +1008,11 @@ skip_phy_reset: void tg3_poll_link(struct tg3 *tp) { DBGP("%s\n", __func__); - u32 mac_stat; - - mac_stat = tr32(MAC_STATUS); - - if (mac_stat & MAC_STATUS_LNKSTATE_CHANGED) + if (tp->hw_status->status & SD_STATUS_LINK_CHG) { + DBGC(tp->dev,"link_changed\n"); + tp->hw_status->status &= ~SD_STATUS_LINK_CHG; tg3_setup_phy(tp, 0); + } } static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex) @@ -1506,9 +1505,8 @@ relink: tw32_f(MAC_MODE, tp->mac_mode); udelay(40); - /* We always use the link change register */ - /* NOTE: this freezes for mdc? */ - tw32_f(MAC_EVENT, 0); + /* Enabled attention when the link has changed state. */ + tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED); udelay(40); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 && From b0ba8923330107ce539b6265af617e497ad5529d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Aug 2012 12:28:50 +0100 Subject: [PATCH 125/250] [realtek] Always set high dword of ring address registers Some RTL8169 cards (observed with an RTL8169SC) power up with garbage values in the ring address registers, and do not clear the registers on reset. Fix by always setting the high dword of the ring address registers. Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 3c7b1f85..6a119db3 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -409,11 +409,9 @@ static int realtek_create_ring ( struct realtek_nic *rtl, /* Program ring address */ address = virt_to_bus ( ring->desc ); + writel ( ( ( ( uint64_t ) address ) >> 32 ), + rtl->regs + ring->reg + 4 ); writel ( ( address & 0xffffffffUL ), rtl->regs + ring->reg ); - if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) { - writel ( ( ( ( uint64_t ) address ) >> 32 ), - rtl->regs + ring->reg + 4 ); - } DBGC ( rtl, "REALTEK %p ring %02x is at [%08llx,%08llx)\n", rtl, ring->reg, ( ( unsigned long long ) address ), ( ( unsigned long long ) address + ring->len ) ); From 5d05220ee034bf6989786303d1e195aaf61da986 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Aug 2012 12:25:08 +0100 Subject: [PATCH 126/250] [realtek] Use explicit values for RCR.RXFTH and RCR.MXDMA Some RTL8169 cards (observed with an RTL8169SC) power up with invalid values in RCR.RXFTH and RCR.MXDMA, causing receive DMA to fail. Fix by setting explicit values for both fields. Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 6 ++++-- src/drivers/net/realtek.h | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 6a119db3..2dded0a5 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -526,8 +526,10 @@ static int realtek_open ( struct net_device *netdev ) { /* Configure receiver */ rcr = readl ( rtl->regs + RTL_RCR ); - rcr &= ~( RTL_RCR_RBLEN_MASK ); - rcr |= ( RTL_RCR_RBLEN_DEFAULT | RTL_RCR_WRAP | RTL_RCR_AB | + rcr &= ~( RTL_RCR_RXFTH_MASK | RTL_RCR_RBLEN_MASK | + RTL_RCR_MXDMA_MASK ); + rcr |= ( RTL_RCR_RXFTH_DEFAULT | RTL_RCR_RBLEN_DEFAULT | + RTL_RCR_MXDMA_DEFAULT | RTL_RCR_WRAP | RTL_RCR_AB | RTL_RCR_AM | RTL_RCR_APM | RTL_RCR_AAP ); writel ( rcr, rtl->regs + RTL_RCR ); diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h index 1c6bc544..24ec09e7 100644 --- a/src/drivers/net/realtek.h +++ b/src/drivers/net/realtek.h @@ -134,9 +134,15 @@ enum realtek_legacy_status { /** Receive (Rx) Configuration Register (dword) */ #define RTL_RCR 0x44 +#define RTL_RCR_RXFTH(x) ( (x) << 13 ) /**< Receive FIFO threshold */ +#define RTL_RCR_RXFTH_MASK RTL_RCR_RXFTH ( 0x7 ) +#define RTL_RCR_RXFTH_DEFAULT RTL_RCR_RXFTH ( 0x7 /* Whole packet */ ) #define RTL_RCR_RBLEN(x) ( (x) << 11 ) /**< Receive buffer length */ #define RTL_RCR_RBLEN_MASK RTL_RCR_RBLEN ( 0x3 ) #define RTL_RCR_RBLEN_DEFAULT RTL_RCR_RBLEN ( 0 /* 8kB */ ) +#define RTL_RCR_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */ +#define RTL_RCR_MXDMA_MASK RTL_RCR_MXDMA ( 0x7 ) +#define RTL_RCR_MXDMA_DEFAULT RTL_RCR_MXDMA ( 0x7 /* Unlimited */ ) #define RTL_RCR_WRAP 0x00000080UL /**< Overrun receive buffer */ #define RTL_RCR_9356SEL 0x00000040UL /**< EEPROM is a 93C56 */ #define RTL_RCR_AB 0x00000008UL /**< Accept broadcast packets */ From 77afdc56439c904b0a8ae167a0a899c1488b328a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Aug 2012 13:27:31 +0100 Subject: [PATCH 127/250] [realtek] Use explicit value for TCR.MXDMA Some RTL8169 cards (observed with an RTL8169SC) power up with TCR.MXDMA set to 16 bytes. While this does not prevent proper operation, it almost certainly degrades performance. Fix by explicitly setting TCR.MXDMA to "unlimited". Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 7 +++++++ src/drivers/net/realtek.h | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 2dded0a5..77df64e6 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -500,6 +500,7 @@ static void realtek_refill_rx ( struct realtek_nic *rtl ) { */ static int realtek_open ( struct net_device *netdev ) { struct realtek_nic *rtl = netdev->priv; + uint32_t tcr; uint32_t rcr; int rc; @@ -524,6 +525,12 @@ static int realtek_open ( struct net_device *netdev ) { */ writeb ( ( RTL_CR_TE | RTL_CR_RE ), rtl->regs + RTL_CR ); + /* Configure transmitter */ + tcr = readl ( rtl->regs + RTL_TCR ); + tcr &= ~RTL_TCR_MXDMA_MASK; + tcr |= RTL_TCR_MXDMA_DEFAULT; + writel ( tcr, rtl->regs + RTL_TCR ); + /* Configure receiver */ rcr = readl ( rtl->regs + RTL_RCR ); rcr &= ~( RTL_RCR_RXFTH_MASK | RTL_RCR_RBLEN_MASK | diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h index 24ec09e7..2591e725 100644 --- a/src/drivers/net/realtek.h +++ b/src/drivers/net/realtek.h @@ -132,6 +132,12 @@ enum realtek_legacy_status { /** Interrupt Status Register (word) */ #define RTL_ISR 0x3e +/** Transmit (Tx) Configuration Register (dword) */ +#define RTL_TCR 0x40 +#define RTL_TCR_MXDMA(x) ( (x) << 8 ) /**< Max DMA burst size */ +#define RTL_TCR_MXDMA_MASK RTL_TCR_MXDMA ( 0x7 ) +#define RTL_TCR_MXDMA_DEFAULT RTL_TCR_MXDMA ( 0x7 /* Unlimited */ ) + /** Receive (Rx) Configuration Register (dword) */ #define RTL_RCR 0x44 #define RTL_RCR_RXFTH(x) ( (x) << 13 ) /**< Receive FIFO threshold */ From 0e61beb26f789da01a566ff4bfdf571faacb9ce3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Aug 2012 12:38:37 +0100 Subject: [PATCH 128/250] [realtek] Use read-modify-write to check for C+ Command register Some bits in the C+ Command register are always one. Testing for the presence of the register must allow for this. Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 77df64e6..f63f25f2 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -879,8 +879,9 @@ static void realtek_detect ( struct realtek_nic *rtl ) { * Try to enable C+ mode and PCI Dual Address Cycle (for * 64-bit systems), if supported. */ - cpcr = ( RTL_CPCR_DAC | RTL_CPCR_MULRW | RTL_CPCR_CPRX | - RTL_CPCR_CPTX ); + cpcr = readw ( rtl->regs + RTL_CPCR ); + cpcr |= ( RTL_CPCR_DAC | RTL_CPCR_MULRW | RTL_CPCR_CPRX | + RTL_CPCR_CPTX ); writew ( cpcr, rtl->regs + RTL_CPCR ); check_cpcr = readw ( rtl->regs + RTL_CPCR ); @@ -890,7 +891,7 @@ static void realtek_detect ( struct realtek_nic *rtl ) { rtl->have_phy_regs = 1; rtl->tppoll = RTL_TPPOLL_8169; } else { - if ( check_cpcr == cpcr ) { + if ( ( check_cpcr == cpcr ) && ( cpcr != 0xffff ) ) { DBGC ( rtl, "REALTEK %p appears to be an RTL8139C+\n", rtl ); rtl->tppoll = RTL_TPPOLL_8139CP; From 0dacd54174a78d32f7bfff958dd120f04f130f4b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Aug 2012 13:35:19 +0100 Subject: [PATCH 129/250] [realtek] Enable DAC only when built as a 64-bit binary Some RTL8169 cards (observed with an RTL8169SC) crash and burn if DAC is enabled, even if only 32-bit addresses are used. Observed behaviour includes system lockups and repeated transmission of garbage data onto the wire. This seems to be a known problem. The Linux r8169 driver disables DAC by default and provides a "use_dac" module parameter. There appears to be no known test for determining whether or not DAC will work. As a workaround, enable DAC only if we are built as as 64-bit binary. This at least eliminates the problem in the common case of a 32-bit build, which will never use 64-bit addresses anyway. Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index f63f25f2..98fc02f4 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -878,10 +878,15 @@ static void realtek_detect ( struct realtek_nic *rtl ) { /* The C+ Command register is present only on 8169 and 8139C+. * Try to enable C+ mode and PCI Dual Address Cycle (for * 64-bit systems), if supported. + * + * Note that enabling DAC seems to cause bizarre behaviour + * (lockups, garbage data on the wire) on some systems, even + * if only 32-bit addresses are used. */ cpcr = readw ( rtl->regs + RTL_CPCR ); - cpcr |= ( RTL_CPCR_DAC | RTL_CPCR_MULRW | RTL_CPCR_CPRX | - RTL_CPCR_CPTX ); + cpcr |= ( RTL_CPCR_MULRW | RTL_CPCR_CPRX | RTL_CPCR_CPTX ); + if ( sizeof ( physaddr_t ) > sizeof ( uint32_t ) ) + cpcr |= RTL_CPCR_DAC; writew ( cpcr, rtl->regs + RTL_CPCR ); check_cpcr = readw ( rtl->regs + RTL_CPCR ); From 6e50e7950f7f4faca450f7be958b1508d2584716 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Aug 2012 21:25:51 +0100 Subject: [PATCH 130/250] [mii] Add separate mii_restart() function Signed-off-by: Michael Brown --- src/drivers/net/mii.c | 36 ++++++++++++++++++++++++++++++++---- src/include/ipxe/mii.h | 1 + 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/drivers/net/mii.c b/src/drivers/net/mii.c index c8e6529d..c4d32514 100644 --- a/src/drivers/net/mii.c +++ b/src/drivers/net/mii.c @@ -30,6 +30,37 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/** + * Restart autonegotiation + * + * @v mii MII interface + * @ret rc Return status code + */ +int mii_restart ( struct mii_interface *mii ) { + int bmcr; + int rc; + + /* Read BMCR */ + bmcr = mii_read ( mii, MII_BMCR ); + if ( bmcr < 0 ) { + rc = bmcr; + DBGC ( mii, "MII %p could not read BMCR: %s\n", + mii, strerror ( rc ) ); + return rc; + } + + /* Enable and restart autonegotiation */ + bmcr |= ( BMCR_ANENABLE | BMCR_ANRESTART ); + if ( ( rc = mii_write ( mii, MII_BMCR, bmcr ) ) != 0 ) { + DBGC ( mii, "MII %p could not write BMCR: %s\n", + mii, strerror ( rc ) ); + return rc; + } + + DBGC ( mii, "MII %p restarted autonegotiation\n", mii ); + return 0; +} + /** * Reset MII interface * @@ -70,11 +101,8 @@ int mii_reset ( struct mii_interface *mii ) { /* Force autonegotation on again, in case it was * cleared by the reset. */ - if ( ( rc = mii_write ( mii, MII_BMCR, BMCR_ANENABLE ) ) != 0 ){ - DBGC ( mii, "MII %p could not write BMCR: %s\n", - mii, strerror ( rc ) ); + if ( ( rc = mii_restart ( mii ) ) != 0 ) return rc; - } DBGC ( mii, "MII %p reset after %dms\n", mii, i ); return 0; diff --git a/src/include/ipxe/mii.h b/src/include/ipxe/mii.h index a33a31d9..cf462418 100644 --- a/src/include/ipxe/mii.h +++ b/src/include/ipxe/mii.h @@ -81,6 +81,7 @@ mii_write ( struct mii_interface *mii, unsigned int reg, unsigned int data ) { /** Maximum time to wait for a reset, in milliseconds */ #define MII_RESET_MAX_WAIT_MS 500 +extern int mii_restart ( struct mii_interface *mii ); extern int mii_reset ( struct mii_interface *mii ); #endif /* _IPXE_MII_H */ From 5676abead23d6b6d9fc14084922ec36c5d5c015e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Aug 2012 22:44:20 +0100 Subject: [PATCH 131/250] [realtek] Forcibly enable advertisement of 1000Mbps speeds Some RTL8169 cards (observed with an RTL8169SC) power up advertising only 100Mbps, despite being capable of 1000Mbps. Forcibly enable advertisement of 1000Mbps on any RTL8169-like card. This change relies on the assumption that the CTRL1000 register will not exist on 100Mbps-only RTL8169 cards such as the RTL8101. Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 79 +++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 98fc02f4..09b3fd06 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -272,6 +272,75 @@ static int realtek_reset ( struct realtek_nic *rtl ) { return -ETIMEDOUT; } +/** + * Configure PHY for Gigabit operation + * + * @v rtl Realtek device + * @ret rc Return status code + */ +static int realtek_phy_speed ( struct realtek_nic *rtl ) { + int ctrl1000; + int rc; + + /* Read CTRL1000 register */ + ctrl1000 = mii_read ( &rtl->mii, MII_CTRL1000 ); + if ( ctrl1000 < 0 ) { + rc = ctrl1000; + DBGC ( rtl, "REALTEK %p could not read CTRL1000: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + /* Advertise 1000Mbps speeds */ + ctrl1000 |= ( ADVERTISE_1000FULL | ADVERTISE_1000HALF ); + if ( ( rc = mii_write ( &rtl->mii, MII_CTRL1000, ctrl1000 ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not write CTRL1000: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** + * Reset PHY + * + * @v rtl Realtek device + * @ret rc Return status code + */ +static int realtek_phy_reset ( struct realtek_nic *rtl ) { + int rc; + + /* Do nothing if we have no separate PHY register access */ + if ( ! rtl->have_phy_regs ) + return 0; + + /* Perform MII reset */ + if ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not reset MII: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + /* Some cards (e.g. RTL8169SC) do not advertise Gigabit by + * default. Try to enable advertisement of Gigabit speeds. + */ + if ( ( rc = realtek_phy_speed ( rtl ) ) != 0 ) { + /* Ignore failures, since the register may not be + * present on non-Gigabit PHYs (e.g. RTL8101). + */ + } + + /* Restart autonegotiation */ + if ( ( rc = mii_restart ( &rtl->mii ) ) != 0 ) { + DBGC ( rtl, "REALTEK %p could not restart MII: %s\n", + rtl, strerror ( rc ) ); + return rc; + } + + return 0; +} + /****************************************************************************** * * Link state @@ -970,12 +1039,8 @@ static int realtek_probe ( struct pci_device *pci ) { /* Initialise and reset MII interface */ mii_init ( &rtl->mii, &realtek_mii_operations ); - if ( rtl->have_phy_regs && - ( ( rc = mii_reset ( &rtl->mii ) ) != 0 ) ) { - DBGC ( rtl, "REALTEK %p could not reset MII: %s\n", - rtl, strerror ( rc ) ); - goto err_mii_reset; - } + if ( ( rc = realtek_phy_reset ( rtl ) ) != 0 ) + goto err_phy_reset; /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) @@ -996,7 +1061,7 @@ static int realtek_probe ( struct pci_device *pci ) { err_register_nvo: unregister_netdev ( netdev ); err_register_netdev: - err_mii_reset: + err_phy_reset: err_nvs_read: realtek_reset ( rtl ); err_reset: From d1949f2737e44b1e0cdc6695ab867bc70002fcea Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 24 Aug 2012 17:25:14 +0100 Subject: [PATCH 132/250] [bitbash] Add optional open() and close() methods for bit-bashing interfaces Signed-off-by: Michael Brown --- src/drivers/bitbash/i2c_bit.c | 11 ++++++++++- src/drivers/bitbash/spi_bit.c | 6 ++++++ src/include/ipxe/bitbash.h | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/drivers/bitbash/i2c_bit.c b/src/drivers/bitbash/i2c_bit.c index a72d1459..decc8d80 100644 --- a/src/drivers/bitbash/i2c_bit.c +++ b/src/drivers/bitbash/i2c_bit.c @@ -239,6 +239,7 @@ static int i2c_reset ( struct bit_basher *basher ) { * pull SDA low while SCL is high (which creates a start * condition). */ + open_bit ( basher ); setscl ( basher, 0 ); setsda ( basher, 1 ); for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) { @@ -251,6 +252,7 @@ static int i2c_reset ( struct bit_basher *basher ) { i2c_stop ( basher ); DBGC ( basher, "I2CBIT %p reset after %d attempts\n", basher, ( i + 1 ) ); + close_bit ( basher ); return 0; } setscl ( basher, 0 ); @@ -258,6 +260,7 @@ static int i2c_reset ( struct bit_basher *basher ) { DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n", basher, i ); + close_bit ( basher ); return -ETIMEDOUT; } @@ -285,6 +288,8 @@ static int i2c_bit_read ( struct i2c_interface *i2c, DBGC ( basher, "I2CBIT %p reading from device %x: ", basher, i2cdev->dev_addr ); + open_bit ( basher ); + for ( ; ; data++, offset++ ) { /* Select device for writing */ @@ -312,6 +317,7 @@ static int i2c_bit_read ( struct i2c_interface *i2c, DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) ); i2c_stop ( basher ); + close_bit ( basher ); return rc; } @@ -339,6 +345,8 @@ static int i2c_bit_write ( struct i2c_interface *i2c, DBGC ( basher, "I2CBIT %p writing to device %x: ", basher, i2cdev->dev_addr ); + open_bit ( basher ); + for ( ; ; data++, offset++ ) { /* Select device for writing */ @@ -359,9 +367,10 @@ static int i2c_bit_write ( struct i2c_interface *i2c, if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 ) break; } - + DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) ); i2c_stop ( basher ); + close_bit ( basher ); return rc; } diff --git a/src/drivers/bitbash/spi_bit.c b/src/drivers/bitbash/spi_bit.c index 4a9af0a3..1b39d72f 100644 --- a/src/drivers/bitbash/spi_bit.c +++ b/src/drivers/bitbash/spi_bit.c @@ -163,6 +163,9 @@ static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device, uint32_t tmp_address; uint32_t tmp_address_detect; + /* Open bit-bashing interface */ + open_bit ( &spibit->basher ); + /* Deassert chip select to reset specified slave */ spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE ); @@ -214,6 +217,9 @@ static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device, /* Deassert chip select on specified slave */ spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE ); + /* Close bit-bashing interface */ + close_bit ( &spibit->basher ); + return 0; } diff --git a/src/include/ipxe/bitbash.h b/src/include/ipxe/bitbash.h index 62b54b10..69d5d9e3 100644 --- a/src/include/ipxe/bitbash.h +++ b/src/include/ipxe/bitbash.h @@ -13,6 +13,18 @@ struct bit_basher; /** Bit-bashing operations */ struct bit_basher_operations { + /** + * Open bit-bashing interface (optional) + * + * @v basher Bit-bashing interface + */ + void ( * open ) ( struct bit_basher *basher ); + /** + * Close bit-bashing interface (optional) + * + * @v basher Bit-bashing interface + */ + void ( * close ) ( struct bit_basher *basher ); /** * Set/clear output bit * @@ -45,6 +57,26 @@ struct bit_basher { struct bit_basher_operations *op; }; +/** + * Open bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static inline void open_bit ( struct bit_basher *basher ) { + if ( basher->op->open ) + basher->op->open ( basher ); +} + +/** + * Close bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static inline void close_bit ( struct bit_basher *basher ) { + if ( basher->op->close ) + basher->op->close ( basher ); +} + extern void write_bit ( struct bit_basher *basher, unsigned int bit_id, unsigned long data ); extern int read_bit ( struct bit_basher *basher, unsigned int bit_id ); From 70618161ad66cabee15a36554d72169e6b9ea3a9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 24 Aug 2012 16:44:29 +0100 Subject: [PATCH 133/250] [realtek] Force EEPROM CS low before disabling EEPROM access mode Some RTL8169 cards seem to drive the EEPROM CS line high (i.e. active) when 9346CR.EEM is set to "normal operating mode", with the result that the CS line is never deasserted. The symptom of this is that the first read from the EEPROM will work, while all subsequent reads will return garbage data. Reported-by: Thomas Miletich Debugged-by: Thomas Miletich Tested-by: Thomas Miletich Signed-off-by: Michael Brown --- src/drivers/net/realtek.c | 30 +++++++++++++++++++++++++++++- src/drivers/net/realtek.h | 5 +++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/drivers/net/realtek.c b/src/drivers/net/realtek.c index 09b3fd06..76fa47bb 100644 --- a/src/drivers/net/realtek.c +++ b/src/drivers/net/realtek.c @@ -60,9 +60,35 @@ static const uint8_t realtek_eeprom_bits[] = { [SPI_BIT_SCLK] = RTL_9346CR_EESK, [SPI_BIT_MOSI] = RTL_9346CR_EEDI, [SPI_BIT_MISO] = RTL_9346CR_EEDO, - [SPI_BIT_SS(0)] = ( RTL_9346CR_EECS | RTL_9346CR_EEM1 ), + [SPI_BIT_SS(0)] = RTL_9346CR_EECS, }; +/** + * Open bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static void realtek_spi_open_bit ( struct bit_basher *basher ) { + struct realtek_nic *rtl = container_of ( basher, struct realtek_nic, + spibit.basher ); + + /* Enable EEPROM access */ + writeb ( RTL_9346CR_EEM_EEPROM, rtl->regs + RTL_9346CR ); +} + +/** + * Close bit-bashing interface + * + * @v basher Bit-bashing interface + */ +static void realtek_spi_close_bit ( struct bit_basher *basher ) { + struct realtek_nic *rtl = container_of ( basher, struct realtek_nic, + spibit.basher ); + + /* Disable EEPROM access */ + writeb ( RTL_9346CR_EEM_NORMAL, rtl->regs + RTL_9346CR ); +} + /** * Read input bit * @@ -108,6 +134,8 @@ static void realtek_spi_write_bit ( struct bit_basher *basher, /** SPI bit-bashing interface */ static struct bit_basher_operations realtek_basher_ops = { + .open = realtek_spi_open_bit, + .close = realtek_spi_close_bit, .read = realtek_spi_read_bit, .write = realtek_spi_write_bit, }; diff --git a/src/drivers/net/realtek.h b/src/drivers/net/realtek.h index 2591e725..6a7b10a9 100644 --- a/src/drivers/net/realtek.h +++ b/src/drivers/net/realtek.h @@ -158,8 +158,9 @@ enum realtek_legacy_status { /** 93C46 (93C56) Command Register (byte) */ #define RTL_9346CR 0x50 -#define RTL_9346CR_EEM1 0x80 /**< Mode select bit 1 */ -#define RTL_9346CR_EEM0 0x40 /**< Mode select bit 0 */ +#define RTL_9346CR_EEM(x) ( (x) << 6 ) /**< Mode select */ +#define RTL_9346CR_EEM_EEPROM RTL_9346CR_EEM ( 0x2 ) /**< EEPROM mode */ +#define RTL_9346CR_EEM_NORMAL RTL_9346CR_EEM ( 0x0 ) /**< Normal mode */ #define RTL_9346CR_EECS 0x08 /**< Chip select */ #define RTL_9346CR_EESK 0x04 /**< Clock */ #define RTL_9346CR_EEDI 0x02 /**< Data in */ From 79300e2ddf289ef3efa40e6948efe54be0c3833d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 25 Aug 2012 04:07:35 +0100 Subject: [PATCH 134/250] [tls] Disambiguate most error causes Signed-off-by: Michael Brown --- src/net/tls.c | 172 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 140 insertions(+), 32 deletions(-) diff --git a/src/net/tls.c b/src/net/tls.c index 05884df5..ec2763b5 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -49,10 +49,118 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include /* Disambiguate the various error causes */ -#define EACCES_WRONG_NAME \ - __einfo_error ( EINFO_EACCES_WRONG_NAME ) -#define EINFO_EACCES_WRONG_NAME \ - __einfo_uniqify ( EINFO_EACCES, 0x02, "Incorrect server name" ) +#define EACCES_WRONG_NAME __einfo_error ( EINFO_EACCES_WRONG_NAME ) +#define EINFO_EACCES_WRONG_NAME \ + __einfo_uniqify ( EINFO_EACCES, 0x02, \ + "Incorrect server name" ) +#define EINVAL_CHANGE_CIPHER __einfo_error ( EINFO_EINVAL_CHANGE_CIPHER ) +#define EINFO_EINVAL_CHANGE_CIPHER \ + __einfo_uniqify ( EINFO_EINVAL, 0x01, \ + "Invalid Change Cipher record" ) +#define EINVAL_ALERT __einfo_error ( EINFO_EINVAL_ALERT ) +#define EINFO_EINVAL_ALERT \ + __einfo_uniqify ( EINFO_EINVAL, 0x02, \ + "Invalid Alert record" ) +#define EINVAL_HELLO __einfo_error ( EINFO_EINVAL_HELLO ) +#define EINFO_EINVAL_HELLO \ + __einfo_uniqify ( EINFO_EINVAL, 0x03, \ + "Invalid Server Hello record" ) +#define EINVAL_CERTIFICATE __einfo_error ( EINFO_EINVAL_CERTIFICATE ) +#define EINFO_EINVAL_CERTIFICATE \ + __einfo_uniqify ( EINFO_EINVAL, 0x04, \ + "Invalid Certificate" ) +#define EINVAL_CERTIFICATES __einfo_error ( EINFO_EINVAL_CERTIFICATES ) +#define EINFO_EINVAL_CERTIFICATES \ + __einfo_uniqify ( EINFO_EINVAL, 0x05, \ + "Invalid Server Certificate record" ) +#define EINVAL_HELLO_DONE __einfo_error ( EINFO_EINVAL_HELLO_DONE ) +#define EINFO_EINVAL_HELLO_DONE \ + __einfo_uniqify ( EINFO_EINVAL, 0x06, \ + "Invalid Server Hello Done record" ) +#define EINVAL_FINISHED __einfo_error ( EINFO_EINVAL_FINISHED ) +#define EINFO_EINVAL_FINISHED \ + __einfo_uniqify ( EINFO_EINVAL, 0x07, \ + "Invalid Server Finished record" ) +#define EINVAL_HANDSHAKE __einfo_error ( EINFO_EINVAL_HANDSHAKE ) +#define EINFO_EINVAL_HANDSHAKE \ + __einfo_uniqify ( EINFO_EINVAL, 0x08, \ + "Invalid Handshake record" ) +#define EINVAL_STREAM __einfo_error ( EINFO_EINVAL_STREAM ) +#define EINFO_EINVAL_STREAM \ + __einfo_uniqify ( EINFO_EINVAL, 0x09, \ + "Invalid stream-ciphered record" ) +#define EINVAL_BLOCK __einfo_error ( EINFO_EINVAL_BLOCK ) +#define EINFO_EINVAL_BLOCK \ + __einfo_uniqify ( EINFO_EINVAL, 0x0a, \ + "Invalid block-ciphered record" ) +#define EINVAL_PADDING __einfo_error ( EINFO_EINVAL_PADDING ) +#define EINFO_EINVAL_PADDING \ + __einfo_uniqify ( EINFO_EINVAL, 0x0b, \ + "Invalid block padding" ) +#define EINVAL_RX_STATE __einfo_error ( EINFO_EINVAL_RX_STATE ) +#define EINFO_EINVAL_RX_STATE \ + __einfo_uniqify ( EINFO_EINVAL, 0x0c, \ + "Invalid receive state" ) +#define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT ) +#define EINFO_EIO_ALERT \ + __einfo_uniqify ( EINFO_EINVAL, 0x01, \ + "Unknown alert level" ) +#define ENOMEM_CONTEXT __einfo_error ( EINFO_ENOMEM_CONTEXT ) +#define EINFO_ENOMEM_CONTEXT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x01, \ + "Not enough space for crypto context" ) +#define ENOMEM_CERTIFICATE __einfo_error ( EINFO_ENOMEM_CERTIFICATE ) +#define EINFO_ENOMEM_CERTIFICATE \ + __einfo_uniqify ( EINFO_ENOMEM, 0x02, \ + "Not enough space for certificate" ) +#define ENOMEM_CHAIN __einfo_error ( EINFO_ENOMEM_CHAIN ) +#define EINFO_ENOMEM_CHAIN \ + __einfo_uniqify ( EINFO_ENOMEM, 0x03, \ + "Not enough space for certificate chain" ) +#define ENOMEM_TX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_TX_PLAINTEXT ) +#define EINFO_ENOMEM_TX_PLAINTEXT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x04, \ + "Not enough space for transmitted plaintext" ) +#define ENOMEM_TX_CIPHERTEXT __einfo_error ( EINFO_ENOMEM_TX_CIPHERTEXT ) +#define EINFO_ENOMEM_TX_CIPHERTEXT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x05, \ + "Not enough space for transmitted ciphertext" ) +#define ENOMEM_RX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_RX_PLAINTEXT ) +#define EINFO_ENOMEM_RX_PLAINTEXT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x06, \ + "Not enough space for received plaintext" ) +#define ENOMEM_RX_DATA __einfo_error ( EINFO_ENOMEM_RX_DATA ) +#define EINFO_ENOMEM_RX_DATA \ + __einfo_uniqify ( EINFO_ENOMEM, 0x07, \ + "Not enough space for received data" ) +#define ENOTSUP_CIPHER __einfo_error ( EINFO_ENOTSUP_CIPHER ) +#define EINFO_ENOTSUP_CIPHER \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \ + "Unsupported cipher" ) +#define ENOTSUP_NULL __einfo_error ( EINFO_ENOTSUP_NULL ) +#define EINFO_ENOTSUP_NULL \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x02, \ + "Refusing to use null cipher" ) +#define ENOTSUP_SIG_HASH __einfo_error ( EINFO_ENOTSUP_SIG_HASH ) +#define EINFO_ENOTSUP_SIG_HASH \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x03, \ + "Unsupported signature and hash algorithm" ) +#define ENOTSUP_VERSION __einfo_error ( EINFO_ENOTSUP_VERSION ) +#define EINFO_ENOTSUP_VERSION \ + __einfo_uniqify ( EINFO_ENOTSUP, 0x04, \ + "Unsupported protocol version" ) +#define EPERM_ALERT __einfo_error ( EINFO_EPERM_ALERT ) +#define EINFO_EPERM_ALERT \ + __einfo_uniqify ( EINFO_EPERM, 0x01, \ + "Received fatal alert" ) +#define EPERM_VERIFY __einfo_error ( EINFO_EPERM_VERIFY ) +#define EINFO_EPERM_VERIFY \ + __einfo_uniqify ( EINFO_EPERM, 0x02, \ + "Handshake verification failed" ) +#define EPROTO_VERSION __einfo_error ( EINFO_EPROTO_VERSION ) +#define EINFO_EPROTO_VERSION \ + __einfo_uniqify ( EINFO_EINVAL, 0x01, \ + "Illegal protocol version upgrade" ) static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, const void *data, size_t len ); @@ -640,7 +748,7 @@ static int tls_set_cipher ( struct tls_session *tls, if ( ! dynamic ) { DBGC ( tls, "TLS %p could not allocate %zd bytes for crypto " "context\n", tls, total ); - return -ENOMEM; + return -ENOMEM_CONTEXT; } /* Assign storage */ @@ -674,7 +782,7 @@ static int tls_select_cipher ( struct tls_session *tls, if ( ! suite ) { DBGC ( tls, "TLS %p does not support cipher %04x\n", tls, ntohs ( cipher_suite ) ); - return -ENOTSUP; + return -ENOTSUP_CIPHER; } /* Set ciphers */ @@ -707,7 +815,7 @@ static int tls_change_cipher ( struct tls_session *tls, /* Sanity check */ if ( pending->suite == &tls_cipher_suite_null ) { DBGC ( tls, "TLS %p refusing to use null cipher\n", tls ); - return -ENOTSUP; + return -ENOTSUP_NULL; } tls_clear_cipher ( tls, active ); @@ -957,7 +1065,7 @@ static int tls_send_certificate ( struct tls_session *tls ) { */ certificate = zalloc ( sizeof ( *certificate ) ); if ( ! certificate ) - return -ENOMEM; + return -ENOMEM_CERTIFICATE; /* Populate record */ certificate->type_length = @@ -1059,7 +1167,7 @@ static int tls_send_certificate_verify ( struct tls_session *tls ) { DBGC ( tls, "TLS %p could not identify (%s,%s) " "signature and hash algorithm\n", tls, pubkey->name, digest->name ); - rc = -ENOTSUP; + rc = -ENOTSUP_SIG_HASH; goto err_sig_hash; } } @@ -1179,7 +1287,7 @@ static int tls_new_change_cipher ( struct tls_session *tls, if ( ( len != 1 ) || ( *( ( uint8_t * ) data ) != 1 ) ) { DBGC ( tls, "TLS %p received invalid Change Cipher\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_CHANGE_CIPHER; } if ( ( rc = tls_change_cipher ( tls, &tls->rx_cipherspec_pending, @@ -1214,7 +1322,7 @@ static int tls_new_alert ( struct tls_session *tls, const void *data, if ( end != ( data + len ) ) { DBGC ( tls, "TLS %p received overlength Alert\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_ALERT; } switch ( alert->level ) { @@ -1225,11 +1333,11 @@ static int tls_new_alert ( struct tls_session *tls, const void *data, case TLS_ALERT_FATAL: DBGC ( tls, "TLS %p received fatal alert %d\n", tls, alert->description ); - return -EPERM; + return -EPERM_ALERT; default: DBGC ( tls, "TLS %p received unknown alert level %d" "(alert %d)\n", tls, alert->level, alert->description ); - return -EIO; + return -EIO_ALERT; } } @@ -1263,7 +1371,7 @@ static int tls_new_server_hello ( struct tls_session *tls, if ( end > ( data + len ) ) { DBGC ( tls, "TLS %p received underlength Server Hello\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_HELLO; } /* Check and store protocol version */ @@ -1271,13 +1379,13 @@ static int tls_new_server_hello ( struct tls_session *tls, if ( version < TLS_VERSION_TLS_1_0 ) { DBGC ( tls, "TLS %p does not support protocol version %d.%d\n", tls, ( version >> 8 ), ( version & 0xff ) ); - return -ENOTSUP; + return -ENOTSUP_VERSION; } if ( version > tls->version ) { DBGC ( tls, "TLS %p server attempted to illegally upgrade to " "protocol version %d.%d\n", tls, ( version >> 8 ), ( version & 0xff ) ); - return -EPROTO; + return -EPROTO_VERSION; } tls->version = version; DBGC ( tls, "TLS %p using protocol version %d.%d\n", @@ -1334,7 +1442,7 @@ static int tls_parse_chain ( struct tls_session *tls, /* Create certificate chain */ tls->chain = x509_alloc_chain(); if ( ! tls->chain ) { - rc = -ENOMEM; + rc = -ENOMEM_CHAIN; goto err_alloc_chain; } @@ -1348,7 +1456,7 @@ static int tls_parse_chain ( struct tls_session *tls, if ( next > end ) { DBGC ( tls, "TLS %p overlength certificate:\n", tls ); DBGC_HDA ( tls, 0, data, ( end - data ) ); - rc = -EINVAL; + rc = -EINVAL_CERTIFICATE; goto err_overlength; } @@ -1401,7 +1509,7 @@ static int tls_new_certificate ( struct tls_session *tls, DBGC ( tls, "TLS %p received overlength Server Certificate\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_CERTIFICATES; } /* Parse certificate chain */ @@ -1456,7 +1564,7 @@ static int tls_new_server_hello_done ( struct tls_session *tls, DBGC ( tls, "TLS %p received overlength Server Hello Done\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_HELLO_DONE; } /* Begin certificate validation */ @@ -1492,7 +1600,7 @@ static int tls_new_finished ( struct tls_session *tls, if ( end != ( data + len ) ) { DBGC ( tls, "TLS %p received overlength Finished\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_FINISHED; } /* Verify data */ @@ -1503,7 +1611,7 @@ static int tls_new_finished ( struct tls_session *tls, if ( memcmp ( verify_data, finished->verify_data, sizeof ( verify_data ) ) != 0 ) { DBGC ( tls, "TLS %p verification failed\n", tls ); - return -EPERM; + return -EPERM_VERIFY; } /* Mark server as finished */ @@ -1543,7 +1651,7 @@ static int tls_new_handshake ( struct tls_session *tls, DBGC ( tls, "TLS %p received overlength Handshake\n", tls ); DBGC_HD ( tls, data, len ); - return -EINVAL; + return -EINVAL_HANDSHAKE; } switch ( handshake->type ) { @@ -1783,7 +1891,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, if ( ! plaintext ) { DBGC ( tls, "TLS %p could not allocate %zd bytes for " "plaintext\n", tls, plaintext_len ); - rc = -ENOMEM; + rc = -ENOMEM_TX_PLAINTEXT; goto done; } @@ -1796,7 +1904,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, if ( ! ciphertext ) { DBGC ( tls, "TLS %p could not allocate %zd bytes for " "ciphertext\n", tls, ciphertext_len ); - rc = -ENOMEM; + rc = -ENOMEM_TX_CIPHERTEXT; goto done; } @@ -1857,7 +1965,7 @@ static int tls_split_stream ( struct tls_session *tls, if ( plaintext_len < mac_len ) { DBGC ( tls, "TLS %p received underlength record\n", tls ); DBGC_HD ( tls, plaintext, plaintext_len ); - return -EINVAL; + return -EINVAL_STREAM; } content_len = ( plaintext_len - mac_len ); content = plaintext; @@ -1900,7 +2008,7 @@ static int tls_split_block ( struct tls_session *tls, if ( plaintext_len < 1 ) { DBGC ( tls, "TLS %p received underlength record\n", tls ); DBGC_HD ( tls, plaintext, plaintext_len ); - return -EINVAL; + return -EINVAL_BLOCK; } /* TLSv1.1 and later use an explicit IV */ @@ -1913,7 +2021,7 @@ static int tls_split_block ( struct tls_session *tls, if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) { DBGC ( tls, "TLS %p received underlength record\n", tls ); DBGC_HD ( tls, plaintext, plaintext_len ); - return -EINVAL; + return -EINVAL_BLOCK; } content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 ); iv = plaintext; @@ -1926,7 +2034,7 @@ static int tls_split_block ( struct tls_session *tls, if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) { DBGC ( tls, "TLS %p received bad padding\n", tls ); DBGC_HD ( tls, plaintext, plaintext_len ); - return -EINVAL; + return -EINVAL_PADDING; } } @@ -1966,7 +2074,7 @@ static int tls_new_ciphertext ( struct tls_session *tls, if ( ! plaintext ) { DBGC ( tls, "TLS %p could not allocate %zd bytes for " "decryption buffer\n", tls, record_len ); - rc = -ENOMEM; + rc = -ENOMEM_RX_PLAINTEXT; goto done; } @@ -2094,7 +2202,7 @@ static int tls_newdata_process_header ( struct tls_session *tls ) { if ( ! tls->rx_data ) { DBGC ( tls, "TLS %p could not allocate %zd bytes " "for receive buffer\n", tls, data_len ); - return -ENOMEM; + return -ENOMEM_RX_DATA; } /* Move to data state */ @@ -2162,7 +2270,7 @@ static int tls_cipherstream_deliver ( struct tls_session *tls, break; default: assert ( 0 ); - rc = -EINVAL; + rc = -EINVAL_RX_STATE; goto done; } From 34a637f46f759a8fe9e3502f730636e4fbd74820 Mon Sep 17 00:00:00 2001 From: "Anton D. Kachalov" Date: Mon, 27 Aug 2012 00:24:23 +0100 Subject: [PATCH 135/250] [build] Display commands for dependency generation when building with V=1 Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 9cfb8a3e..1e05beba 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -663,7 +663,7 @@ $(BIN)/clientcert.o : override CC := env CCACHE_DISABLE=1 $(CC) define deps_template @$(ECHO) " [DEPS] $(1)" @$(MKDIR) -p $(BIN)/deps/$(dir $(1)) - @$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \ + $(Q)$(CPP) $(CFLAGS) $(CFLAGS_$(2)) $(CFLAGS_$(3)) -DOBJECT=$(3) \ -Wno-error -M $(1) -MG -MP | \ sed 's/\.o\s*:/_DEPS +=/' > $(BIN)/deps/$(1).d endef From 5e73677a01133546e1da35f8b8d26cb1f092417a Mon Sep 17 00:00:00 2001 From: "Anton D. Kachalov" Date: Mon, 27 Aug 2012 00:28:49 +0100 Subject: [PATCH 136/250] [build] Add missing #include Signed-off-by: Michael Brown --- src/config/sideband.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/sideband.h b/src/config/sideband.h index a16c2e37..52339993 100644 --- a/src/config/sideband.h +++ b/src/config/sideband.h @@ -12,4 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); //#define CONFIG_BOFM /* IBM's BladeCenter Open Fabric Manager */ //#define VMWARE_SETTINGS /* VMware GuestInfo settings */ +#include + #endif /* CONFIG_SIDEBAND_H */ From 1cbb1581f16e235fafc963c906ad02b38d5457bd Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 30 Aug 2012 15:58:58 +0100 Subject: [PATCH 137/250] [ethernet] Expose eth_broadcast as a global constant Signed-off-by: Michael Brown --- src/include/ipxe/ethernet.h | 1 + src/net/80211/net80211.c | 7 ++----- src/net/ethernet.c | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/include/ipxe/ethernet.h b/src/include/ipxe/ethernet.h index 3d2d462e..1794ff67 100644 --- a/src/include/ipxe/ethernet.h +++ b/src/include/ipxe/ethernet.h @@ -79,6 +79,7 @@ static inline int is_valid_ether_addr ( const void *addr ) { ( ! is_zero_ether_addr ( addr ) ) ); } +extern uint8_t eth_broadcast[]; extern int eth_push ( struct net_device *netdev, struct io_buffer *iobuf, const void *ll_dest, const void *ll_source, uint16_t net_proto ); diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c index a3d3e76e..2181fc4a 100644 --- a/src/net/80211/net80211.c +++ b/src/net/80211/net80211.c @@ -387,9 +387,6 @@ static struct net_device_operations net80211_netdev_ops = { /* ---------- 802.11 link-layer protocol ---------- */ -/** 802.11 broadcast MAC address */ -static u8 net80211_ll_broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - /** * Determine whether a transmission rate uses ERP/OFDM * @@ -763,7 +760,7 @@ struct net80211_device * net80211_alloc ( size_t priv_size ) return NULL; netdev->ll_protocol = &net80211_ll_protocol; - netdev->ll_broadcast = net80211_ll_broadcast; + netdev->ll_broadcast = eth_broadcast; netdev->max_pkt_len = IEEE80211_MAX_DATA_LEN; netdev_init ( netdev, &net80211_netdev_ops ); @@ -1399,7 +1396,7 @@ int net80211_probe_step ( struct net80211_probe_ctx *ctx ) ctx->probe = iob; rc = net80211_tx_mgmt ( dev, IEEE80211_STYPE_PROBE_REQ, - net80211_ll_broadcast, + eth_broadcast, iob_disown ( siob ) ); if ( rc ) { DBGC ( dev, "802.11 %p send probe failed: " diff --git a/src/net/ethernet.c b/src/net/ethernet.c index ed1bb7a0..4fd2ab6e 100644 --- a/src/net/ethernet.c +++ b/src/net/ethernet.c @@ -39,7 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** Ethernet broadcast MAC address */ -static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /** * Add Ethernet link-layer header From de802310bc3ce8adc42d2df71793da8cb830e2c8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 31 Aug 2012 19:50:56 +0100 Subject: [PATCH 138/250] [retry] Expose retry_poll() to explicitly poll all running timers Signed-off-by: Michael Brown --- src/include/ipxe/retry.h | 1 + src/net/retry.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/include/ipxe/retry.h b/src/include/ipxe/retry.h index 87f69a5d..c514822b 100644 --- a/src/include/ipxe/retry.h +++ b/src/include/ipxe/retry.h @@ -85,6 +85,7 @@ extern void start_timer ( struct retry_timer *timer ); extern void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ); extern void stop_timer ( struct retry_timer *timer ); +extern void retry_poll ( void ); /** * Start timer with no delay diff --git a/src/net/retry.c b/src/net/retry.c index 4f43b76f..8f210bdc 100644 --- a/src/net/retry.c +++ b/src/net/retry.c @@ -177,11 +177,10 @@ static void timer_expired ( struct retry_timer *timer ) { } /** - * Single-step the retry timer list + * Poll the retry timer list * - * @v process Retry timer process */ -static void retry_step ( struct process *process __unused ) { +void retry_poll ( void ) { struct retry_timer *timer; unsigned long now = currticks(); unsigned long used; @@ -200,5 +199,14 @@ static void retry_step ( struct process *process __unused ) { } } +/** + * Single-step the retry timer list + * + * @v process Retry timer process + */ +static void retry_step ( struct process *process __unused ) { + retry_poll(); +} + /** Retry timer process */ PERMANENT_PROCESS ( retry_process, retry_step ); From e2becce1862abbf4b656967c2fda95f28a19e0e4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 29 Aug 2012 15:35:46 +0100 Subject: [PATCH 139/250] [malloc] Allow allocation of memory with a specified alignment offset Allow for allocation of memory blocks having a specified offset from a specified physical alignment, such as being 12 bytes before a 2kB boundary. Signed-off-by: Michael Brown --- src/core/malloc.c | 12 +++++++----- src/include/ipxe/malloc.h | 29 ++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/core/malloc.c b/src/core/malloc.c index 9d81ca5c..56ca7edc 100644 --- a/src/core/malloc.c +++ b/src/core/malloc.c @@ -220,6 +220,7 @@ static void discard_all_cache ( void ) { * * @v size Requested size * @v align Physical alignment + * @v offset Offset from physical alignment * @ret ptr Memory block, or NULL * * Allocates a memory block @b physically aligned as requested. No @@ -227,7 +228,7 @@ static void discard_all_cache ( void ) { * * @c align must be a power of two. @c size may not be zero. */ -void * alloc_memblock ( size_t size, size_t align ) { +void * alloc_memblock ( size_t size, size_t align, size_t offset ) { struct memory_block *block; size_t align_mask; size_t pre_size; @@ -244,12 +245,13 @@ void * alloc_memblock ( size_t size, size_t align ) { size = ( size + MIN_MEMBLOCK_SIZE - 1 ) & ~( MIN_MEMBLOCK_SIZE - 1 ); align_mask = ( align - 1 ) | ( MIN_MEMBLOCK_SIZE - 1 ); - DBG ( "Allocating %#zx (aligned %#zx)\n", size, align ); + DBG ( "Allocating %#zx (aligned %#zx+%zx)\n", size, align, offset ); while ( 1 ) { /* Search through blocks for the first one with enough space */ list_for_each_entry ( block, &free_blocks, list ) { - pre_size = ( - virt_to_phys ( block ) ) & align_mask; - post_size = block->size - pre_size - size; + pre_size = ( ( offset - virt_to_phys ( block ) ) + & align_mask ); + post_size = ( block->size - pre_size - size ); if ( post_size >= 0 ) { /* Split block into pre-block, block, and * post-block. After this split, the "pre" @@ -418,7 +420,7 @@ void * realloc ( void *old_ptr, size_t new_size ) { if ( new_size ) { new_total_size = ( new_size + offsetof ( struct autosized_block, data ) ); - new_block = alloc_memblock ( new_total_size, 1 ); + new_block = alloc_memblock ( new_total_size, 1, 0 ); if ( ! new_block ) return NULL; VALGRIND_MAKE_MEM_UNDEFINED ( new_block, offsetof ( struct autosized_block, data ) ); diff --git a/src/include/ipxe/malloc.h b/src/include/ipxe/malloc.h index d41b0562..bbd6cb89 100644 --- a/src/include/ipxe/malloc.h +++ b/src/include/ipxe/malloc.h @@ -23,11 +23,33 @@ FILE_LICENCE ( GPL2_OR_LATER ); extern size_t freemem; -extern void * __malloc alloc_memblock ( size_t size, size_t align ); +extern void * __malloc alloc_memblock ( size_t size, size_t align, + size_t offset ); extern void free_memblock ( void *ptr, size_t size ); extern void mpopulate ( void *start, size_t len ); extern void mdumpfree ( void ); +/** + * Allocate memory for DMA + * + * @v size Requested size + * @v align Physical alignment + * @v offset Offset from physical alignment + * @ret ptr Memory, or NULL + * + * Allocates physically-aligned memory for DMA. + * + * @c align must be a power of two. @c size may not be zero. + */ +static inline void * __malloc malloc_dma_offset ( size_t size, + size_t phys_align, + size_t offset ) { + void * ptr = alloc_memblock ( size, phys_align, offset ); + if ( ptr && size ) + VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 ); + return ptr; +} + /** * Allocate memory for DMA * @@ -40,10 +62,7 @@ extern void mdumpfree ( void ); * @c align must be a power of two. @c size may not be zero. */ static inline void * __malloc malloc_dma ( size_t size, size_t phys_align ) { - void * ptr = alloc_memblock ( size, phys_align ); - if ( ptr && size ) - VALGRIND_MALLOCLIKE_BLOCK ( ptr, size, 0, 0 ); - return ptr; + return malloc_dma_offset ( size, phys_align, 0 ); } /** From 96be171be572496f0ee4c1cfdc9c507b97caba00 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 29 Aug 2012 16:13:56 +0100 Subject: [PATCH 140/250] [iobuf] Allow allocation of I/O buffers with a specified alignment offset Signed-off-by: Michael Brown --- src/core/iobuf.c | 45 ++++++++++++++++++++++++++-------------- src/include/ipxe/iobuf.h | 2 ++ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/core/iobuf.c b/src/core/iobuf.c index c0491181..3f67d2f5 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -32,31 +32,25 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** - * Allocate I/O buffer + * Allocate I/O buffer with specified alignment and offset * * @v len Required length of buffer + * @v align Physical alignment + * @v offset Offset from physical alignment * @ret iobuf I/O buffer, or NULL if none available * - * The I/O buffer will be physically aligned to a multiple of - * @c IOBUF_SIZE. + * @c align will be rounded up to the nearest power of two. */ -struct io_buffer * alloc_iob ( size_t len ) { +struct io_buffer * alloc_iob_raw ( size_t len, size_t align, size_t offset ) { struct io_buffer *iobuf; - size_t align; void *data; - /* Pad to minimum length */ - if ( len < IOB_ZLEN ) - len = IOB_ZLEN; - /* Align buffer length to ensure that struct io_buffer is aligned */ len = ( len + __alignof__ ( *iobuf ) - 1 ) & ~( __alignof__ ( *iobuf ) - 1 ); - /* Align buffer on its own size to avoid potential problems - * with boundary-crossing DMA. - */ - align = ( 1 << fls ( len - 1 ) ); + /* Round up alignment to the nearest power of two */ + align = ( 1 << fls ( align - 1 ) ); /* Allocate buffer plus descriptor as a single unit, unless * doing so will push the total size over the alignment @@ -65,7 +59,8 @@ struct io_buffer * alloc_iob ( size_t len ) { if ( ( len + sizeof ( *iobuf ) ) <= align ) { /* Allocate memory for buffer plus descriptor */ - data = malloc_dma ( len + sizeof ( *iobuf ), align ); + data = malloc_dma_offset ( len + sizeof ( *iobuf ), align, + offset ); if ( ! data ) return NULL; iobuf = ( data + len ); @@ -73,7 +68,7 @@ struct io_buffer * alloc_iob ( size_t len ) { } else { /* Allocate memory for buffer */ - data = malloc_dma ( len, align ); + data = malloc_dma_offset ( len, align, offset ); if ( ! data ) return NULL; @@ -92,6 +87,26 @@ struct io_buffer * alloc_iob ( size_t len ) { return iobuf; } +/** + * Allocate I/O buffer + * + * @v len Required length of buffer + * @ret iobuf I/O buffer, or NULL if none available + * + * The I/O buffer will be physically aligned on its own size (rounded + * up to the nearest power of two). + */ +struct io_buffer * alloc_iob ( size_t len ) { + + /* Pad to minimum length */ + if ( len < IOB_ZLEN ) + len = IOB_ZLEN; + + /* Align buffer on its own size to avoid potential problems + * with boundary-crossing DMA. + */ + return alloc_iob_raw ( len, len, 0 ); +} /** * Free I/O buffer diff --git a/src/include/ipxe/iobuf.h b/src/include/ipxe/iobuf.h index 8134ae76..65a8e80d 100644 --- a/src/include/ipxe/iobuf.h +++ b/src/include/ipxe/iobuf.h @@ -210,6 +210,8 @@ static inline void iob_populate ( struct io_buffer *iobuf, (iobuf) = NULL; \ __iobuf; } ) +extern struct io_buffer * __malloc alloc_iob_raw ( size_t len, size_t align, + size_t offset ); extern struct io_buffer * __malloc alloc_iob ( size_t len ); extern void free_iob ( struct io_buffer *iobuf ); extern void iob_pad ( struct io_buffer *iobuf, size_t min_len ); From f747fac3e1dad31378579326d8e9dce0df85c214 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 29 Aug 2012 22:11:58 +0100 Subject: [PATCH 141/250] [infiniband] Allow queue pairs to have a custom allocator for receive iobufs Signed-off-by: Michael Brown --- src/drivers/infiniband/hermon.c | 8 +++++++- src/drivers/net/ipoib.c | 11 ++++++++--- src/include/ipxe/infiniband.h | 16 ++++++++++++++-- src/net/infiniband.c | 7 +++++-- src/net/infiniband/ib_cmrc.c | 8 +++++++- src/net/infiniband/ib_mi.c | 8 +++++++- 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index e7db0359..ff95e95f 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -3128,6 +3128,11 @@ static int hermon_eth_transmit ( struct net_device *netdev, return 0; } +/** Hermon Ethernet queue pair operations */ +static struct ib_queue_pair_operations hermon_eth_qp_op = { + .alloc_iob = alloc_iob, +}; + /** * Handle Hermon Ethernet device send completion * @@ -3225,7 +3230,8 @@ static int hermon_eth_open ( struct net_device *netdev ) { /* Allocate queue pair */ port->eth_qp = ib_create_qp ( ibdev, IB_QPT_ETH, HERMON_ETH_NUM_SEND_WQES, port->eth_cq, - HERMON_ETH_NUM_RECV_WQES, port->eth_cq ); + HERMON_ETH_NUM_RECV_WQES, port->eth_cq, + &hermon_eth_qp_op ); if ( ! port->eth_qp ) { DBGC ( hermon, "Hermon %p port %d could not create queue " "pair\n", hermon, ibdev->port ); diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 44afa2b6..8d4cc49e 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -534,6 +534,11 @@ static struct ib_completion_queue_operations ipoib_cq_op = { .complete_recv = ipoib_complete_recv, }; +/** IPoIB queue pair operations */ +static struct ib_queue_pair_operations ipoib_qp_op = { + .alloc_iob = alloc_iob, +}; + /** * Poll IPoIB network device * @@ -667,9 +672,9 @@ static int ipoib_open ( struct net_device *netdev ) { } /* Allocate queue pair */ - ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD, - IPOIB_NUM_SEND_WQES, ipoib->cq, - IPOIB_NUM_RECV_WQES, ipoib->cq ); + ipoib->qp = ib_create_qp ( ibdev, IB_QPT_UD, IPOIB_NUM_SEND_WQES, + ipoib->cq, IPOIB_NUM_RECV_WQES, ipoib->cq, + &ipoib_qp_op ); if ( ! ipoib->qp ) { DBGC ( ipoib, "IPoIB %p could not allocate queue pair\n", ipoib ); diff --git a/src/include/ipxe/infiniband.h b/src/include/ipxe/infiniband.h index f97a5d4f..1a64eef6 100644 --- a/src/include/ipxe/infiniband.h +++ b/src/include/ipxe/infiniband.h @@ -142,6 +142,16 @@ enum ib_queue_pair_type { IB_QPT_ETH, }; +/** Infiniband queue pair operations */ +struct ib_queue_pair_operations { + /** Allocate receive I/O buffer + * + * @v len Maximum receive length + * @ret iobuf I/O buffer (or NULL if out of memory) + */ + struct io_buffer * ( * alloc_iob ) ( size_t len ); +}; + /** An Infiniband Queue Pair */ struct ib_queue_pair { /** Containing Infiniband device */ @@ -169,6 +179,8 @@ struct ib_queue_pair { struct list_head mgids; /** Address vector */ struct ib_address_vector av; + /** Queue pair operations */ + struct ib_queue_pair_operations *op; /** Driver private data */ void *drv_priv; /** Queue owner private data */ @@ -478,8 +490,8 @@ extern void ib_poll_cq ( struct ib_device *ibdev, extern struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, enum ib_queue_pair_type type, unsigned int num_send_wqes, struct ib_completion_queue *send_cq, - unsigned int num_recv_wqes, - struct ib_completion_queue *recv_cq ); + unsigned int num_recv_wqes, struct ib_completion_queue *recv_cq, + struct ib_queue_pair_operations *op ); extern int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ); extern void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ); diff --git a/src/net/infiniband.c b/src/net/infiniband.c index c17b6181..a50b7a03 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -168,6 +168,7 @@ void ib_poll_cq ( struct ib_device *ibdev, * @v send_cq Send completion queue * @v num_recv_wqes Number of receive work queue entries * @v recv_cq Receive completion queue + * @v op Queue pair operations * @ret qp Queue pair * * The queue pair will be left in the INIT state; you must call @@ -178,7 +179,8 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, unsigned int num_send_wqes, struct ib_completion_queue *send_cq, unsigned int num_recv_wqes, - struct ib_completion_queue *recv_cq ) { + struct ib_completion_queue *recv_cq, + struct ib_queue_pair_operations *op ) { struct ib_queue_pair *qp; size_t total_size; int rc; @@ -210,6 +212,7 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, qp->recv.iobufs = ( ( ( void * ) qp ) + sizeof ( *qp ) + ( num_send_wqes * sizeof ( qp->send.iobufs[0] ) )); INIT_LIST_HEAD ( &qp->mgids ); + qp->op = op; /* Perform device-specific initialisation and get QPN */ if ( ( rc = ibdev->op->create_qp ( ibdev, qp ) ) != 0 ) { @@ -514,7 +517,7 @@ void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ) { while ( qp->recv.fill < qp->recv.num_wqes ) { /* Allocate I/O buffer */ - iobuf = alloc_iob ( IB_MAX_PAYLOAD_SIZE ); + iobuf = qp->op->alloc_iob ( IB_MAX_PAYLOAD_SIZE ); if ( ! iobuf ) { /* Non-fatal; we will refill on next attempt */ return; diff --git a/src/net/infiniband/ib_cmrc.c b/src/net/infiniband/ib_cmrc.c index 369e2e90..dd623ddb 100644 --- a/src/net/infiniband/ib_cmrc.c +++ b/src/net/infiniband/ib_cmrc.c @@ -257,6 +257,11 @@ static struct ib_completion_queue_operations ib_cmrc_completion_ops = { .complete_recv = ib_cmrc_complete_recv, }; +/** Infiniband CMRC queue pair operations */ +static struct ib_queue_pair_operations ib_cmrc_queue_pair_ops = { + .alloc_iob = alloc_iob, +}; + /** * Send data via CMRC * @@ -410,7 +415,8 @@ int ib_cmrc_open ( struct interface *xfer, struct ib_device *ibdev, /* Create queue pair */ cmrc->qp = ib_create_qp ( ibdev, IB_QPT_RC, IB_CMRC_NUM_SEND_WQES, - cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq ); + cmrc->cq, IB_CMRC_NUM_RECV_WQES, cmrc->cq, + &ib_cmrc_queue_pair_ops ); if ( ! cmrc->qp ) { DBGC ( cmrc, "CMRC %p could not create queue pair\n", cmrc ); rc = -ENOMEM; diff --git a/src/net/infiniband/ib_mi.c b/src/net/infiniband/ib_mi.c index ced2eea1..31fe71a4 100644 --- a/src/net/infiniband/ib_mi.c +++ b/src/net/infiniband/ib_mi.c @@ -164,6 +164,11 @@ static struct ib_completion_queue_operations ib_mi_completion_ops = { .complete_recv = ib_mi_complete_recv, }; +/** Management interface queue pair operations */ +static struct ib_queue_pair_operations ib_mi_queue_pair_ops = { + .alloc_iob = alloc_iob, +}; + /** * Transmit MAD * @@ -353,7 +358,8 @@ struct ib_mad_interface * ib_create_mi ( struct ib_device *ibdev, /* Create queue pair */ mi->qp = ib_create_qp ( ibdev, type, IB_MI_NUM_SEND_WQES, mi->cq, - IB_MI_NUM_RECV_WQES, mi->cq ); + IB_MI_NUM_RECV_WQES, mi->cq, + &ib_mi_queue_pair_ops ); if ( ! mi->qp ) { DBGC ( mi, "MI %p could not allocate queue pair\n", mi ); goto err_create_qp; From cbe41cb31be10edc234e96cf4291245c21272a57 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 31 Aug 2012 00:47:37 +0100 Subject: [PATCH 142/250] [infiniband] Use explicit "source" and "dest" address vector parameter names Signed-off-by: Michael Brown --- src/drivers/infiniband/arbel.c | 65 ++++++++++++------------ src/drivers/infiniband/hermon.c | 85 ++++++++++++++++---------------- src/drivers/infiniband/linda.c | 16 +++--- src/drivers/infiniband/qib7322.c | 16 +++--- src/drivers/net/ipoib.c | 32 ++++++------ src/include/ipxe/ib_packet.h | 4 +- src/include/ipxe/infiniband.h | 12 ++--- src/net/infiniband.c | 31 ++++++------ src/net/infiniband/ib_cmrc.c | 4 +- src/net/infiniband/ib_mi.c | 6 +-- src/net/infiniband/ib_packet.c | 41 ++++++++------- 11 files changed, 159 insertions(+), 153 deletions(-) diff --git a/src/drivers/infiniband/arbel.c b/src/drivers/infiniband/arbel.c index 95957d68..61fe4621 100644 --- a/src/drivers/infiniband/arbel.c +++ b/src/drivers/infiniband/arbel.c @@ -1250,14 +1250,14 @@ static const union ib_gid arbel_no_gid = { * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret nds Work queue entry size */ static size_t arbel_fill_ud_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp __unused, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union arbel_send_wqe *wqe ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); @@ -1269,16 +1269,16 @@ static size_t arbel_fill_ud_send_wqe ( struct ib_device *ibdev, ud_address_vector.pd, ARBEL_GLOBAL_PD, ud_address_vector.port_number, ibdev->port ); MLX_FILL_2 ( &wqe->ud.ud, 1, - ud_address_vector.rlid, av->lid, - ud_address_vector.g, av->gid_present ); + ud_address_vector.rlid, dest->lid, + ud_address_vector.g, dest->gid_present ); MLX_FILL_2 ( &wqe->ud.ud, 2, - ud_address_vector.max_stat_rate, arbel_rate ( av ), + ud_address_vector.max_stat_rate, arbel_rate ( dest ), ud_address_vector.msg, 3 ); - MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, av->sl ); - gid = ( av->gid_present ? &av->gid : &arbel_no_gid ); + MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, dest->sl ); + gid = ( dest->gid_present ? &dest->gid : &arbel_no_gid ); memcpy ( &wqe->ud.ud.u.dwords[4], gid, sizeof ( *gid ) ); - MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, av->qpn ); - MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, av->qkey ); + MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, dest->qpn ); + MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, dest->qkey ); MLX_FILL_1 ( &wqe->ud.data[0], 0, byte_count, iob_len ( iobuf ) ); MLX_FILL_1 ( &wqe->ud.data[0], 1, l_key, arbel->lkey ); MLX_FILL_H ( &wqe->ud.data[0], 2, @@ -1294,15 +1294,14 @@ static size_t arbel_fill_ud_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry - * @v next Previous work queue entry's "next" field * @ret nds Work queue entry size */ static size_t arbel_fill_mlx_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union arbel_send_wqe *wqe ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); @@ -1312,16 +1311,16 @@ static size_t arbel_fill_mlx_send_wqe ( struct ib_device *ibdev, iob_populate ( &headers, &wqe->mlx.headers, 0, sizeof ( wqe->mlx.headers ) ); iob_reserve ( &headers, sizeof ( wqe->mlx.headers ) ); - ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* Construct this work queue entry */ MLX_FILL_5 ( &wqe->mlx.ctrl, 0, c, 1 /* generate completion */, icrc, 0 /* generate ICRC */, - max_statrate, arbel_rate ( av ), + max_statrate, arbel_rate ( dest ), slr, 0, v15, ( ( qp->ext_qpn == IB_QPN_SMI ) ? 1 : 0 ) ); - MLX_FILL_1 ( &wqe->mlx.ctrl, 1, rlid, av->lid ); + MLX_FILL_1 ( &wqe->mlx.ctrl, 1, rlid, dest->lid ); MLX_FILL_1 ( &wqe->mlx.data[0], 0, byte_count, iob_len ( &headers ) ); MLX_FILL_1 ( &wqe->mlx.data[0], 1, l_key, arbel->lkey ); @@ -1345,15 +1344,14 @@ static size_t arbel_fill_mlx_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry - * @v next Previous work queue entry's "next" field * @ret nds Work queue entry size */ static size_t arbel_fill_rc_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp __unused, - struct ib_address_vector *av __unused, + struct ib_address_vector *dest __unused, struct io_buffer *iobuf, union arbel_send_wqe *wqe ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); @@ -1374,7 +1372,7 @@ static size_t arbel_fill_rc_send_wqe ( struct ib_device *ibdev, static size_t ( * arbel_fill_send_wqe[] ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union arbel_send_wqe *wqe ) = { [IB_QPT_SMI] = arbel_fill_mlx_send_wqe, @@ -1388,13 +1386,13 @@ static size_t * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @ret rc Return status code */ static int arbel_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ) { struct arbel *arbel = ib_get_drvdata ( ibdev ); struct arbel_queue_pair *arbel_qp = ib_qp_get_drvdata ( qp ); @@ -1424,7 +1422,7 @@ static int arbel_post_send ( struct ib_device *ibdev, assert ( qp->type < ( sizeof ( arbel_fill_send_wqe ) / sizeof ( arbel_fill_send_wqe[0] ) ) ); assert ( arbel_fill_send_wqe[qp->type] != NULL ); - nds = arbel_fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf, wqe ); + nds = arbel_fill_send_wqe[qp->type] ( ibdev, qp, dest, iobuf, wqe ); DBGCP ( arbel, "Arbel %p QPN %#lx posting send WQE %#lx:\n", arbel, qp->qpn, ( wq->next_idx & wqe_idx_mask ) ); DBGCP_HDA ( arbel, virt_to_phys ( wqe ), wqe, sizeof ( *wqe ) ); @@ -1527,9 +1525,9 @@ static int arbel_complete ( struct ib_device *ibdev, struct arbel_recv_work_queue *arbel_recv_wq; struct arbelprm_recv_wqe *recv_wqe; struct io_buffer *iobuf; - struct ib_address_vector recv_av; + struct ib_address_vector recv_source; struct ib_global_route_header *grh; - struct ib_address_vector *av; + struct ib_address_vector *source; unsigned int opcode; unsigned long qpn; int is_send; @@ -1618,23 +1616,24 @@ static int arbel_complete ( struct ib_device *ibdev, grh = iobuf->data; iob_pull ( iobuf, sizeof ( *grh ) ); /* Construct address vector */ - av = &recv_av; - memset ( av, 0, sizeof ( *av ) ); - av->qpn = MLX_GET ( &cqe->normal, rqpn ); - av->lid = MLX_GET ( &cqe->normal, rlid ); - av->sl = MLX_GET ( &cqe->normal, sl ); - av->gid_present = MLX_GET ( &cqe->normal, g ); - memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) ); + source = &recv_source; + memset ( source, 0, sizeof ( *source ) ); + source->qpn = MLX_GET ( &cqe->normal, rqpn ); + source->lid = MLX_GET ( &cqe->normal, rlid ); + source->sl = MLX_GET ( &cqe->normal, sl ); + source->gid_present = MLX_GET ( &cqe->normal, g ); + memcpy ( &source->gid, &grh->sgid, + sizeof ( source->gid ) ); break; case IB_QPT_RC: - av = &qp->av; + source = &qp->av; break; default: assert ( 0 ); return -EINVAL; } /* Hand off to completion handler */ - ib_complete_recv ( ibdev, qp, av, iobuf, rc ); + ib_complete_recv ( ibdev, qp, source, iobuf, rc ); } return rc; diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index ff95e95f..7849b143 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -1364,7 +1364,7 @@ static void hermon_destroy_qp ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1372,7 +1372,7 @@ static void hermon_destroy_qp ( struct ib_device *ibdev, static __attribute__ (( unused )) unsigned int hermon_fill_nop_send_wqe ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp __unused, - struct ib_address_vector *av __unused, + struct ib_address_vector *dest __unused, struct io_buffer *iobuf __unused, union hermon_send_wqe *wqe ) { @@ -1386,7 +1386,7 @@ hermon_fill_nop_send_wqe ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1394,7 +1394,7 @@ hermon_fill_nop_send_wqe ( struct ib_device *ibdev __unused, static unsigned int hermon_fill_ud_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp __unused, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1406,14 +1406,14 @@ hermon_fill_ud_send_wqe ( struct ib_device *ibdev, ud_address_vector.pd, HERMON_GLOBAL_PD, ud_address_vector.port_number, ibdev->port ); MLX_FILL_2 ( &wqe->ud.ud, 1, - ud_address_vector.rlid, av->lid, - ud_address_vector.g, av->gid_present ); + ud_address_vector.rlid, dest->lid, + ud_address_vector.g, dest->gid_present ); MLX_FILL_1 ( &wqe->ud.ud, 2, - ud_address_vector.max_stat_rate, hermon_rate ( av ) ); - MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, av->sl ); - memcpy ( &wqe->ud.ud.u.dwords[4], &av->gid, sizeof ( av->gid ) ); - MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, av->qpn ); - MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, av->qkey ); + ud_address_vector.max_stat_rate, hermon_rate ( dest ) ); + MLX_FILL_1 ( &wqe->ud.ud, 3, ud_address_vector.sl, dest->sl ); + memcpy ( &wqe->ud.ud.u.dwords[4], &dest->gid, sizeof ( dest->gid ) ); + MLX_FILL_1 ( &wqe->ud.ud, 8, destination_qp, dest->qpn ); + MLX_FILL_1 ( &wqe->ud.ud, 9, q_key, dest->qkey ); MLX_FILL_1 ( &wqe->ud.data[0], 0, byte_count, iob_len ( iobuf ) ); MLX_FILL_1 ( &wqe->ud.data[0], 1, l_key, hermon->lkey ); MLX_FILL_H ( &wqe->ud.data[0], 2, @@ -1428,7 +1428,7 @@ hermon_fill_ud_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1436,7 +1436,7 @@ hermon_fill_ud_send_wqe ( struct ib_device *ibdev, static unsigned int hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1446,7 +1446,7 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, iob_populate ( &headers, &wqe->mlx.headers, 0, sizeof ( wqe->mlx.headers ) ); iob_reserve ( &headers, sizeof ( wqe->mlx.headers ) ); - ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* Fill work queue entry */ MLX_FILL_1 ( &wqe->mlx.ctrl, 1, ds, @@ -1454,10 +1454,10 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, MLX_FILL_5 ( &wqe->mlx.ctrl, 2, c, 0x03 /* generate completion */, icrc, 0 /* generate ICRC */, - max_statrate, hermon_rate ( av ), + max_statrate, hermon_rate ( dest ), slr, 0, v15, ( ( qp->ext_qpn == IB_QPN_SMI ) ? 1 : 0 ) ); - MLX_FILL_1 ( &wqe->mlx.ctrl, 3, rlid, av->lid ); + MLX_FILL_1 ( &wqe->mlx.ctrl, 3, rlid, dest->lid ); MLX_FILL_1 ( &wqe->mlx.data[0], 0, byte_count, iob_len ( &headers ) ); MLX_FILL_1 ( &wqe->mlx.data[0], 1, l_key, hermon->lkey ); @@ -1480,7 +1480,7 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1488,7 +1488,7 @@ hermon_fill_mlx_send_wqe ( struct ib_device *ibdev, static unsigned int hermon_fill_rc_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp __unused, - struct ib_address_vector *av __unused, + struct ib_address_vector *dest __unused, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1510,7 +1510,7 @@ hermon_fill_rc_send_wqe ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @v wqe Send work queue entry * @ret opcode Control opcode @@ -1518,7 +1518,7 @@ hermon_fill_rc_send_wqe ( struct ib_device *ibdev, static unsigned int hermon_fill_eth_send_wqe ( struct ib_device *ibdev, struct ib_queue_pair *qp __unused, - struct ib_address_vector *av __unused, + struct ib_address_vector *dest __unused, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); @@ -1543,7 +1543,7 @@ hermon_fill_eth_send_wqe ( struct ib_device *ibdev, static unsigned int ( * hermon_fill_send_wqe[] ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf, union hermon_send_wqe *wqe ) = { [IB_QPT_SMI] = hermon_fill_mlx_send_wqe, @@ -1558,13 +1558,13 @@ static unsigned int * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @ret rc Return status code */ static int hermon_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ) { struct hermon *hermon = ib_get_drvdata ( ibdev ); struct hermon_queue_pair *hermon_qp = ib_qp_get_drvdata ( qp ); @@ -1595,7 +1595,7 @@ static int hermon_post_send ( struct ib_device *ibdev, assert ( qp->type < ( sizeof ( hermon_fill_send_wqe ) / sizeof ( hermon_fill_send_wqe[0] ) ) ); assert ( hermon_fill_send_wqe[qp->type] != NULL ); - opcode = hermon_fill_send_wqe[qp->type] ( ibdev, qp, av, iobuf, wqe ); + opcode = hermon_fill_send_wqe[qp->type] ( ibdev, qp, dest, iobuf, wqe ); barrier(); MLX_FILL_2 ( &wqe->ctrl, 0, opcode, opcode, @@ -1677,9 +1677,9 @@ static int hermon_complete ( struct ib_device *ibdev, struct ib_work_queue *wq; struct ib_queue_pair *qp; struct io_buffer *iobuf; - struct ib_address_vector recv_av; + struct ib_address_vector recv_source; struct ib_global_route_header *grh; - struct ib_address_vector *av; + struct ib_address_vector *source; unsigned int opcode; unsigned long qpn; int is_send; @@ -1737,7 +1737,7 @@ static int hermon_complete ( struct ib_device *ibdev, len = MLX_GET ( &cqe->normal, byte_cnt ); assert ( len <= iob_tailroom ( iobuf ) ); iob_put ( iobuf, len ); - memset ( &recv_av, 0, sizeof ( recv_av ) ); + memset ( &recv_source, 0, sizeof ( recv_source ) ); switch ( qp->type ) { case IB_QPT_SMI: case IB_QPT_GSI: @@ -1746,28 +1746,29 @@ static int hermon_complete ( struct ib_device *ibdev, grh = iobuf->data; iob_pull ( iobuf, sizeof ( *grh ) ); /* Construct address vector */ - av = &recv_av; - av->qpn = MLX_GET ( &cqe->normal, srq_rqpn ); - av->lid = MLX_GET ( &cqe->normal, slid_smac47_32 ); - av->sl = MLX_GET ( &cqe->normal, sl ); - av->gid_present = MLX_GET ( &cqe->normal, g ); - memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) ); + source = &recv_source; + source->qpn = MLX_GET ( &cqe->normal, srq_rqpn ); + source->lid = MLX_GET ( &cqe->normal, slid_smac47_32 ); + source->sl = MLX_GET ( &cqe->normal, sl ); + source->gid_present = MLX_GET ( &cqe->normal, g ); + memcpy ( &source->gid, &grh->sgid, + sizeof ( source->gid ) ); break; case IB_QPT_RC: - av = &qp->av; + source = &qp->av; break; case IB_QPT_ETH: /* Construct address vector */ - av = &recv_av; - av->vlan_present = MLX_GET ( &cqe->normal, vlan ); - av->vlan = MLX_GET ( &cqe->normal, vid ); + source = &recv_source; + source->vlan_present = MLX_GET ( &cqe->normal, vlan ); + source->vlan = MLX_GET ( &cqe->normal, vid ); break; default: assert ( 0 ); return -EINVAL; } /* Hand off to completion handler */ - ib_complete_recv ( ibdev, qp, av, iobuf, rc ); + ib_complete_recv ( ibdev, qp, source, iobuf, rc ); } return rc; @@ -3154,20 +3155,20 @@ static void hermon_eth_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct net_device *netdev = ib_qp_get_ownerdata ( qp ); struct net_device *vlan; /* Find VLAN device, if applicable */ - if ( av->vlan_present ) { - if ( ( vlan = vlan_find ( netdev, av->vlan ) ) != NULL ) { + if ( source->vlan_present ) { + if ( ( vlan = vlan_find ( netdev, source->vlan ) ) != NULL ) { netdev = vlan; } else if ( rc == 0 ) { rc = -ENODEV; diff --git a/src/drivers/infiniband/linda.c b/src/drivers/infiniband/linda.c index ae0a3039..fca17475 100644 --- a/src/drivers/infiniband/linda.c +++ b/src/drivers/infiniband/linda.c @@ -936,13 +936,13 @@ static void linda_destroy_qp ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @ret rc Return status code */ static int linda_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ) { struct linda *linda = ib_get_drvdata ( ibdev ); struct ib_work_queue *wq = &qp->send; @@ -969,7 +969,7 @@ static int linda_post_send ( struct ib_device *ibdev, /* Construct headers */ iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) ); iob_reserve ( &headers, sizeof ( header_buf ) ); - ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* Calculate packet length */ len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) + @@ -1170,7 +1170,7 @@ static void linda_complete_recv ( struct ib_device *ibdev, struct io_buffer headers; struct io_buffer *iobuf; struct ib_queue_pair *intended_qp; - struct ib_address_vector av; + struct ib_address_vector source; unsigned int rcvtype; unsigned int pktlen; unsigned int egrindex; @@ -1238,7 +1238,7 @@ static void linda_complete_recv ( struct ib_device *ibdev, qp0 = ( qp->qpn == 0 ); intended_qp = NULL; if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ), - &payload_len, &av ) ) != 0 ) { + &payload_len, &source ) ) != 0 ) { DBGC ( linda, "Linda %p could not parse headers: %s\n", linda, strerror ( rc ) ); err = 1; @@ -1295,10 +1295,12 @@ static void linda_complete_recv ( struct ib_device *ibdev, qp->recv.fill--; intended_qp->recv.fill++; } - ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc); + ib_complete_recv ( ibdev, intended_qp, &source, + iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ - ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED ); + ib_complete_recv ( ibdev, qp, &source, iobuf, + -ECANCELED ); } /* Clear eager buffer */ diff --git a/src/drivers/infiniband/qib7322.c b/src/drivers/infiniband/qib7322.c index d9baf46d..89614129 100644 --- a/src/drivers/infiniband/qib7322.c +++ b/src/drivers/infiniband/qib7322.c @@ -1173,13 +1173,13 @@ static void qib7322_destroy_qp ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @ret rc Return status code */ static int qib7322_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ) { struct qib7322 *qib7322 = ib_get_drvdata ( ibdev ); struct ib_work_queue *wq = &qp->send; @@ -1211,7 +1211,7 @@ static int qib7322_post_send ( struct ib_device *ibdev, /* Construct headers */ iob_populate ( &headers, header_buf, 0, sizeof ( header_buf ) ); iob_reserve ( &headers, sizeof ( header_buf ) ); - ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), av ); + ib_push ( ibdev, &headers, qp, iob_len ( iobuf ), dest ); /* Calculate packet length */ len = ( ( sizeof ( sendpbc ) + iob_len ( &headers ) + @@ -1413,7 +1413,7 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, struct io_buffer headers; struct io_buffer *iobuf; struct ib_queue_pair *intended_qp; - struct ib_address_vector av; + struct ib_address_vector source; unsigned int rcvtype; unsigned int pktlen; unsigned int egrindex; @@ -1474,7 +1474,7 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, qp0 = ( qp->qpn == 0 ); intended_qp = NULL; if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ), - &payload_len, &av ) ) != 0 ) { + &payload_len, &source ) ) != 0 ) { DBGC ( qib7322, "QIB7322 %p could not parse headers: %s\n", qib7322, strerror ( rc ) ); err = 1; @@ -1531,10 +1531,12 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, qp->recv.fill--; intended_qp->recv.fill++; } - ib_complete_recv ( ibdev, intended_qp, &av, iobuf, rc); + ib_complete_recv ( ibdev, intended_qp, &source, + iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ - ib_complete_recv ( ibdev, qp, &av, iobuf, -ECANCELED ); + ib_complete_recv ( ibdev, qp, &source, iobuf, + -ECANCELED ); } /* Clear eager buffer */ diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 8d4cc49e..bbc9425a 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -423,8 +423,8 @@ static int ipoib_transmit ( struct net_device *netdev, struct ipoib_device *ipoib = netdev->priv; struct ib_device *ibdev = ipoib->ibdev; struct ipoib_hdr *ipoib_hdr; - struct ipoib_peer *dest; - struct ib_address_vector av; + struct ipoib_peer *peer; + struct ib_address_vector dest; int rc; /* Sanity check */ @@ -441,22 +441,22 @@ static int ipoib_transmit ( struct net_device *netdev, return -ENETUNREACH; /* Identify destination address */ - dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest ); - if ( ! dest ) + peer = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest ); + if ( ! peer ) return -ENXIO; ipoib_hdr->u.reserved = 0; /* Construct address vector */ - memset ( &av, 0, sizeof ( av ) ); - av.qpn = ( ntohl ( dest->mac.flags__qpn ) & IB_QPN_MASK ); - av.gid_present = 1; - memcpy ( &av.gid, &dest->mac.gid, sizeof ( av.gid ) ); - if ( ( rc = ib_resolve_path ( ibdev, &av ) ) != 0 ) { + memset ( &dest, 0, sizeof ( dest ) ); + dest.qpn = ( ntohl ( peer->mac.flags__qpn ) & IB_QPN_MASK ); + dest.gid_present = 1; + memcpy ( &dest.gid, &peer->mac.gid, sizeof ( dest.gid ) ); + if ( ( rc = ib_resolve_path ( ibdev, &dest ) ) != 0 ) { /* Path not resolved yet */ return rc; } - return ib_post_send ( ibdev, ipoib->qp, &av, iobuf ); + return ib_post_send ( ibdev, ipoib->qp, &dest, iobuf ); } /** @@ -480,13 +480,13 @@ static void ipoib_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp ); struct net_device *netdev = ipoib->netdev; @@ -509,7 +509,7 @@ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, return; } ipoib_hdr = iobuf->data; - if ( ! av ) { + if ( ! source ) { DBGC ( ipoib, "IPoIB %p received packet without address " "vector\n", ipoib ); netdev_rx_err ( netdev, iobuf, -ENOTTY ); @@ -517,9 +517,9 @@ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, } /* Parse source address */ - if ( av->gid_present ) { - ll_src.flags__qpn = htonl ( av->qpn ); - memcpy ( &ll_src.gid, &av->gid, sizeof ( ll_src.gid ) ); + if ( source->gid_present ) { + ll_src.flags__qpn = htonl ( source->qpn ); + memcpy ( &ll_src.gid, &source->gid, sizeof ( ll_src.gid ) ); src = ipoib_cache_peer ( &ll_src ); ipoib_hdr->u.peer.src = src->key; } diff --git a/src/include/ipxe/ib_packet.h b/src/include/ipxe/ib_packet.h index 4bd33576..2556b6e1 100644 --- a/src/include/ipxe/ib_packet.h +++ b/src/include/ipxe/ib_packet.h @@ -152,9 +152,9 @@ union ib_headers { extern int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair *qp, size_t payload_len, - const struct ib_address_vector *av ); + const struct ib_address_vector *dest ); extern int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair **qp, size_t *payload_len, - struct ib_address_vector *av ); + struct ib_address_vector *source ); #endif /* _IPXE_IB_PACKET_H */ diff --git a/src/include/ipxe/infiniband.h b/src/include/ipxe/infiniband.h index 1a64eef6..48c61887 100644 --- a/src/include/ipxe/infiniband.h +++ b/src/include/ipxe/infiniband.h @@ -205,13 +205,13 @@ struct ib_completion_queue_operations { * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ void ( * complete_recv ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ); }; @@ -289,7 +289,7 @@ struct ib_device_operations { * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @ret rc Return status code * @@ -300,7 +300,7 @@ struct ib_device_operations { */ int ( * post_send ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ); /** Post receive work queue entry * @@ -502,7 +502,7 @@ extern struct ib_queue_pair * ib_find_qp_mgid ( struct ib_device *ibdev, extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq, unsigned long qpn, int is_send ); extern int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ); extern int ib_post_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, struct io_buffer *iobuf ); @@ -511,7 +511,7 @@ extern void ib_complete_send ( struct ib_device *ibdev, struct io_buffer *iobuf, int rc ); extern void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ); extern void ib_refill_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp ); diff --git a/src/net/infiniband.c b/src/net/infiniband.c index a50b7a03..f50778d0 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -263,7 +263,6 @@ struct ib_queue_pair * ib_create_qp ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av New address vector, if applicable * @ret rc Return status code */ int ib_modify_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) { @@ -384,14 +383,14 @@ struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v dest Destination address vector * @v iobuf I/O buffer * @ret rc Return status code */ int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *dest, struct io_buffer *iobuf ) { - struct ib_address_vector av_copy; + struct ib_address_vector dest_copy; int rc; /* Check queue fill level */ @@ -402,21 +401,21 @@ int ib_post_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, } /* Use default address vector if none specified */ - if ( ! av ) - av = &qp->av; + if ( ! dest ) + dest = &qp->av; /* Make modifiable copy of address vector */ - memcpy ( &av_copy, av, sizeof ( av_copy ) ); - av = &av_copy; + memcpy ( &dest_copy, dest, sizeof ( dest_copy ) ); + dest = &dest_copy; /* Fill in optional parameters in address vector */ - if ( ! av->qkey ) - av->qkey = qp->qkey; - if ( ! av->rate ) - av->rate = IB_RATE_2_5; + if ( ! dest->qkey ) + dest->qkey = qp->qkey; + if ( ! dest->rate ) + dest->rate = IB_RATE_2_5; /* Post to hardware */ - if ( ( rc = ibdev->op->post_send ( ibdev, qp, av, iobuf ) ) != 0 ) { + if ( ( rc = ibdev->op->post_send ( ibdev, qp, dest, iobuf ) ) != 0 ) { DBGC ( ibdev, "IBDEV %p QPN %#lx could not post send WQE: " "%s\n", ibdev, qp->qpn, strerror ( rc ) ); return rc; @@ -487,16 +486,16 @@ void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { if ( qp->recv.cq->op->complete_recv ) { - qp->recv.cq->op->complete_recv ( ibdev, qp, av, iobuf, rc ); + qp->recv.cq->op->complete_recv ( ibdev, qp, source, iobuf, rc ); } else { free_iob ( iobuf ); } diff --git a/src/net/infiniband/ib_cmrc.c b/src/net/infiniband/ib_cmrc.c index dd623ddb..cb5ed47b 100644 --- a/src/net/infiniband/ib_cmrc.c +++ b/src/net/infiniband/ib_cmrc.c @@ -220,13 +220,13 @@ static void ib_cmrc_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector, or NULL + * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ static void ib_cmrc_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, - struct ib_address_vector *av __unused, + struct ib_address_vector *source __unused, struct io_buffer *iobuf, int rc ) { struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp ); diff --git a/src/net/infiniband/ib_mi.c b/src/net/infiniband/ib_mi.c index 31fe71a4..2ca91943 100644 --- a/src/net/infiniband/ib_mi.c +++ b/src/net/infiniband/ib_mi.c @@ -112,13 +112,13 @@ static int ib_mi_handle ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v av Address vector + * @v source Address vector * @v iobuf I/O buffer * @v rc Completion status code */ static void ib_mi_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, - struct ib_address_vector *av, + struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct ib_mad_interface *mi = ib_qp_get_ownerdata ( qp ); union ib_mad *mad; @@ -152,7 +152,7 @@ static void ib_mi_complete_recv ( struct ib_device *ibdev, DBGC2_HDA ( mi, 0, mad, sizeof ( *mad ) ); /* Handle MAD */ - if ( ( rc = ib_mi_handle ( ibdev, mi, mad, av ) ) != 0 ) + if ( ( rc = ib_mi_handle ( ibdev, mi, mad, source ) ) != 0 ) goto out; out: diff --git a/src/net/infiniband/ib_packet.c b/src/net/infiniband/ib_packet.c index df883faf..36b533f5 100644 --- a/src/net/infiniband/ib_packet.c +++ b/src/net/infiniband/ib_packet.c @@ -42,11 +42,12 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @v iobuf I/O buffer to contain headers * @v qp Queue pair * @v payload_len Payload length - * @v av Address vector + * @v dest Destination address vector + * @ret rc Return status code */ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair *qp, size_t payload_len, - const struct ib_address_vector *av ) { + const struct ib_address_vector *dest ) { struct ib_local_route_header *lrh; struct ib_global_route_header *grh; struct ib_base_transport_header *bth; @@ -59,7 +60,8 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, unsigned int lnh; DBGC2 ( ibdev, "IBDEV %p TX %04x:%08lx => %04x:%08lx (key %08lx)\n", - ibdev, ibdev->lid, qp->ext_qpn, av->lid, av->qpn, av->qkey ); + ibdev, ibdev->lid, qp->ext_qpn, dest->lid, dest->qpn, + dest->qkey ); /* Calculate packet length */ pad_len = ( (-payload_len) & 0x3 ); @@ -71,7 +73,7 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, deth = iob_push ( iobuf, sizeof ( *deth ) ); bth = iob_push ( iobuf, sizeof ( *bth ) ); grh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len ); - grh = ( av->gid_present ? + grh = ( dest->gid_present ? iob_push ( iobuf, sizeof ( *grh ) ) : NULL ); lrh = iob_push ( iobuf, sizeof ( *lrh ) ); lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len ); @@ -80,8 +82,8 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, vl = ( ( qp->ext_qpn == IB_QPN_SMI ) ? IB_VL_SMP : IB_VL_DEFAULT ); lrh->vl__lver = ( vl << 4 ); lnh = ( grh ? IB_LNH_GRH : IB_LNH_BTH ); - lrh->sl__lnh = ( ( av->sl << 4 ) | lnh ); - lrh->dlid = htons ( av->lid ); + lrh->sl__lnh = ( ( dest->sl << 4 ) | lnh ); + lrh->dlid = htons ( dest->lid ); lrh->length = htons ( lrh_len >> 2 ); lrh->slid = htons ( ibdev->lid ); @@ -93,18 +95,18 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, grh->nxthdr = IB_GRH_NXTHDR_IBA; grh->hoplmt = 0; memcpy ( &grh->sgid, &ibdev->gid, sizeof ( grh->sgid ) ); - memcpy ( &grh->dgid, &av->gid, sizeof ( grh->dgid ) ); + memcpy ( &grh->dgid, &dest->gid, sizeof ( grh->dgid ) ); } /* Construct BTH */ bth->opcode = BTH_OPCODE_UD_SEND; bth->se__m__padcnt__tver = ( pad_len << 4 ); bth->pkey = htons ( ibdev->pkey ); - bth->dest_qp = htonl ( av->qpn ); + bth->dest_qp = htonl ( dest->qpn ); bth->ack__psn = htonl ( ( qp->send.psn++ ) & 0xffffffUL ); /* Construct DETH */ - deth->qkey = htonl ( av->qkey ); + deth->qkey = htonl ( dest->qkey ); deth->src_qp = htonl ( qp->ext_qpn ); DBGCP_HDA ( ibdev, 0, iobuf->data, @@ -120,11 +122,12 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, * @v iobuf I/O buffer containing headers * @v qp Queue pair to fill in, or NULL * @v payload_len Payload length to fill in, or NULL - * @v av Address vector to fill in + * @v source Source address vector to fill in + * @ret rc Return status code */ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair **qp, size_t *payload_len, - struct ib_address_vector *av ) { + struct ib_address_vector *source ) { struct ib_local_route_header *lrh; struct ib_global_route_header *grh; struct ib_base_transport_header *bth; @@ -140,7 +143,7 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, *qp = NULL; if ( payload_len ) *payload_len = 0; - memset ( av, 0, sizeof ( *av ) ); + memset ( source, 0, sizeof ( *source ) ); /* Extract LRH */ if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) { @@ -150,8 +153,8 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } lrh = iobuf->data; iob_pull ( iobuf, sizeof ( *lrh ) ); - av->lid = ntohs ( lrh->slid ); - av->sl = ( lrh->sl__lnh >> 4 ); + source->lid = ntohs ( lrh->slid ); + source->sl = ( lrh->sl__lnh >> 4 ); lnh = ( lrh->sl__lnh & 0x3 ); lid = ntohs ( lrh->dlid ); @@ -171,8 +174,8 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } grh = iobuf->data; iob_pull ( iobuf, sizeof ( *grh ) ); - av->gid_present = 1; - memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) ); + source->gid_present = 1; + memcpy ( &source->gid, &grh->sgid, sizeof ( source->gid ) ); } else { grh = NULL; } @@ -200,8 +203,8 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } deth = iobuf->data; iob_pull ( iobuf, sizeof ( *deth ) ); - av->qpn = ntohl ( deth->src_qp ); - av->qkey = ntohl ( deth->qkey ); + source->qpn = ntohl ( deth->src_qp ); + source->qkey = ntohl ( deth->qkey ); /* Calculate payload length, if applicable */ if ( payload_len ) { @@ -233,7 +236,7 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, DBGC2 ( ibdev, "IBDEV %p RX %04x:%08lx <= %04x:%08lx (key %08x)\n", ibdev, lid, ( IB_LID_MULTICAST( lid ) ? ( qp ? (*qp)->ext_qpn : -1UL ) : qpn ), - av->lid, av->qpn, ntohl ( deth->qkey ) ); + source->lid, source->qpn, ntohl ( deth->qkey ) ); DBGCP_HDA ( ibdev, 0, ( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ), ( orig_iob_len - iob_len ( iobuf ) ) ); From f54a61e43450fae7d045bebabc4c368d325e71d3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 31 Aug 2012 01:48:49 +0100 Subject: [PATCH 143/250] [infiniband] Include destination address vector in ib_complete_recv() Signed-off-by: Michael Brown --- src/drivers/infiniband/arbel.c | 10 ++++++++-- src/drivers/infiniband/hermon.c | 12 ++++++++++-- src/drivers/infiniband/linda.c | 7 ++++--- src/drivers/infiniband/qib7322.c | 7 ++++--- src/drivers/net/ipoib.c | 2 ++ src/include/ipxe/ib_packet.h | 1 + src/include/ipxe/infiniband.h | 3 +++ src/net/infiniband.c | 7 +++++-- src/net/infiniband/ib_cmrc.c | 2 ++ src/net/infiniband/ib_mi.c | 4 +++- src/net/infiniband/ib_packet.c | 22 +++++++++++++--------- 11 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/drivers/infiniband/arbel.c b/src/drivers/infiniband/arbel.c index 61fe4621..1a56ff9a 100644 --- a/src/drivers/infiniband/arbel.c +++ b/src/drivers/infiniband/arbel.c @@ -1525,6 +1525,7 @@ static int arbel_complete ( struct ib_device *ibdev, struct arbel_recv_work_queue *arbel_recv_wq; struct arbelprm_recv_wqe *recv_wqe; struct io_buffer *iobuf; + struct ib_address_vector recv_dest; struct ib_address_vector recv_source; struct ib_global_route_header *grh; struct ib_address_vector *source; @@ -1608,6 +1609,8 @@ static int arbel_complete ( struct ib_device *ibdev, l_key, ARBEL_INVALID_LKEY ); assert ( len <= iob_tailroom ( iobuf ) ); iob_put ( iobuf, len ); + memset ( &recv_dest, 0, sizeof ( recv_dest ) ); + recv_dest.qpn = qpn; switch ( qp->type ) { case IB_QPT_SMI: case IB_QPT_GSI: @@ -1621,7 +1624,10 @@ static int arbel_complete ( struct ib_device *ibdev, source->qpn = MLX_GET ( &cqe->normal, rqpn ); source->lid = MLX_GET ( &cqe->normal, rlid ); source->sl = MLX_GET ( &cqe->normal, sl ); - source->gid_present = MLX_GET ( &cqe->normal, g ); + recv_dest.gid_present = source->gid_present = + MLX_GET ( &cqe->normal, g ); + memcpy ( &recv_dest.gid, &grh->dgid, + sizeof ( recv_dest.gid ) ); memcpy ( &source->gid, &grh->sgid, sizeof ( source->gid ) ); break; @@ -1633,7 +1639,7 @@ static int arbel_complete ( struct ib_device *ibdev, return -EINVAL; } /* Hand off to completion handler */ - ib_complete_recv ( ibdev, qp, source, iobuf, rc ); + ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc ); } return rc; diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index 7849b143..8a4fba94 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -1677,6 +1677,7 @@ static int hermon_complete ( struct ib_device *ibdev, struct ib_work_queue *wq; struct ib_queue_pair *qp; struct io_buffer *iobuf; + struct ib_address_vector recv_dest; struct ib_address_vector recv_source; struct ib_global_route_header *grh; struct ib_address_vector *source; @@ -1737,6 +1738,8 @@ static int hermon_complete ( struct ib_device *ibdev, len = MLX_GET ( &cqe->normal, byte_cnt ); assert ( len <= iob_tailroom ( iobuf ) ); iob_put ( iobuf, len ); + memset ( &recv_dest, 0, sizeof ( recv_dest ) ); + recv_dest.qpn = qpn; memset ( &recv_source, 0, sizeof ( recv_source ) ); switch ( qp->type ) { case IB_QPT_SMI: @@ -1750,7 +1753,10 @@ static int hermon_complete ( struct ib_device *ibdev, source->qpn = MLX_GET ( &cqe->normal, srq_rqpn ); source->lid = MLX_GET ( &cqe->normal, slid_smac47_32 ); source->sl = MLX_GET ( &cqe->normal, sl ); - source->gid_present = MLX_GET ( &cqe->normal, g ); + recv_dest.gid_present = source->gid_present = + MLX_GET ( &cqe->normal, g ); + memcpy ( &recv_dest.gid, &grh->dgid, + sizeof ( recv_dest.gid ) ); memcpy ( &source->gid, &grh->sgid, sizeof ( source->gid ) ); break; @@ -1768,7 +1774,7 @@ static int hermon_complete ( struct ib_device *ibdev, return -EINVAL; } /* Hand off to completion handler */ - ib_complete_recv ( ibdev, qp, source, iobuf, rc ); + ib_complete_recv ( ibdev, qp, &recv_dest, source, iobuf, rc ); } return rc; @@ -3155,12 +3161,14 @@ static void hermon_eth_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair + * @v dest Destination address vector, or NULL * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ static void hermon_eth_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, + struct ib_address_vector *dest __unused, struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct net_device *netdev = ib_qp_get_ownerdata ( qp ); diff --git a/src/drivers/infiniband/linda.c b/src/drivers/infiniband/linda.c index fca17475..4afda120 100644 --- a/src/drivers/infiniband/linda.c +++ b/src/drivers/infiniband/linda.c @@ -1170,6 +1170,7 @@ static void linda_complete_recv ( struct ib_device *ibdev, struct io_buffer headers; struct io_buffer *iobuf; struct ib_queue_pair *intended_qp; + struct ib_address_vector dest; struct ib_address_vector source; unsigned int rcvtype; unsigned int pktlen; @@ -1238,7 +1239,7 @@ static void linda_complete_recv ( struct ib_device *ibdev, qp0 = ( qp->qpn == 0 ); intended_qp = NULL; if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ), - &payload_len, &source ) ) != 0 ) { + &payload_len, &dest, &source ) ) != 0 ) { DBGC ( linda, "Linda %p could not parse headers: %s\n", linda, strerror ( rc ) ); err = 1; @@ -1295,11 +1296,11 @@ static void linda_complete_recv ( struct ib_device *ibdev, qp->recv.fill--; intended_qp->recv.fill++; } - ib_complete_recv ( ibdev, intended_qp, &source, + ib_complete_recv ( ibdev, intended_qp, &dest, &source, iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ - ib_complete_recv ( ibdev, qp, &source, iobuf, + ib_complete_recv ( ibdev, qp, &dest, &source, iobuf, -ECANCELED ); } diff --git a/src/drivers/infiniband/qib7322.c b/src/drivers/infiniband/qib7322.c index 89614129..9979b346 100644 --- a/src/drivers/infiniband/qib7322.c +++ b/src/drivers/infiniband/qib7322.c @@ -1413,6 +1413,7 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, struct io_buffer headers; struct io_buffer *iobuf; struct ib_queue_pair *intended_qp; + struct ib_address_vector dest; struct ib_address_vector source; unsigned int rcvtype; unsigned int pktlen; @@ -1474,7 +1475,7 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, qp0 = ( qp->qpn == 0 ); intended_qp = NULL; if ( ( rc = ib_pull ( ibdev, &headers, ( qp0 ? &intended_qp : NULL ), - &payload_len, &source ) ) != 0 ) { + &payload_len, &dest, &source ) ) != 0 ) { DBGC ( qib7322, "QIB7322 %p could not parse headers: %s\n", qib7322, strerror ( rc ) ); err = 1; @@ -1531,11 +1532,11 @@ static void qib7322_complete_recv ( struct ib_device *ibdev, qp->recv.fill--; intended_qp->recv.fill++; } - ib_complete_recv ( ibdev, intended_qp, &source, + ib_complete_recv ( ibdev, intended_qp, &dest, &source, iobuf, rc); } else { /* Completing on a skipped-over eager buffer */ - ib_complete_recv ( ibdev, qp, &source, iobuf, + ib_complete_recv ( ibdev, qp, &dest, &source, iobuf, -ECANCELED ); } diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index bbc9425a..41ba348b 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -480,12 +480,14 @@ static void ipoib_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair + * @v dest Destination address vector, or NULL * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, + struct ib_address_vector *dest __unused, struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp ); diff --git a/src/include/ipxe/ib_packet.h b/src/include/ipxe/ib_packet.h index 2556b6e1..a959967c 100644 --- a/src/include/ipxe/ib_packet.h +++ b/src/include/ipxe/ib_packet.h @@ -155,6 +155,7 @@ extern int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, const struct ib_address_vector *dest ); extern int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair **qp, size_t *payload_len, + struct ib_address_vector *dest, struct ib_address_vector *source ); #endif /* _IPXE_IB_PACKET_H */ diff --git a/src/include/ipxe/infiniband.h b/src/include/ipxe/infiniband.h index 48c61887..f546ea61 100644 --- a/src/include/ipxe/infiniband.h +++ b/src/include/ipxe/infiniband.h @@ -205,12 +205,14 @@ struct ib_completion_queue_operations { * * @v ibdev Infiniband device * @v qp Queue pair + * @v dest Destination address vector, or NULL * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ void ( * complete_recv ) ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_address_vector *dest, struct ib_address_vector *source, struct io_buffer *iobuf, int rc ); }; @@ -511,6 +513,7 @@ extern void ib_complete_send ( struct ib_device *ibdev, struct io_buffer *iobuf, int rc ); extern void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_address_vector *dest, struct ib_address_vector *source, struct io_buffer *iobuf, int rc ); extern void ib_refill_recv ( struct ib_device *ibdev, diff --git a/src/net/infiniband.c b/src/net/infiniband.c index f50778d0..12d1d83c 100644 --- a/src/net/infiniband.c +++ b/src/net/infiniband.c @@ -304,7 +304,7 @@ void ib_destroy_qp ( struct ib_device *ibdev, struct ib_queue_pair *qp ) { } for ( i = 0 ; i < qp->recv.num_wqes ; i++ ) { if ( ( iobuf = qp->recv.iobufs[i] ) != NULL ) { - ib_complete_recv ( ibdev, qp, NULL, iobuf, + ib_complete_recv ( ibdev, qp, NULL, NULL, iobuf, -ECANCELED ); } } @@ -486,16 +486,19 @@ void ib_complete_send ( struct ib_device *ibdev, struct ib_queue_pair *qp, * * @v ibdev Infiniband device * @v qp Queue pair + * @v dest Destination address vector, or NULL * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ void ib_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_address_vector *dest, struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { if ( qp->recv.cq->op->complete_recv ) { - qp->recv.cq->op->complete_recv ( ibdev, qp, source, iobuf, rc ); + qp->recv.cq->op->complete_recv ( ibdev, qp, dest, source, + iobuf, rc ); } else { free_iob ( iobuf ); } diff --git a/src/net/infiniband/ib_cmrc.c b/src/net/infiniband/ib_cmrc.c index cb5ed47b..1cc0fcfe 100644 --- a/src/net/infiniband/ib_cmrc.c +++ b/src/net/infiniband/ib_cmrc.c @@ -220,12 +220,14 @@ static void ib_cmrc_complete_send ( struct ib_device *ibdev __unused, * * @v ibdev Infiniband device * @v qp Queue pair + * @v dest Destination address vector, or NULL * @v source Source address vector, or NULL * @v iobuf I/O buffer * @v rc Completion status code */ static void ib_cmrc_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, + struct ib_address_vector *dest __unused, struct ib_address_vector *source __unused, struct io_buffer *iobuf, int rc ) { struct ib_cmrc_connection *cmrc = ib_qp_get_ownerdata ( qp ); diff --git a/src/net/infiniband/ib_mi.c b/src/net/infiniband/ib_mi.c index 2ca91943..ef6d539f 100644 --- a/src/net/infiniband/ib_mi.c +++ b/src/net/infiniband/ib_mi.c @@ -112,12 +112,14 @@ static int ib_mi_handle ( struct ib_device *ibdev, * * @v ibdev Infiniband device * @v qp Queue pair - * @v source Address vector + * @v dest Destination address vector + * @v source Source address vector * @v iobuf I/O buffer * @v rc Completion status code */ static void ib_mi_complete_recv ( struct ib_device *ibdev, struct ib_queue_pair *qp, + struct ib_address_vector *dest __unused, struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct ib_mad_interface *mi = ib_qp_get_ownerdata ( qp ); diff --git a/src/net/infiniband/ib_packet.c b/src/net/infiniband/ib_packet.c index 36b533f5..6c850e39 100644 --- a/src/net/infiniband/ib_packet.c +++ b/src/net/infiniband/ib_packet.c @@ -122,11 +122,13 @@ int ib_push ( struct ib_device *ibdev, struct io_buffer *iobuf, * @v iobuf I/O buffer containing headers * @v qp Queue pair to fill in, or NULL * @v payload_len Payload length to fill in, or NULL + * @v dest Destination address vector to fill in * @v source Source address vector to fill in * @ret rc Return status code */ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair **qp, size_t *payload_len, + struct ib_address_vector *dest, struct ib_address_vector *source ) { struct ib_local_route_header *lrh; struct ib_global_route_header *grh; @@ -135,14 +137,13 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, size_t orig_iob_len = iob_len ( iobuf ); unsigned int lnh; size_t pad_len; - unsigned long qpn; - unsigned int lid; /* Clear return values */ if ( qp ) *qp = NULL; if ( payload_len ) *payload_len = 0; + memset ( dest, 0, sizeof ( *dest ) ); memset ( source, 0, sizeof ( *source ) ); /* Extract LRH */ @@ -153,10 +154,11 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } lrh = iobuf->data; iob_pull ( iobuf, sizeof ( *lrh ) ); + dest->lid = ntohs ( lrh->dlid ); + dest->sl = ( lrh->sl__lnh >> 4 ); source->lid = ntohs ( lrh->slid ); source->sl = ( lrh->sl__lnh >> 4 ); lnh = ( lrh->sl__lnh & 0x3 ); - lid = ntohs ( lrh->dlid ); /* Reject unsupported packets */ if ( ! ( ( lnh == IB_LNH_BTH ) || ( lnh == IB_LNH_GRH ) ) ) { @@ -174,6 +176,8 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } grh = iobuf->data; iob_pull ( iobuf, sizeof ( *grh ) ); + dest->gid_present = 1; + memcpy ( &dest->gid, &grh->dgid, sizeof ( dest->gid ) ); source->gid_present = 1; memcpy ( &source->gid, &grh->sgid, sizeof ( source->gid ) ); } else { @@ -193,7 +197,7 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, ibdev, bth->opcode ); return -ENOTSUP; } - qpn = ntohl ( bth->dest_qp ); + dest->qpn = ntohl ( bth->dest_qp ); /* Extract DETH */ if ( iob_len ( iobuf ) < sizeof ( *deth ) ) { @@ -216,7 +220,7 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, /* Determine destination QP, if applicable */ if ( qp ) { - if ( IB_LID_MULTICAST ( lid ) && grh ) { + if ( IB_LID_MULTICAST ( dest->lid ) && grh ) { if ( ! ( *qp = ib_find_qp_mgid ( ibdev, &grh->dgid ))){ DBGC ( ibdev, "IBDEV %p RX for unknown MGID " IB_GID_FMT "\n", @@ -224,9 +228,9 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, return -ENODEV; } } else { - if ( ! ( *qp = ib_find_qp_qpn ( ibdev, qpn ) ) ) { + if ( ! ( *qp = ib_find_qp_qpn ( ibdev, dest->qpn ) ) ) { DBGC ( ibdev, "IBDEV %p RX for nonexistent " - "QPN %lx\n", ibdev, qpn ); + "QPN %lx\n", ibdev, dest->qpn ); return -ENODEV; } } @@ -234,8 +238,8 @@ int ib_pull ( struct ib_device *ibdev, struct io_buffer *iobuf, } DBGC2 ( ibdev, "IBDEV %p RX %04x:%08lx <= %04x:%08lx (key %08x)\n", - ibdev, lid, ( IB_LID_MULTICAST( lid ) ? - ( qp ? (*qp)->ext_qpn : -1UL ) : qpn ), + ibdev, dest->lid, ( IB_LID_MULTICAST ( dest->lid ) ? + ( qp ? (*qp)->ext_qpn : -1UL ) : dest->qpn ), source->lid, source->qpn, ntohl ( deth->qkey ) ); DBGCP_HDA ( ibdev, 0, ( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ), From 03f0c23f8b1a60575f788dd1b9d4ea47debf2345 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 29 Aug 2012 23:34:14 +0100 Subject: [PATCH 144/250] [ipoib] Expose Ethernet-compatible eIPoIB link-layer addresses and headers Almost all clients of the raw-packet interfaces (UNDI and SNP) can handle only Ethernet link layers. Expose an Ethernet-compatible link layer to local clients, while remaining compatible with IPoIB on the wire. This requires manipulation of ARP (but not DHCP) packets within the IPoIB driver. This is ugly, but it's the only viable way to allow IPoIB devices to be driven via the raw-packet interfaces. Signed-off-by: Michael Brown --- src/arch/i386/interface/pxe/pxe_undi.c | 3 +- src/drivers/net/ipoib.c | 655 +++++++++++++++---------- src/include/ipxe/dhcp.h | 2 - src/include/ipxe/ipoib.h | 42 +- src/include/ipxe/netdevice.h | 9 + src/interface/efi/efi_snp.c | 3 +- src/net/udp/dhcp.c | 12 +- src/usr/dhcpmgmt.c | 12 +- 8 files changed, 435 insertions(+), 303 deletions(-) diff --git a/src/arch/i386/interface/pxe/pxe_undi.c b/src/arch/i386/interface/pxe/pxe_undi.c index f9282db1..5d212269 100644 --- a/src/arch/i386/interface/pxe/pxe_undi.c +++ b/src/arch/i386/interface/pxe/pxe_undi.c @@ -358,7 +358,8 @@ pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT *undi_transmit ) { } /* Allocate and fill I/O buffer */ - iobuf = alloc_iob ( MAX_LL_HEADER_LEN + len ); + iobuf = alloc_iob ( MAX_LL_HEADER_LEN + + ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) ); if ( ! iobuf ) { DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" ); undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES; diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 41ba348b..c1b8cad9 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -20,18 +20,23 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include #include #include #include #include #include #include +#include #include +#include +#include #include #include #include #include #include +#include #include /** @file @@ -58,6 +63,8 @@ struct ipoib_device { struct ib_completion_queue *cq; /** Queue pair */ struct ib_queue_pair *qp; + /** Local MAC */ + struct ipoib_mac mac; /** Broadcast MAC */ struct ipoib_mac broadcast; /** Joined to IPv4 broadcast multicast group @@ -68,6 +75,8 @@ struct ipoib_device { int broadcast_joined; /** IPv4 broadcast multicast group membership */ struct ib_mc_membership broadcast_membership; + /** REMAC cache */ + struct list_head peers; }; /** Broadcast IPoIB address */ @@ -89,99 +98,134 @@ struct errortab ipoib_errors[] __errortab = { /**************************************************************************** * - * IPoIB peer cache + * IPoIB REMAC cache * **************************************************************************** */ -/** - * IPoIB peer address - * - * The IPoIB link-layer header is only four bytes long and so does not - * have sufficient room to store IPoIB MAC address(es). We therefore - * maintain a cache of MAC addresses identified by a single-byte key, - * and abuse the spare two bytes within the link-layer header to - * communicate these MAC addresses between the link-layer code and the - * netdevice driver. - */ +/** An IPoIB REMAC cache entry */ struct ipoib_peer { - /** Key */ - uint8_t key; + /** List of REMAC cache entries */ + struct list_head list; + /** Remote Ethermet MAC */ + struct ipoib_remac remac; /** MAC address */ struct ipoib_mac mac; }; -/** Number of IPoIB peer cache entries - * - * Must be a power of two. - */ -#define IPOIB_NUM_CACHED_PEERS 4 - -/** IPoIB peer address cache */ -static struct ipoib_peer ipoib_peer_cache[IPOIB_NUM_CACHED_PEERS]; - -/** Oldest IPoIB peer cache entry index */ -static unsigned int ipoib_peer_cache_idx = 0; - -/** IPoIB peer cache entry validity flag */ -#define IPOIB_PEER_KEY_VALID 0x80 - /** - * Look up cached peer by key + * Find IPoIB MAC from REMAC * - * @v key Peer cache key - * @ret peer Peer cache entry, or NULL + * @v ipoib IPoIB device + * @v remac Remote Ethernet MAC + * @ret mac IPoIB MAC (or NULL if not found) */ -static struct ipoib_peer * ipoib_lookup_peer_by_key ( unsigned int key ) { +static struct ipoib_mac * ipoib_find_remac ( struct ipoib_device *ipoib, + const struct ipoib_remac *remac ) { struct ipoib_peer *peer; - unsigned int i; - if ( ! key ) - return NULL; + /* Check for broadcast REMAC */ + if ( is_broadcast_ether_addr ( remac ) ) + return &ipoib->broadcast; - for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) { - peer = &ipoib_peer_cache[i]; - if ( peer->key == key ) - return peer; + /* Try to find via REMAC cache */ + list_for_each_entry ( peer, &ipoib->peers, list ) { + if ( memcmp ( remac, &peer->remac, + sizeof ( peer->remac ) ) == 0 ) { + /* Move peer to start of list */ + list_del ( &peer->list ); + list_add ( &peer->list, &ipoib->peers ); + return &peer->mac; + } } - DBG ( "IPoIB warning: peer cache lost track of key %x while still in " - "use\n", key ); + DBGC ( ipoib, "IPoIB %p unknown REMAC %s\n", + ipoib, eth_ntoa ( remac ) ); return NULL; } /** - * Store GID and QPN in peer cache + * Add IPoIB MAC to REMAC cache * - * @v mac Peer MAC address - * @ret peer Peer cache entry + * @v ipoib IPoIB device + * @v remac Remote Ethernet MAC + * @v mac IPoIB MAC + * @ret rc Return status code */ -static struct ipoib_peer * ipoib_cache_peer ( const struct ipoib_mac *mac ) { +static int ipoib_map_remac ( struct ipoib_device *ipoib, + const struct ipoib_remac *remac, + const struct ipoib_mac *mac ) { struct ipoib_peer *peer; - uint8_t key; - unsigned int i; - /* Look for existing cache entry */ - for ( i = 0 ; i < IPOIB_NUM_CACHED_PEERS ; i++ ) { - peer = &ipoib_peer_cache[i]; - if ( memcmp ( &peer->mac, mac, sizeof ( peer->mac ) ) == 0 ) - return peer; + /* Check for existing entry in REMAC cache */ + list_for_each_entry ( peer, &ipoib->peers, list ) { + if ( memcmp ( remac, &peer->remac, + sizeof ( peer->remac ) ) == 0 ) { + /* Move peer to start of list */ + list_del ( &peer->list ); + list_add ( &peer->list, &ipoib->peers ); + /* Update MAC */ + memcpy ( &peer->mac, mac, sizeof ( peer->mac ) ); + return 0; + } } - /* No entry found: create a new one */ - key = ( ipoib_peer_cache_idx++ | IPOIB_PEER_KEY_VALID ); - peer = &ipoib_peer_cache[ key % IPOIB_NUM_CACHED_PEERS ]; - if ( peer->key ) - DBG ( "IPoIB peer %x evicted from cache\n", peer->key ); - - memset ( peer, 0, sizeof ( *peer ) ); - peer->key = key; + /* Create new entry */ + peer = malloc ( sizeof ( *peer ) ); + if ( ! peer ) + return -ENOMEM; + memcpy ( &peer->remac, remac, sizeof ( peer->remac ) ); memcpy ( &peer->mac, mac, sizeof ( peer->mac ) ); - DBG ( "IPoIB peer %x has MAC %s\n", - peer->key, ipoib_ntoa ( &peer->mac ) ); - return peer; + list_add ( &peer->list, &ipoib->peers ); + + return 0; } +/** + * Flush REMAC cache + * + * @v ipoib IPoIB device + */ +static void ipoib_flush_remac ( struct ipoib_device *ipoib ) { + struct ipoib_peer *peer; + struct ipoib_peer *tmp; + + list_for_each_entry_safe ( peer, tmp, &ipoib->peers, list ) { + list_del ( &peer->list ); + free ( peer ); + } +} + +/** + * Discard some entries from the REMAC cache + * + * @ret discarded Number of cached items discarded + */ +static unsigned int ipoib_discard_remac ( void ) { + struct ib_device *ibdev; + struct ipoib_device *ipoib; + struct ipoib_peer *peer; + unsigned int discarded = 0; + + /* Try to discard one cache entry for each IPoIB device */ + for_each_ibdev ( ibdev ) { + ipoib = ib_get_ownerdata ( ibdev ); + list_for_each_entry_reverse ( peer, &ipoib->peers, list ) { + list_del ( &peer->list ); + free ( peer ); + discarded++; + break; + } + } + + return discarded; +} + +/** IPoIB cache discarder */ +struct cache_discarder ipoib_discarder __cache_discarder ( CACHE_NORMAL ) = { + .discard = ipoib_discard_remac, +}; + /**************************************************************************** * * IPoIB link layer @@ -189,85 +233,6 @@ static struct ipoib_peer * ipoib_cache_peer ( const struct ipoib_mac *mac ) { **************************************************************************** */ -/** - * Add IPoIB link-layer header - * - * @v netdev Network device - * @v iobuf I/O buffer - * @v ll_dest Link-layer destination address - * @v ll_source Source link-layer address - * @v net_proto Network-layer protocol, in network-byte order - * @ret rc Return status code - */ -static int ipoib_push ( struct net_device *netdev __unused, - struct io_buffer *iobuf, const void *ll_dest, - const void *ll_source __unused, uint16_t net_proto ) { - struct ipoib_hdr *ipoib_hdr = - iob_push ( iobuf, sizeof ( *ipoib_hdr ) ); - const struct ipoib_mac *dest_mac = ll_dest; - const struct ipoib_mac *src_mac = ll_source; - struct ipoib_peer *dest; - struct ipoib_peer *src; - - /* Add link-layer addresses to cache */ - dest = ipoib_cache_peer ( dest_mac ); - src = ipoib_cache_peer ( src_mac ); - - /* Build IPoIB header */ - ipoib_hdr->proto = net_proto; - ipoib_hdr->u.peer.dest = dest->key; - ipoib_hdr->u.peer.src = src->key; - - return 0; -} - -/** - * Remove IPoIB link-layer header - * - * @v netdev Network device - * @v iobuf I/O buffer - * @ret ll_dest Link-layer destination address - * @ret ll_source Source link-layer address - * @ret net_proto Network-layer protocol, in network-byte order - * @ret flags Packet flags - * @ret rc Return status code - */ -static int ipoib_pull ( struct net_device *netdev, - struct io_buffer *iobuf, const void **ll_dest, - const void **ll_source, uint16_t *net_proto, - unsigned int *flags ) { - struct ipoib_device *ipoib = netdev->priv; - struct ipoib_hdr *ipoib_hdr = iobuf->data; - struct ipoib_peer *dest; - struct ipoib_peer *source; - - /* Sanity check */ - if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) { - DBG ( "IPoIB packet too short for link-layer header\n" ); - DBG_HD ( iobuf->data, iob_len ( iobuf ) ); - return -EINVAL; - } - - /* Strip off IPoIB header */ - iob_pull ( iobuf, sizeof ( *ipoib_hdr ) ); - - /* Identify source and destination addresses, and clear - * reserved word in IPoIB header - */ - dest = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest ); - source = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.src ); - ipoib_hdr->u.reserved = 0; - - /* Fill in required fields */ - *ll_dest = ( dest ? &dest->mac : &ipoib->broadcast ); - *ll_source = ( source ? &source->mac : &ipoib->broadcast ); - *net_proto = ipoib_hdr->proto; - *flags = ( ( *ll_dest == &ipoib->broadcast ) ? - ( LL_MULTICAST | LL_BROADCAST ) : 0 ); - - return 0; -} - /** * Initialise IPoIB link-layer address * @@ -275,115 +240,32 @@ static int ipoib_pull ( struct net_device *netdev, * @v ll_addr Link-layer address */ static void ipoib_init_addr ( const void *hw_addr, void *ll_addr ) { - const union ib_guid *guid = hw_addr; - struct ipoib_mac *mac = ll_addr; - - memset ( mac, 0, sizeof ( *mac ) ); - memcpy ( &mac->gid.s.guid, guid, sizeof ( mac->gid.s.guid ) ); -} - -/** - * Transcribe IPoIB link-layer address - * - * @v ll_addr Link-layer address - * @ret string Link-layer address in human-readable format - */ -const char * ipoib_ntoa ( const void *ll_addr ) { - static char buf[45]; - const struct ipoib_mac *mac = ll_addr; - - snprintf ( buf, sizeof ( buf ), "%08x:%08x:%08x:%08x:%08x", - htonl ( mac->flags__qpn ), htonl ( mac->gid.dwords[0] ), - htonl ( mac->gid.dwords[1] ), - htonl ( mac->gid.dwords[2] ), - htonl ( mac->gid.dwords[3] ) ); - return buf; -} - -/** - * Hash multicast address - * - * @v af Address family - * @v net_addr Network-layer address - * @v ll_addr Link-layer address to fill in - * @ret rc Return status code - */ -static int ipoib_mc_hash ( unsigned int af __unused, - const void *net_addr __unused, - void *ll_addr __unused ) { - - return -ENOTSUP; -} - -/** - * Generate Mellanox Ethernet-compatible compressed link-layer address - * - * @v ll_addr Link-layer address - * @v eth_addr Ethernet-compatible address to fill in - */ -static int ipoib_mlx_eth_addr ( const union ib_guid *guid, - uint8_t *eth_addr ) { - eth_addr[0] = ( ( guid->bytes[3] == 2 ) ? 0x00 : 0x02 ); - eth_addr[1] = guid->bytes[1]; - eth_addr[2] = guid->bytes[2]; - eth_addr[3] = guid->bytes[5]; - eth_addr[4] = guid->bytes[6]; - eth_addr[5] = guid->bytes[7]; - return 0; -} - -/** An IPoIB Ethernet-compatible compressed link-layer address generator */ -struct ipoib_eth_addr_handler { - /** GUID byte 1 */ - uint8_t byte1; - /** GUID byte 2 */ - uint8_t byte2; - /** Handler */ - int ( * eth_addr ) ( const union ib_guid *guid, - uint8_t *eth_addr ); -}; - -/** IPoIB Ethernet-compatible compressed link-layer address generators */ -static struct ipoib_eth_addr_handler ipoib_eth_addr_handlers[] = { - { 0x02, 0xc9, ipoib_mlx_eth_addr }, -}; - -/** - * Generate Ethernet-compatible compressed link-layer address - * - * @v ll_addr Link-layer address - * @v eth_addr Ethernet-compatible address to fill in - */ -static int ipoib_eth_addr ( const void *ll_addr, void *eth_addr ) { - const struct ipoib_mac *ipoib_addr = ll_addr; - const union ib_guid *guid = &ipoib_addr->gid.s.guid; - struct ipoib_eth_addr_handler *handler; + const uint8_t *guid = hw_addr; + uint8_t *eth_addr = ll_addr; + uint8_t guid_mask = IPOIB_GUID_MASK; unsigned int i; - for ( i = 0 ; i < ( sizeof ( ipoib_eth_addr_handlers ) / - sizeof ( ipoib_eth_addr_handlers[0] ) ) ; i++ ) { - handler = &ipoib_eth_addr_handlers[i]; - if ( ( handler->byte1 == guid->bytes[1] ) && - ( handler->byte2 == guid->bytes[2] ) ) { - return handler->eth_addr ( guid, eth_addr ); - } + /* Extract bytes from GUID according to mask */ + for ( i = 0 ; i < 8 ; i++, guid++, guid_mask <<= 1 ) { + if ( guid_mask & 0x80 ) + *(eth_addr++) = *guid; } - return -ENOTSUP; } /** IPoIB protocol */ struct ll_protocol ipoib_protocol __ll_protocol = { .name = "IPoIB", - .ll_proto = htons ( ARPHRD_INFINIBAND ), + .ll_proto = htons ( ARPHRD_ETHER ), .hw_addr_len = sizeof ( union ib_guid ), - .ll_addr_len = IPOIB_ALEN, - .ll_header_len = IPOIB_HLEN, - .push = ipoib_push, - .pull = ipoib_pull, + .ll_addr_len = ETH_ALEN, + .ll_header_len = ETH_HLEN, + .push = eth_push, + .pull = eth_pull, .init_addr = ipoib_init_addr, - .ntoa = ipoib_ntoa, - .mc_hash = ipoib_mc_hash, - .eth_addr = ipoib_eth_addr, + .ntoa = eth_ntoa, + .mc_hash = eth_mc_hash, + .eth_addr = eth_eth_addr, + .flags = LL_NAME_ONLY, }; /** @@ -398,12 +280,167 @@ struct net_device * alloc_ipoibdev ( size_t priv_size ) { netdev = alloc_netdev ( priv_size ); if ( netdev ) { netdev->ll_protocol = &ipoib_protocol; - netdev->ll_broadcast = ( uint8_t * ) &ipoib_broadcast; + netdev->ll_broadcast = eth_broadcast; netdev->max_pkt_len = IB_MAX_PAYLOAD_SIZE; } return netdev; } +/**************************************************************************** + * + * IPoIB translation layer + * + **************************************************************************** + */ + +/** + * Translate transmitted ARP packet + * + * @v netdev Network device + * @v iobuf Packet to be transmitted (with no link-layer headers) + * @ret rc Return status code + */ +static int ipoib_translate_tx_arp ( struct net_device *netdev, + struct io_buffer *iobuf ) { + struct ipoib_device *ipoib = netdev->priv; + struct arphdr *arphdr = iobuf->data; + struct ipoib_mac *target_ha = NULL; + void *sender_pa; + void *target_pa; + + /* Do nothing unless ARP contains eIPoIB link-layer addresses */ + if ( arphdr->ar_hln != ETH_ALEN ) + return 0; + + /* Fail unless we have room to expand packet */ + if ( iob_tailroom ( iobuf ) < ( 2 * ( sizeof ( ipoib->mac ) - + ETH_ALEN ) ) ) { + DBGC ( ipoib, "IPoIB %p insufficient space in TX ARP\n", + ipoib ); + return -ENOBUFS; + } + + /* Look up REMAC, if applicable */ + if ( arphdr->ar_op == ARPOP_REPLY ) { + target_ha = ipoib_find_remac ( ipoib, arp_target_pa ( arphdr )); + if ( ! target_ha ) + return -ENXIO; + } + + /* Construct new packet */ + iob_put ( iobuf, ( 2 * ( sizeof ( ipoib->mac ) - ETH_ALEN ) ) ); + sender_pa = arp_sender_pa ( arphdr ); + target_pa = arp_target_pa ( arphdr ); + arphdr->ar_hrd = htons ( ARPHRD_INFINIBAND ); + arphdr->ar_hln = sizeof ( ipoib->mac ); + memcpy ( arp_target_pa ( arphdr ), target_pa, arphdr->ar_pln ); + memcpy ( arp_sender_pa ( arphdr ), sender_pa, arphdr->ar_pln ); + memcpy ( arp_sender_ha ( arphdr ), &ipoib->mac, sizeof ( ipoib->mac ) ); + memset ( arp_target_ha ( arphdr ), 0, sizeof ( ipoib->mac ) ); + if ( target_ha ) { + memcpy ( arp_target_ha ( arphdr ), target_ha, + sizeof ( *target_ha ) ); + } + + return 0; +} + +/** + * Translate transmitted packet + * + * @v netdev Network device + * @v iobuf Packet to be transmitted (with no link-layer headers) + * @v net_proto Network-layer protocol (in network byte order) + * @ret rc Return status code + */ +static int ipoib_translate_tx ( struct net_device *netdev, + struct io_buffer *iobuf, uint16_t net_proto ) { + + switch ( net_proto ) { + case htons ( ETH_P_ARP ) : + return ipoib_translate_tx_arp ( netdev, iobuf ); + case htons ( ETH_P_IP ) : + /* No translation needed */ + return 0; + default: + /* Cannot handle other traffic via eIPoIB */ + return -ENOTSUP; + } +} + +/** + * Translate received ARP packet + * + * @v netdev Network device + * @v iobuf Received packet (with no link-layer headers) + * @v remac Constructed Remote Ethernet MAC + * @ret rc Return status code + */ +static int ipoib_translate_rx_arp ( struct net_device *netdev, + struct io_buffer *iobuf, + struct ipoib_remac *remac ) { + struct ipoib_device *ipoib = netdev->priv; + struct arphdr *arphdr = iobuf->data; + void *sender_pa; + void *target_pa; + int rc; + + /* Do nothing unless ARP contains IPoIB link-layer addresses */ + if ( arphdr->ar_hln != sizeof ( ipoib->mac ) ) + return 0; + + /* Create REMAC cache entry */ + if ( ( rc = ipoib_map_remac ( ipoib, remac, + arp_sender_ha ( arphdr ) ) ) != 0 ) { + DBGC ( ipoib, "IPoIB %p could not map REMAC: %s\n", + ipoib, strerror ( rc ) ); + return rc; + } + + /* Construct new packet */ + sender_pa = arp_sender_pa ( arphdr ); + target_pa = arp_target_pa ( arphdr ); + arphdr->ar_hrd = htons ( ARPHRD_ETHER ); + arphdr->ar_hln = ETH_ALEN; + memcpy ( arp_sender_pa ( arphdr ), sender_pa, arphdr->ar_pln ); + memcpy ( arp_target_pa ( arphdr ), target_pa, arphdr->ar_pln ); + memcpy ( arp_sender_ha ( arphdr ), remac, ETH_ALEN ); + memset ( arp_target_ha ( arphdr ), 0, ETH_ALEN ); + if ( arphdr->ar_op == ARPOP_REPLY ) { + /* Assume received replies were directed to us */ + memcpy ( arp_target_ha ( arphdr ), netdev->ll_addr, ETH_ALEN ); + } + iob_unput ( iobuf, ( 2 * ( sizeof ( ipoib->mac ) - ETH_ALEN ) ) ); + + return 0; +} + +/** + * Translate received packet + * + * @v netdev Network device + * @v iobuf Received packet (with no link-layer headers) + * @v remac Constructed Remote Ethernet MAC + * @v net_proto Network-layer protocol (in network byte order) + * @ret rc Return status code + */ +static int ipoib_translate_rx ( struct net_device *netdev, + struct io_buffer *iobuf, + struct ipoib_remac *remac, + uint16_t net_proto ) { + + switch ( net_proto ) { + case htons ( ETH_P_ARP ) : + return ipoib_translate_rx_arp ( netdev, iobuf, remac ); + case htons ( ETH_P_IP ) : + /* No translation needed */ + return 0; + default: + /* Cannot handle other traffic via eIPoIB */ + return -ENOTSUP; + } +} + /**************************************************************************** * * IPoIB network device @@ -422,17 +459,18 @@ static int ipoib_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) { struct ipoib_device *ipoib = netdev->priv; struct ib_device *ibdev = ipoib->ibdev; + struct ethhdr *ethhdr; struct ipoib_hdr *ipoib_hdr; - struct ipoib_peer *peer; + struct ipoib_mac *mac; struct ib_address_vector dest; + uint16_t net_proto; int rc; /* Sanity check */ - if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) { + if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) { DBGC ( ipoib, "IPoIB %p buffer too short\n", ipoib ); return -EINVAL; } - ipoib_hdr = iobuf->data; /* Attempting transmission while link is down will put the * queue pair into an error state, so don't try it. @@ -440,17 +478,30 @@ static int ipoib_transmit ( struct net_device *netdev, if ( ! ib_link_ok ( ibdev ) ) return -ENETUNREACH; + /* Strip eIPoIB header */ + ethhdr = iobuf->data; + net_proto = ethhdr->h_protocol; + iob_pull ( iobuf, sizeof ( *ethhdr ) ); + /* Identify destination address */ - peer = ipoib_lookup_peer_by_key ( ipoib_hdr->u.peer.dest ); - if ( ! peer ) + mac = ipoib_find_remac ( ipoib, ( ( void *) ethhdr->h_dest ) ); + if ( ! mac ) return -ENXIO; - ipoib_hdr->u.reserved = 0; + + /* Translate packet if applicable */ + if ( ( rc = ipoib_translate_tx ( netdev, iobuf, net_proto ) ) != 0 ) + return rc; + + /* Prepend real IPoIB header */ + ipoib_hdr = iob_push ( iobuf, sizeof ( *ipoib_hdr ) ); + ipoib_hdr->proto = net_proto; + ipoib_hdr->reserved = 0; /* Construct address vector */ memset ( &dest, 0, sizeof ( dest ) ); - dest.qpn = ( ntohl ( peer->mac.flags__qpn ) & IB_QPN_MASK ); + dest.qpn = ( ntohl ( mac->flags__qpn ) & IB_QPN_MASK ); dest.gid_present = 1; - memcpy ( &dest.gid, &peer->mac.gid, sizeof ( dest.gid ) ); + memcpy ( &dest.gid, &mac->gid, sizeof ( dest.gid ) ); if ( ( rc = ib_resolve_path ( ibdev, &dest ) ) != 0 ) { /* Path not resolved yet */ return rc; @@ -487,14 +538,15 @@ static void ipoib_complete_send ( struct ib_device *ibdev __unused, */ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, struct ib_queue_pair *qp, - struct ib_address_vector *dest __unused, + struct ib_address_vector *dest, struct ib_address_vector *source, struct io_buffer *iobuf, int rc ) { struct ipoib_device *ipoib = ib_qp_get_ownerdata ( qp ); struct net_device *netdev = ipoib->netdev; struct ipoib_hdr *ipoib_hdr; - struct ipoib_mac ll_src; - struct ipoib_peer *src; + struct ethhdr *ethhdr; + struct ipoib_remac remac; + uint16_t net_proto; /* Record errors */ if ( rc != 0 ) { @@ -510,7 +562,6 @@ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, netdev_rx_err ( netdev, iobuf, -EIO ); return; } - ipoib_hdr = iobuf->data; if ( ! source ) { DBGC ( ipoib, "IPoIB %p received packet without address " "vector\n", ipoib ); @@ -518,12 +569,37 @@ static void ipoib_complete_recv ( struct ib_device *ibdev __unused, return; } - /* Parse source address */ - if ( source->gid_present ) { - ll_src.flags__qpn = htonl ( source->qpn ); - memcpy ( &ll_src.gid, &source->gid, sizeof ( ll_src.gid ) ); - src = ipoib_cache_peer ( &ll_src ); - ipoib_hdr->u.peer.src = src->key; + /* Strip real IPoIB header */ + ipoib_hdr = iobuf->data; + net_proto = ipoib_hdr->proto; + iob_pull ( iobuf, sizeof ( *ipoib_hdr ) ); + + /* Construct source address from remote QPN and LID */ + remac.qpn = htonl ( source->qpn | EIPOIB_QPN_LA ); + remac.lid = htons ( source->lid ); + + /* Translate packet if applicable */ + if ( ( rc = ipoib_translate_rx ( netdev, iobuf, &remac, + net_proto ) ) != 0 ) { + netdev_rx_err ( netdev, iobuf, rc ); + return; + } + + /* Prepend eIPoIB header */ + ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) ); + memcpy ( ðhdr->h_source, &remac, sizeof ( ethhdr->h_source ) ); + ethhdr->h_protocol = net_proto; + + /* Construct destination address */ + if ( dest->gid_present && ( memcmp ( &dest->gid, &ipoib->broadcast.gid, + sizeof ( dest->gid ) ) == 0 ) ) { + /* Broadcast GID; use the Ethernet broadcast address */ + memcpy ( ðhdr->h_dest, eth_broadcast, + sizeof ( ethhdr->h_dest ) ); + } else { + /* Assume destination address is local Ethernet MAC */ + memcpy ( ðhdr->h_dest, netdev->ll_addr, + sizeof ( ethhdr->h_dest ) ); } /* Hand off to network layer */ @@ -536,9 +612,40 @@ static struct ib_completion_queue_operations ipoib_cq_op = { .complete_recv = ipoib_complete_recv, }; +/** + * Allocate IPoIB receive I/O buffer + * + * @v len Length of buffer + * @ret iobuf I/O buffer, or NULL + * + * Some Infiniband hardware requires 2kB alignment of receive buffers + * and provides no way to disable header separation. The result is + * that there are only four bytes of link-layer header (the real IPoIB + * header) before the payload. This is not sufficient space to insert + * an eIPoIB link-layer pseudo-header. + * + * We therefore allocate I/O buffers offset to start slightly before + * the natural alignment boundary, in order to allow sufficient space. + */ +static struct io_buffer * ipoib_alloc_iob ( size_t len ) { + struct io_buffer *iobuf; + size_t reserve_len; + + /* Calculate additional length required at start of buffer */ + reserve_len = ( sizeof ( struct ethhdr ) - + sizeof ( struct ipoib_hdr ) ); + + /* Allocate buffer */ + iobuf = alloc_iob_raw ( ( len + reserve_len ), len, -reserve_len ); + if ( iobuf ) { + iob_reserve ( iobuf, reserve_len ); + } + return iobuf; +} + /** IPoIB queue pair operations */ static struct ib_queue_pair_operations ipoib_qp_op = { - .alloc_iob = alloc_iob, + .alloc_iob = ipoib_alloc_iob, }; /** @@ -550,7 +657,11 @@ static void ipoib_poll ( struct net_device *netdev ) { struct ipoib_device *ipoib = netdev->priv; struct ib_device *ibdev = ipoib->ibdev; + /* Poll Infiniband device */ ib_poll_eq ( ibdev ); + + /* Poll the retry timers (required for IPoIB multicast join) */ + retry_poll(); } /** @@ -617,15 +728,14 @@ static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) { static void ipoib_link_state_changed ( struct ib_device *ibdev ) { struct net_device *netdev = ib_get_ownerdata ( ibdev ); struct ipoib_device *ipoib = netdev->priv; - struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr ); int rc; /* Leave existing broadcast group */ ipoib_leave_broadcast_group ( ipoib ); /* Update MAC address based on potentially-new GID prefix */ - memcpy ( &mac->gid.s.prefix, &ibdev->gid.s.prefix, - sizeof ( mac->gid.s.prefix ) ); + memcpy ( &ipoib->mac.gid.s.prefix, &ibdev->gid.s.prefix, + sizeof ( ipoib->mac.gid.s.prefix ) ); /* Update broadcast GID based on potentially-new partition key */ ipoib->broadcast.gid.words[2] = @@ -654,7 +764,6 @@ static void ipoib_link_state_changed ( struct ib_device *ibdev ) { static int ipoib_open ( struct net_device *netdev ) { struct ipoib_device *ipoib = netdev->priv; struct ib_device *ibdev = ipoib->ibdev; - struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr ); int rc; /* Open IB device */ @@ -686,7 +795,7 @@ static int ipoib_open ( struct net_device *netdev ) { ib_qp_set_ownerdata ( ipoib->qp, ipoib ); /* Update MAC address with QPN */ - mac->flags__qpn = htonl ( ipoib->qp->qpn ); + ipoib->mac.flags__qpn = htonl ( ipoib->qp->qpn ); /* Fill receive rings */ ib_refill_recv ( ibdev, ipoib->qp ); @@ -713,13 +822,15 @@ static int ipoib_open ( struct net_device *netdev ) { static void ipoib_close ( struct net_device *netdev ) { struct ipoib_device *ipoib = netdev->priv; struct ib_device *ibdev = ipoib->ibdev; - struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr ); + + /* Flush REMAC cache */ + ipoib_flush_remac ( ipoib ); /* Leave broadcast group */ ipoib_leave_broadcast_group ( ipoib ); /* Remove QPN from MAC address */ - mac->flags__qpn = 0; + ipoib->mac.flags__qpn = 0; /* Tear down the queues */ ib_destroy_qp ( ibdev, ipoib->qp ); @@ -759,15 +870,19 @@ static int ipoib_probe ( struct ib_device *ibdev ) { memset ( ipoib, 0, sizeof ( *ipoib ) ); ipoib->netdev = netdev; ipoib->ibdev = ibdev; + INIT_LIST_HEAD ( &ipoib->peers ); /* Extract hardware address */ memcpy ( netdev->hw_addr, &ibdev->gid.s.guid, sizeof ( ibdev->gid.s.guid ) ); - /* Set default broadcast address */ + /* Set local MAC address */ + memcpy ( &ipoib->mac.gid.s.guid, &ibdev->gid.s.guid, + sizeof ( ipoib->mac.gid.s.guid ) ); + + /* Set default broadcast MAC address */ memcpy ( &ipoib->broadcast, &ipoib_broadcast, sizeof ( ipoib->broadcast ) ); - netdev->ll_broadcast = ( ( uint8_t * ) &ipoib->broadcast ); /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) diff --git a/src/include/ipxe/dhcp.h b/src/include/ipxe/dhcp.h index 34b4d3fd..b97dfe32 100644 --- a/src/include/ipxe/dhcp.h +++ b/src/include/ipxe/dhcp.h @@ -651,8 +651,6 @@ struct dhcphdr { #define PXEBS_SETTINGS_NAME "pxebs" extern uint32_t dhcp_last_xid; -extern unsigned int dhcp_chaddr ( struct net_device *netdev, void *chaddr, - uint16_t *flags ); extern int dhcp_create_packet ( struct dhcp_packet *dhcppkt, struct net_device *netdev, uint8_t msgtype, uint32_t xid, const void *options, diff --git a/src/include/ipxe/ipoib.h b/src/include/ipxe/ipoib.h index e8f12dc5..68ff8df4 100644 --- a/src/include/ipxe/ipoib.h +++ b/src/include/ipxe/ipoib.h @@ -8,6 +8,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include #include /** IPoIB MAC address length */ @@ -33,25 +34,32 @@ struct ipoib_hdr { /** Network-layer protocol */ uint16_t proto; /** Reserved, must be zero */ - union { - /** Reserved, must be zero */ - uint16_t reserved; - /** Peer addresses - * - * We use these fields internally to represent the - * peer addresses using a lookup key. There simply - * isn't enough room in the IPoIB header to store - * literal source or destination MAC addresses. - */ - struct { - /** Destination address key */ - uint8_t dest; - /** Source address key */ - uint8_t src; - } __attribute__ (( packed )) peer; - } __attribute__ (( packed )) u; + uint16_t reserved; } __attribute__ (( packed )); +/** GUID mask used for constructing eIPoIB Local Ethernet MAC address (LEMAC) */ +#define IPOIB_GUID_MASK 0xe7 + +/** eIPoIB Remote Ethernet MAC address + * + * An eIPoIB REMAC address is an Ethernet-like (6 byte) link-layer + * pseudo-address used to look up a full IPoIB link-layer address. + */ +struct ipoib_remac { + /** Remote QPN + * + * Must be ORed with EIPOIB_QPN_LA so that eIPoIB REMAC + * addresses are considered as locally-assigned Ethernet MAC + * addreses. + */ + uint32_t qpn; + /** Remote LID */ + uint16_t lid; +} __attribute__ (( packed )); + +/** eIPoIB REMAC locally-assigned address indicator */ +#define EIPOIB_QPN_LA 0x02000000UL + extern const char * ipoib_ntoa ( const void *ll_addr ); extern struct net_device * alloc_ipoibdev ( size_t priv_size ); diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index 3633a165..e5dbd996 100644 --- a/src/include/ipxe/netdevice.h +++ b/src/include/ipxe/netdevice.h @@ -188,8 +188,17 @@ struct ll_protocol { uint8_t ll_addr_len; /** Link-layer header length */ uint8_t ll_header_len; + /** Flags */ + unsigned int flags; }; +/** Local link-layer address functions only as a name + * + * This flag indicates that the local link-layer address cannot + * directly be used as a destination address by a remote node. + */ +#define LL_NAME_ONLY 0x0001 + /** Network device operations */ struct net_device_operations { /** Open network device diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 88072aa6..6d7865dd 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -590,7 +590,8 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, /* Allocate buffer */ ll_headroom = ( MAX_LL_HEADER_LEN - ll_header_len ); - iobuf = alloc_iob ( ll_headroom + len ); + iobuf = alloc_iob ( ll_headroom + + ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) ); if ( ! iobuf ) { DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte " "buffer\n", snpdev, ( ( unsigned long ) len ) ); diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index a7206164..e652503d 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -938,10 +938,18 @@ int dhcp_create_packet ( struct dhcp_packet *dhcppkt, dhcphdr->magic = htonl ( DHCP_MAGIC_COOKIE ); dhcphdr->htype = ntohs ( netdev->ll_protocol->ll_proto ); dhcphdr->op = dhcp_op[msgtype]; - dhcphdr->hlen = dhcp_chaddr ( netdev, dhcphdr->chaddr, - &dhcphdr->flags ); + dhcphdr->hlen = netdev->ll_protocol->ll_addr_len; + memcpy ( dhcphdr->chaddr, netdev->ll_addr, + netdev->ll_protocol->ll_addr_len ); memcpy ( dhcphdr->options, options, options_len ); + /* If the local link-layer address functions only as a name + * (i.e. cannot be used as a destination address), then + * request broadcast responses. + */ + if ( netdev->ll_protocol->flags & LL_NAME_ONLY ) + dhcphdr->flags |= htons ( BOOTP_FL_BROADCAST ); + /* If the network device already has an IPv4 address then * unicast responses from the DHCP server may be rejected, so * request broadcast responses. diff --git a/src/usr/dhcpmgmt.c b/src/usr/dhcpmgmt.c index 1bd9bff0..b61c01aa 100644 --- a/src/usr/dhcpmgmt.c +++ b/src/usr/dhcpmgmt.c @@ -38,10 +38,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ int dhcp ( struct net_device *netdev ) { - struct dhcphdr *dhcphdr; - typeof ( dhcphdr->chaddr ) chaddr; - unsigned int hlen; - unsigned int i; int rc; /* Check we can open the interface first */ @@ -53,12 +49,8 @@ int dhcp ( struct net_device *netdev ) { return rc; /* Perform DHCP */ - printf ( "DHCP (%s", netdev->name ); - hlen = dhcp_chaddr ( netdev, chaddr, NULL ); - for ( i = 0 ; i < hlen ; i++ ) - printf ( "%c%02x", ( i ? ':' : ' ' ), chaddr[i] ); - printf ( ")" ); - + printf ( "DHCP (%s %s)", netdev->name, + netdev->ll_protocol->ntoa ( netdev->ll_addr ) ); if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) { rc = monojob_wait ( "" ); } else if ( rc > 0 ) { From e6427b7ee117ea4af0812bb13b57999bccd8e058 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 4 Sep 2012 01:26:48 +0100 Subject: [PATCH 145/250] [sdi] Add support for SDI images Add support (disabled by default) for booting .sdi images as used by Windows XP Embedded. Signed-off-by: Michael Brown --- src/arch/i386/image/sdi.c | 136 ++++++++++++++++++++++++++++ src/arch/i386/include/sdi.h | 39 ++++++++ src/arch/x86/include/bits/errfile.h | 1 + src/config/config.c | 3 + src/config/general.h | 1 + src/include/ipxe/features.h | 1 + 6 files changed, 181 insertions(+) create mode 100644 src/arch/i386/image/sdi.c create mode 100644 src/arch/i386/include/sdi.h diff --git a/src/arch/i386/image/sdi.c b/src/arch/i386/image/sdi.c new file mode 100644 index 00000000..df1c3a86 --- /dev/null +++ b/src/arch/i386/image/sdi.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * System Deployment Image (SDI) + * + * Based on the MSDN article "RAM boot using SDI in Windows XP + * Embedded with Service Pack 1", available at the time of writing + * from: + * + * http://msdn.microsoft.com/en-us/library/ms838543.aspx + */ + +FEATURE ( FEATURE_IMAGE, "SDI", DHCP_EB_FEATURE_SDI, 1 ); + +/** + * Parse SDI image header + * + * @v image SDI file + * @v sdi SDI header to fill in + * @ret rc Return status code + */ +static int sdi_parse_header ( struct image *image, struct sdi_header *sdi ) { + + /* Sanity check */ + if ( image->len < sizeof ( *sdi ) ) { + DBGC ( image, "SDI %p too short for SDI header\n", image ); + return -ENOEXEC; + } + + /* Read in header */ + copy_from_user ( sdi, image->data, 0, sizeof ( *sdi ) ); + + /* Check signature */ + if ( sdi->magic != SDI_MAGIC ) { + DBGC ( image, "SDI %p is not an SDI image\n", image ); + return -ENOEXEC; + } + + return 0; +} + +/** + * Execute SDI image + * + * @v image SDI file + * @ret rc Return status code + */ +static int sdi_exec ( struct image *image ) { + struct sdi_header sdi; + uint32_t sdiptr; + int rc; + + /* Parse image header */ + if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 ) + return rc; + + /* Check that image is bootable */ + if ( sdi.boot_size == 0 ) { + DBGC ( image, "SDI %p is not bootable\n", image ); + return -ENOTTY; + } + DBGC ( image, "SDI %p image at %08lx+%08zx\n", + image, user_to_phys ( image->data, 0 ), image->len ); + DBGC ( image, "SDI %p boot code at %08lx+%llx\n", image, + user_to_phys ( image->data, sdi.boot_offset ), sdi.boot_size ); + + /* Copy boot code */ + memcpy_user ( real_to_user ( SDI_BOOT_SEG, SDI_BOOT_OFF ), 0, + image->data, sdi.boot_offset, sdi.boot_size ); + + /* Jump to boot code */ + sdiptr = ( user_to_phys ( image->data, 0 ) | SDI_WTF ); + __asm__ __volatile__ ( REAL_CODE ( "ljmp %0, %1\n\t" ) + : : "i" ( SDI_BOOT_SEG ), + "i" ( SDI_BOOT_OFF ), + "d" ( sdiptr ) ); + + /* There is no way for the image to return, since we provide + * no return address. + */ + assert ( 0 ); + + return -ECANCELED; /* -EIMPOSSIBLE */ +} + +/** + * Probe SDI image + * + * @v image SDI file + * @ret rc Return status code + */ +static int sdi_probe ( struct image *image ) { + struct sdi_header sdi; + int rc; + + /* Parse image */ + if ( ( rc = sdi_parse_header ( image, &sdi ) ) != 0 ) + return rc; + + return 0; +} + +/** SDI image type */ +struct image_type sdi_image_type __image_type ( PROBE_NORMAL ) = { + .name = "SDI", + .probe = sdi_probe, + .exec = sdi_exec, +}; diff --git a/src/arch/i386/include/sdi.h b/src/arch/i386/include/sdi.h new file mode 100644 index 00000000..fc486402 --- /dev/null +++ b/src/arch/i386/include/sdi.h @@ -0,0 +1,39 @@ +#ifndef _SDI_H +#define _SDI_H + +/** @file + * + * System Deployment Image (SDI) + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** SDI image header */ +struct sdi_header { + /** Signature */ + uint32_t magic; + /** Version (as an ASCII string) */ + uint32_t version; + /** Reserved */ + uint8_t reserved[8]; + /** Boot code offset */ + uint64_t boot_offset; + /** Boot code size */ + uint64_t boot_size; +} __attribute__ (( packed )); + +/** SDI image signature */ +#define SDI_MAGIC \ + ( ( '$' << 0 ) | ( 'S' << 8 ) | ( 'D' << 16 ) | ( 'I' << 24 ) ) + +/** SDI boot segment */ +#define SDI_BOOT_SEG 0x0000 + +/** SDI boot offset */ +#define SDI_BOOT_OFF 0x7c00 + +/** Constant to binary-OR with physical address of SDI image */ +#define SDI_WTF 0x41 + +#endif /* _SDI_H */ diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index f66cbaa1..25e070e8 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_com32 ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00080000 ) #define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 ) #define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 ) +#define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 ) #define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 ) #define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 ) diff --git a/src/config/config.c b/src/config/config.c index 202da726..78ae93c4 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -181,6 +181,9 @@ REQUIRE_OBJECT ( comboot_resolv ); #ifdef IMAGE_EFI REQUIRE_OBJECT ( efi_image ); #endif +#ifdef IMAGE_SDI +REQUIRE_OBJECT ( sdi ); +#endif /* * Drag in all requested commands diff --git a/src/config/general.h b/src/config/general.h index 6fc39831..638320a4 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -100,6 +100,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); //#define IMAGE_BZIMAGE /* Linux bzImage image support */ //#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */ //#define IMAGE_EFI /* EFI image support */ +//#define IMAGE_SDI /* SDI image support */ /* * Command-line commands to include diff --git a/src/include/ipxe/features.h b/src/include/ipxe/features.h index 498ec944..0c92f5be 100644 --- a/src/include/ipxe/features.h +++ b/src/include/ipxe/features.h @@ -53,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define DHCP_EB_FEATURE_FCOE 0x25 /**< FCoE protocol */ #define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */ #define DHCP_EB_FEATURE_MENU 0x27 /**< Menu support */ +#define DHCP_EB_FEATURE_SDI 0x28 /**< SDI image support */ /** @} */ From 25ec56e0ecaa516a790fc409798e031af4bba650 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 31 Aug 2012 03:52:06 +0100 Subject: [PATCH 146/250] [settings] Use a generic setting's own type as its default type When fetching a named setting using a name that does not explicitly specify a type, default to using the type stored when the setting was created, rather than always defaulting to "string". This allows the behaviour of user-defined settings to match the behaviour of predefined settings (which have a sensible default type). For example: set server:ipv4 192.168.0.1 echo ${server} will now print "192.168.0.1", rather than trying to print out the raw IPv4 address bytes as a string. The downside of this change is that existing tricks for printing special characters within scripts may require (backwards-compatible) modification. For example, the "clear screen" sequence: set esc:hex 1b set cls ${esc}[2J echo ${cls} will now have to become set esc:hex 1b set cls ${esc:string}[2J # Must now explicitly specify ":string" echo ${cls} Signed-off-by: Michael Brown --- src/core/settings.c | 57 ++++++++++++++++++++++++++++++++----- src/hci/commands/menu_cmd.c | 3 +- src/hci/commands/nvo_cmd.c | 3 +- src/include/ipxe/settings.h | 9 ++++-- 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 392f598d..20b7f949 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -180,6 +180,11 @@ int generic_settings_fetch ( struct settings *settings, if ( len > generic->data_len ) len = generic->data_len; memcpy ( data, generic_setting_data ( generic ), len ); + + /* Set setting type, if not yet specified */ + if ( ! setting->type ) + setting->type = generic->setting.type; + return generic->data_len; } @@ -614,8 +619,12 @@ static int fetch_setting_and_origin ( struct settings *settings, if ( setting_applies ( settings, setting ) && ( ( ret = settings->op->fetch ( settings, setting, data, len ) ) >= 0 ) ) { + /* Record origin, if applicable */ if ( origin ) *origin = settings; + /* Default to string setting type, if not yet specified */ + if ( ! setting->type ) + setting->type = &setting_type_string; return ret; } @@ -1132,6 +1141,7 @@ static struct setting_type * find_setting_type ( const char *name ) { * @v get_child Function to find or create child settings block * @v settings Settings block to fill in * @v setting Setting to fill in + * @v default_type Default type to use, if none specified * @v tmp_name Buffer for copy of setting name * @ret rc Return status code * @@ -1147,6 +1157,7 @@ parse_setting_name ( const char *name, struct settings * ( * get_child ) ( struct settings *, const char * ), struct settings **settings, struct setting *setting, + struct setting_type *default_type, char *tmp_name ) { char *settings_name; char *setting_name; @@ -1157,7 +1168,7 @@ parse_setting_name ( const char *name, *settings = &settings_root; memset ( setting, 0, sizeof ( *setting ) ); setting->name = ""; - setting->type = &setting_type_string; + setting->type = default_type; /* Split name into "[settings_name/]setting_name[:type_name]" */ strcpy ( tmp_name, name ); @@ -1227,13 +1238,16 @@ int setting_name ( struct settings *settings, struct setting *setting, } /** - * Parse and store value of named setting + * Store value of named setting * * @v name Name of setting - * @v value Formatted setting data, or NULL + * @v default_type Default type to use, if none specified + * @v data Setting data, or NULL to clear setting + * @v len Length of setting data * @ret rc Return status code */ -int storef_named_setting ( const char *name, const char *value ) { +int store_named_setting ( const char *name, struct setting_type *default_type, + const void *data, size_t len ) { struct settings *settings; struct setting setting; char tmp_name[ strlen ( name ) + 1 ]; @@ -1241,7 +1255,36 @@ int storef_named_setting ( const char *name, const char *value ) { /* Parse setting name */ if ( ( rc = parse_setting_name ( name, autovivify_child_settings, - &settings, &setting, tmp_name )) != 0) + &settings, &setting, default_type, + tmp_name ) ) != 0 ) + return rc; + + /* Store setting */ + if ( ( rc = store_setting ( settings, &setting, data, len ) ) != 0 ) + return rc; + + return 0; +} + +/** + * Parse and store value of named setting + * + * @v name Name of setting + * @v default_type Default type to use, if none specified + * @v value Formatted setting data, or NULL + * @ret rc Return status code + */ +int storef_named_setting ( const char *name, struct setting_type *default_type, + const char *value ) { + struct settings *settings; + struct setting setting; + char tmp_name[ strlen ( name ) + 1 ]; + int rc; + + /* Parse setting name */ + if ( ( rc = parse_setting_name ( name, autovivify_child_settings, + &settings, &setting, default_type, + tmp_name ) ) != 0 ) return rc; /* Store setting */ @@ -1272,8 +1315,8 @@ int fetchf_named_setting ( const char *name, int rc; /* Parse setting name */ - if ( ( rc = parse_setting_name ( name, find_child_settings, - &settings, &setting, tmp_name )) != 0) + if ( ( rc = parse_setting_name ( name, find_child_settings, &settings, + &setting, NULL, tmp_name ) ) != 0 ) return rc; /* Fetch setting */ diff --git a/src/hci/commands/menu_cmd.c b/src/hci/commands/menu_cmd.c index c11baea7..10966db2 100644 --- a/src/hci/commands/menu_cmd.c +++ b/src/hci/commands/menu_cmd.c @@ -249,7 +249,8 @@ static int choose_exec ( int argc, char **argv ) { goto err_show_menu; /* Store setting */ - if ( ( rc = storef_named_setting ( setting, item->label ) ) != 0 ) { + if ( ( rc = storef_named_setting ( setting, &setting_type_string, + item->label ) ) != 0 ) { printf ( "Could not store \"%s\": %s\n", setting, strerror ( rc ) ); goto err_store; diff --git a/src/hci/commands/nvo_cmd.c b/src/hci/commands/nvo_cmd.c index 4bb7f457..fb8ec876 100644 --- a/src/hci/commands/nvo_cmd.c +++ b/src/hci/commands/nvo_cmd.c @@ -127,7 +127,8 @@ static int set_core_exec ( int argc, char **argv, goto err_get_value; /* Determine total length of command line */ - if ( ( rc = storef_named_setting ( name, value ) ) != 0 ) { + if ( ( rc = storef_named_setting ( name, &setting_type_string, + value ) ) != 0 ) { printf ( "Could not %s \"%s\": %s\n", argv[0], name, strerror ( rc ) ); goto err_store; diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index cd446202..a81e5ccf 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -280,7 +280,12 @@ extern int fetchf_setting ( struct settings *settings, struct setting *setting, extern int storef_setting ( struct settings *settings, struct setting *setting, const char *value ); -extern int storef_named_setting ( const char *name, const char *value ); +extern int store_named_setting ( const char *name, + struct setting_type *default_type, + const void *data, size_t len ); +extern int storef_named_setting ( const char *name, + struct setting_type *default_type, + const char *value ); extern int fetchf_named_setting ( const char *name, char *name_buf, size_t name_len, char *value_buf, size_t value_len ); @@ -366,7 +371,7 @@ static inline int delete_setting ( struct settings *settings, * @ret rc Return status code */ static inline int delete_named_setting ( const char *name ) { - return storef_named_setting ( name, NULL ); + return store_named_setting ( name, NULL, NULL, 0 ); } /** From c4500fb7cab08beabeee5c2d1e35f964764a7045 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 10 Sep 2012 15:29:36 +0100 Subject: [PATCH 147/250] [smbios] Default to "hex" type for non-string SMBIOS settings Signed-off-by: Michael Brown --- src/interface/smbios/smbios_settings.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 727970e9..893b958e 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -120,14 +120,21 @@ static int smbios_fetch ( struct settings *settings __unused, if ( tag_len == 0 ) { /* String */ - return read_smbios_string ( &structure, - buf[tag_offset], - data, len ); + if ( ( rc = read_smbios_string ( &structure, + buf[tag_offset], + data, len ) ) < 0 ) { + return rc; + } + if ( ! setting->type ) + setting->type = &setting_type_string; + return rc; } else { /* Raw data */ if ( len > tag_len ) len = tag_len; memcpy ( data, &buf[tag_offset], len ); + if ( ! setting->type ) + setting->type = &setting_type_hex; return tag_len; } } From 8e4faa094824cae9633ad512ea40c12805435f82 Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch Date: Thu, 30 Aug 2012 00:21:33 +0100 Subject: [PATCH 148/250] [cmdline] Add standalone "nslookup" command Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/config/config.c | 3 + src/config/general.h | 1 + src/hci/commands/nslookup_cmd.c | 79 ++++++++++++++ src/include/ipxe/errfile.h | 1 + src/include/usr/nslookup.h | 14 +++ src/usr/nslookup.c | 185 ++++++++++++++++++++++++++++++++ 6 files changed, 283 insertions(+) create mode 100644 src/hci/commands/nslookup_cmd.c create mode 100644 src/include/usr/nslookup.h create mode 100644 src/usr/nslookup.c diff --git a/src/config/config.c b/src/config/config.c index 78ae93c4..81519779 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -247,6 +247,9 @@ REQUIRE_OBJECT ( cpuid_cmd ); #ifdef SYNC_CMD REQUIRE_OBJECT ( sync_cmd ); #endif +#ifdef NSLOOKUP_CMD +REQUIRE_OBJECT ( nslookup_cmd ); +#endif /* * Drag in miscellaneous objects diff --git a/src/config/general.h b/src/config/general.h index 638320a4..9f0bb521 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -119,6 +119,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define MENU_CMD /* Menu commands */ #define LOGIN_CMD /* Login command */ #define SYNC_CMD /* Sync command */ +//#define NSLOOKUP_CMD /* DNS resolving command */ //#define TIME_CMD /* Time commands */ //#define DIGEST_CMD /* Image crypto digest commands */ //#define LOTEST_CMD /* Loopback testing commands */ diff --git a/src/hci/commands/nslookup_cmd.c b/src/hci/commands/nslookup_cmd.c new file mode 100644 index 00000000..265afdc3 --- /dev/null +++ b/src/hci/commands/nslookup_cmd.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 Patrick Plenefisch . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include + +/** @file + * + * nslookup command + * + */ + +/** "nslookup" options */ +struct nslookup_options {}; + +/** "nslookup" option list */ +static struct option_descriptor nslookup_opts[] = {}; + +/** "nslookup" command descriptor */ +static struct command_descriptor nslookup_cmd = + COMMAND_DESC ( struct nslookup_options, nslookup_opts, 2, 2, + " " ); + +/** + * The "nslookup" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Return status code + */ +static int nslookup_exec ( int argc, char **argv ) { + struct nslookup_options opts; + const char *name; + const char *setting_name; + int rc; + + /* Parse options */ + if ( ( rc = parse_options ( argc, argv, &nslookup_cmd, &opts ) ) != 0 ) + return rc; + + /* Parse setting name */ + setting_name = argv[optind]; + + /* Parse name to be resolved */ + name = argv[ optind + 1 ]; + + /* Look up name */ + if ( ( rc = nslookup ( name, setting_name ) ) != 0 ) + return rc; + + return 0; +} + +/** The "nslookup" command */ +struct command nslookup_command __command = { + .name = "nslookup", + .exec = nslookup_exec, +}; diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 5fc0e082..8edf5ccb 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -262,6 +262,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_menu_cmd ( ERRFILE_OTHER | 0x002d0000 ) #define ERRFILE_validator ( ERRFILE_OTHER | 0x002e0000 ) #define ERRFILE_ocsp ( ERRFILE_OTHER | 0x002f0000 ) +#define ERRFILE_nslookup ( ERRFILE_OTHER | 0x00300000 ) /** @} */ diff --git a/src/include/usr/nslookup.h b/src/include/usr/nslookup.h new file mode 100644 index 00000000..d34649e9 --- /dev/null +++ b/src/include/usr/nslookup.h @@ -0,0 +1,14 @@ +#ifndef _USR_NSLOOKUP_H +#define _USR_NSLOOKUP_H + +/** @file + * + * Standalone name resolution + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +extern int nslookup ( const char *name, const char *setting_name ); + +#endif /* _USR_NSLOOKUP_H */ diff --git a/src/usr/nslookup.c b/src/usr/nslookup.c new file mode 100644 index 00000000..c931ec5a --- /dev/null +++ b/src/usr/nslookup.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2012 Patrick Plenefisch . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @file + * + * Standalone name resolution + * + */ + +/** A name resolution request */ +struct nslookup { + /** Reference count for this object */ + struct refcnt refcnt; + + /** Job control interface */ + struct interface job; + /** Data transfer interface */ + struct interface resolver; + + /** Setting name */ + const char *setting_name; +}; + +/** + * Terminate name resolution + * + * @v nslookup Name resolution request + * @v rc Reason for termination + */ +static void nslookup_close ( struct nslookup *nslookup, int rc ) { + + /* Shut down interfaces */ + intf_shutdown ( &nslookup->resolver, rc ); + intf_shutdown ( &nslookup->job, rc ); +} + +/** + * Handle resolved name + * + * @v nslookup Name resolution request + * @v sa Completed socket address + */ +static void nslookup_resolv_done ( struct nslookup *nslookup, + struct sockaddr *sa ) { + struct sockaddr_in *sin; + struct setting_type *type; + void *data; + size_t len; + int rc; + + /* Extract address */ + switch ( sa->sa_family ) { + case AF_INET: + sin = ( ( struct sockaddr_in * ) sa ); + data = &sin->sin_addr; + len = sizeof ( sin->sin_addr ); + type = &setting_type_ipv4; + break; + default: + rc = -ENOTSUP; + goto err; + } + + /* Save in specified setting */ + if ( ( rc = store_named_setting ( nslookup->setting_name, type, + data, len ) ) != 0 ) + goto err; + + err: + /* Terminate name resolution */ + nslookup_close ( nslookup, rc ); +} + +/** Name resolution resolver interface operations */ +static struct interface_operation nslookup_resolver_operations[] = { + INTF_OP ( resolv_done, struct nslookup *, nslookup_resolv_done ), + INTF_OP ( intf_close, struct nslookup *, nslookup_close ), +}; + +/** Name resolution resolver interface descriptor */ +static struct interface_descriptor nslookup_resolver_desc = + INTF_DESC_PASSTHRU ( struct nslookup, resolver, + nslookup_resolver_operations, job ); + +/** Name resolution job control interface operations */ +static struct interface_operation nslookup_job_operations[] = { + INTF_OP ( intf_close, struct nslookup *, nslookup_close ), +}; + +/** Name resolution job control interface descriptor */ +static struct interface_descriptor nslookup_job_desc = + INTF_DESC_PASSTHRU ( struct nslookup, job, + nslookup_job_operations, resolver ); + +/** + * Initiate standalone name resolution + * + * @v job Parent interface + * @v name Name to resolve + * @v setting_name Setting name + * @ret rc Return status code + */ +static int resolv_setting ( struct interface *job, const char *name, + const char *setting_name ) { + struct nslookup *nslookup; + struct sockaddr sa; + char *setting_name_copy; + int rc; + + /* Allocate and initialise structure */ + nslookup = zalloc ( sizeof ( *nslookup ) + strlen ( setting_name ) + + 1 /* NUL */ ); + if ( ! nslookup ) + return -ENOMEM; + ref_init ( &nslookup->refcnt, NULL ); + intf_init ( &nslookup->job, &nslookup_job_desc, &nslookup->refcnt ); + intf_init ( &nslookup->resolver, &nslookup_resolver_desc, + &nslookup->refcnt ); + setting_name_copy = ( ( void * ) ( nslookup + 1 ) ); + strcpy ( setting_name_copy, setting_name ); + nslookup->setting_name = setting_name_copy; + + /* Start name resolution */ + memset ( &sa, 0, sizeof ( sa ) ); + if ( ( rc = resolv ( &nslookup->resolver, name, &sa ) ) != 0 ) + goto err_resolv; + + /* Attach parent interface, mortalise self, and return */ + intf_plug_plug ( &nslookup->job, job ); + ref_put ( &nslookup->refcnt ); + return 0; + + err_resolv: + ref_put ( &nslookup->refcnt ); + return rc; +} + +/** + * Perform (blocking) standalone name resolution + * + * @v name Name to resolve + * @v setting_name Setting name + * @ret rc Return status code + */ +int nslookup ( const char *name, const char *setting_name ) { + int rc; + + /* Perform name resolution */ + if ( ( rc = resolv_setting ( &monojob, name, setting_name ) ) == 0 ) + rc = monojob_wait ( NULL ); + if ( rc != 0 ) { + printf ( "Could not resolve %s: %s\n", name, strerror ( rc ) ); + return rc; + } + + return 0; +} From 117fc6173891657d68a02d99a784705a1b5ec8f4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 10 Sep 2012 15:58:02 +0100 Subject: [PATCH 149/250] [console] Add support for the bochs/qemu debug port console Signed-off-by: Michael Brown --- src/arch/x86/core/debugcon.c | 86 ++++++++++++++++++++++++++++++++++++ src/config/config.c | 3 ++ src/config/console.h | 1 + 3 files changed, 90 insertions(+) create mode 100644 src/arch/x86/core/debugcon.c diff --git a/src/arch/x86/core/debugcon.c b/src/arch/x86/core/debugcon.c new file mode 100644 index 00000000..b89480aa --- /dev/null +++ b/src/arch/x86/core/debugcon.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Debug port console + * + * The debug port is supported by bochs (via the "port_e9_hack" + * configuration file directive) and by qemu (via the "-debugcon" + * command-line option). + */ + +#include +#include +#include +#include +#include + +/** Debug port */ +#define DEBUG_PORT 0xe9 + +/** Debug port installation check magic value */ +#define DEBUG_PORT_CHECK 0xe9 + +/* Set default console usage if applicable */ +#if ! ( defined ( CONSOLE_DEBUGCON ) && CONSOLE_EXPLICIT ( CONSOLE_DEBUGCON ) ) +#undef CONSOLE_DEBUGCON +#define CONSOLE_DEBUGCON ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI ) +#endif + +/** + * Print a character to debug port console + * + * @v character Character to be printed + */ +static void debugcon_putchar ( int character ) { + + /* Write character to debug port */ + outb ( character, DEBUG_PORT ); +} + +/** Debug port console driver */ +struct console_driver debugcon_console __console_driver = { + .putchar = debugcon_putchar, + .usage = CONSOLE_DEBUGCON, +}; + +/** + * Initialise debug port console + * + */ +static void debugcon_init ( void ) { + uint8_t check; + + /* Check if console is present */ + check = inb ( DEBUG_PORT ); + if ( check != DEBUG_PORT_CHECK ) { + DBG ( "Debug port not present; disabling console\n" ); + debugcon_console.disabled = 1; + } +} + +/** + * Debug port console initialisation function + */ +struct init_fn debugcon_init_fn __init_fn ( INIT_EARLY ) = { + .initialise = debugcon_init, +}; diff --git a/src/config/config.c b/src/config/config.c index 81519779..bd1d9885 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -89,6 +89,9 @@ REQUIRE_OBJECT ( linux_console ); #ifdef CONSOLE_VMWARE REQUIRE_OBJECT ( vmconsole ); #endif +#ifdef CONSOLE_DEBUGCON +REQUIRE_OBJECT ( debugcon ); +#endif /* * Drag in all requested network protocols diff --git a/src/config/console.h b/src/config/console.h index 95c32803..04be02dc 100644 --- a/src/config/console.h +++ b/src/config/console.h @@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); //#define CONSOLE_SYSLOG /* Syslog console */ //#define CONSOLE_SYSLOGS /* Encrypted syslog console */ //#define CONSOLE_VMWARE /* VMware logfile console */ +//#define CONSOLE_DEBUGCON /* Debug port console */ #define KEYBOARD_MAP us From 8509dbf86acce7aacb3518c3f8b5bcb0cb4809da Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 14 Sep 2012 15:04:53 +0100 Subject: [PATCH 150/250] [int13] Use correct size when estimating floppy disk geometry Signed-off-by: Michael Brown --- src/arch/i386/interface/pcbios/int13.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/i386/interface/pcbios/int13.c b/src/arch/i386/interface/pcbios/int13.c index 191e7418..263f861e 100644 --- a/src/arch/i386/interface/pcbios/int13.c +++ b/src/arch/i386/interface/pcbios/int13.c @@ -627,7 +627,7 @@ static const struct int13_fdd_geometry int13_fdd_geometries[] = { static int int13_guess_geometry_fdd ( struct int13_drive *int13, unsigned int *heads, unsigned int *sectors ) { - unsigned int blocks = int13_blksize ( int13 ); + unsigned int blocks = int13_capacity ( int13 ); const struct int13_fdd_geometry *geometry; unsigned int cylinders; unsigned int i; From 73eb3f17db3ff0a57a52507eafb5ef78eb5dc66e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 14 Sep 2012 15:42:54 +0100 Subject: [PATCH 151/250] [int13] Zero all possible registers when jumping to a boot sector At least one boot sector (the DUET boot sector used for bootstrapping EFI from a non-EFI system) fails to initialise the high words of registers before using them in calculations, leading to undefined behaviour. Work around such broken boot sectors by explicitly zeroing the contents of all registers apart from %cs:%ip and %ss:%sp. Signed-off-by: Michael Brown --- src/arch/i386/image/bootsector.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/arch/i386/image/bootsector.c b/src/arch/i386/image/bootsector.c index 289be7d7..faf21c6f 100644 --- a/src/arch/i386/image/bootsector.c +++ b/src/arch/i386/image/bootsector.c @@ -80,9 +80,22 @@ int call_bootsector ( unsigned int segment, unsigned int offset, "movw %%ss, %%ax\n\t" "movw %%ax, %%cs:saved_ss\n\t" "movw %%sp, %%cs:saved_sp\n\t" - /* Jump to boot sector */ + /* Prepare jump to boot sector */ "pushw %%bx\n\t" "pushw %%di\n\t" + /* Clear all registers */ + "xorl %%eax, %%eax\n\t" + "xorl %%ebx, %%ebx\n\t" + "xorl %%ecx, %%ecx\n\t" + "xorl %%edx, %%edx\n\t" + "xorl %%esi, %%esi\n\t" + "xorl %%edi, %%edi\n\t" + "xorl %%ebp, %%ebp\n\t" + "movw %%ax, %%ds\n\t" + "movw %%ax, %%es\n\t" + "movw %%ax, %%fs\n\t" + "movw %%ax, %%gs\n\t" + /* Jump to boot sector */ "sti\n\t" "lret\n\t" /* Preserved variables */ From 09cc63fc8bd083c58d7276a01675612dbd6a3cfb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 14 Sep 2012 17:49:53 +0100 Subject: [PATCH 152/250] [efi] Provide guaranteed space in transmitted packets eIPoIB requires space to expand a transmitted ARP packet. This guarantee is met by ensuring that a transmitted packet consists of at least MAX_LL_HEADER_LEN bytes from the start of the I/O buffer up to the end of the link-layer header, and at least IOB_ZLEN bytes thereafter. Adjust the I/O buffer allocation for SNP transmitted packets to ensure that this guarantee is met. Signed-off-by: Michael Brown --- src/interface/efi/efi_snp.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 6d7865dd..b4ae5113 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -536,7 +536,7 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, container_of ( snp, struct efi_snp_device, snp ); struct ll_protocol *ll_protocol = snpdev->netdev->ll_protocol; struct io_buffer *iobuf; - size_t ll_headroom; + size_t payload_len; int rc; EFI_STATUS efirc; @@ -589,21 +589,22 @@ efi_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, } /* Allocate buffer */ - ll_headroom = ( MAX_LL_HEADER_LEN - ll_header_len ); - iobuf = alloc_iob ( ll_headroom + - ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) ); + payload_len = ( len - ll_protocol->ll_header_len ); + iobuf = alloc_iob ( MAX_LL_HEADER_LEN + ( ( payload_len > IOB_ZLEN ) ? + payload_len : IOB_ZLEN ) ); if ( ! iobuf ) { DBGC ( snpdev, "SNPDEV %p TX could not allocate %ld-byte " "buffer\n", snpdev, ( ( unsigned long ) len ) ); efirc = EFI_DEVICE_ERROR; goto err_alloc_iob; } - iob_reserve ( iobuf, ll_headroom ); + iob_reserve ( iobuf, ( MAX_LL_HEADER_LEN - + ll_protocol->ll_header_len ) ); memcpy ( iob_put ( iobuf, len ), data, len ); /* Create link-layer header, if specified */ if ( ll_header_len ) { - iob_pull ( iobuf, ll_header_len ); + iob_pull ( iobuf, ll_protocol->ll_header_len ); if ( ( rc = ll_protocol->push ( snpdev->netdev, iobuf, ll_dest, ll_src, htons ( *net_proto ) )) != 0 ){ From 681a219caaa5f9379641232157cc0b38e64a839d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 26 Sep 2012 14:54:02 +0100 Subject: [PATCH 153/250] [test] Add speed tests for digest algorithms Signed-off-by: Michael Brown --- src/tests/digest_test.c | 35 +++++++++++++++++++++++++++++++++++ src/tests/digest_test.h | 1 + src/tests/md5_test.c | 6 ++++++ src/tests/sha1_test.c | 6 ++++++ src/tests/sha256_test.c | 6 ++++++ 5 files changed, 54 insertions(+) diff --git a/src/tests/digest_test.c b/src/tests/digest_test.c index ccec0e9a..6428cc72 100644 --- a/src/tests/digest_test.c +++ b/src/tests/digest_test.c @@ -25,8 +25,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +#include #include #include +#include #include "digest_test.h" /** @@ -68,3 +70,36 @@ int digest_test ( struct digest_algorithm *digest, /* Compare against expected output */ return ( memcmp ( expected, out, sizeof ( out ) ) == 0 ); } + +/** + * Calculate digest algorithm cost + * + * @v digest Digest algorithm + * @ret cost Cost (in cycles per byte) + */ +unsigned long digest_cost ( struct digest_algorithm *digest ) { + static uint8_t random[8192]; /* Too large for stack */ + uint8_t ctx[digest->ctxsize]; + uint8_t out[digest->digestsize]; + union profiler profiler; + unsigned long long elapsed; + unsigned long cost; + unsigned int i; + + /* Fill buffer with pseudo-random data */ + srand ( 0x1234568 ); + for ( i = 0 ; i < sizeof ( random ) ; i++ ) + random[i] = rand(); + + /* Time digest calculation */ + profile ( &profiler ); + digest_init ( digest, ctx ); + digest_update ( digest, ctx, random, sizeof ( random ) ); + digest_final ( digest, ctx, out ); + elapsed = profile ( &profiler ); + + /* Round to nearest whole number of cycles per byte */ + cost = ( ( elapsed + ( sizeof ( random ) / 2 ) ) / sizeof ( random ) ); + + return cost; +} diff --git a/src/tests/digest_test.h b/src/tests/digest_test.h index c2558780..49e06d1c 100644 --- a/src/tests/digest_test.h +++ b/src/tests/digest_test.h @@ -19,6 +19,7 @@ struct digest_test_fragments { extern int digest_test ( struct digest_algorithm *digest, struct digest_test_fragments *fragments, void *data, size_t len, void *expected ); +extern unsigned long digest_cost ( struct digest_algorithm *digest ); /** * Report digest test result diff --git a/src/tests/md5_test.c b/src/tests/md5_test.c index e54296ac..ba5f24c3 100644 --- a/src/tests/md5_test.c +++ b/src/tests/md5_test.c @@ -70,9 +70,11 @@ static struct digest_test_fragments md5_test_fragments[] = { static void md5_test_exec ( void ) { struct digest_algorithm *digest = &md5_algorithm; struct md5_test_vector *test; + unsigned long cost; unsigned int i; unsigned int j; + /* Correctness test */ for ( i = 0 ; i < ( sizeof ( md5_test_vectors ) / sizeof ( md5_test_vectors[0] ) ) ; i++ ) { test = &md5_test_vectors[i]; @@ -85,6 +87,10 @@ static void md5_test_exec ( void ) { test->data, test->len, test->digest ); } } + + /* Speed test */ + cost = digest_cost ( digest ); + DBG ( "MD5 required %ld cycles per byte\n", cost ); } /** MD5 self-test */ diff --git a/src/tests/sha1_test.c b/src/tests/sha1_test.c index 3ff7e3c2..bcf761bd 100644 --- a/src/tests/sha1_test.c +++ b/src/tests/sha1_test.c @@ -75,9 +75,11 @@ static struct digest_test_fragments sha1_test_fragments[] = { static void sha1_test_exec ( void ) { struct digest_algorithm *digest = &sha1_algorithm; struct sha1_test_vector *test; + unsigned long cost; unsigned int i; unsigned int j; + /* Correctness test */ for ( i = 0 ; i < ( sizeof ( sha1_test_vectors ) / sizeof ( sha1_test_vectors[0] ) ) ; i++ ) { test = &sha1_test_vectors[i]; @@ -90,6 +92,10 @@ static void sha1_test_exec ( void ) { test->data, test->len, test->digest ); } } + + /* Speed test */ + cost = digest_cost ( digest ); + DBG ( "SHA1 required %ld cycles per byte\n", cost ); } /** SHA-1 self-test */ diff --git a/src/tests/sha256_test.c b/src/tests/sha256_test.c index 77b6b10f..06a8cae2 100644 --- a/src/tests/sha256_test.c +++ b/src/tests/sha256_test.c @@ -78,9 +78,11 @@ static struct digest_test_fragments sha256_test_fragments[] = { static void sha256_test_exec ( void ) { struct digest_algorithm *digest = &sha256_algorithm; struct sha256_test_vector *test; + unsigned long cost; unsigned int i; unsigned int j; + /* Correctness test */ for ( i = 0 ; i < ( sizeof ( sha256_test_vectors ) / sizeof ( sha256_test_vectors[0] ) ) ; i++ ) { test = &sha256_test_vectors[i]; @@ -93,6 +95,10 @@ static void sha256_test_exec ( void ) { test->data, test->len, test->digest ); } } + + /* Speed test */ + cost = digest_cost ( digest ); + DBG ( "SHA256 required %ld cycles per byte\n", cost ); } /** SHA-256 self-test */ From c1adf7dabee103c1ca0b73e78c2d5a79b241830e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 26 Sep 2012 15:27:33 +0100 Subject: [PATCH 154/250] [test] Add speed tests for cipher algorithms Signed-off-by: Michael Brown --- src/tests/aes_cbc_test.c | 12 ++++++ src/tests/cbc_test.c | 82 ++++++++++++++++++++++++++++++++++++++-- src/tests/cbc_test.h | 4 ++ 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/tests/aes_cbc_test.c b/src/tests/aes_cbc_test.c index 09d38075..4ae3a92e 100644 --- a/src/tests/aes_cbc_test.c +++ b/src/tests/aes_cbc_test.c @@ -169,9 +169,21 @@ AES_CBC_TEST ( test_256, * */ static void aes_cbc_test_exec ( void ) { + struct cipher_algorithm *cipher = &aes_cbc_algorithm; + /* Correctness tests */ aes_cbc_ok ( &test_128 ); aes_cbc_ok ( &test_256 ); + + /* Speed tests */ + DBG ( "AES128 encryption required %ld cycles per byte\n", + cbc_cost_encrypt ( cipher, test_128.key_len ) ); + DBG ( "AES128 decryption required %ld cycles per byte\n", + cbc_cost_decrypt ( cipher, test_128.key_len ) ); + DBG ( "AES256 encryption required %ld cycles per byte\n", + cbc_cost_encrypt ( cipher, test_256.key_len ) ); + DBG ( "AES256 decryption required %ld cycles per byte\n", + cbc_cost_decrypt ( cipher, test_256.key_len ) ); } /** AES-in-CBC-mode self-test */ diff --git a/src/tests/cbc_test.c b/src/tests/cbc_test.c index 7d755309..ada991b2 100644 --- a/src/tests/cbc_test.c +++ b/src/tests/cbc_test.c @@ -29,9 +29,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #undef NDEBUG #include +#include #include #include #include +#include #include "cbc_test.h" /** @@ -49,8 +51,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key, size_t key_len, const void *iv, const void *plaintext, const void *expected_ciphertext, size_t len ) { - uint8_t ctx[ cipher->ctxsize ]; - uint8_t ciphertext[ len ]; + uint8_t ctx[cipher->ctxsize]; + uint8_t ciphertext[len]; int rc; /* Initialise cipher */ @@ -80,8 +82,8 @@ int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key, int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key, size_t key_len, const void *iv, const void *ciphertext, const void *expected_plaintext, size_t len ) { - uint8_t ctx[ cipher->ctxsize ]; - uint8_t plaintext[ len ]; + uint8_t ctx[cipher->ctxsize]; + uint8_t plaintext[len]; int rc; /* Initialise cipher */ @@ -95,3 +97,75 @@ int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key, /* Verify result */ return ( memcmp ( plaintext, expected_plaintext, len ) == 0 ); } + +/** + * Calculate CBC encryption or decryption cost + * + * @v cipher Cipher algorithm + * @v key_len Length of key + * @v op Encryption or decryption operation + * @ret cost Cost (in cycles per byte) + */ +static unsigned long cbc_cost ( struct cipher_algorithm *cipher, + size_t key_len, + void ( * op ) ( struct cipher_algorithm *cipher, + void *ctx, const void *src, + void *dst, size_t len ) ) { + static uint8_t random[8192]; /* Too large for stack */ + uint8_t key[key_len]; + uint8_t iv[cipher->blocksize]; + uint8_t ctx[cipher->ctxsize]; + union profiler profiler; + unsigned long long elapsed; + unsigned long cost; + unsigned int i; + int rc; + + /* Fill buffer with pseudo-random data */ + srand ( 0x1234568 ); + for ( i = 0 ; i < sizeof ( random ) ; i++ ) + random[i] = rand(); + for ( i = 0 ; i < sizeof ( key ) ; i++ ) + key[i] = rand(); + for ( i = 0 ; i < sizeof ( iv ) ; i++ ) + iv[i] = rand(); + + /* Initialise cipher */ + rc = cipher_setkey ( cipher, ctx, key, key_len ); + assert ( rc == 0 ); + cipher_setiv ( cipher, ctx, iv ); + + /* Time operation */ + profile ( &profiler ); + op ( cipher, ctx, random, random, sizeof ( random ) ); + elapsed = profile ( &profiler ); + + /* Round to nearest whole number of cycles per byte */ + cost = ( ( elapsed + ( sizeof ( random ) / 2 ) ) / sizeof ( random ) ); + + return cost; +} + +/** + * Calculate CBC encryption cost + * + * @v cipher Cipher algorithm + * @v key_len Length of key + * @ret cost Cost (in cycles per byte) + */ +unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher, + size_t key_len ) { + return cbc_cost ( cipher, key_len, cipher_encrypt ); +} + +/** + * Calculate CBC decryption cost + * + * @v cipher Cipher algorithm + * @v key_len Length of key + * @ret cost Cost (in cycles per byte) + */ +unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher, + size_t key_len ) { + return cbc_cost ( cipher, key_len, cipher_decrypt ); +} diff --git a/src/tests/cbc_test.h b/src/tests/cbc_test.h index 40356cc3..ad9e6f34 100644 --- a/src/tests/cbc_test.h +++ b/src/tests/cbc_test.h @@ -15,6 +15,10 @@ extern int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key, size_t key_len, const void *iv, const void *ciphertext, const void *expected_plaintext, size_t len ); +extern unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher, + size_t key_len ); +extern unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher, + size_t key_len ); /** * Report CBC encryption test result From 09d45ffd7991e6b64a76d86f338a2f0973527be6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 27 Sep 2012 01:37:06 +0100 Subject: [PATCH 155/250] [crypto] Allow in-place CBC decryption Signed-off-by: Michael Brown --- src/crypto/cbc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/crypto/cbc.c b/src/crypto/cbc.c index 28d38b2d..9bf0e8b4 100644 --- a/src/crypto/cbc.c +++ b/src/crypto/cbc.c @@ -88,13 +88,15 @@ void cbc_encrypt ( void *ctx, const void *src, void *dst, size_t len, void cbc_decrypt ( void *ctx, const void *src, void *dst, size_t len, struct cipher_algorithm *raw_cipher, void *cbc_ctx ) { size_t blocksize = raw_cipher->blocksize; + uint8_t next_cbc_ctx[blocksize]; assert ( ( len % blocksize ) == 0 ); while ( len ) { + memcpy ( next_cbc_ctx, src, blocksize ); cipher_decrypt ( raw_cipher, ctx, src, dst, blocksize ); cbc_xor ( cbc_ctx, dst, blocksize ); - memcpy ( cbc_ctx, src, blocksize ); + memcpy ( cbc_ctx, next_cbc_ctx, blocksize ); dst += blocksize; src += blocksize; len -= blocksize; From 72db14640c2a9eac0ba53baa955b180f1f4b9c2f Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 26 Sep 2012 21:42:23 +0100 Subject: [PATCH 156/250] [tls] Split received records over multiple I/O buffers TLS servers are not obliged to implement the RFC3546 maximum fragment length extension, and many common servers (including OpenSSL, as used in Apache's mod_ssl) do not do so. iPXE may therefore have to cope with TLS records of up to 16kB. Allocations for 16kB have a non-negligible chance of failing, causing the TLS connection to abort. Fix by maintaining the received record as a linked list of I/O buffers, rather than a single contiguous buffer. To reduce memory pressure, we also decrypt in situ, and deliver the decrypted data via xfer_deliver_iob() rather than xfer_deliver_raw(). Signed-off-by: Michael Brown --- src/include/ipxe/tls.h | 30 ++- src/net/tls.c | 442 ++++++++++++++++++++++++++--------------- 2 files changed, 304 insertions(+), 168 deletions(-) diff --git a/src/include/ipxe/tls.h b/src/include/ipxe/tls.h index 2af864df..f8a75409 100644 --- a/src/include/ipxe/tls.h +++ b/src/include/ipxe/tls.h @@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** A TLS header */ struct tls_header { @@ -264,14 +265,35 @@ struct tls_session { uint64_t rx_seq; /** RX state */ enum tls_rx_state rx_state; - /** Offset within current RX state */ - size_t rx_rcvd; /** Current received record header */ struct tls_header rx_header; - /** Current received raw data buffer */ - void *rx_data; + /** Current received record header (static I/O buffer) */ + struct io_buffer rx_header_iobuf; + /** List of received data buffers */ + struct list_head rx_data; }; +/** RX I/O buffer size + * + * The maximum fragment length extension is optional, and many common + * implementations (including OpenSSL) do not support it. We must + * therefore be prepared to receive records of up to 16kB in length. + * The chance of an allocation of this size failing is non-negligible, + * so we must split received data into smaller allocations. + */ +#define TLS_RX_BUFSIZE 4096 + +/** Minimum RX I/O buffer size + * + * To simplify manipulations, we ensure that no RX I/O buffer is + * smaller than this size. This allows us to assume that the MAC and + * padding are entirely contained within the final I/O buffer. + */ +#define TLS_RX_MIN_BUFSIZE 512 + +/** RX I/O buffer alignment */ +#define TLS_RX_ALIGN 16 + extern int add_tls ( struct interface *xfer, const char *name, struct interface **next ); diff --git a/src/net/tls.c b/src/net/tls.c index ec2763b5..45b7e525 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -101,6 +101,14 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_EINVAL_RX_STATE \ __einfo_uniqify ( EINFO_EINVAL, 0x0c, \ "Invalid receive state" ) +#define EINVAL_MAC __einfo_error ( EINFO_EINVAL_MAC ) +#define EINFO_EINVAL_MAC \ + __einfo_uniqify ( EINFO_EINVAL, 0x0d, \ + "Invalid MAC" ) +#define EINVAL_NON_DATA __einfo_error ( EINFO_EINVAL_NON_DATA ) +#define EINFO_EINVAL_NON_DATA \ + __einfo_uniqify ( EINFO_EINVAL, 0x0e, \ + "Overlength non-data record" ) #define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT ) #define EINFO_EIO_ALERT \ __einfo_uniqify ( EINFO_EINVAL, 0x01, \ @@ -125,10 +133,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_ENOMEM_TX_CIPHERTEXT \ __einfo_uniqify ( EINFO_ENOMEM, 0x05, \ "Not enough space for transmitted ciphertext" ) -#define ENOMEM_RX_PLAINTEXT __einfo_error ( EINFO_ENOMEM_RX_PLAINTEXT ) -#define EINFO_ENOMEM_RX_PLAINTEXT \ - __einfo_uniqify ( EINFO_ENOMEM, 0x06, \ - "Not enough space for received plaintext" ) #define ENOMEM_RX_DATA __einfo_error ( EINFO_ENOMEM_RX_DATA ) #define EINFO_ENOMEM_RX_DATA \ __einfo_uniqify ( EINFO_ENOMEM, 0x07, \ @@ -159,7 +163,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); "Handshake verification failed" ) #define EPROTO_VERSION __einfo_error ( EINFO_EPROTO_VERSION ) #define EINFO_EPROTO_VERSION \ - __einfo_uniqify ( EINFO_EINVAL, 0x01, \ + __einfo_uniqify ( EINFO_EPROTO, 0x01, \ "Illegal protocol version upgrade" ) static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, @@ -295,13 +299,18 @@ struct rsa_digestinfo_prefix rsa_md5_sha1_prefix __rsa_digestinfo_prefix = { static void free_tls ( struct refcnt *refcnt ) { struct tls_session *tls = container_of ( refcnt, struct tls_session, refcnt ); + struct io_buffer *iobuf; + struct io_buffer *tmp; /* Free dynamically-allocated resources */ tls_clear_cipher ( tls, &tls->tx_cipherspec ); tls_clear_cipher ( tls, &tls->tx_cipherspec_pending ); tls_clear_cipher ( tls, &tls->rx_cipherspec ); tls_clear_cipher ( tls, &tls->rx_cipherspec_pending ); - free ( tls->rx_data ); + list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) { + list_del ( &iobuf->list ); + free_iob ( iobuf ); + } x509_chain_put ( tls->chain ); /* Free TLS structure itself */ @@ -1013,7 +1022,7 @@ static int tls_send_client_hello ( struct tls_session *tls ) { hello.extensions.max_fragment_length_len = htons ( sizeof ( hello.extensions.max_fragment_length ) ); hello.extensions.max_fragment_length.max - = TLS_MAX_FRAGMENT_LENGTH_2048; + = TLS_MAX_FRAGMENT_LENGTH_4096; return tls_send_handshake ( tls, &hello, sizeof ( hello ) ); } @@ -1703,31 +1712,71 @@ static int tls_new_handshake ( struct tls_session *tls, * * @v tls TLS session * @v type Record type - * @v data Plaintext record - * @v len Length of plaintext record + * @v rx_data List of received data buffers * @ret rc Return status code */ static int tls_new_record ( struct tls_session *tls, unsigned int type, - const void *data, size_t len ) { + struct list_head *rx_data ) { + struct io_buffer *iobuf; + int ( * handler ) ( struct tls_session *tls, const void *data, + size_t len ); + int rc; - switch ( type ) { - case TLS_TYPE_CHANGE_CIPHER: - return tls_new_change_cipher ( tls, data, len ); - case TLS_TYPE_ALERT: - return tls_new_alert ( tls, data, len ); - case TLS_TYPE_HANDSHAKE: - return tls_new_handshake ( tls, data, len ); - case TLS_TYPE_DATA: + /* Deliver data records to the plainstream interface */ + if ( type == TLS_TYPE_DATA ) { + + /* Fail unless we are ready to receive data */ if ( ! tls_ready ( tls ) ) return -ENOTCONN; - return xfer_deliver_raw ( &tls->plainstream, data, len ); + + /* Deliver each I/O buffer in turn */ + while ( ( iobuf = list_first_entry ( rx_data, struct io_buffer, + list ) ) ) { + list_del ( &iobuf->list ); + if ( ( rc = xfer_deliver_iob ( &tls->plainstream, + iobuf ) ) != 0 ) { + DBGC ( tls, "TLS %p could not deliver data: " + "%s\n", tls, strerror ( rc ) ); + return rc; + } + } + return 0; + } + + /* For all other records, fail unless we have exactly one I/O buffer */ + iobuf = list_first_entry ( rx_data, struct io_buffer, list ); + assert ( iobuf != NULL ); + list_del ( &iobuf->list ); + if ( ! list_empty ( rx_data ) ) { + DBGC ( tls, "TLS %p overlength non-data record\n", tls ); + return -EINVAL_NON_DATA; + } + + /* Determine handler */ + switch ( type ) { + case TLS_TYPE_CHANGE_CIPHER: + handler = tls_new_change_cipher; + break; + case TLS_TYPE_ALERT: + handler = tls_new_alert; + break; + case TLS_TYPE_HANDSHAKE: + handler = tls_new_handshake; + break; default: /* RFC4346 says that we should just ignore unknown * record types. */ + handler = NULL; DBGC ( tls, "TLS %p ignoring record type %d\n", tls, type ); - return 0; + break; } + + /* Handle record and free I/O buffer */ + if ( handler ) + rc = handler ( tls, iobuf->data, iob_len ( iobuf ) ); + free_iob ( iobuf ); + return rc; } /****************************************************************************** @@ -1737,10 +1786,57 @@ static int tls_new_record ( struct tls_session *tls, unsigned int type, ****************************************************************************** */ +/** + * Initialise HMAC + * + * @v cipherspec Cipher specification + * @v ctx Context + * @v seq Sequence number + * @v tlshdr TLS header + */ +static void tls_hmac_init ( struct tls_cipherspec *cipherspec, void *ctx, + uint64_t seq, struct tls_header *tlshdr ) { + struct digest_algorithm *digest = cipherspec->suite->digest; + + hmac_init ( digest, ctx, cipherspec->mac_secret, &digest->digestsize ); + seq = cpu_to_be64 ( seq ); + hmac_update ( digest, ctx, &seq, sizeof ( seq ) ); + hmac_update ( digest, ctx, tlshdr, sizeof ( *tlshdr ) ); +} + +/** + * Update HMAC + * + * @v cipherspec Cipher specification + * @v ctx Context + * @v data Data + * @v len Length of data + */ +static void tls_hmac_update ( struct tls_cipherspec *cipherspec, void *ctx, + const void *data, size_t len ) { + struct digest_algorithm *digest = cipherspec->suite->digest; + + hmac_update ( digest, ctx, data, len ); +} + +/** + * Finalise HMAC + * + * @v cipherspec Cipher specification + * @v ctx Context + * @v mac HMAC to fill in + */ +static void tls_hmac_final ( struct tls_cipherspec *cipherspec, void *ctx, + void *hmac ) { + struct digest_algorithm *digest = cipherspec->suite->digest; + + hmac_final ( digest, ctx, cipherspec->mac_secret, + &digest->digestsize, hmac ); +} + /** * Calculate HMAC * - * @v tls TLS session * @v cipherspec Cipher specification * @v seq Sequence number * @v tlshdr TLS header @@ -1748,21 +1844,15 @@ static int tls_new_record ( struct tls_session *tls, unsigned int type, * @v len Length of data * @v mac HMAC to fill in */ -static void tls_hmac ( struct tls_session *tls __unused, - struct tls_cipherspec *cipherspec, +static void tls_hmac ( struct tls_cipherspec *cipherspec, uint64_t seq, struct tls_header *tlshdr, const void *data, size_t len, void *hmac ) { struct digest_algorithm *digest = cipherspec->suite->digest; - uint8_t digest_ctx[digest->ctxsize]; + uint8_t ctx[digest->ctxsize]; - hmac_init ( digest, digest_ctx, cipherspec->mac_secret, - &digest->digestsize ); - seq = cpu_to_be64 ( seq ); - hmac_update ( digest, digest_ctx, &seq, sizeof ( seq ) ); - hmac_update ( digest, digest_ctx, tlshdr, sizeof ( *tlshdr ) ); - hmac_update ( digest, digest_ctx, data, len ); - hmac_final ( digest, digest_ctx, cipherspec->mac_secret, - &digest->digestsize, hmac ); + tls_hmac_init ( cipherspec, ctx, seq, tlshdr ); + tls_hmac_update ( cipherspec, ctx, data, len ); + tls_hmac_final ( cipherspec, ctx, hmac ); } /** @@ -1877,8 +1967,7 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, plaintext_tlshdr.length = htons ( len ); /* Calculate MAC */ - tls_hmac ( tls, cipherspec, tls->tx_seq, &plaintext_tlshdr, - data, len, mac ); + tls_hmac ( cipherspec, tls->tx_seq, &plaintext_tlshdr, data, len, mac ); /* Allocate and assemble plaintext struct */ if ( is_stream_cipher ( cipher ) ) { @@ -1945,36 +2034,25 @@ static int tls_send_plaintext ( struct tls_session *tls, unsigned int type, * Split stream-ciphered record into data and MAC portions * * @v tls TLS session - * @v plaintext Plaintext record - * @v plaintext_len Length of record - * @ret data Data - * @ret len Length of data - * @ret digest MAC digest + * @v rx_data List of received data buffers + * @v mac MAC to fill in * @ret rc Return status code */ static int tls_split_stream ( struct tls_session *tls, - void *plaintext, size_t plaintext_len, - void **data, size_t *len, void **digest ) { - void *content; - size_t content_len; - void *mac; - size_t mac_len; + struct list_head *rx_data, void **mac ) { + size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize; + struct io_buffer *iobuf; - /* Decompose stream-ciphered data */ - mac_len = tls->rx_cipherspec.suite->digest->digestsize; - if ( plaintext_len < mac_len ) { - DBGC ( tls, "TLS %p received underlength record\n", tls ); - DBGC_HD ( tls, plaintext, plaintext_len ); + /* Extract MAC */ + iobuf = list_last_entry ( rx_data, struct io_buffer, list ); + assert ( iobuf != NULL ); + if ( iob_len ( iobuf ) < mac_len ) { + DBGC ( tls, "TLS %p received underlength MAC\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); return -EINVAL_STREAM; } - content_len = ( plaintext_len - mac_len ); - content = plaintext; - mac = ( content + content_len ); - - /* Fill in return values */ - *data = content; - *len = content_len; - *digest = mac; + iob_unput ( iobuf, mac_len ); + *mac = iobuf->tail; return 0; } @@ -1983,65 +2061,56 @@ static int tls_split_stream ( struct tls_session *tls, * Split block-ciphered record into data and MAC portions * * @v tls TLS session - * @v plaintext Plaintext record - * @v plaintext_len Length of record - * @ret data Data - * @ret len Length of data - * @ret digest MAC digest + * @v rx_data List of received data buffers + * @v mac MAC to fill in * @ret rc Return status code */ static int tls_split_block ( struct tls_session *tls, - void *plaintext, size_t plaintext_len, - void **data, size_t *len, - void **digest ) { - void *iv; + struct list_head *rx_data, void **mac ) { + size_t mac_len = tls->rx_cipherspec.suite->digest->digestsize; + struct io_buffer *iobuf; size_t iv_len; - void *content; - size_t content_len; - void *mac; - size_t mac_len; - void *padding; + uint8_t *padding_final; + uint8_t *padding; size_t padding_len; - unsigned int i; - - /* Sanity check */ - if ( plaintext_len < 1 ) { - DBGC ( tls, "TLS %p received underlength record\n", tls ); - DBGC_HD ( tls, plaintext, plaintext_len ); - return -EINVAL_BLOCK; - } /* TLSv1.1 and later use an explicit IV */ + iobuf = list_first_entry ( rx_data, struct io_buffer, list ); iv_len = ( ( tls->version >= TLS_VERSION_TLS_1_1 ) ? tls->rx_cipherspec.suite->cipher->blocksize : 0 ); - - /* Decompose block-ciphered data */ - mac_len = tls->rx_cipherspec.suite->digest->digestsize; - padding_len = *( ( uint8_t * ) ( plaintext + plaintext_len - 1 ) ); - if ( plaintext_len < ( iv_len + mac_len + padding_len + 1 ) ) { - DBGC ( tls, "TLS %p received underlength record\n", tls ); - DBGC_HD ( tls, plaintext, plaintext_len ); + if ( iob_len ( iobuf ) < iv_len ) { + DBGC ( tls, "TLS %p received underlength IV\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); return -EINVAL_BLOCK; } - content_len = ( plaintext_len - iv_len - mac_len - padding_len - 1 ); - iv = plaintext; - content = ( iv + iv_len ); - mac = ( content + content_len ); - padding = ( mac + mac_len ); + iob_pull ( iobuf, iv_len ); - /* Verify padding bytes */ - for ( i = 0 ; i < padding_len ; i++ ) { - if ( *( ( uint8_t * ) ( padding + i ) ) != padding_len ) { + /* Extract and verify padding */ + iobuf = list_last_entry ( rx_data, struct io_buffer, list ); + padding_final = ( iobuf->tail - 1 ); + padding_len = *padding_final; + if ( ( padding_len + 1 ) > iob_len ( iobuf ) ) { + DBGC ( tls, "TLS %p received underlength padding\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + return -EINVAL_BLOCK; + } + iob_unput ( iobuf, ( padding_len + 1 ) ); + for ( padding = iobuf->tail ; padding < padding_final ; padding++ ) { + if ( *padding != padding_len ) { DBGC ( tls, "TLS %p received bad padding\n", tls ); - DBGC_HD ( tls, plaintext, plaintext_len ); + DBGC_HD ( tls, padding, padding_len ); return -EINVAL_PADDING; } } - /* Fill in return values */ - *data = content; - *len = content_len; - *digest = mac; + /* Extract MAC */ + if ( iob_len ( iobuf ) < mac_len ) { + DBGC ( tls, "TLS %p received underlength MAC\n", tls ); + DBGC_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + return -EINVAL_BLOCK; + } + iob_unput ( iobuf, mac_len ); + *mac = iobuf->tail; return 0; } @@ -2051,71 +2120,65 @@ static int tls_split_block ( struct tls_session *tls, * * @v tls TLS session * @v tlshdr Record header - * @v ciphertext Ciphertext record + * @v rx_data List of received data buffers * @ret rc Return status code */ static int tls_new_ciphertext ( struct tls_session *tls, struct tls_header *tlshdr, - const void *ciphertext ) { + struct list_head *rx_data ) { struct tls_header plaintext_tlshdr; struct tls_cipherspec *cipherspec = &tls->rx_cipherspec; struct cipher_algorithm *cipher = cipherspec->suite->cipher; - size_t record_len = ntohs ( tlshdr->length ); - void *plaintext = NULL; - void *data; - size_t len; + struct digest_algorithm *digest = cipherspec->suite->digest; + uint8_t ctx[digest->ctxsize]; + uint8_t verify_mac[digest->digestsize]; + struct io_buffer *iobuf; void *mac; - size_t mac_len = cipherspec->suite->digest->digestsize; - uint8_t verify_mac[mac_len]; + size_t len = 0; int rc; - /* Allocate buffer for plaintext */ - plaintext = malloc ( record_len ); - if ( ! plaintext ) { - DBGC ( tls, "TLS %p could not allocate %zd bytes for " - "decryption buffer\n", tls, record_len ); - rc = -ENOMEM_RX_PLAINTEXT; - goto done; + /* Decrypt the received data */ + list_for_each_entry ( iobuf, &tls->rx_data, list ) { + cipher_decrypt ( cipher, cipherspec->cipher_ctx, + iobuf->data, iobuf->data, iob_len ( iobuf ) ); } - /* Decrypt the record */ - cipher_decrypt ( cipher, cipherspec->cipher_ctx, - ciphertext, plaintext, record_len ); - /* Split record into content and MAC */ if ( is_stream_cipher ( cipher ) ) { - if ( ( rc = tls_split_stream ( tls, plaintext, record_len, - &data, &len, &mac ) ) != 0 ) - goto done; + if ( ( rc = tls_split_stream ( tls, rx_data, &mac ) ) != 0 ) + return rc; } else { - if ( ( rc = tls_split_block ( tls, plaintext, record_len, - &data, &len, &mac ) ) != 0 ) - goto done; + if ( ( rc = tls_split_block ( tls, rx_data, &mac ) ) != 0 ) + return rc; + } + + /* Calculate total length */ + DBGC2 ( tls, "Received plaintext data:\n" ); + list_for_each_entry ( iobuf, rx_data, list ) { + DBGC2_HD ( tls, iobuf->data, iob_len ( iobuf ) ); + len += iob_len ( iobuf ); } /* Verify MAC */ plaintext_tlshdr.type = tlshdr->type; plaintext_tlshdr.version = tlshdr->version; plaintext_tlshdr.length = htons ( len ); - tls_hmac ( tls, cipherspec, tls->rx_seq, &plaintext_tlshdr, - data, len, verify_mac); - if ( memcmp ( mac, verify_mac, mac_len ) != 0 ) { + tls_hmac_init ( cipherspec, ctx, tls->rx_seq, &plaintext_tlshdr ); + list_for_each_entry ( iobuf, rx_data, list ) { + tls_hmac_update ( cipherspec, ctx, iobuf->data, + iob_len ( iobuf ) ); + } + tls_hmac_final ( cipherspec, ctx, verify_mac ); + if ( memcmp ( mac, verify_mac, sizeof ( verify_mac ) ) != 0 ) { DBGC ( tls, "TLS %p failed MAC verification\n", tls ); - DBGC_HD ( tls, plaintext, record_len ); - goto done; + return -EINVAL_MAC; } - DBGC2 ( tls, "Received plaintext data:\n" ); - DBGC2_HD ( tls, data, len ); - /* Process plaintext record */ - if ( ( rc = tls_new_record ( tls, tlshdr->type, data, len ) ) != 0 ) - goto done; + if ( ( rc = tls_new_record ( tls, tlshdr->type, rx_data ) ) != 0 ) + return rc; - rc = 0; - done: - free ( plaintext ); - return rc; + return 0; } /****************************************************************************** @@ -2195,20 +2258,61 @@ static struct interface_descriptor tls_plainstream_desc = */ static int tls_newdata_process_header ( struct tls_session *tls ) { size_t data_len = ntohs ( tls->rx_header.length ); + size_t remaining = data_len; + size_t frag_len; + struct io_buffer *iobuf; + struct io_buffer *tmp; + int rc; - /* Allocate data buffer now that we know the length */ - assert ( tls->rx_data == NULL ); - tls->rx_data = malloc ( data_len ); - if ( ! tls->rx_data ) { - DBGC ( tls, "TLS %p could not allocate %zd bytes " - "for receive buffer\n", tls, data_len ); - return -ENOMEM_RX_DATA; + /* Allocate data buffers now that we know the length */ + assert ( list_empty ( &tls->rx_data ) ); + while ( remaining ) { + + /* Calculate fragment length. Ensure that no block is + * smaller than TLS_RX_MIN_BUFSIZE (by increasing the + * allocation length if necessary). + */ + frag_len = remaining; + if ( frag_len > TLS_RX_BUFSIZE ) + frag_len = TLS_RX_BUFSIZE; + remaining -= frag_len; + if ( remaining < TLS_RX_MIN_BUFSIZE ) { + frag_len += remaining; + remaining = 0; + } + + /* Allocate buffer */ + iobuf = alloc_iob_raw ( frag_len, TLS_RX_ALIGN, 0 ); + if ( ! iobuf ) { + DBGC ( tls, "TLS %p could not allocate %zd of %zd " + "bytes for receive buffer\n", tls, + remaining, data_len ); + rc = -ENOMEM_RX_DATA; + goto err; + } + + /* Ensure tailroom is exactly what we asked for. This + * will result in unaligned I/O buffers when the + * fragment length is unaligned, which can happen only + * before we switch to using a block cipher. + */ + iob_reserve ( iobuf, ( iob_tailroom ( iobuf ) - frag_len ) ); + + /* Add I/O buffer to list */ + list_add_tail ( &iobuf->list, &tls->rx_data ); } /* Move to data state */ tls->rx_state = TLS_RX_DATA; return 0; + + err: + list_for_each_entry_safe ( iobuf, tmp, &tls->rx_data, list ) { + list_del ( &iobuf->list ); + free_iob ( iobuf ); + } + return rc; } /** @@ -2218,22 +2322,31 @@ static int tls_newdata_process_header ( struct tls_session *tls ) { * @ret rc Returned status code */ static int tls_newdata_process_data ( struct tls_session *tls ) { + struct io_buffer *iobuf; int rc; + /* Move current buffer to end of list */ + iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list ); + list_del ( &iobuf->list ); + list_add_tail ( &iobuf->list, &tls->rx_data ); + + /* Continue receiving data if any space remains */ + iobuf = list_first_entry ( &tls->rx_data, struct io_buffer, list ); + if ( iob_tailroom ( iobuf ) ) + return 0; + /* Process record */ if ( ( rc = tls_new_ciphertext ( tls, &tls->rx_header, - tls->rx_data ) ) != 0 ) + &tls->rx_data ) ) != 0 ) return rc; /* Increment RX sequence number */ tls->rx_seq += 1; - /* Free data buffer */ - free ( tls->rx_data ); - tls->rx_data = NULL; - /* Return to header state */ + assert ( list_empty ( &tls->rx_data ) ); tls->rx_state = TLS_RX_HEADER; + iob_unput ( &tls->rx_header_iobuf, sizeof ( tls->rx_header ) ); return 0; } @@ -2250,22 +2363,22 @@ static int tls_cipherstream_deliver ( struct tls_session *tls, struct io_buffer *iobuf, struct xfer_metadata *xfer __unused ) { size_t frag_len; - void *buf; - size_t buf_len; int ( * process ) ( struct tls_session *tls ); + struct io_buffer *dest; int rc; while ( iob_len ( iobuf ) ) { + /* Select buffer according to current state */ switch ( tls->rx_state ) { case TLS_RX_HEADER: - buf = &tls->rx_header; - buf_len = sizeof ( tls->rx_header ); + dest = &tls->rx_header_iobuf; process = tls_newdata_process_header; break; case TLS_RX_DATA: - buf = tls->rx_data; - buf_len = ntohs ( tls->rx_header.length ); + dest = list_first_entry ( &tls->rx_data, + struct io_buffer, list ); + assert ( dest != NULL ); process = tls_newdata_process_data; break; default: @@ -2275,20 +2388,18 @@ static int tls_cipherstream_deliver ( struct tls_session *tls, } /* Copy data portion to buffer */ - frag_len = ( buf_len - tls->rx_rcvd ); - if ( frag_len > iob_len ( iobuf ) ) - frag_len = iob_len ( iobuf ); - memcpy ( ( buf + tls->rx_rcvd ), iobuf->data, frag_len ); - tls->rx_rcvd += frag_len; + frag_len = iob_len ( iobuf ); + if ( frag_len > iob_tailroom ( dest ) ) + frag_len = iob_tailroom ( dest ); + memcpy ( iob_put ( dest, frag_len ), iobuf->data, frag_len ); iob_pull ( iobuf, frag_len ); /* Process data if buffer is now full */ - if ( tls->rx_rcvd == buf_len ) { + if ( iob_tailroom ( dest ) == 0 ) { if ( ( rc = process ( tls ) ) != 0 ) { tls_close ( tls, rc ); goto done; } - tls->rx_rcvd = 0; } } rc = 0; @@ -2521,6 +2632,9 @@ int add_tls ( struct interface *xfer, const char *name, tls->handshake_digest = &sha256_algorithm; tls->handshake_ctx = tls->handshake_sha256_ctx; tls->tx_pending = TLS_TX_CLIENT_HELLO; + iob_populate ( &tls->rx_header_iobuf, &tls->rx_header, 0, + sizeof ( tls->rx_header ) ); + INIT_LIST_HEAD ( &tls->rx_data ); /* Add pending operations for server and client Finished messages */ pending_get ( &tls->client_negotiation ); From 1e199c82601a9182752017a5fd36d297ed0dc6e2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 28 Sep 2012 10:52:17 +0100 Subject: [PATCH 157/250] [tls] Fix uninitialised variable Reported-by: Christian Hesse Signed-off-by: Michael Brown --- src/net/tls.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net/tls.c b/src/net/tls.c index 45b7e525..52a83393 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -1773,8 +1773,7 @@ static int tls_new_record ( struct tls_session *tls, unsigned int type, } /* Handle record and free I/O buffer */ - if ( handler ) - rc = handler ( tls, iobuf->data, iob_len ( iobuf ) ); + rc = ( handler ? handler ( tls, iobuf->data, iob_len ( iobuf ) ) : 0 ); free_iob ( iobuf ); return rc; } From d23db2848813a9d872e1d71272e7f41df7d0d01c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 28 Sep 2012 10:54:07 +0100 Subject: [PATCH 158/250] [tls] Fix potential memory leak Signed-off-by: Michael Brown --- src/net/tls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/net/tls.c b/src/net/tls.c index 52a83393..4ad131c8 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -1749,6 +1749,7 @@ static int tls_new_record ( struct tls_session *tls, unsigned int type, list_del ( &iobuf->list ); if ( ! list_empty ( rx_data ) ) { DBGC ( tls, "TLS %p overlength non-data record\n", tls ); + free_iob ( iobuf ); return -EINVAL_NON_DATA; } From dcbbf54eb2fd6e06d47c43013c696dc36d6ece52 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 5 Oct 2012 13:23:05 +0100 Subject: [PATCH 159/250] [contrib] Allow more space for Bochs option ROM Signed-off-by: Michael Brown --- contrib/vm/bochsrc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/vm/bochsrc.txt b/contrib/vm/bochsrc.txt index 22ba40fb..4c4acbae 100644 --- a/contrib/vm/bochsrc.txt +++ b/contrib/vm/bochsrc.txt @@ -341,7 +341,7 @@ memory: guest=512, host=256 #optromimage2: file=optionalrom.bin, address=0xd1000 #optromimage3: file=optionalrom.bin, address=0xd2000 #optromimage4: file=optionalrom.bin, address=0xd3000 -optromimage1: file=../../src/bin/intel.rom, address=0xd0000 +optromimage1: file=../../src/bin/intel.rom, address=0xcb000 #optramimage1: file=/path/file1.img, address=0x0010000 #optramimage2: file=/path/file2.img, address=0x0020000 From 40044f9d43afb1714e74142f7f55bc774f24345c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 5 Oct 2012 13:23:34 +0100 Subject: [PATCH 160/250] [contrib] Enable bochs debug port by default Signed-off-by: Michael Brown --- contrib/vm/bochsrc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/vm/bochsrc.txt b/contrib/vm/bochsrc.txt index 4c4acbae..d0f12504 100644 --- a/contrib/vm/bochsrc.txt +++ b/contrib/vm/bochsrc.txt @@ -1066,7 +1066,7 @@ magic_break: enabled=1 # Example: # port_e9_hack: enabled=1 #======================================================================= -#port_e9_hack: enabled=1 +port_e9_hack: enabled=1 #======================================================================= # DEBUG_SYMBOLS: From bab0a4c1ce5dc0485c35dcda9338dc92c1802121 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 18 Jul 2012 00:34:04 +0100 Subject: [PATCH 161/250] [efi] Mark SNP formset compliant with IBM's Unified Configuration Manager Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi_hii.h | 5 +++++ src/interface/efi/efi_snp.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/include/ipxe/efi/efi_hii.h b/src/include/ipxe/efi/efi_hii.h index 1a98750f..f95a75f6 100644 --- a/src/include/ipxe/efi/efi_hii.h +++ b/src/include/ipxe/efi/efi_hii.h @@ -137,4 +137,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); }, \ } +/** GUID indicating formset compliance for IBM Unified Configuration Manager */ +#define EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID \ + { 0x5c8e9746, 0xa5f7, 0x4593, \ + { 0xaf, 0x1f, 0x66, 0xa8, 0x2a, 0xa1, 0x9c, 0xb1 } } + #endif /* _IPXE_EFI_HII_H */ diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index b4ae5113..48645dc0 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -805,7 +805,7 @@ enum efi_snp_hii_string_id { /** EFI SNP formset */ struct efi_snp_formset { EFI_HII_PACKAGE_HEADER Header; - EFI_IFR_FORM_SET_TYPE(1) FormSet; + EFI_IFR_FORM_SET_TYPE(2) FormSet; EFI_IFR_GUID_CLASS Class; EFI_IFR_GUID_SUBCLASS SubClass; EFI_IFR_FORM Form; @@ -824,7 +824,8 @@ struct efi_snp_formset { EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP, typeof ( efi_snp_formset.FormSet ), - EFI_HII_PLATFORM_SETUP_FORMSET_GUID ), + EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID ), .Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ), .SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ), .Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ), From fcdfe817644c601f40a5435c03f16a46b5264ab1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 5 Oct 2012 15:02:30 +0100 Subject: [PATCH 162/250] [int13] Do not zero %edx when jumping to a boot sector Commit 73eb3f1 ("[int13] Zero all possible registers when jumping to a boot sector") introduced a regression preventing the SAN-booting of boot sectors which rely upon %dl containing the correct drive number (such as most CD-ROM boot sectors). Fix by not zeroing %edx. Signed-off-by: Michael Brown --- src/arch/i386/image/bootsector.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/i386/image/bootsector.c b/src/arch/i386/image/bootsector.c index faf21c6f..ab3cf94c 100644 --- a/src/arch/i386/image/bootsector.c +++ b/src/arch/i386/image/bootsector.c @@ -87,7 +87,7 @@ int call_bootsector ( unsigned int segment, unsigned int offset, "xorl %%eax, %%eax\n\t" "xorl %%ebx, %%ebx\n\t" "xorl %%ecx, %%ecx\n\t" - "xorl %%edx, %%edx\n\t" + /* %edx contains drive number */ "xorl %%esi, %%esi\n\t" "xorl %%edi, %%edi\n\t" "xorl %%ebp, %%ebp\n\t" From a712dae709adc76c76646fa1c86d2cfb5c3edfbc Mon Sep 17 00:00:00 2001 From: Shao Miller Date: Fri, 5 Oct 2012 15:14:12 +0100 Subject: [PATCH 163/250] [serial] Don't enable serial console without serial support serial_console_init() would enable serial console support without knowing if the serial driver succeeded or not. As a result, the serial console would interfere with a normal keyboard on a system lacking serial support. Reported-by: Jan ONDREJ (SAL) Signed-off-by: Shao Miller Signed-off-by: Michael Brown --- src/core/serial.c | 7 ++++++- src/core/serial_console.c | 9 ++++++--- src/include/ipxe/serial.h | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/core/serial.c b/src/core/serial.c index a5551b13..8f5a159c 100644 --- a/src/core/serial.c +++ b/src/core/serial.c @@ -93,6 +93,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define uart_writeb(val,addr) outb((val),(addr)) #endif +/* Boolean for the state of serial driver initialization */ +int serial_initialized = 0; + /* * void serial_putc(int ch); * Write character `ch' to port UART_BASE. @@ -207,7 +210,6 @@ static void serial_init ( void ) { /* Set clear to send, so flow control works... */ uart_writeb((1<<1), UART_BASE + UART_MCR); - /* Flush the input buffer. */ do { /* rx buffer reg @@ -217,6 +219,9 @@ static void serial_init ( void ) { /* line status reg */ status = uart_readb(UART_BASE + UART_LSR); } while(status & UART_LSR_DR); + + /* Note that serial support has been initialized */ + serial_initialized = 1; out: return; } diff --git a/src/core/serial_console.c b/src/core/serial_console.c index bbddd6b2..3852a308 100644 --- a/src/core/serial_console.c +++ b/src/core/serial_console.c @@ -18,9 +18,12 @@ struct console_driver serial_console __console_driver; static void serial_console_init ( void ) { - /* Serial driver initialization should already be done, - * time to enable the serial console. */ - serial_console.disabled = 0; + /* + * Check if serial driver initialization is done. + * If so, it's time to enable the serial console. + */ + if ( serial_initialized ) + serial_console.disabled = 0; } struct console_driver serial_console __console_driver = { diff --git a/src/include/ipxe/serial.h b/src/include/ipxe/serial.h index c16e56ae..b47b1d12 100644 --- a/src/include/ipxe/serial.h +++ b/src/include/ipxe/serial.h @@ -12,5 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); extern void serial_putc ( int ch ); extern int serial_getc ( void ); extern int serial_ischar ( void ); +extern int serial_initialized; #endif /* _IPXE_SERIAL_H */ From 51b65d5f9c5d9f02a11810ac068b781b84c65143 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 15 Oct 2012 00:36:48 +0100 Subject: [PATCH 164/250] [libc] Add wcslen() function Signed-off-by: Michael Brown --- src/core/wchar.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/include/wchar.h | 2 ++ 2 files changed, 45 insertions(+) create mode 100644 src/core/wchar.c diff --git a/src/core/wchar.c b/src/core/wchar.c new file mode 100644 index 00000000..7fabca47 --- /dev/null +++ b/src/core/wchar.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @file + * + * Wide-character strings + * + */ + +#include + +/** + * Calculate length of wide-character string + * + * @v string String + * @ret len Length (excluding terminating NUL) + */ +size_t wcslen ( const wchar_t *string ) { + size_t len = 0; + + while ( *(string++) ) + len++; + return len; +} diff --git a/src/include/wchar.h b/src/include/wchar.h index 84312c70..ba349aae 100644 --- a/src/include/wchar.h +++ b/src/include/wchar.h @@ -24,4 +24,6 @@ size_t wcrtomb ( char *buf, wchar_t wc, mbstate_t *ps __unused ) { return 1; } +extern size_t wcslen ( const wchar_t *string ); + #endif /* WCHAR_H */ From 1c2b6d29ea0eae83da627aca560f5e4a5d521fe4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 15 Oct 2012 03:08:12 +0100 Subject: [PATCH 165/250] [settings] Expose find_child_settings() Signed-off-by: Michael Brown --- src/core/settings.c | 4 ++-- src/include/ipxe/settings.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 20b7f949..9b5bc054 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -265,8 +265,8 @@ static void autovivified_settings_free ( struct refcnt *refcnt ) { * @v name Name within this parent * @ret settings Settings block, or NULL */ -static struct settings * find_child_settings ( struct settings *parent, - const char *name ) { +struct settings * find_child_settings ( struct settings *parent, + const char *name ) { struct settings *settings; /* Treat empty name as meaning "this block" */ diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index a81e5ccf..68987bdd 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -269,6 +269,8 @@ extern int fetch_uuid_setting ( struct settings *settings, extern void clear_settings ( struct settings *settings ); extern int setting_cmp ( struct setting *a, struct setting *b ); +extern struct settings * find_child_settings ( struct settings *parent, + const char *name ); extern const char * settings_name ( struct settings *settings ); extern struct settings * find_settings ( const char *name ); extern struct setting * find_setting ( const char *name ); From 5ad445fd0b955f74d45ec3af1822248572c2dd3b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 15 Oct 2012 12:41:04 +0100 Subject: [PATCH 166/250] [settings] Treat an empty formatted value as meaning "delete setting" Signed-off-by: Michael Brown --- src/core/settings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 9b5bc054..1b19c8f6 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -1052,8 +1052,8 @@ int storef_setting ( struct settings *settings, struct setting *setting, int check_len; int rc; - /* NULL value implies deletion */ - if ( ! value ) + /* NULL value or empty string implies deletion */ + if ( ( ! value ) || ( ! value[0] ) ) return delete_setting ( settings, setting ); /* Parse formatted value */ From 08a6ae86a2ddafe51fa64e8f40a4c89cd613ecfb Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 15 Oct 2012 03:08:41 +0100 Subject: [PATCH 167/250] [nvo] Expose non-volatile options block name Signed-off-by: Michael Brown --- src/core/nvo.c | 3 ++- src/include/ipxe/nvo.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/nvo.c b/src/core/nvo.c index ffa30b89..11074e67 100644 --- a/src/core/nvo.c +++ b/src/core/nvo.c @@ -296,7 +296,8 @@ int register_nvo ( struct nvo_block *nvo, struct settings *parent ) { goto err_load; /* Register settings */ - if ( ( rc = register_settings ( &nvo->settings, parent, "nvo" ) ) != 0 ) + if ( ( rc = register_settings ( &nvo->settings, parent, + NVO_SETTINGS_NAME ) ) != 0 ) goto err_register; DBGC ( nvo, "NVO %p registered\n", nvo ); diff --git a/src/include/ipxe/nvo.h b/src/include/ipxe/nvo.h index 995afd74..36f41505 100644 --- a/src/include/ipxe/nvo.h +++ b/src/include/ipxe/nvo.h @@ -42,6 +42,9 @@ struct nvo_block { struct dhcp_options dhcpopts; }; +/** Name of non-volatile options settings block */ +#define NVO_SETTINGS_NAME "nvo" + extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs, size_t address, size_t len, int ( * resize ) ( struct nvo_block *nvo, size_t len ), From 0fd29e15b51b439f8b0714cbc20e114a9ae7e91a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 15 Oct 2012 12:41:51 +0100 Subject: [PATCH 168/250] [nvo] Expose nvo_applies() Signed-off-by: Michael Brown --- src/core/nvo.c | 4 ++-- src/include/ipxe/nvo.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/nvo.c b/src/core/nvo.c index 11074e67..5383fe5c 100644 --- a/src/core/nvo.c +++ b/src/core/nvo.c @@ -192,8 +192,8 @@ static int nvo_save ( struct nvo_block *nvo ) { * @v setting Setting * @ret applies Setting applies within this settings block */ -static int nvo_applies ( struct settings *settings __unused, - struct setting *setting ) { +int nvo_applies ( struct settings *settings __unused, + struct setting *setting ) { return dhcpopt_applies ( setting->tag ); } diff --git a/src/include/ipxe/nvo.h b/src/include/ipxe/nvo.h index 36f41505..487f8b3f 100644 --- a/src/include/ipxe/nvo.h +++ b/src/include/ipxe/nvo.h @@ -45,6 +45,7 @@ struct nvo_block { /** Name of non-volatile options settings block */ #define NVO_SETTINGS_NAME "nvo" +extern int nvo_applies ( struct settings *settings, struct setting *setting ); extern void nvo_init ( struct nvo_block *nvo, struct nvs_device *nvs, size_t address, size_t len, int ( * resize ) ( struct nvo_block *nvo, size_t len ), From 41ea18a45500bde018edbb01ebcd5c8059adcf2e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 18 Jul 2012 18:14:04 +0100 Subject: [PATCH 169/250] [efi] Split SNP HII functionality into a separate file Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi_snp.h | 68 +++++ src/include/ipxe/errfile.h | 1 + src/interface/efi/efi_snp.c | 427 +------------------------------ src/interface/efi/efi_snp_hii.c | 430 ++++++++++++++++++++++++++++++++ 4 files changed, 508 insertions(+), 418 deletions(-) create mode 100644 src/include/ipxe/efi/efi_snp.h create mode 100644 src/interface/efi/efi_snp_hii.c diff --git a/src/include/ipxe/efi/efi_snp.h b/src/include/ipxe/efi/efi_snp.h new file mode 100644 index 00000000..81564921 --- /dev/null +++ b/src/include/ipxe/efi/efi_snp.h @@ -0,0 +1,68 @@ +#ifndef _IPXE_EFI_SNP_H +#define _IPXE_EFI_SNP_H + +/** @file + * + * iPXE EFI SNP interface + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** An SNP device */ +struct efi_snp_device { + /** List of SNP devices */ + struct list_head list; + /** The underlying iPXE network device */ + struct net_device *netdev; + /** The underlying EFI PCI device */ + struct efi_pci_device *efipci; + /** EFI device handle */ + EFI_HANDLE handle; + /** The SNP structure itself */ + EFI_SIMPLE_NETWORK_PROTOCOL snp; + /** The SNP "mode" (parameters) */ + EFI_SIMPLE_NETWORK_MODE mode; + /** Outstanding TX packet count (via "interrupt status") + * + * Used in order to generate TX completions. + */ + unsigned int tx_count_interrupts; + /** Outstanding TX packet count (via "recycled tx buffers") + * + * Used in order to generate TX completions. + */ + unsigned int tx_count_txbufs; + /** Outstanding RX packet count (via "interrupt status") */ + unsigned int rx_count_interrupts; + /** Outstanding RX packet count (via WaitForPacket event) */ + unsigned int rx_count_events; + /** The network interface identifier */ + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii; + /** HII configuration access protocol */ + EFI_HII_CONFIG_ACCESS_PROTOCOL hii; + /** HII package list */ + EFI_HII_PACKAGE_LIST_HEADER *package_list; + /** HII handle */ + EFI_HII_HANDLE hii_handle; + /** Device name */ + wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ]; + /** The device path + * + * This field is variable in size and must appear at the end + * of the structure. + */ + EFI_DEVICE_PATH_PROTOCOL path; +}; + +extern int efi_snp_hii_install ( struct efi_snp_device *snpdev ); +extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ); + +#endif /* _IPXE_EFI_SNP_H */ diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index 8edf5ccb..dd63225d 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -263,6 +263,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_validator ( ERRFILE_OTHER | 0x002e0000 ) #define ERRFILE_ocsp ( ERRFILE_OTHER | 0x002f0000 ) #define ERRFILE_nslookup ( ERRFILE_OTHER | 0x00300000 ) +#define ERRFILE_efi_snp_hii ( ERRFILE_OTHER | 0x00310000 ) /** @} */ diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 48645dc0..84d522b9 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -32,65 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include -#include -#include -#include -#include -#include -#include - -/** @file - * - * iPXE EFI SNP interface - * - */ - -/** An SNP device */ -struct efi_snp_device { - /** List of SNP devices */ - struct list_head list; - /** The underlying iPXE network device */ - struct net_device *netdev; - /** The underlying EFI PCI device */ - struct efi_pci_device *efipci; - /** EFI device handle */ - EFI_HANDLE handle; - /** The SNP structure itself */ - EFI_SIMPLE_NETWORK_PROTOCOL snp; - /** The SNP "mode" (parameters) */ - EFI_SIMPLE_NETWORK_MODE mode; - /** Outstanding TX packet count (via "interrupt status") - * - * Used in order to generate TX completions. - */ - unsigned int tx_count_interrupts; - /** Outstanding TX packet count (via "recycled tx buffers") - * - * Used in order to generate TX completions. - */ - unsigned int tx_count_txbufs; - /** Outstanding RX packet count (via "interrupt status") */ - unsigned int rx_count_interrupts; - /** Outstanding RX packet count (via WaitForPacket event) */ - unsigned int rx_count_events; - /** The network interface identifier */ - EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii; - /** HII configuration access protocol */ - EFI_HII_CONFIG_ACCESS_PROTOCOL hii; - /** HII package list */ - EFI_HII_PACKAGE_LIST_HEADER *package_list; - /** HII handle */ - EFI_HII_HANDLE hii_handle; - /** Device name */ - wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ]; - /** The device path - * - * This field is variable in size and must appear at the end - * of the structure. - */ - EFI_DEVICE_PATH_PROTOCOL path; -}; +#include /** EFI simple network protocol GUID */ static EFI_GUID efi_simple_network_protocol_guid @@ -759,336 +701,6 @@ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = { .Receive = efi_snp_receive, }; -/****************************************************************************** - * - * Human Interface Infrastructure - * - ****************************************************************************** - */ - -/** EFI configuration access protocol GUID */ -static EFI_GUID efi_hii_config_access_protocol_guid - = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; - -/** EFI HII database protocol */ -static EFI_HII_DATABASE_PROTOCOL *efihii; -EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii ); - -/** Local base GUID used for our EFI SNP formset */ -#define EFI_SNP_FORMSET_GUID_BASE \ - { 0xc4f84019, 0x6dfd, 0x4a27, \ - { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } } - -/** Form identifiers used for our EFI SNP HII */ -enum efi_snp_hii_form_id { - EFI_SNP_FORM = 0x0001, /**< The only form */ -}; - -/** String identifiers used for our EFI SNP HII */ -enum efi_snp_hii_string_id { - /* Language name */ - EFI_SNP_LANGUAGE_NAME = 0x0001, - /* Formset */ - EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP, - /* Product name */ - EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT, - /* Version */ - EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT, - /* Driver */ - EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT, - /* Device */ - EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT, - /* End of list */ - EFI_SNP_MAX_STRING_ID -}; - -/** EFI SNP formset */ -struct efi_snp_formset { - EFI_HII_PACKAGE_HEADER Header; - EFI_IFR_FORM_SET_TYPE(2) FormSet; - EFI_IFR_GUID_CLASS Class; - EFI_IFR_GUID_SUBCLASS SubClass; - EFI_IFR_FORM Form; - EFI_IFR_TEXT ProductText; - EFI_IFR_TEXT VersionText; - EFI_IFR_TEXT DriverText; - EFI_IFR_TEXT DeviceText; - EFI_IFR_END EndForm; - EFI_IFR_END EndFormSet; -} __attribute__ (( packed )) efi_snp_formset = { - .Header = { - .Length = sizeof ( efi_snp_formset ), - .Type = EFI_HII_PACKAGE_FORMS, - }, - .FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE, - EFI_SNP_FORMSET_TITLE, - EFI_SNP_FORMSET_HELP, - typeof ( efi_snp_formset.FormSet ), - EFI_HII_PLATFORM_SETUP_FORMSET_GUID, - EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID ), - .Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ), - .SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ), - .Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ), - .ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT, - EFI_SNP_PRODUCT_HELP, - EFI_SNP_PRODUCT_TEXT ), - .VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT, - EFI_SNP_VERSION_HELP, - EFI_SNP_VERSION_TEXT ), - .DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT, - EFI_SNP_DRIVER_HELP, - EFI_SNP_DRIVER_TEXT ), - .DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT, - EFI_SNP_DEVICE_HELP, - EFI_SNP_DEVICE_TEXT ), - .EndForm = EFI_IFR_END(), - .EndFormSet = EFI_IFR_END(), -}; - -/** - * Generate EFI SNP string - * - * @v wbuf Buffer - * @v swlen Size of buffer (in wide characters) - * @v snpdev SNP device - * @ret wlen Length of string (in wide characters) - */ -static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen, - enum efi_snp_hii_string_id id, - struct efi_snp_device *snpdev ) { - struct net_device *netdev = snpdev->netdev; - struct device *dev = netdev->dev; - - switch ( id ) { - case EFI_SNP_LANGUAGE_NAME: - return efi_ssnprintf ( wbuf, swlen, "English" ); - case EFI_SNP_FORMSET_TITLE: - return efi_ssnprintf ( wbuf, swlen, "%s (%s)", - ( PRODUCT_NAME[0] ? - PRODUCT_NAME : PRODUCT_SHORT_NAME ), - netdev_addr ( netdev ) ); - case EFI_SNP_FORMSET_HELP: - return efi_ssnprintf ( wbuf, swlen, - "Configure " PRODUCT_SHORT_NAME ); - case EFI_SNP_PRODUCT_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Name" ); - case EFI_SNP_PRODUCT_HELP: - return efi_ssnprintf ( wbuf, swlen, "Firmware product name" ); - case EFI_SNP_PRODUCT_TEXT: - return efi_ssnprintf ( wbuf, swlen, "%s", - ( PRODUCT_NAME[0] ? - PRODUCT_NAME : PRODUCT_SHORT_NAME ) ); - case EFI_SNP_VERSION_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Version" ); - case EFI_SNP_VERSION_HELP: - return efi_ssnprintf ( wbuf, swlen, "Firmware version" ); - case EFI_SNP_VERSION_TEXT: - return efi_ssnprintf ( wbuf, swlen, VERSION ); - case EFI_SNP_DRIVER_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Driver" ); - case EFI_SNP_DRIVER_HELP: - return efi_ssnprintf ( wbuf, swlen, "Firmware driver" ); - case EFI_SNP_DRIVER_TEXT: - return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name ); - case EFI_SNP_DEVICE_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Device" ); - case EFI_SNP_DEVICE_HELP: - return efi_ssnprintf ( wbuf, swlen, "Hardware device" ); - case EFI_SNP_DEVICE_TEXT: - return efi_ssnprintf ( wbuf, swlen, "%s", dev->name ); - default: - assert ( 0 ); - return 0; - } -} - -/** - * Generate EFI SNP string package - * - * @v strings String package header buffer - * @v max_len Buffer length - * @v snpdev SNP device - * @ret len Length of string package - */ -static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings, - size_t max_len, struct efi_snp_device *snpdev ) { - static const char language[] = "en-us"; - void *buf = strings; - ssize_t remaining = max_len; - size_t hdrsize; - EFI_HII_SIBT_STRING_UCS2_BLOCK *string; - ssize_t wremaining; - size_t string_wlen; - unsigned int id; - EFI_HII_STRING_BLOCK *end; - size_t len; - - /* Calculate header size */ - hdrsize = ( offsetof ( typeof ( *strings ), Language ) + - sizeof ( language ) ); - buf += hdrsize; - remaining -= hdrsize; - - /* Fill in strings */ - for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) { - string = buf; - if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) ) - string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; - buf += offsetof ( typeof ( *string ), StringText ); - remaining -= offsetof ( typeof ( *string ), StringText ); - wremaining = ( remaining / - ( ( ssize_t ) sizeof ( string->StringText[0] ))); - assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) ); - string_wlen = efi_snp_string ( string->StringText, wremaining, - id, snpdev ); - buf += ( ( string_wlen + 1 /* wNUL */ ) * - sizeof ( string->StringText[0] ) ); - remaining -= ( ( string_wlen + 1 /* wNUL */ ) * - sizeof ( string->StringText[0] ) ); - } - - /* Fill in end marker */ - end = buf; - if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) ) - end->BlockType = EFI_HII_SIBT_END; - buf += sizeof ( *end ); - remaining -= sizeof ( *end ); - - /* Calculate overall length */ - len = ( max_len - remaining ); - - /* Fill in string package header */ - if ( strings ) { - memset ( strings, 0, sizeof ( *strings ) ); - strings->Header.Length = len; - strings->Header.Type = EFI_HII_PACKAGE_STRINGS; - strings->HdrSize = hdrsize; - strings->StringInfoOffset = hdrsize; - strings->LanguageName = EFI_SNP_LANGUAGE_NAME; - memcpy ( strings->Language, language, sizeof ( language ) ); - } - - return len; -} - -/** - * Generate EFI SNP package list - * - * @v snpdev SNP device - * @ret package_list Package list, or NULL on error - * - * The package list is allocated using malloc(), and must eventually - * be freed by the caller. - */ -static EFI_HII_PACKAGE_LIST_HEADER * -efi_snp_package_list ( struct efi_snp_device *snpdev ) { - size_t strings_len = efi_snp_strings ( NULL, 0, snpdev ); - struct { - EFI_HII_PACKAGE_LIST_HEADER header; - struct efi_snp_formset formset; - union { - EFI_HII_STRING_PACKAGE_HDR strings; - uint8_t pad[strings_len]; - } __attribute__ (( packed )) strings; - EFI_HII_PACKAGE_HEADER end; - } __attribute__ (( packed )) *package_list; - - /* Allocate package list */ - package_list = zalloc ( sizeof ( *package_list ) ); - if ( ! package_list ) - return NULL; - - /* Create a unique GUID for this package list and formset */ - efi_snp_formset.FormSet.FormSet.Guid.Data1++; - - /* Populate package list */ - memcpy ( &package_list->header.PackageListGuid, - &efi_snp_formset.FormSet.FormSet.Guid, - sizeof ( package_list->header.PackageListGuid ) ); - package_list->header.PackageLength = sizeof ( *package_list ); - memcpy ( &package_list->formset, &efi_snp_formset, - sizeof ( package_list->formset ) ); - efi_snp_strings ( &package_list->strings.strings, - sizeof ( package_list->strings ), snpdev ); - package_list->end.Length = sizeof ( package_list->end ); - package_list->end.Type = EFI_HII_PACKAGE_END; - - return &package_list->header; -} - -/** - * Fetch configuration - * - * @v hii HII configuration access protocol - * @v request Configuration to fetch - * @ret progress Progress made through configuration to fetch - * @ret results Query results - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, - EFI_STRING request, EFI_STRING *progress, - EFI_STRING *results __unused ) { - struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); - - DBGC ( snpdev, "SNPDEV %p ExtractConfig\n", snpdev ); - - *progress = request; - return EFI_INVALID_PARAMETER; -} - -/** - * Store configuration - * - * @v hii HII configuration access protocol - * @v config Configuration to store - * @ret progress Progress made through configuration to store - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, - EFI_STRING config, EFI_STRING *progress ) { - struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); - - DBGC ( snpdev, "SNPDEV %p RouteConfig\n", snpdev ); - - *progress = config; - return EFI_INVALID_PARAMETER; -} - -/** - * Handle form actions - * - * @v hii HII configuration access protocol - * @v action Form browser action - * @v question_id Question ID - * @v type Type of value - * @v value Value - * @ret action_request Action requested by driver - * @ret efirc EFI status code - */ -static EFI_STATUS EFIAPI -efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, - EFI_BROWSER_ACTION action __unused, - EFI_QUESTION_ID question_id __unused, - UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused, - EFI_BROWSER_ACTION_REQUEST *action_request __unused ) { - struct efi_snp_device *snpdev = - container_of ( hii, struct efi_snp_device, hii ); - - DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev ); - return EFI_UNSUPPORTED; -} - -/** HII configuration access protocol */ -static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = { - .ExtractConfig = efi_snp_hii_extract_config, - .RouteConfig = efi_snp_hii_route_config, - .Callback = efi_snp_hii_callback, -}; - /****************************************************************************** * * iPXE network driver @@ -1182,9 +794,6 @@ static int efi_snp_probe ( struct net_device *netdev ) { strncpy ( snpdev->nii.StringId, "iPXE", sizeof ( snpdev->nii.StringId ) ); - /* Populate the HII configuration access structure */ - memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) ); - /* Populate the device name */ efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) / sizeof ( snpdev->name[0] ) ), @@ -1213,7 +822,6 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, - &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not install protocols: " "%s\n", snpdev, efi_strerror ( efirc ) ); @@ -1230,23 +838,11 @@ static int efi_snp_probe ( struct net_device *netdev ) { goto err_efipci_child_add; } - /* Create HII package list */ - snpdev->package_list = efi_snp_package_list ( snpdev ); - if ( ! snpdev->package_list ) { - DBGC ( snpdev, "SNPDEV %p could not create HII package list\n", - snpdev ); - rc = -ENOMEM; - goto err_create_hii; - } - - /* Add HII packages */ - if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list, - snpdev->handle, - &snpdev->hii_handle ) ) != 0 ) { - DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n", - snpdev, efi_strerror ( efirc ) ); - rc = EFIRC_TO_RC ( efirc ); - goto err_register_hii; + /* Install HII */ + if ( ( rc = efi_snp_hii_install ( snpdev ) ) != 0 ) { + DBGC ( snpdev, "SNPDEV %p could not install HII: %s\n", + snpdev, strerror ( rc ) ); + goto err_hii_install; } /* Add to list of SNP devices */ @@ -1256,10 +852,8 @@ static int efi_snp_probe ( struct net_device *netdev ) { snpdev, netdev->name, snpdev->handle ); return 0; - efihii->RemovePackageList ( efihii, snpdev->hii_handle ); - err_register_hii: - free ( snpdev->package_list ); - err_create_hii: + efi_snp_hii_uninstall ( snpdev ); + err_hii_install: efipci_child_del ( efipci, snpdev->handle ); err_efipci_child_add: bs->UninstallMultipleProtocolInterfaces ( @@ -1268,7 +862,6 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, - &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ); err_install_protocol_interface: bs->CloseEvent ( snpdev->snp.WaitForPacket ); @@ -1320,8 +913,7 @@ static void efi_snp_remove ( struct net_device *netdev ) { } /* Uninstall the SNP */ - efihii->RemovePackageList ( efihii, snpdev->hii_handle ); - free ( snpdev->package_list ); + efi_snp_hii_uninstall ( snpdev ); efipci_child_del ( snpdev->efipci, snpdev->handle ); list_del ( &snpdev->list ); bs->UninstallMultipleProtocolInterfaces ( @@ -1330,7 +922,6 @@ static void efi_snp_remove ( struct net_device *netdev ) { &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, - &efi_hii_config_access_protocol_guid, &snpdev->hii, NULL ); bs->CloseEvent ( snpdev->snp.WaitForPacket ); netdev_put ( snpdev->netdev ); diff --git a/src/interface/efi/efi_snp_hii.c b/src/interface/efi/efi_snp_hii.c new file mode 100644 index 00000000..c02233db --- /dev/null +++ b/src/interface/efi/efi_snp_hii.c @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** EFI configuration access protocol GUID */ +static EFI_GUID efi_hii_config_access_protocol_guid + = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; + +/** EFI HII database protocol */ +static EFI_HII_DATABASE_PROTOCOL *efihii; +EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii ); + +/** Local base GUID used for our EFI SNP formset */ +#define EFI_SNP_FORMSET_GUID_BASE \ + { 0xc4f84019, 0x6dfd, 0x4a27, \ + { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } } + +/** Form identifiers used for our EFI SNP HII */ +enum efi_snp_hii_form_id { + EFI_SNP_FORM = 0x0001, /**< The only form */ +}; + +/** String identifiers used for our EFI SNP HII */ +enum efi_snp_hii_string_id { + /* Language name */ + EFI_SNP_LANGUAGE_NAME = 0x0001, + /* Formset */ + EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP, + /* Product name */ + EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT, + /* Version */ + EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT, + /* Driver */ + EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT, + /* Device */ + EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT, + /* End of list */ + EFI_SNP_MAX_STRING_ID +}; + +/** EFI SNP formset */ +struct efi_snp_formset { + EFI_HII_PACKAGE_HEADER Header; + EFI_IFR_FORM_SET_TYPE(2) FormSet; + EFI_IFR_GUID_CLASS Class; + EFI_IFR_GUID_SUBCLASS SubClass; + EFI_IFR_FORM Form; + EFI_IFR_TEXT ProductText; + EFI_IFR_TEXT VersionText; + EFI_IFR_TEXT DriverText; + EFI_IFR_TEXT DeviceText; + EFI_IFR_END EndForm; + EFI_IFR_END EndFormSet; +} __attribute__ (( packed )) efi_snp_formset = { + .Header = { + .Length = sizeof ( efi_snp_formset ), + .Type = EFI_HII_PACKAGE_FORMS, + }, + .FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE, + EFI_SNP_FORMSET_TITLE, + EFI_SNP_FORMSET_HELP, + typeof ( efi_snp_formset.FormSet ), + EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID ), + .Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ), + .SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ), + .Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ), + .ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT, + EFI_SNP_PRODUCT_HELP, + EFI_SNP_PRODUCT_TEXT ), + .VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT, + EFI_SNP_VERSION_HELP, + EFI_SNP_VERSION_TEXT ), + .DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT, + EFI_SNP_DRIVER_HELP, + EFI_SNP_DRIVER_TEXT ), + .DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT, + EFI_SNP_DEVICE_HELP, + EFI_SNP_DEVICE_TEXT ), + .EndForm = EFI_IFR_END(), + .EndFormSet = EFI_IFR_END(), +}; + +/** + * Generate EFI SNP string + * + * @v wbuf Buffer + * @v swlen Size of buffer (in wide characters) + * @v snpdev SNP device + * @ret wlen Length of string (in wide characters) + */ +static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen, + enum efi_snp_hii_string_id id, + struct efi_snp_device *snpdev ) { + struct net_device *netdev = snpdev->netdev; + struct device *dev = netdev->dev; + + switch ( id ) { + case EFI_SNP_LANGUAGE_NAME: + return efi_ssnprintf ( wbuf, swlen, "English" ); + case EFI_SNP_FORMSET_TITLE: + return efi_ssnprintf ( wbuf, swlen, "%s (%s)", + ( PRODUCT_NAME[0] ? + PRODUCT_NAME : PRODUCT_SHORT_NAME ), + netdev_addr ( netdev ) ); + case EFI_SNP_FORMSET_HELP: + return efi_ssnprintf ( wbuf, swlen, + "Configure " PRODUCT_SHORT_NAME ); + case EFI_SNP_PRODUCT_PROMPT: + return efi_ssnprintf ( wbuf, swlen, "Name" ); + case EFI_SNP_PRODUCT_HELP: + return efi_ssnprintf ( wbuf, swlen, "Firmware product name" ); + case EFI_SNP_PRODUCT_TEXT: + return efi_ssnprintf ( wbuf, swlen, "%s", + ( PRODUCT_NAME[0] ? + PRODUCT_NAME : PRODUCT_SHORT_NAME ) ); + case EFI_SNP_VERSION_PROMPT: + return efi_ssnprintf ( wbuf, swlen, "Version" ); + case EFI_SNP_VERSION_HELP: + return efi_ssnprintf ( wbuf, swlen, "Firmware version" ); + case EFI_SNP_VERSION_TEXT: + return efi_ssnprintf ( wbuf, swlen, VERSION ); + case EFI_SNP_DRIVER_PROMPT: + return efi_ssnprintf ( wbuf, swlen, "Driver" ); + case EFI_SNP_DRIVER_HELP: + return efi_ssnprintf ( wbuf, swlen, "Firmware driver" ); + case EFI_SNP_DRIVER_TEXT: + return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name ); + case EFI_SNP_DEVICE_PROMPT: + return efi_ssnprintf ( wbuf, swlen, "Device" ); + case EFI_SNP_DEVICE_HELP: + return efi_ssnprintf ( wbuf, swlen, "Hardware device" ); + case EFI_SNP_DEVICE_TEXT: + return efi_ssnprintf ( wbuf, swlen, "%s", dev->name ); + default: + assert ( 0 ); + return 0; + } +} + +/** + * Generate EFI SNP string package + * + * @v strings String package header buffer + * @v max_len Buffer length + * @v snpdev SNP device + * @ret len Length of string package + */ +static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings, + size_t max_len, struct efi_snp_device *snpdev ) { + static const char language[] = "en-us"; + void *buf = strings; + ssize_t remaining = max_len; + size_t hdrsize; + EFI_HII_SIBT_STRING_UCS2_BLOCK *string; + ssize_t wremaining; + size_t string_wlen; + unsigned int id; + EFI_HII_STRING_BLOCK *end; + size_t len; + + /* Calculate header size */ + hdrsize = ( offsetof ( typeof ( *strings ), Language ) + + sizeof ( language ) ); + buf += hdrsize; + remaining -= hdrsize; + + /* Fill in strings */ + for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) { + string = buf; + if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) ) + string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; + buf += offsetof ( typeof ( *string ), StringText ); + remaining -= offsetof ( typeof ( *string ), StringText ); + wremaining = ( remaining / + ( ( ssize_t ) sizeof ( string->StringText[0] ))); + assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) ); + string_wlen = efi_snp_string ( string->StringText, wremaining, + id, snpdev ); + buf += ( ( string_wlen + 1 /* wNUL */ ) * + sizeof ( string->StringText[0] ) ); + remaining -= ( ( string_wlen + 1 /* wNUL */ ) * + sizeof ( string->StringText[0] ) ); + } + + /* Fill in end marker */ + end = buf; + if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) ) + end->BlockType = EFI_HII_SIBT_END; + buf += sizeof ( *end ); + remaining -= sizeof ( *end ); + + /* Calculate overall length */ + len = ( max_len - remaining ); + + /* Fill in string package header */ + if ( strings ) { + memset ( strings, 0, sizeof ( *strings ) ); + strings->Header.Length = len; + strings->Header.Type = EFI_HII_PACKAGE_STRINGS; + strings->HdrSize = hdrsize; + strings->StringInfoOffset = hdrsize; + strings->LanguageName = EFI_SNP_LANGUAGE_NAME; + memcpy ( strings->Language, language, sizeof ( language ) ); + } + + return len; +} + +/** + * Generate EFI SNP package list + * + * @v snpdev SNP device + * @ret package_list Package list, or NULL on error + * + * The package list is allocated using malloc(), and must eventually + * be freed by the caller. + */ +static EFI_HII_PACKAGE_LIST_HEADER * +efi_snp_package_list ( struct efi_snp_device *snpdev ) { + size_t strings_len = efi_snp_strings ( NULL, 0, snpdev ); + struct { + EFI_HII_PACKAGE_LIST_HEADER header; + struct efi_snp_formset formset; + union { + EFI_HII_STRING_PACKAGE_HDR strings; + uint8_t pad[strings_len]; + } __attribute__ (( packed )) strings; + EFI_HII_PACKAGE_HEADER end; + } __attribute__ (( packed )) *package_list; + + /* Allocate package list */ + package_list = zalloc ( sizeof ( *package_list ) ); + if ( ! package_list ) + return NULL; + + /* Create a unique GUID for this package list and formset */ + efi_snp_formset.FormSet.FormSet.Guid.Data1++; + + /* Populate package list */ + memcpy ( &package_list->header.PackageListGuid, + &efi_snp_formset.FormSet.FormSet.Guid, + sizeof ( package_list->header.PackageListGuid ) ); + package_list->header.PackageLength = sizeof ( *package_list ); + memcpy ( &package_list->formset, &efi_snp_formset, + sizeof ( package_list->formset ) ); + efi_snp_strings ( &package_list->strings.strings, + sizeof ( package_list->strings ), snpdev ); + package_list->end.Length = sizeof ( package_list->end ); + package_list->end.Type = EFI_HII_PACKAGE_END; + + return &package_list->header; +} + +/** + * Fetch configuration + * + * @v hii HII configuration access protocol + * @v request Configuration to fetch + * @ret progress Progress made through configuration to fetch + * @ret results Query results + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, + EFI_STRING request, EFI_STRING *progress, + EFI_STRING *results __unused ) { + struct efi_snp_device *snpdev = + container_of ( hii, struct efi_snp_device, hii ); + + DBGC ( snpdev, "SNPDEV %p ExtractConfig \"%ls\"\n", snpdev, request ); + + *progress = request; + return EFI_INVALID_PARAMETER; +} + +/** + * Store configuration + * + * @v hii HII configuration access protocol + * @v config Configuration to store + * @ret progress Progress made through configuration to store + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, + EFI_STRING config, EFI_STRING *progress ) { + struct efi_snp_device *snpdev = + container_of ( hii, struct efi_snp_device, hii ); + + DBGC ( snpdev, "SNPDEV %p RouteConfig \"%ls\"\n", snpdev, config ); + + *progress = config; + return EFI_INVALID_PARAMETER; +} + +/** + * Handle form actions + * + * @v hii HII configuration access protocol + * @v action Form browser action + * @v question_id Question ID + * @v type Type of value + * @v value Value + * @ret action_request Action requested by driver + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_snp_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, + EFI_BROWSER_ACTION action __unused, + EFI_QUESTION_ID question_id __unused, + UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused, + EFI_BROWSER_ACTION_REQUEST *action_request __unused ) { + struct efi_snp_device *snpdev = + container_of ( hii, struct efi_snp_device, hii ); + + DBGC ( snpdev, "SNPDEV %p Callback\n", snpdev ); + return EFI_UNSUPPORTED; +} + +/** HII configuration access protocol */ +static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = { + .ExtractConfig = efi_snp_hii_extract_config, + .RouteConfig = efi_snp_hii_route_config, + .Callback = efi_snp_hii_callback, +}; + +/** + * Install HII protocol and packages for SNP device + * + * @v snpdev SNP device + * @ret rc Return status code + */ +int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + int efirc; + int rc; + + /* Initialise HII protocol */ + memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) ); + + /* Create HII package list */ + snpdev->package_list = efi_snp_package_list ( snpdev ); + if ( ! snpdev->package_list ) { + DBGC ( snpdev, "SNPDEV %p could not create HII package list\n", + snpdev ); + rc = -ENOMEM; + goto err_build_package_list; + } + + /* Add HII packages */ + if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list, + snpdev->handle, + &snpdev->hii_handle ) ) != 0 ) { + DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n", + snpdev, efi_strerror ( efirc ) ); + rc = EFIRC_TO_RC ( efirc ); + goto err_new_package_list; + } + + /* Install HII protocol */ + if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( + &snpdev->handle, + &efi_hii_config_access_protocol_guid, &snpdev->hii, + NULL ) ) != 0 ) { + DBGC ( snpdev, "SNPDEV %p could not install HII protocol: %s\n", + snpdev, efi_strerror ( efirc ) ); + rc = EFIRC_TO_RC ( efirc ); + goto err_install_protocol; + } + + return 0; + + bs->UninstallMultipleProtocolInterfaces ( + snpdev->handle, + &efi_hii_config_access_protocol_guid, &snpdev->hii, + NULL ); + err_install_protocol: + efihii->RemovePackageList ( efihii, snpdev->hii_handle ); + err_new_package_list: + free ( snpdev->package_list ); + snpdev->package_list = NULL; + err_build_package_list: + return rc; +} + +/** + * Uninstall HII protocol and package for SNP device + * + * @v snpdev SNP device + */ +void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + + bs->UninstallMultipleProtocolInterfaces ( + snpdev->handle, + &efi_hii_config_access_protocol_guid, &snpdev->hii, + NULL ); + efihii->RemovePackageList ( efihii, snpdev->hii_handle ); + free ( snpdev->package_list ); + snpdev->package_list = NULL; +} From a4d125081010ff9816add31af2f732e6ec22a704 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 11 Oct 2012 15:02:50 +0100 Subject: [PATCH 170/250] [efi] Expose net device non-volatile settings via HII Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi_hii.h | 203 ++++----- src/interface/efi/efi_hii.c | 577 +++++++++++++++++++++++++ src/interface/efi/efi_snp_hii.c | 730 ++++++++++++++++++++++---------- 3 files changed, 1157 insertions(+), 353 deletions(-) create mode 100644 src/interface/efi/efi_hii.c diff --git a/src/include/ipxe/efi/efi_hii.h b/src/include/ipxe/efi/efi_hii.h index f95a75f6..8e94bbe7 100644 --- a/src/include/ipxe/efi/efi_hii.h +++ b/src/include/ipxe/efi/efi_hii.h @@ -8,138 +8,89 @@ FILE_LICENCE ( GPL2_OR_LATER ); +#include #include #include -/** - * Define an EFI IFR form set type - * - * @v num_class_guids Number of class GUIDs - * @ret type Form set type - */ -#define EFI_IFR_FORM_SET_TYPE( num_class_guids ) \ - struct { \ - EFI_IFR_FORM_SET FormSet; \ - EFI_GUID ClassGuid[num_class_guids]; \ - } __attribute__ (( packed )) - -/** - * Define an EFI IFR form set - * - * @v guid GUID - * @v title Title string - * @v help Help string - * @v type Form set type (as returned by EFI_IFR_FORM_SET_TYPE()) - * @ret ifr Form set - * - * This definition opens a new scope, which must be closed by an - * EFI_IFR_END(). - */ -#define EFI_IFR_FORM_SET( guid, title, help, type, ... ) { \ - .FormSet = { \ - .Header = { \ - .OpCode = EFI_IFR_FORM_SET_OP, \ - .Length = sizeof ( type ), \ - .Scope = 1, \ - }, \ - .Guid = guid, \ - .FormSetTitle = title, \ - .Help = help, \ - .Flags = ( sizeof ( ( ( type * ) NULL )->ClassGuid ) / \ - sizeof ( ( ( type * ) NULL )->ClassGuid[0] ) ), \ - }, \ - .ClassGuid = { \ - __VA_ARGS__ \ - }, \ - } - -/** - * Define an EFI IFR GUID class - * - * @v class Class - * @ret ifr GUID class - */ -#define EFI_IFR_GUID_CLASS( class ) { \ - .Header = { \ - .OpCode = EFI_IFR_GUID_OP, \ - .Length = sizeof ( EFI_IFR_GUID_CLASS ), \ - }, \ - .Guid = EFI_IFR_TIANO_GUID, \ - .ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS, \ - .Class = class, \ - } - -/** - * Define an EFI IFR GUID subclass - * - * @v subclass Subclass - * @ret ifr GUID subclass - */ -#define EFI_IFR_GUID_SUBCLASS( subclass ) { \ - .Header = { \ - .OpCode = EFI_IFR_GUID_OP, \ - .Length = sizeof ( EFI_IFR_GUID_SUBCLASS ), \ - }, \ - .Guid = EFI_IFR_TIANO_GUID, \ - .ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS, \ - .SubClass = subclass, \ - } - -/** - * Define an EFI IFR form - * - * @v formid Form ID - * @v title Title string - * @ret ifr Form - * - * This definition opens a new scope, which must be closed by an - * EFI_IFR_END(). - */ -#define EFI_IFR_FORM( formid, title ) { \ - .Header = { \ - .OpCode = EFI_IFR_FORM_OP, \ - .Length = sizeof ( EFI_IFR_FORM ), \ - .Scope = 1, \ - }, \ - .FormId = formid, \ - .FormTitle = title, \ - } - -/** - * Define an EFI IFR text widget - * - * @v prompt Prompt string - * @v help Help string - * @v text Text string - * @ret ifr Text widget - */ -#define EFI_IFR_TEXT( prompt, help, text ) { \ - .Header = { \ - .OpCode = EFI_IFR_TEXT_OP, \ - .Length = sizeof ( EFI_IFR_TEXT ), \ - }, \ - .Statement = { \ - .Prompt = prompt, \ - .Help = help, \ - }, \ - .TextTwo = text, \ - } - -/** - * Define an EFI IFR end marker - * - * @ret ifr End marker - */ -#define EFI_IFR_END() { \ - .Header = { \ - .OpCode = EFI_IFR_END_OP, \ - .Length = sizeof ( EFI_IFR_END ), \ - }, \ - } - /** GUID indicating formset compliance for IBM Unified Configuration Manager */ #define EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID \ { 0x5c8e9746, 0xa5f7, 0x4593, \ { 0xaf, 0x1f, 0x66, 0xa8, 0x2a, 0xa1, 0x9c, 0xb1 } } +/** An EFI IFR builder */ +struct efi_ifr_builder { + /** IFR opcodes */ + EFI_IFR_OP_HEADER *ops; + /** Length of IFR opcodes */ + size_t ops_len; + /** Strings */ + EFI_HII_STRING_BLOCK *strings; + /** Length of strings */ + size_t strings_len; + /** Current string identifier */ + unsigned int string_id; + /** Current variable store identifier */ + unsigned int varstore_id; + /** Current form identifier */ + unsigned int form_id; + /** An allocation has failed */ + int failed; +}; + +/** + * Initialise IFR builder + * + * @v ifr IFR builder + * + * The caller must eventually call efi_ifr_free() to free the dynamic + * storage associated with the IFR builder. + */ +static inline void efi_ifr_init ( struct efi_ifr_builder *ifr ) { + memset ( ifr, 0, sizeof ( *ifr ) ); +} + +extern unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr, + const char *fmt, ... ); +extern void efi_ifr_end_op ( struct efi_ifr_builder *ifr ); +extern void efi_ifr_false_op ( struct efi_ifr_builder *ifr ); +extern unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr, + unsigned int title_id ); +extern void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid, + unsigned int title_id, unsigned int help_id, + ... ); +void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id, + unsigned int varstore_info, unsigned int varstore_type ); +extern void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr, + unsigned int class ); +extern void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr, + unsigned int subclass ); +extern void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr, + unsigned int prompt_id, + unsigned int help_id, unsigned int question_id, + unsigned int varstore_id, + unsigned int varstore_info, + unsigned int vflags, unsigned long min_value, + unsigned long max_value, unsigned int step, + unsigned int flags ); +extern void efi_ifr_string_op ( struct efi_ifr_builder *ifr, + unsigned int prompt_id, unsigned int help_id, + unsigned int question_id, + unsigned int varstore_id, + unsigned int varstore_info, unsigned int vflags, + unsigned int min_size, unsigned int max_size, + unsigned int flags ); +extern void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr ); +extern void efi_ifr_text_op ( struct efi_ifr_builder *ifr, + unsigned int prompt_id, unsigned int help_id, + unsigned int text_id ); +extern void efi_ifr_true_op ( struct efi_ifr_builder *ifr ); +extern unsigned int +efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid ); +extern void efi_ifr_free ( struct efi_ifr_builder *ifr ); +extern EFI_HII_PACKAGE_LIST_HEADER * +efi_ifr_package ( struct efi_ifr_builder *ifr, const EFI_GUID *guid, + const char *language, unsigned int language_id ); + #endif /* _IPXE_EFI_HII_H */ diff --git a/src/interface/efi/efi_hii.c b/src/interface/efi/efi_hii.c new file mode 100644 index 00000000..834060b5 --- /dev/null +++ b/src/interface/efi/efi_hii.c @@ -0,0 +1,577 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include +#include + +/** Tiano GUID */ +static const EFI_GUID tiano_guid = EFI_IFR_TIANO_GUID; + +/** + * Add string to IFR builder + * + * @v ifr IFR builder + * @v fmt Format string + * @v ... Arguments + * @ret string_id String identifier, or zero on failure + */ +unsigned int efi_ifr_string ( struct efi_ifr_builder *ifr, const char *fmt, + ... ) { + EFI_HII_STRING_BLOCK *new_strings; + EFI_HII_SIBT_STRING_UCS2_BLOCK *ucs2; + size_t new_strings_len; + va_list args; + size_t len; + unsigned int string_id; + + /* Do nothing if a previous allocation has failed */ + if ( ifr->failed ) + return 0; + + /* Calculate string length */ + va_start ( args, fmt ); + len = ( efi_vsnprintf ( NULL, 0, fmt, args ) + 1 /* wNUL */ ); + va_end ( args ); + + /* Reallocate strings */ + new_strings_len = ( ifr->strings_len + + offsetof ( typeof ( *ucs2 ), StringText ) + + ( len * sizeof ( ucs2->StringText[0] ) ) ); + new_strings = realloc ( ifr->strings, new_strings_len ); + if ( ! new_strings ) { + ifr->failed = 1; + return 0; + } + ucs2 = ( ( ( void * ) new_strings ) + ifr->strings_len ); + ifr->strings = new_strings; + ifr->strings_len = new_strings_len; + + /* Fill in string */ + ucs2->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; + va_start ( args, fmt ); + efi_vsnprintf ( ucs2->StringText, len, fmt, args ); + va_end ( args ); + + /* Allocate string ID */ + string_id = ++(ifr->string_id); + + DBGC ( ifr, "IFR %p string %#04x is \"%ls\"\n", + ifr, string_id, ucs2->StringText ); + return string_id; +} + +/** + * Add IFR opcode to IFR builder + * + * @v ifr IFR builder + * @v opcode Opcode + * @v len Opcode length + * @ret op Opcode, or NULL + */ +static void * efi_ifr_op ( struct efi_ifr_builder *ifr, unsigned int opcode, + size_t len ) { + EFI_IFR_OP_HEADER *new_ops; + EFI_IFR_OP_HEADER *op; + size_t new_ops_len; + + /* Do nothing if a previous allocation has failed */ + if ( ifr->failed ) + return NULL; + + /* Reallocate opcodes */ + new_ops_len = ( ifr->ops_len + len ); + new_ops = realloc ( ifr->ops, new_ops_len ); + if ( ! new_ops ) { + ifr->failed = 1; + return NULL; + } + op = ( ( ( void * ) new_ops ) + ifr->ops_len ); + ifr->ops = new_ops; + ifr->ops_len = new_ops_len; + + /* Fill in opcode header */ + op->OpCode = opcode; + op->Length = len; + + return op; +} + +/** + * Add end opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_end_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_END *end; + + /* Add opcode */ + end = efi_ifr_op ( ifr, EFI_IFR_END_OP, sizeof ( *end ) ); + + DBGC ( ifr, "IFR %p end\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, end, sizeof ( *end ) ); +} + +/** + * Add false opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_false_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_FALSE *false; + + /* Add opcode */ + false = efi_ifr_op ( ifr, EFI_IFR_FALSE_OP, sizeof ( *false ) ); + + DBGC ( ifr, "IFR %p false\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, false, sizeof ( *false ) ); +} + +/** + * Add form opcode to IFR builder + * + * @v ifr IFR builder + * @v title_id Title string identifier + * @ret form_id Form identifier + */ +unsigned int efi_ifr_form_op ( struct efi_ifr_builder *ifr, + unsigned int title_id ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_FORM *form; + + /* Add opcode */ + form = efi_ifr_op ( ifr, EFI_IFR_FORM_OP, sizeof ( *form ) ); + if ( ! form ) + return 0; + form->Header.Scope = 1; + form->FormId = ++(ifr->form_id); + form->FormTitle = title_id; + + DBGC ( ifr, "IFR %p name/value store %#04x title %#04x\n", + ifr, form->FormId, title_id ); + DBGC2_HDA ( ifr, dispaddr, form, sizeof ( *form ) ); + return form->FormId; +} + +/** + * Add formset opcode to IFR builder + * + * @v ifr IFR builder + * @v guid GUID + * @v title_id Title string identifier + * @v help_id Help string identifier + * @v ... Class GUIDs (terminated by NULL) + */ +void efi_ifr_form_set_op ( struct efi_ifr_builder *ifr, const EFI_GUID *guid, + unsigned int title_id, unsigned int help_id, ... ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_FORM_SET *formset; + EFI_GUID *class_guid; + unsigned int num_class_guids = 0; + size_t len; + va_list args; + + /* Count number of class GUIDs */ + va_start ( args, help_id ); + while ( va_arg ( args, const EFI_GUID * ) != NULL ) + num_class_guids++; + va_end ( args ); + + /* Add opcode */ + len = ( sizeof ( *formset ) + + ( num_class_guids * sizeof ( *class_guid ) ) ); + formset = efi_ifr_op ( ifr, EFI_IFR_FORM_SET_OP, len ); + if ( ! formset ) + return; + formset->Header.Scope = 1; + memcpy ( &formset->Guid, guid, sizeof ( formset->Guid ) ); + formset->FormSetTitle = title_id; + formset->Help = help_id; + formset->Flags = num_class_guids; + + /* Add class GUIDs */ + class_guid = ( ( ( void * ) formset ) + sizeof ( *formset ) ); + va_start ( args, help_id ); + while ( num_class_guids-- ) { + memcpy ( class_guid++, va_arg ( args, const EFI_GUID * ), + sizeof ( *class_guid ) ); + } + va_end ( args ); + + DBGC ( ifr, "IFR %p formset title %#04x help %#04x\n", + ifr, title_id, help_id ); + DBGC2_HDA ( ifr, dispaddr, formset, len ); +} + +/** + * Add get opcode to IFR builder + * + * @v ifr IFR builder + * @v varstore_id Variable store identifier + * @v varstore_info Variable string identifier or offset + * @v varstore_type Variable type + */ +void efi_ifr_get_op ( struct efi_ifr_builder *ifr, unsigned int varstore_id, + unsigned int varstore_info, unsigned int varstore_type ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_GET *get; + + /* Add opcode */ + get = efi_ifr_op ( ifr, EFI_IFR_GET_OP, sizeof ( *get ) ); + get->VarStoreId = varstore_id; + get->VarStoreInfo.VarName = varstore_info; + get->VarStoreType = varstore_type; + + DBGC ( ifr, "IFR %p get varstore %#04x:%#04x type %#02x\n", + ifr, varstore_id, varstore_info, varstore_type ); + DBGC2_HDA ( ifr, dispaddr, get, sizeof ( *get ) ); +} + +/** + * Add GUID class opcode to IFR builder + * + * @v ifr IFR builder + * @v class Class + */ +void efi_ifr_guid_class_op ( struct efi_ifr_builder *ifr, unsigned int class ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_GUID_CLASS *guid_class; + + /* Add opcode */ + guid_class = efi_ifr_op ( ifr, EFI_IFR_GUID_OP, + sizeof ( *guid_class ) ); + if ( ! guid_class ) + return; + memcpy ( &guid_class->Guid, &tiano_guid, sizeof ( guid_class->Guid ) ); + guid_class->ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS; + guid_class->Class = class; + + DBGC ( ifr, "IFR %p GUID class %#02x\n", ifr, class ); + DBGC2_HDA ( ifr, dispaddr, guid_class, sizeof ( *guid_class ) ); +} + +/** + * Add GUID subclass opcode to IFR builder + * + * @v ifr IFR builder + * @v subclass Subclass + */ +void efi_ifr_guid_subclass_op ( struct efi_ifr_builder *ifr, + unsigned int subclass ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_GUID_SUBCLASS *guid_subclass; + + /* Add opcode */ + guid_subclass = efi_ifr_op ( ifr, EFI_IFR_GUID_OP, + sizeof ( *guid_subclass ) ); + if ( ! guid_subclass ) + return; + memcpy ( &guid_subclass->Guid, &tiano_guid, + sizeof ( guid_subclass->Guid ) ); + guid_subclass->ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS; + guid_subclass->SubClass = subclass; + + DBGC ( ifr, "IFR %p GUID subclass %#02x\n", ifr, subclass ); + DBGC2_HDA ( ifr, dispaddr, guid_subclass, sizeof ( *guid_subclass ) ); +} + +/** + * Add numeric opcode to IFR builder + * + * @v ifr IFR builder + * @v prompt_id Prompt string identifier + * @v help_id Help string identifier + * @v question_id Question identifier + * @v varstore_id Variable store identifier + * @v varstore_info Variable string identifier or offset + * @v vflags Variable flags + * @v min_value Minimum value + * @v max_value Maximum value + * @v step Step + * @v flags Flags + */ +void efi_ifr_numeric_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, + unsigned int help_id, unsigned int question_id, + unsigned int varstore_id, unsigned int varstore_info, + unsigned int vflags, unsigned long min_value, + unsigned long max_value, unsigned int step, + unsigned int flags ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_NUMERIC *numeric; + unsigned int size; + + /* Add opcode */ + numeric = efi_ifr_op ( ifr, EFI_IFR_NUMERIC_OP, sizeof ( *numeric ) ); + if ( ! numeric ) + return; + numeric->Question.Header.Prompt = prompt_id; + numeric->Question.Header.Help = help_id; + numeric->Question.QuestionId = question_id; + numeric->Question.VarStoreId = varstore_id; + numeric->Question.VarStoreInfo.VarName = varstore_info; + numeric->Question.Flags = vflags; + size = ( flags & EFI_IFR_NUMERIC_SIZE ); + switch ( size ) { + case EFI_IFR_NUMERIC_SIZE_1 : + numeric->data.u8.MinValue = min_value; + numeric->data.u8.MaxValue = max_value; + numeric->data.u8.Step = step; + break; + case EFI_IFR_NUMERIC_SIZE_2 : + numeric->data.u16.MinValue = min_value; + numeric->data.u16.MaxValue = max_value; + numeric->data.u16.Step = step; + break; + case EFI_IFR_NUMERIC_SIZE_4 : + numeric->data.u32.MinValue = min_value; + numeric->data.u32.MaxValue = max_value; + numeric->data.u32.Step = step; + break; + case EFI_IFR_NUMERIC_SIZE_8 : + numeric->data.u64.MinValue = min_value; + numeric->data.u64.MaxValue = max_value; + numeric->data.u64.Step = step; + break; + } + + DBGC ( ifr, "IFR %p numeric prompt %#04x help %#04x question %#04x " + "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id, + varstore_id, varstore_info ); + DBGC2_HDA ( ifr, dispaddr, numeric, sizeof ( *numeric ) ); +} + +/** + * Add string opcode to IFR builder + * + * @v ifr IFR builder + * @v prompt_id Prompt string identifier + * @v help_id Help string identifier + * @v question_id Question identifier + * @v varstore_id Variable store identifier + * @v varstore_info Variable string identifier or offset + * @v vflags Variable flags + * @v min_size Minimum size + * @v max_size Maximum size + * @v flags Flags + */ +void efi_ifr_string_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, + unsigned int help_id, unsigned int question_id, + unsigned int varstore_id, unsigned int varstore_info, + unsigned int vflags, unsigned int min_size, + unsigned int max_size, unsigned int flags ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_STRING *string; + + /* Add opcode */ + string = efi_ifr_op ( ifr, EFI_IFR_STRING_OP, sizeof ( *string ) ); + if ( ! string ) + return; + string->Question.Header.Prompt = prompt_id; + string->Question.Header.Help = help_id; + string->Question.QuestionId = question_id; + string->Question.VarStoreId = varstore_id; + string->Question.VarStoreInfo.VarName = varstore_info; + string->Question.Flags = vflags; + string->MinSize = min_size; + string->MaxSize = max_size; + string->Flags = flags; + + DBGC ( ifr, "IFR %p string prompt %#04x help %#04x question %#04x " + "varstore %#04x:%#04x\n", ifr, prompt_id, help_id, question_id, + varstore_id, varstore_info ); + DBGC2_HDA ( ifr, dispaddr, string, sizeof ( *string ) ); +} + +/** + * Add suppress-if opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_suppress_if_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_SUPPRESS_IF *suppress_if; + + /* Add opcode */ + suppress_if = efi_ifr_op ( ifr, EFI_IFR_SUPPRESS_IF_OP, + sizeof ( *suppress_if ) ); + suppress_if->Header.Scope = 1; + + DBGC ( ifr, "IFR %p suppress-if\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, suppress_if, sizeof ( *suppress_if ) ); +} + +/** + * Add text opcode to IFR builder + * + * @v ifr IFR builder + * @v prompt_id Prompt string identifier + * @v help_id Help string identifier + * @v text_id Text string identifier + */ +void efi_ifr_text_op ( struct efi_ifr_builder *ifr, unsigned int prompt_id, + unsigned int help_id, unsigned int text_id ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_TEXT *text; + + /* Add opcode */ + text = efi_ifr_op ( ifr, EFI_IFR_TEXT_OP, sizeof ( *text ) ); + if ( ! text ) + return; + text->Statement.Prompt = prompt_id; + text->Statement.Help = help_id; + text->TextTwo = text_id; + + DBGC ( ifr, "IFR %p text prompt %#04x help %#04x text %#04x\n", + ifr, prompt_id, help_id, text_id ); + DBGC2_HDA ( ifr, dispaddr, text, sizeof ( *text ) ); +} + +/** + * Add true opcode to IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_true_op ( struct efi_ifr_builder *ifr ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_TRUE *true; + + /* Add opcode */ + true = efi_ifr_op ( ifr, EFI_IFR_TRUE_OP, sizeof ( *true ) ); + + DBGC ( ifr, "IFR %p true\n", ifr ); + DBGC2_HDA ( ifr, dispaddr, true, sizeof ( *true ) ); +} + +/** + * Add name/value store opcode to IFR builder + * + * @v ifr IFR builder + * @v guid GUID + * @ret varstore_id Variable store identifier, or 0 on failure + */ +unsigned int efi_ifr_varstore_name_value_op ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid ) { + size_t dispaddr = ifr->ops_len; + EFI_IFR_VARSTORE_NAME_VALUE *varstore; + + /* Add opcode */ + varstore = efi_ifr_op ( ifr, EFI_IFR_VARSTORE_NAME_VALUE_OP, + sizeof ( *varstore ) ); + if ( ! varstore ) + return 0; + varstore->VarStoreId = ++(ifr->varstore_id); + memcpy ( &varstore->Guid, guid, sizeof ( varstore->Guid ) ); + + DBGC ( ifr, "IFR %p name/value store %#04x\n", + ifr, varstore->VarStoreId ); + DBGC2_HDA ( ifr, dispaddr, varstore, sizeof ( *varstore ) ); + return varstore->VarStoreId; +} + +/** + * Free memory used by IFR builder + * + * @v ifr IFR builder + */ +void efi_ifr_free ( struct efi_ifr_builder *ifr ) { + + free ( ifr->ops ); + free ( ifr->strings ); + memset ( ifr, 0, sizeof ( *ifr ) ); +} + +/** + * Construct package list from IFR builder + * + * @v ifr IFR builder + * @v guid Package GUID + * @v language Language + * @v language_id Language string ID + * @ret package Package list, or NULL + * + * The package list is allocated using malloc(), and must eventually + * be freed by the caller. (The caller must also call efi_ifr_free() + * to free the temporary storage used during construction.) + */ +EFI_HII_PACKAGE_LIST_HEADER * efi_ifr_package ( struct efi_ifr_builder *ifr, + const EFI_GUID *guid, + const char *language, + unsigned int language_id ) { + struct { + EFI_HII_PACKAGE_LIST_HEADER header; + struct { + EFI_HII_PACKAGE_HEADER header; + uint8_t data[ifr->ops_len]; + } __attribute__ (( packed )) ops; + struct { + union { + EFI_HII_STRING_PACKAGE_HDR header; + uint8_t pad[offsetof(EFI_HII_STRING_PACKAGE_HDR, + Language) + + strlen ( language ) + 1 /* NUL */ ]; + } __attribute__ (( packed )) header; + uint8_t data[ifr->strings_len]; + EFI_HII_STRING_BLOCK end; + } __attribute__ (( packed )) strings; + EFI_HII_PACKAGE_HEADER end; + } __attribute__ (( packed )) *package; + + /* Fail if any previous allocation failed */ + if ( ifr->failed ) + return NULL; + + /* Allocate package list */ + package = zalloc ( sizeof ( *package ) ); + if ( ! package ) + return NULL; + + /* Populate package list */ + package->header.PackageLength = sizeof ( *package ); + memcpy ( &package->header.PackageListGuid, guid, + sizeof ( package->header.PackageListGuid ) ); + package->ops.header.Length = sizeof ( package->ops ); + package->ops.header.Type = EFI_HII_PACKAGE_FORMS; + memcpy ( package->ops.data, ifr->ops, sizeof ( package->ops.data ) ); + package->strings.header.header.Header.Length = + sizeof ( package->strings ); + package->strings.header.header.Header.Type = + EFI_HII_PACKAGE_STRINGS; + package->strings.header.header.HdrSize = + sizeof ( package->strings.header ); + package->strings.header.header.StringInfoOffset = + sizeof ( package->strings.header ); + package->strings.header.header.LanguageName = language_id; + strcpy ( package->strings.header.header.Language, language ); + memcpy ( package->strings.data, ifr->strings, + sizeof ( package->strings.data ) ); + package->strings.end.BlockType = EFI_HII_SIBT_END; + package->end.Type = EFI_HII_PACKAGE_END; + package->end.Length = sizeof ( package->end ); + + return &package->header; +} + diff --git a/src/interface/efi/efi_snp_hii.c b/src/interface/efi/efi_snp_hii.c index c02233db..96e9aa20 100644 --- a/src/interface/efi/efi_snp_hii.c +++ b/src/interface/efi/efi_snp_hii.c @@ -19,9 +19,39 @@ FILE_LICENCE ( GPL2_OR_LATER ); +/** + * @file + * + * EFI SNP HII protocol + * + * The HII protocols are some of the less-well designed parts of the + * entire EFI specification. This is a significant accomplishment. + * + * The face-slappingly ludicrous query string syntax seems to be + * motivated by the desire to allow a caller to query multiple drivers + * simultaneously via the single-instance HII_CONFIG_ROUTING_PROTOCOL, + * which is supposed to pass relevant subsets of the query string to + * the relevant drivers. + * + * Nobody uses the HII_CONFIG_ROUTING_PROTOCOL. Not even the EFI + * setup browser uses the HII_CONFIG_ROUTING_PROTOCOL. To the best of + * my knowledge, there has only ever been one implementation of the + * HII_CONFIG_ROUTING_PROTOCOL (as part of EDK2), and it just doesn't + * work. It's so badly broken that I can't even figure out what the + * code is _trying_ to do. + * + * Fundamentally, the problem seems to be that Javascript programmers + * should not be allowed to design APIs for C code. + */ + #include +#include #include +#include +#include #include +#include +#include #include #include #include @@ -34,250 +64,452 @@ FILE_LICENCE ( GPL2_OR_LATER ); static EFI_GUID efi_hii_config_access_protocol_guid = EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID; +/** EFI platform setup formset GUID */ +static EFI_GUID efi_hii_platform_setup_formset_guid + = EFI_HII_PLATFORM_SETUP_FORMSET_GUID; + +/** EFI IBM UCM compliant formset GUID */ +static EFI_GUID efi_hii_ibm_ucm_compliant_formset_guid + = EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID; + /** EFI HII database protocol */ static EFI_HII_DATABASE_PROTOCOL *efihii; EFI_REQUIRE_PROTOCOL ( EFI_HII_DATABASE_PROTOCOL, &efihii ); -/** Local base GUID used for our EFI SNP formset */ -#define EFI_SNP_FORMSET_GUID_BASE \ - { 0xc4f84019, 0x6dfd, 0x4a27, \ - { 0x9b, 0x94, 0xb7, 0x2e, 0x1f, 0xbc, 0xad, 0xca } } +/** + * Identify settings to be exposed via HII + * + * @v snpdev SNP device + * @ret settings Settings, or NULL + */ +static struct settings * efi_snp_hii_settings ( struct efi_snp_device *snpdev ){ -/** Form identifiers used for our EFI SNP HII */ -enum efi_snp_hii_form_id { - EFI_SNP_FORM = 0x0001, /**< The only form */ -}; - -/** String identifiers used for our EFI SNP HII */ -enum efi_snp_hii_string_id { - /* Language name */ - EFI_SNP_LANGUAGE_NAME = 0x0001, - /* Formset */ - EFI_SNP_FORMSET_TITLE, EFI_SNP_FORMSET_HELP, - /* Product name */ - EFI_SNP_PRODUCT_PROMPT, EFI_SNP_PRODUCT_HELP, EFI_SNP_PRODUCT_TEXT, - /* Version */ - EFI_SNP_VERSION_PROMPT, EFI_SNP_VERSION_HELP, EFI_SNP_VERSION_TEXT, - /* Driver */ - EFI_SNP_DRIVER_PROMPT, EFI_SNP_DRIVER_HELP, EFI_SNP_DRIVER_TEXT, - /* Device */ - EFI_SNP_DEVICE_PROMPT, EFI_SNP_DEVICE_HELP, EFI_SNP_DEVICE_TEXT, - /* End of list */ - EFI_SNP_MAX_STRING_ID -}; - -/** EFI SNP formset */ -struct efi_snp_formset { - EFI_HII_PACKAGE_HEADER Header; - EFI_IFR_FORM_SET_TYPE(2) FormSet; - EFI_IFR_GUID_CLASS Class; - EFI_IFR_GUID_SUBCLASS SubClass; - EFI_IFR_FORM Form; - EFI_IFR_TEXT ProductText; - EFI_IFR_TEXT VersionText; - EFI_IFR_TEXT DriverText; - EFI_IFR_TEXT DeviceText; - EFI_IFR_END EndForm; - EFI_IFR_END EndFormSet; -} __attribute__ (( packed )) efi_snp_formset = { - .Header = { - .Length = sizeof ( efi_snp_formset ), - .Type = EFI_HII_PACKAGE_FORMS, - }, - .FormSet = EFI_IFR_FORM_SET ( EFI_SNP_FORMSET_GUID_BASE, - EFI_SNP_FORMSET_TITLE, - EFI_SNP_FORMSET_HELP, - typeof ( efi_snp_formset.FormSet ), - EFI_HII_PLATFORM_SETUP_FORMSET_GUID, - EFI_HII_IBM_UCM_COMPLIANT_FORMSET_GUID ), - .Class = EFI_IFR_GUID_CLASS ( EFI_NETWORK_DEVICE_CLASS ), - .SubClass = EFI_IFR_GUID_SUBCLASS ( 0x03 ), - .Form = EFI_IFR_FORM ( EFI_SNP_FORM, EFI_SNP_FORMSET_TITLE ), - .ProductText = EFI_IFR_TEXT ( EFI_SNP_PRODUCT_PROMPT, - EFI_SNP_PRODUCT_HELP, - EFI_SNP_PRODUCT_TEXT ), - .VersionText = EFI_IFR_TEXT ( EFI_SNP_VERSION_PROMPT, - EFI_SNP_VERSION_HELP, - EFI_SNP_VERSION_TEXT ), - .DriverText = EFI_IFR_TEXT ( EFI_SNP_DRIVER_PROMPT, - EFI_SNP_DRIVER_HELP, - EFI_SNP_DRIVER_TEXT ), - .DeviceText = EFI_IFR_TEXT ( EFI_SNP_DEVICE_PROMPT, - EFI_SNP_DEVICE_HELP, - EFI_SNP_DEVICE_TEXT ), - .EndForm = EFI_IFR_END(), - .EndFormSet = EFI_IFR_END(), -}; + return find_child_settings ( netdev_settings ( snpdev->netdev ), + NVO_SETTINGS_NAME ); +} /** - * Generate EFI SNP string + * Check whether or not setting is applicable * - * @v wbuf Buffer - * @v swlen Size of buffer (in wide characters) * @v snpdev SNP device - * @ret wlen Length of string (in wide characters) + * @v setting Setting + * @ret applies Setting applies */ -static int efi_snp_string ( wchar_t *wbuf, ssize_t swlen, - enum efi_snp_hii_string_id id, - struct efi_snp_device *snpdev ) { - struct net_device *netdev = snpdev->netdev; - struct device *dev = netdev->dev; +static int efi_snp_hii_setting_applies ( struct efi_snp_device *snpdev, + struct setting *setting ) { - switch ( id ) { - case EFI_SNP_LANGUAGE_NAME: - return efi_ssnprintf ( wbuf, swlen, "English" ); - case EFI_SNP_FORMSET_TITLE: - return efi_ssnprintf ( wbuf, swlen, "%s (%s)", - ( PRODUCT_NAME[0] ? - PRODUCT_NAME : PRODUCT_SHORT_NAME ), - netdev_addr ( netdev ) ); - case EFI_SNP_FORMSET_HELP: - return efi_ssnprintf ( wbuf, swlen, - "Configure " PRODUCT_SHORT_NAME ); - case EFI_SNP_PRODUCT_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Name" ); - case EFI_SNP_PRODUCT_HELP: - return efi_ssnprintf ( wbuf, swlen, "Firmware product name" ); - case EFI_SNP_PRODUCT_TEXT: - return efi_ssnprintf ( wbuf, swlen, "%s", - ( PRODUCT_NAME[0] ? - PRODUCT_NAME : PRODUCT_SHORT_NAME ) ); - case EFI_SNP_VERSION_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Version" ); - case EFI_SNP_VERSION_HELP: - return efi_ssnprintf ( wbuf, swlen, "Firmware version" ); - case EFI_SNP_VERSION_TEXT: - return efi_ssnprintf ( wbuf, swlen, VERSION ); - case EFI_SNP_DRIVER_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Driver" ); - case EFI_SNP_DRIVER_HELP: - return efi_ssnprintf ( wbuf, swlen, "Firmware driver" ); - case EFI_SNP_DRIVER_TEXT: - return efi_ssnprintf ( wbuf, swlen, "%s", dev->driver_name ); - case EFI_SNP_DEVICE_PROMPT: - return efi_ssnprintf ( wbuf, swlen, "Device" ); - case EFI_SNP_DEVICE_HELP: - return efi_ssnprintf ( wbuf, swlen, "Hardware device" ); - case EFI_SNP_DEVICE_TEXT: - return efi_ssnprintf ( wbuf, swlen, "%s", dev->name ); - default: - assert ( 0 ); - return 0; + return nvo_applies ( efi_snp_hii_settings ( snpdev ), setting ); +} + +/** + * Generate a random GUID + * + * @v guid GUID to fill in + */ +static void efi_snp_hii_random_guid ( EFI_GUID *guid ) { + uint8_t *byte = ( ( uint8_t * ) guid ); + unsigned int i; + + for ( i = 0 ; i < sizeof ( *guid ) ; i++ ) + *(byte++) = random(); +} + +/** + * Generate EFI SNP questions + * + * @v snpdev SNP device + * @v ifr IFR builder + * @v varstore_id Variable store identifier + */ +static void efi_snp_hii_questions ( struct efi_snp_device *snpdev, + struct efi_ifr_builder *ifr, + unsigned int varstore_id ) { + struct setting *setting; + unsigned int name_id; + unsigned int prompt_id; + unsigned int help_id; + unsigned int question_id; + + /* Add all applicable settings */ + for_each_table_entry ( setting, SETTINGS ) { + if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) ) + continue; + name_id = efi_ifr_string ( ifr, "%s", setting->name ); + prompt_id = efi_ifr_string ( ifr, "%s", setting->description ); + help_id = efi_ifr_string ( ifr, "http://ipxe.org/cfg/%s", + setting->name ); + question_id = setting->tag; + efi_ifr_string_op ( ifr, prompt_id, help_id, + question_id, varstore_id, name_id, + 0, 0x00, 0xff, 0 ); } } /** - * Generate EFI SNP string package - * - * @v strings String package header buffer - * @v max_len Buffer length - * @v snpdev SNP device - * @ret len Length of string package - */ -static int efi_snp_strings ( EFI_HII_STRING_PACKAGE_HDR *strings, - size_t max_len, struct efi_snp_device *snpdev ) { - static const char language[] = "en-us"; - void *buf = strings; - ssize_t remaining = max_len; - size_t hdrsize; - EFI_HII_SIBT_STRING_UCS2_BLOCK *string; - ssize_t wremaining; - size_t string_wlen; - unsigned int id; - EFI_HII_STRING_BLOCK *end; - size_t len; - - /* Calculate header size */ - hdrsize = ( offsetof ( typeof ( *strings ), Language ) + - sizeof ( language ) ); - buf += hdrsize; - remaining -= hdrsize; - - /* Fill in strings */ - for ( id = 1 ; id < EFI_SNP_MAX_STRING_ID ; id++ ) { - string = buf; - if ( remaining >= ( ( ssize_t ) sizeof ( string->Header ) ) ) - string->Header.BlockType = EFI_HII_SIBT_STRING_UCS2; - buf += offsetof ( typeof ( *string ), StringText ); - remaining -= offsetof ( typeof ( *string ), StringText ); - wremaining = ( remaining / - ( ( ssize_t ) sizeof ( string->StringText[0] ))); - assert ( ! ( ( remaining <= 0 ) && ( wremaining > 0 ) ) ); - string_wlen = efi_snp_string ( string->StringText, wremaining, - id, snpdev ); - buf += ( ( string_wlen + 1 /* wNUL */ ) * - sizeof ( string->StringText[0] ) ); - remaining -= ( ( string_wlen + 1 /* wNUL */ ) * - sizeof ( string->StringText[0] ) ); - } - - /* Fill in end marker */ - end = buf; - if ( remaining >= ( ( ssize_t ) sizeof ( *end ) ) ) - end->BlockType = EFI_HII_SIBT_END; - buf += sizeof ( *end ); - remaining -= sizeof ( *end ); - - /* Calculate overall length */ - len = ( max_len - remaining ); - - /* Fill in string package header */ - if ( strings ) { - memset ( strings, 0, sizeof ( *strings ) ); - strings->Header.Length = len; - strings->Header.Type = EFI_HII_PACKAGE_STRINGS; - strings->HdrSize = hdrsize; - strings->StringInfoOffset = hdrsize; - strings->LanguageName = EFI_SNP_LANGUAGE_NAME; - memcpy ( strings->Language, language, sizeof ( language ) ); - } - - return len; -} - -/** - * Generate EFI SNP package list + * Build HII package list for SNP device * * @v snpdev SNP device - * @ret package_list Package list, or NULL on error - * - * The package list is allocated using malloc(), and must eventually - * be freed by the caller. + * @ret package Package list, or NULL on error */ static EFI_HII_PACKAGE_LIST_HEADER * -efi_snp_package_list ( struct efi_snp_device *snpdev ) { - size_t strings_len = efi_snp_strings ( NULL, 0, snpdev ); - struct { - EFI_HII_PACKAGE_LIST_HEADER header; - struct efi_snp_formset formset; - union { - EFI_HII_STRING_PACKAGE_HDR strings; - uint8_t pad[strings_len]; - } __attribute__ (( packed )) strings; - EFI_HII_PACKAGE_HEADER end; - } __attribute__ (( packed )) *package_list; +efi_snp_hii_package_list ( struct efi_snp_device *snpdev ) { + struct net_device *netdev = snpdev->netdev; + struct device *dev = netdev->dev; + struct efi_ifr_builder ifr; + EFI_HII_PACKAGE_LIST_HEADER *package; + const char *product_name; + EFI_GUID package_guid; + EFI_GUID formset_guid; + EFI_GUID varstore_guid; + unsigned int title_id; + unsigned int varstore_id; - /* Allocate package list */ - package_list = zalloc ( sizeof ( *package_list ) ); - if ( ! package_list ) + /* Initialise IFR builder */ + efi_ifr_init ( &ifr ); + + /* Determine product name */ + product_name = ( PRODUCT_NAME[0] ? PRODUCT_NAME : PRODUCT_SHORT_NAME ); + + /* Generate GUIDs */ + efi_snp_hii_random_guid ( &package_guid ); + efi_snp_hii_random_guid ( &formset_guid ); + efi_snp_hii_random_guid ( &varstore_guid ); + + /* Generate title string (used more than once) */ + title_id = efi_ifr_string ( &ifr, "%s (%s)", product_name, + netdev_addr ( netdev ) ); + + /* Generate opcodes */ + efi_ifr_form_set_op ( &ifr, &formset_guid, title_id, + efi_ifr_string ( &ifr, + "Configure " PRODUCT_SHORT_NAME), + &efi_hii_platform_setup_formset_guid, + &efi_hii_ibm_ucm_compliant_formset_guid, NULL ); + efi_ifr_guid_class_op ( &ifr, EFI_NETWORK_DEVICE_CLASS ); + efi_ifr_guid_subclass_op ( &ifr, 0x03 ); + varstore_id = efi_ifr_varstore_name_value_op ( &ifr, &varstore_guid ); + efi_ifr_form_op ( &ifr, title_id ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Name" ), + efi_ifr_string ( &ifr, "Firmware product name" ), + efi_ifr_string ( &ifr, "%s", product_name ) ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Version" ), + efi_ifr_string ( &ifr, "Firmware version" ), + efi_ifr_string ( &ifr, VERSION ) ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Driver" ), + efi_ifr_string ( &ifr, "Firmware driver" ), + efi_ifr_string ( &ifr, "%s", dev->driver_name ) ); + efi_ifr_text_op ( &ifr, + efi_ifr_string ( &ifr, "Device" ), + efi_ifr_string ( &ifr, "Hardware device" ), + efi_ifr_string ( &ifr, "%s", dev->name ) ); + efi_snp_hii_questions ( snpdev, &ifr, varstore_id ); + efi_ifr_end_op ( &ifr ); + efi_ifr_end_op ( &ifr ); + + /* Build package */ + package = efi_ifr_package ( &ifr, &package_guid, "en-us", + efi_ifr_string ( &ifr, "English" ) ); + if ( ! package ) { + DBGC ( snpdev, "SNPDEV %p could not build IFR package\n", + snpdev ); + efi_ifr_free ( &ifr ); return NULL; + } - /* Create a unique GUID for this package list and formset */ - efi_snp_formset.FormSet.FormSet.Guid.Data1++; + /* Free temporary storage */ + efi_ifr_free ( &ifr ); + return package; +} - /* Populate package list */ - memcpy ( &package_list->header.PackageListGuid, - &efi_snp_formset.FormSet.FormSet.Guid, - sizeof ( package_list->header.PackageListGuid ) ); - package_list->header.PackageLength = sizeof ( *package_list ); - memcpy ( &package_list->formset, &efi_snp_formset, - sizeof ( package_list->formset ) ); - efi_snp_strings ( &package_list->strings.strings, - sizeof ( package_list->strings ), snpdev ); - package_list->end.Length = sizeof ( package_list->end ); - package_list->end.Type = EFI_HII_PACKAGE_END; +/** + * Append response to result string + * + * @v snpdev SNP device + * @v key Key + * @v value Value + * @v results Result string + * @ret rc Return status code + * + * The result string is allocated dynamically using + * BootServices::AllocatePool(), and the caller is responsible for + * eventually calling BootServices::FreePool(). + */ +static int efi_snp_hii_append ( struct efi_snp_device *snpdev __unused, + const char *key, const char *value, + wchar_t **results ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + size_t len; + void *new; - return &package_list->header; + /* Allocate new string */ + len = ( ( *results ? ( wcslen ( *results ) + 1 /* "&" */ ) : 0 ) + + strlen ( key ) + 1 /* "=" */ + strlen ( value ) + 1 /* NUL */ ); + bs->AllocatePool ( EfiBootServicesData, ( len * sizeof ( wchar_t ) ), + &new ); + if ( ! new ) + return -ENOMEM; + + /* Populate string */ + efi_snprintf ( new, len, "%ls%s%s=%s", ( *results ? *results : L"" ), + ( *results ? L"&" : L"" ), key, value ); + bs->FreePool ( *results ); + *results = new; + + return 0; +} + +/** + * Fetch HII setting + * + * @v snpdev SNP device + * @v key Key + * @v value Value + * @v results Result string + * @v have_setting Flag indicating detection of a setting + * @ret rc Return status code + */ +static int efi_snp_hii_fetch ( struct efi_snp_device *snpdev, + const char *key, const char *value, + wchar_t **results, int *have_setting ) { + struct settings *settings = efi_snp_hii_settings ( snpdev ); + struct setting *setting; + int len; + char *buf; + char *encoded; + int i; + int rc; + + /* Handle ConfigHdr components */ + if ( ( strcasecmp ( key, "GUID" ) == 0 ) || + ( strcasecmp ( key, "NAME" ) == 0 ) || + ( strcasecmp ( key, "PATH" ) == 0 ) ) { + return efi_snp_hii_append ( snpdev, key, value, results ); + } + if ( have_setting ) + *have_setting = 1; + + /* Do nothing more unless we have a settings block */ + if ( ! settings ) { + rc = -ENOTSUP; + goto err_no_settings; + } + + /* Identify setting */ + setting = find_setting ( key ); + if ( ! setting ) { + DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n", + snpdev, key ); + rc = -ENODEV; + goto err_find_setting; + } + + /* Encode value */ + if ( setting_exists ( settings, setting ) ) { + + /* Calculate formatted length */ + len = fetchf_setting ( settings, setting, NULL, 0 ); + if ( len < 0 ) { + rc = len; + DBGC ( snpdev, "SNPDEV %p could not fetch %s: %s\n", + snpdev, setting->name, strerror ( rc ) ); + goto err_fetchf_len; + } + + /* Allocate buffer for formatted value and HII-encoded value */ + buf = zalloc ( len + 1 /* NUL */ + ( len * 4 ) + 1 /* NUL */ ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + encoded = ( buf + len + 1 /* NUL */ ); + + /* Format value */ + fetchf_setting ( settings, setting, buf, ( len + 1 /* NUL */ )); + for ( i = 0 ; i < len ; i++ ) { + sprintf ( ( encoded + ( 4 * i ) ), "%04x", + *( ( uint8_t * ) buf + i ) ); + } + + } else { + + /* Non-existent or inapplicable setting */ + buf = NULL; + encoded = ""; + } + + /* Append results */ + if ( ( rc = efi_snp_hii_append ( snpdev, key, encoded, + results ) ) != 0 ) { + goto err_append; + } + + /* Success */ + rc = 0; + + err_append: + free ( buf ); + err_alloc: + err_fetchf_len: + err_find_setting: + err_no_settings: + return rc; +} + +/** + * Fetch HII setting + * + * @v snpdev SNP device + * @v key Key + * @v value Value + * @v results Result string (unused) + * @v have_setting Flag indicating detection of a setting (unused) + * @ret rc Return status code + */ +static int efi_snp_hii_store ( struct efi_snp_device *snpdev, + const char *key, const char *value, + wchar_t **results __unused, + int *have_setting __unused ) { + struct settings *settings = efi_snp_hii_settings ( snpdev ); + struct setting *setting; + char *buf; + char tmp[5]; + char *endp; + int len; + int i; + int rc; + + /* Handle ConfigHdr components */ + if ( ( strcasecmp ( key, "GUID" ) == 0 ) || + ( strcasecmp ( key, "NAME" ) == 0 ) || + ( strcasecmp ( key, "PATH" ) == 0 ) ) { + /* Nothing to do */ + return 0; + } + + /* Do nothing more unless we have a settings block */ + if ( ! settings ) { + rc = -ENOTSUP; + goto err_no_settings; + } + + /* Identify setting */ + setting = find_setting ( key ); + if ( ! setting ) { + DBGC ( snpdev, "SNPDEV %p no such setting \"%s\"\n", + snpdev, key ); + rc = -ENODEV; + goto err_find_setting; + } + + /* Allocate buffer */ + len = ( strlen ( value ) / 4 ); + buf = zalloc ( len + 1 /* NUL */ ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + + /* Decode value */ + tmp[4] = '\0'; + for ( i = 0 ; i < len ; i++ ) { + memcpy ( tmp, ( value + ( i * 4 ) ), 4 ); + buf[i] = strtoul ( tmp, &endp, 16 ); + if ( endp != &tmp[4] ) { + DBGC ( snpdev, "SNPDEV %p invalid character %s\n", + snpdev, tmp ); + rc = -EINVAL; + goto err_inval; + } + } + + /* Store value */ + if ( ( rc = storef_setting ( settings, setting, buf ) ) != 0 ) { + DBGC ( snpdev, "SNPDEV %p could not store \"%s\" into %s: %s\n", + snpdev, buf, setting->name, strerror ( rc ) ); + goto err_storef; + } + + /* Success */ + rc = 0; + + err_storef: + err_inval: + free ( buf ); + err_alloc: + err_find_setting: + err_no_settings: + return rc; +} + +/** + * Process portion of HII configuration string + * + * @v snpdev SNP device + * @v string HII configuration string + * @v progress Progress through HII configuration string + * @v results Results string + * @v have_setting Flag indicating detection of a setting (unused) + * @v process Function used to process key=value pairs + * @ret rc Return status code + */ +static int efi_snp_hii_process ( struct efi_snp_device *snpdev, + wchar_t *string, wchar_t **progress, + wchar_t **results, int *have_setting, + int ( * process ) ( struct efi_snp_device *, + const char *key, + const char *value, + wchar_t **results, + int *have_setting ) ) { + wchar_t *wkey = string; + wchar_t *wend = string; + wchar_t *wvalue = NULL; + size_t key_len; + size_t value_len; + void *temp; + char *key; + char *value; + int rc; + + /* Locate key, value (if any), and end */ + while ( *wend ) { + if ( *wend == L'&' ) + break; + if ( *(wend++) == L'=' ) + wvalue = wend; + } + + /* Allocate memory for key and value */ + key_len = ( ( wvalue ? ( wvalue - 1 ) : wend ) - wkey ); + value_len = ( wvalue ? ( wend - wvalue ) : 0 ); + temp = zalloc ( key_len + 1 /* NUL */ + value_len + 1 /* NUL */ ); + if ( ! temp ) + return -ENOMEM; + key = temp; + value = ( temp + key_len + 1 /* NUL */ ); + + /* Copy key and value */ + while ( key_len-- ) + key[key_len] = wkey[key_len]; + while ( value_len-- ) + value[value_len] = wvalue[value_len]; + + /* Process key and value */ + if ( ( rc = process ( snpdev, key, value, results, + have_setting ) ) != 0 ) { + goto err; + } + + /* Update progress marker */ + *progress = wend; + + err: + /* Free temporary storage */ + free ( temp ); + + return rc; } /** @@ -292,14 +524,47 @@ efi_snp_package_list ( struct efi_snp_device *snpdev ) { static EFI_STATUS EFIAPI efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_STRING request, EFI_STRING *progress, - EFI_STRING *results __unused ) { + EFI_STRING *results ) { struct efi_snp_device *snpdev = container_of ( hii, struct efi_snp_device, hii ); + int have_setting = 0; + wchar_t *pos; + int rc; - DBGC ( snpdev, "SNPDEV %p ExtractConfig \"%ls\"\n", snpdev, request ); + DBGC ( snpdev, "SNPDEV %p ExtractConfig request \"%ls\"\n", + snpdev, request ); - *progress = request; - return EFI_INVALID_PARAMETER; + /* Initialise results */ + *results = NULL; + + /* Process all request fragments */ + for ( pos = *progress = request ; *progress && **progress ; + pos = *progress + 1 ) { + if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, + results, &have_setting, + efi_snp_hii_fetch ) ) != 0 ) { + return RC_TO_EFIRC ( rc ); + } + } + + /* If we have no explicit request, return all settings */ + if ( ! have_setting ) { + struct setting *setting; + + for_each_table_entry ( setting, SETTINGS ) { + if ( ! efi_snp_hii_setting_applies ( snpdev, setting ) ) + continue; + if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name, + NULL, results, + NULL ) ) != 0 ) { + return rc; + } + } + } + + DBGC ( snpdev, "SNPDEV %p ExtractConfig results \"%ls\"\n", + snpdev, *results ); + return 0; } /** @@ -315,11 +580,22 @@ efi_snp_hii_route_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, EFI_STRING config, EFI_STRING *progress ) { struct efi_snp_device *snpdev = container_of ( hii, struct efi_snp_device, hii ); + wchar_t *pos; + int rc; DBGC ( snpdev, "SNPDEV %p RouteConfig \"%ls\"\n", snpdev, config ); - *progress = config; - return EFI_INVALID_PARAMETER; + /* Process all request fragments */ + for ( pos = *progress = config ; *progress && **progress ; + pos = *progress + 1 ) { + if ( ( rc = efi_snp_hii_process ( snpdev, pos, progress, + NULL, NULL, + efi_snp_hii_store ) ) != 0 ) { + return RC_TO_EFIRC ( rc ); + } + } + + return 0; } /** @@ -368,7 +644,7 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) { memcpy ( &snpdev->hii, &efi_snp_device_hii, sizeof ( snpdev->hii ) ); /* Create HII package list */ - snpdev->package_list = efi_snp_package_list ( snpdev ); + snpdev->package_list = efi_snp_hii_package_list ( snpdev ); if ( ! snpdev->package_list ) { DBGC ( snpdev, "SNPDEV %p could not create HII package list\n", snpdev ); From 885384faf360c7501382182e620c32880fc783a5 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 19 Oct 2012 23:03:38 +0100 Subject: [PATCH 171/250] [arp] Increase robustness of ARP discarder Take ownership from the ARP cache at the start of arp_destroy(), to ensure that no code path can lead to arp_destroy() being re-entered. Signed-off-by: Michael Brown --- src/net/arp.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/net/arp.c b/src/net/arp.c index d96cb4cc..b94eb906 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -180,13 +180,16 @@ static void arp_destroy ( struct arp_entry *arp, int rc ) { struct net_device *netdev = arp->netdev; struct net_protocol *net_protocol = arp->net_protocol; struct io_buffer *iobuf; - struct io_buffer *tmp; + + /* Take ownership from cache */ + list_del ( &arp->list ); /* Stop timer */ stop_timer ( &arp->timer ); /* Discard any outstanding I/O buffers */ - list_for_each_entry_safe ( iobuf, tmp, &arp->tx_queue, list ) { + while ( ( iobuf = list_first_entry ( &arp->tx_queue, struct io_buffer, + list ) ) != NULL ) { DBGC2 ( arp, "ARP %p %s %s %s discarding deferred packet: " "%s\n", arp, netdev->name, net_protocol->name, net_protocol->ntoa ( arp->net_dest ), strerror ( rc ) ); @@ -198,8 +201,7 @@ static void arp_destroy ( struct arp_entry *arp, int rc ) { net_protocol->name, net_protocol->ntoa ( arp->net_dest ), strerror ( rc ) ); - /* Remove from cache and drop reference */ - list_del ( &arp->list ); + /* Drop remaining reference */ ref_put ( &arp->refcnt ); } @@ -518,12 +520,13 @@ static unsigned int arp_discard ( void ) { struct arp_entry *arp; /* Drop oldest cache entry, if any */ - list_for_each_entry_reverse ( arp, &arp_entries, list ) { + arp = list_last_entry ( &arp_entries, struct arp_entry, list ); + if ( arp ) { arp_destroy ( arp, -ENOBUFS ); return 1; + } else { + return 0; } - - return 0; } /** ARP cache discarder From 34a81da0c8dd47628a7408cd3f8d8a926d1ecbee Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 20 Oct 2012 14:44:34 -0700 Subject: [PATCH 172/250] [test] Remove self-test for empty formatted setting value Commit 5ad445f ("[settings] Treat an empty formatted value as meaning "delete setting"") (re)defined the semantics of storing an empty formatted setting as meaning "delete setting". Remove the existing self-test using an empty formatted hex setting value, since it no longer conforms to the defined semantics. Signed-off-by: Michael Brown --- src/tests/settings_test.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tests/settings_test.c b/src/tests/settings_test.c index 9e87a514..028f8163 100644 --- a/src/tests/settings_test.c +++ b/src/tests/settings_test.c @@ -239,8 +239,6 @@ static void settings_test_exec ( void ) { RAW ( 0xf2, 0x37, 0xb2, 0x18 ), "0xf237b218" ); /* "hex" setting type */ - storef_ok ( &test_settings, &test_hex_setting, - "", RAW ( 0x00 ) ); storef_ok ( &test_settings, &test_hex_setting, ":", RAW ( 0x00, 0x00 ) ); storef_ok ( &test_settings, &test_hex_setting, From a27413c82a29a9d35a72e0d789f1f17fd9910739 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 Oct 2012 08:26:43 -0700 Subject: [PATCH 173/250] [util] Fix uninitialised-variable warning in einfo.c Signed-off-by: Michael Brown --- src/util/einfo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/einfo.c b/src/util/einfo.c index d83828df..354d475f 100644 --- a/src/util/einfo.c +++ b/src/util/einfo.c @@ -93,10 +93,11 @@ static void einfo ( const char *infile, ( ( ( char * ) einfo ) + einfo->desc ) ); } + /* Unmap file */ + munmap ( start, len ); } - /* Unmap and close file */ - munmap ( start, len ); + /* Close file */ close ( fd ); } From 0e7819d298958084e64c0d413ec0b13fae07c479 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 22 Oct 2012 08:42:53 -0700 Subject: [PATCH 174/250] [efi] Add missing RC_TO_EFIRC() conversion Signed-off-by: Michael Brown --- src/interface/efi/efi_snp_hii.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface/efi/efi_snp_hii.c b/src/interface/efi/efi_snp_hii.c index 96e9aa20..90f94984 100644 --- a/src/interface/efi/efi_snp_hii.c +++ b/src/interface/efi/efi_snp_hii.c @@ -557,7 +557,7 @@ efi_snp_hii_extract_config ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii, if ( ( rc = efi_snp_hii_fetch ( snpdev, setting->name, NULL, results, NULL ) ) != 0 ) { - return rc; + return RC_TO_EFIRC ( rc ); } } } From 1d381680647ad7484a765533dcff37387ff01c65 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 20 Oct 2012 18:30:19 -0700 Subject: [PATCH 175/250] [autoboot] Avoid excess backspacing after displaying Ctrl-B prompt Remove the newline from the "Press Ctrl-B..." prompt string, so that prompt() does not attempt to backspace beyond the start of the line. Signed-off-by: Michael Brown --- src/core/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/main.c b/src/core/main.c index 9fd4a76f..9ee31d2d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -48,7 +48,9 @@ static int shell_banner ( void ) { if ( BANNER_TIMEOUT <= 0 ) return 0; - return ( prompt ( "\nPress Ctrl-B for the iPXE command line...", + /* Prompt user */ + printf ( "\n" ); + return ( prompt ( "Press Ctrl-B for the iPXE command line...", ( BANNER_TIMEOUT * 100 ), CTRL_B ) == 0 ); } From 7cf6c6bfedb9cda38bd1ea4a30035527cb5195d5 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 23 Oct 2012 14:05:03 -0700 Subject: [PATCH 176/250] [efi] Add EFI_COMPONENT_NAME2_PROTOCOL instance for each SNP device Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi_snp.h | 7 ++++ src/interface/efi/efi_snp.c | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/include/ipxe/efi/efi_snp.h b/src/include/ipxe/efi/efi_snp.h index 81564921..c8676090 100644 --- a/src/include/ipxe/efi/efi_snp.h +++ b/src/include/ipxe/efi/efi_snp.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,8 @@ struct efi_snp_device { unsigned int rx_count_events; /** The network interface identifier */ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii; + /** Component name protocol */ + EFI_COMPONENT_NAME2_PROTOCOL name2; /** HII configuration access protocol */ EFI_HII_CONFIG_ACCESS_PROTOCOL hii; /** HII package list */ @@ -54,6 +57,10 @@ struct efi_snp_device { EFI_HII_HANDLE hii_handle; /** Device name */ wchar_t name[ sizeof ( ( ( struct net_device * ) NULL )->name ) ]; + /** Driver name */ + wchar_t driver_name[16]; + /** Controller name */ + wchar_t controller_name[32]; /** The device path * * This field is variable in size and must appear at the end diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 84d522b9..c48572e8 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -56,6 +56,10 @@ static EFI_GUID efi_nii31_protocol_guid = { { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 } }; +/** EFI component name protocol */ +static EFI_GUID efi_component_name2_protocol_guid + = EFI_COMPONENT_NAME2_PROTOCOL_GUID; + /** List of SNP devices */ static LIST_HEAD ( efi_snp_devices ); @@ -701,6 +705,54 @@ static EFI_SIMPLE_NETWORK_PROTOCOL efi_snp_device_snp = { .Receive = efi_snp_receive, }; +/****************************************************************************** + * + * Component name protocol + * + ****************************************************************************** + */ + +/** + * Look up driver name + * + * @v name2 Component name protocol + * @v language Language to use + * @v driver_name Driver name to fill in + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_snp_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2, + CHAR8 *language __unused, CHAR16 **driver_name ) { + struct efi_snp_device *snpdev = + container_of ( name2, struct efi_snp_device, name2 ); + + *driver_name = snpdev->driver_name; + return 0; +} + +/** + * Look up controller name + * + * @v name2 Component name protocol + * @v device Device + * @v child Child device, or NULL + * @v language Language to use + * @v driver_name Device name to fill in + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2, + EFI_HANDLE device __unused, + EFI_HANDLE child __unused, + CHAR8 *language __unused, + CHAR16 **controller_name ) { + struct efi_snp_device *snpdev = + container_of ( name2, struct efi_snp_device, name2 ); + + *controller_name = snpdev->controller_name; + return 0; +} + /****************************************************************************** * * iPXE network driver @@ -794,6 +846,19 @@ static int efi_snp_probe ( struct net_device *netdev ) { strncpy ( snpdev->nii.StringId, "iPXE", sizeof ( snpdev->nii.StringId ) ); + /* Populate the component name structure */ + efi_snprintf ( snpdev->driver_name, + ( sizeof ( snpdev->driver_name ) / + sizeof ( snpdev->driver_name[0] ) ), "%s", + netdev->dev->driver_name ); + efi_snprintf ( snpdev->controller_name, + ( sizeof ( snpdev->controller_name ) / + sizeof ( snpdev->controller_name[0] ) ), "%s (%s)", + netdev->name, netdev_addr ( netdev ) ); + snpdev->name2.GetDriverName = efi_snp_get_driver_name; + snpdev->name2.GetControllerName = efi_snp_get_controller_name; + snpdev->name2.SupportedLanguages = "en"; + /* Populate the device name */ efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) / sizeof ( snpdev->name[0] ) ), @@ -822,6 +887,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, + &efi_component_name2_protocol_guid, &snpdev->name2, NULL ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not install protocols: " "%s\n", snpdev, efi_strerror ( efirc ) ); @@ -862,6 +928,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, + &efi_component_name2_protocol_guid, &snpdev->name2, NULL ); err_install_protocol_interface: bs->CloseEvent ( snpdev->snp.WaitForPacket ); @@ -922,6 +989,7 @@ static void efi_snp_remove ( struct net_device *netdev ) { &efi_device_path_protocol_guid, &snpdev->path, &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, + &efi_component_name2_protocol_guid, &snpdev->name2, NULL ); bs->CloseEvent ( snpdev->snp.WaitForPacket ); netdev_put ( snpdev->netdev ); From dace457bafd839eeabbf18a2a34c1005ccab4cc0 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Oct 2012 11:21:34 -0700 Subject: [PATCH 177/250] [intel] Report receive overruns via network device errors Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 6 +++++- src/drivers/net/intel.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 353fc971..0811ed91 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -699,10 +699,14 @@ static void intel_poll ( struct net_device *netdev ) { if ( icr & INTEL_IRQ_TXDW ) intel_poll_tx ( netdev ); - /* Poll for RX completionsm, if applicable */ + /* Poll for RX completions, if applicable */ if ( icr & INTEL_IRQ_RXT0 ) intel_poll_rx ( netdev ); + /* Report receive overruns */ + if ( icr & INTEL_IRQ_RXO ) + netdev_rx_err ( netdev, NULL, -ENOBUFS ); + /* Check link state, if applicable */ if ( icr & INTEL_IRQ_LSC ) intel_check_link ( netdev ); diff --git a/src/drivers/net/intel.h b/src/drivers/net/intel.h index b38a7139..e9e9052b 100644 --- a/src/drivers/net/intel.h +++ b/src/drivers/net/intel.h @@ -93,6 +93,7 @@ enum intel_descriptor_status { #define INTEL_IRQ_TXDW 0x00000001UL /**< Transmit descriptor done */ #define INTEL_IRQ_LSC 0x00000004UL /**< Link status change */ #define INTEL_IRQ_RXT0 0x00000080UL /**< Receive timer */ +#define INTEL_IRQ_RXO 0x00000400UL /**< Receive overrun */ /** Interrupt Mask Set/Read Register */ #define INTEL_IMS 0x000d0UL From 947976da0caa929434775d978f2dcc7c9aee69f9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Oct 2012 13:26:51 -0700 Subject: [PATCH 178/250] [netdevice] Do not force a poll on net_tx() Including a netdev_poll() within net_tx() can cause the net_step() loop to end up processing hundreds or thousands of packets within a single step, since each received packet being processed may trigger a response which, in turn causes a poll for further received packets. Network devices must now ensure that the TX ring is at least as large as the RX ring, in order to avoid running out of TX descriptors. This should not cause any problems; unlike the RX ring, there is no substantial memory cost incurred by increasing the TX ring size. Signed-off-by: Michael Brown --- src/net/netdevice.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/net/netdevice.c b/src/net/netdevice.c index 5a4d8635..bea06752 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -672,13 +672,6 @@ int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, struct ll_protocol *ll_protocol = netdev->ll_protocol; int rc; - /* Force a poll on the netdevice to (potentially) clear any - * backed-up TX completions. This is needed on some network - * devices to avoid excessive losses due to small TX ring - * sizes. - */ - netdev_poll ( netdev ); - /* Add link-layer header */ if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source, net_protocol->net_proto ) ) != 0 ) { From c86790df5cd50b47b8a6b69a3c2367bd28f6cf3c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Oct 2012 20:41:39 -0700 Subject: [PATCH 179/250] [settings] Add fetchf_named_setting_copy() Signed-off-by: Michael Brown --- src/core/settings.c | 39 +++++++++++++++++++++++++++++++++++++ src/include/ipxe/settings.h | 1 + 2 files changed, 40 insertions(+) diff --git a/src/core/settings.c b/src/core/settings.c index 1b19c8f6..656ae19f 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -1332,6 +1332,45 @@ int fetchf_named_setting ( const char *name, return len; } +/** + * Fetch and format copy of value of named setting + * + * @v name Name of setting + * @v data Buffer to allocate and fill with formatted value + * @ret len Length of formatted value, or negative error + * + * The caller is responsible for eventually freeing the allocated + * buffer. + * + * To allow the caller to distinguish between a non-existent setting + * and an error in allocating memory for the copy, this function will + * return success (and a NULL buffer pointer) for a non-existent + * setting. + */ +int fetchf_named_setting_copy ( const char *name, char **data ) { + int len; + int check_len; + + /* Avoid returning uninitialised data on error */ + *data = NULL; + + /* Fetch formatted value length, and return success if non-existent */ + len = fetchf_named_setting ( name, NULL, 0, NULL, 0 ); + if ( len < 0 ) + return 0; + + /* Allocate buffer */ + *data = malloc ( len + 1 /* NUL */ ); + if ( ! *data ) + return -ENOMEM; + + /* Fetch formatted value */ + check_len = fetchf_named_setting ( name, NULL, 0, *data, + ( len + 1 /* NUL */ ) ); + assert ( check_len == len ); + return len; +} + /****************************************************************************** * * Setting types diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index 68987bdd..3f887602 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -291,6 +291,7 @@ extern int storef_named_setting ( const char *name, extern int fetchf_named_setting ( const char *name, char *name_buf, size_t name_len, char *value_buf, size_t value_len ); +extern int fetchf_named_setting_copy ( const char *name, char **data ); extern char * expand_settings ( const char *string ); extern struct setting_type setting_type_string __setting_type; From 4dedccfa1fece8d8e2d6d22c81023817aebd7e2e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Oct 2012 20:16:15 -0700 Subject: [PATCH 180/250] [readline] Allow a prefilled input string to be provided Signed-off-by: Michael Brown --- src/hci/readline.c | 11 +++++++++-- src/hci/shell.c | 2 +- src/include/readline/readline.h | 1 + 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/hci/readline.c b/src/hci/readline.c index 2ecb8f27..a199fb0e 100644 --- a/src/hci/readline.c +++ b/src/hci/readline.c @@ -241,13 +241,14 @@ void history_free ( struct readline_history *history ) { * Read line from console (with history) * * @v prompt Prompt string + * @v prefill Prefill string, or NULL for no prefill * @v history History buffer, or NULL for no history * @ret line Line read from console (excluding terminating newline) * * The returned line is allocated with malloc(); the caller must * eventually call free() to release the storage. */ -char * readline_history ( const char *prompt, +char * readline_history ( const char *prompt, const char *prefill, struct readline_history *history ) { char buf[READLINE_MAX]; struct edit_string string; @@ -265,6 +266,12 @@ char * readline_history ( const char *prompt, init_editstring ( &string, buf, sizeof ( buf ) ); buf[0] = '\0'; + /* Prefill string, if applicable */ + if ( prefill ) { + replace_string ( &string, prefill ); + sync_console ( &string ); + } + while ( 1 ) { /* Handle keypress */ key = edit_string ( &string, getkey ( 0 ) ); @@ -321,5 +328,5 @@ char * readline_history ( const char *prompt, * eventually call free() to release the storage. */ char * readline ( const char *prompt ) { - return readline_history ( prompt, NULL ); + return readline_history ( prompt, NULL, NULL ); } diff --git a/src/hci/shell.c b/src/hci/shell.c index 33438da0..f4cf9bc8 100644 --- a/src/hci/shell.c +++ b/src/hci/shell.c @@ -86,7 +86,7 @@ int shell ( void ) { /* Read and execute commands */ do { - line = readline_history ( shell_prompt, &history ); + line = readline_history ( shell_prompt, NULL, &history ); if ( line ) { rc = system ( line ); free ( line ); diff --git a/src/include/readline/readline.h b/src/include/readline/readline.h index 42dfd8c4..8b159975 100644 --- a/src/include/readline/readline.h +++ b/src/include/readline/readline.h @@ -51,6 +51,7 @@ struct readline_history { extern void history_free ( struct readline_history *history ); extern char * __malloc readline_history ( const char *prompt, + const char *prefill, struct readline_history *history ); extern char * __malloc readline ( const char *prompt ); From 34863a51c27164fd9a9f83dda45ff2a79131c42e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Oct 2012 20:42:21 -0700 Subject: [PATCH 181/250] [settings] Prefill existing setting value in "read" command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When prompting the user to enter a setting value via the "read" command, prefill the input buffer with the setting's current value. Requested-by: Ján Ondrej (SAL) Signed-off-by: Michael Brown --- src/hci/commands/nvo_cmd.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/hci/commands/nvo_cmd.c b/src/hci/commands/nvo_cmd.c index fb8ec876..b3775d09 100644 --- a/src/hci/commands/nvo_cmd.c +++ b/src/hci/commands/nvo_cmd.c @@ -109,7 +109,8 @@ static struct command_descriptor clear_read_cmd = */ static int set_core_exec ( int argc, char **argv, struct command_descriptor *cmd, - int ( * get_value ) ( char **args, char **value ) ) { + int ( * get_value ) ( const char *name, + char **args, char **value ) ) { struct set_core_options opts; const char *name; char *value; @@ -123,7 +124,7 @@ static int set_core_exec ( int argc, char **argv, name = argv[optind]; /* Parse setting value */ - if ( ( rc = get_value ( &argv[ optind + 1 ], &value ) ) != 0 ) + if ( ( rc = get_value ( name, &argv[ optind + 1 ], &value ) ) != 0 ) goto err_get_value; /* Determine total length of command line */ @@ -147,11 +148,12 @@ static int set_core_exec ( int argc, char **argv, /** * Get setting value for "set" command * + * @v name Setting name * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ -static int set_value ( char **args, char **value ) { +static int set_value ( const char *name __unused, char **args, char **value ) { *value = concat_args ( args ); if ( ! *value ) @@ -174,11 +176,13 @@ static int set_exec ( int argc, char **argv ) { /** * Get setting value for "clear" command * + * @v name Setting name * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ -static int clear_value ( char **args __unused, char **value ) { +static int clear_value ( const char *name __unused, char **args __unused, + char **value ) { *value = NULL; return 0; @@ -198,14 +202,24 @@ static int clear_exec ( int argc, char **argv ) { /** * Get setting value for "read" command * + * @v name Setting name + * @v args Remaining arguments * @ret value Setting value * @ret rc Return status code */ -static int read_value ( char **args __unused, char **value ) { +static int read_value ( const char *name, char **args __unused, char **value ) { + char *existing; + int rc; - *value = readline ( NULL ); - if ( ! *value ) - return -ENOMEM; + /* Read existing value */ + if ( ( rc = fetchf_named_setting_copy ( name, &existing ) ) < 0 ) + return rc; + + /* Read new value */ + *value = readline_history ( NULL, existing, NULL ); + + /* Free existing value */ + free ( existing ); return 0; } From 88e19fcda95fa1ea59d262898001207c4406eb6d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Oct 2012 22:44:00 -0700 Subject: [PATCH 182/250] [netdevice] Clear network device setting before unregistering Avoid memory leaks by clearing any (non-child) settings immediately before unregistering the network device settings block. Signed-off-by: Michael Brown --- src/net/netdevice.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net/netdevice.c b/src/net/netdevice.c index bea06752..ec3456a9 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -486,6 +486,7 @@ int register_netdev ( struct net_device *netdev ) { err_probe: for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) driver->remove ( netdev ); + clear_settings ( netdev_settings ( netdev ) ); unregister_settings ( netdev_settings ( netdev ) ); err_register_settings: return rc; @@ -570,6 +571,7 @@ void unregister_netdev ( struct net_device *netdev ) { driver->remove ( netdev ); /* Unregister per-netdev configuration settings */ + clear_settings ( netdev_settings ( netdev ) ); unregister_settings ( netdev_settings ( netdev ) ); /* Remove from device list */ From 2c011d77ae0147b8cc68bc4f3c577ebf55b83f16 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 24 Oct 2012 23:21:49 -0700 Subject: [PATCH 183/250] [readline] Allow readline_history() to return a meaningful status Signed-off-by: Michael Brown --- src/hci/commands/nvo_cmd.c | 14 +++++++++----- src/hci/readline.c | 30 +++++++++++++++++++----------- src/hci/shell.c | 2 +- src/include/ipxe/errfile.h | 1 + src/include/readline/readline.h | 5 ++--- 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/hci/commands/nvo_cmd.c b/src/hci/commands/nvo_cmd.c index b3775d09..f255bbf5 100644 --- a/src/hci/commands/nvo_cmd.c +++ b/src/hci/commands/nvo_cmd.c @@ -213,15 +213,19 @@ static int read_value ( const char *name, char **args __unused, char **value ) { /* Read existing value */ if ( ( rc = fetchf_named_setting_copy ( name, &existing ) ) < 0 ) - return rc; + goto err_existing; /* Read new value */ - *value = readline_history ( NULL, existing, NULL ); + if ( ( rc = readline_history ( NULL, existing, NULL, value ) ) != 0 ) + goto err_new; - /* Free existing value */ + /* Success */ + rc = 0; + + err_new: free ( existing ); - - return 0; + err_existing: + return rc; } /** diff --git a/src/hci/readline.c b/src/hci/readline.c index a199fb0e..d67980b2 100644 --- a/src/hci/readline.c +++ b/src/hci/readline.c @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -244,18 +245,22 @@ void history_free ( struct readline_history *history ) { * @v prefill Prefill string, or NULL for no prefill * @v history History buffer, or NULL for no history * @ret line Line read from console (excluding terminating newline) + * @ret rc Return status code * * The returned line is allocated with malloc(); the caller must * eventually call free() to release the storage. */ -char * readline_history ( const char *prompt, const char *prefill, - struct readline_history *history ) { +int readline_history ( const char *prompt, const char *prefill, + struct readline_history *history, char **line ) { char buf[READLINE_MAX]; struct edit_string string; int key; int move_by; const char *new_string; - char *line; + int rc; + + /* Avoid returning uninitialised data on error */ + *line = NULL; /* Display prompt, if applicable */ if ( prompt ) @@ -280,12 +285,11 @@ char * readline_history ( const char *prompt, const char *prefill, switch ( key ) { case CR: case LF: - line = strdup ( buf ); - if ( ! line ) - printf ( "\nOut of memory" ); + *line = strdup ( buf ); + rc = ( ( *line ) ? 0 : -ENOMEM ); goto done; case CTRL_C: - line = NULL; + rc = -ECANCELED; goto done; case KEY_UP: move_by = 1; @@ -311,11 +315,12 @@ char * readline_history ( const char *prompt, const char *prefill, done: putchar ( '\n' ); if ( history ) { - if ( line && line[0] ) - history_append ( history, line ); + if ( *line && (*line)[0] ) + history_append ( history, *line ); history_cleanup ( history ); } - return line; + assert ( ( rc == 0 ) ^ ( *line == NULL ) ); + return rc; } /** @@ -328,5 +333,8 @@ char * readline_history ( const char *prompt, const char *prefill, * eventually call free() to release the storage. */ char * readline ( const char *prompt ) { - return readline_history ( prompt, NULL, NULL ); + char *line; + + readline_history ( prompt, NULL, NULL, &line ); + return line; } diff --git a/src/hci/shell.c b/src/hci/shell.c index f4cf9bc8..b6208676 100644 --- a/src/hci/shell.c +++ b/src/hci/shell.c @@ -86,7 +86,7 @@ int shell ( void ) { /* Read and execute commands */ do { - line = readline_history ( shell_prompt, NULL, &history ); + readline_history ( shell_prompt, NULL, &history, &line ); if ( line ) { rc = system ( line ); free ( line ); diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index dd63225d..514e1f8a 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -264,6 +264,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_ocsp ( ERRFILE_OTHER | 0x002f0000 ) #define ERRFILE_nslookup ( ERRFILE_OTHER | 0x00300000 ) #define ERRFILE_efi_snp_hii ( ERRFILE_OTHER | 0x00310000 ) +#define ERRFILE_readline ( ERRFILE_OTHER | 0x00320000 ) /** @} */ diff --git a/src/include/readline/readline.h b/src/include/readline/readline.h index 8b159975..0449a3f9 100644 --- a/src/include/readline/readline.h +++ b/src/include/readline/readline.h @@ -50,9 +50,8 @@ struct readline_history { }; extern void history_free ( struct readline_history *history ); -extern char * __malloc readline_history ( const char *prompt, - const char *prefill, - struct readline_history *history ); +extern int readline_history ( const char *prompt, const char *prefill, + struct readline_history *history, char **line ); extern char * __malloc readline ( const char *prompt ); #endif /* _READLINE_H */ From c4ee23e7c6421016400eb76d28a3e2d12617c8ea Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 15 Oct 2012 13:04:31 +0100 Subject: [PATCH 184/250] [hermon] Use PCI VPD for non-volatile option storage Signed-off-by: Michael Brown --- src/drivers/infiniband/hermon.c | 32 ++++++++++++++++++++++++++++++-- src/drivers/infiniband/hermon.h | 10 ++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index 8a4fba94..a9c72870 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -42,6 +42,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include "hermon.h" /** @@ -3383,7 +3385,7 @@ static int hermon_register_netdev ( struct hermon *hermon, &query_port ) ) != 0 ) { DBGC ( hermon, "Hermon %p port %d could not query port: %s\n", hermon, ibdev->port, strerror ( rc ) ); - return rc; + goto err_query_port; } mac.dwords[0] = htonl ( MLX_GET ( &query_port, mac_47_32 ) ); mac.dwords[1] = htonl ( MLX_GET ( &query_port, mac_31_0 ) ); @@ -3394,10 +3396,26 @@ static int hermon_register_netdev ( struct hermon *hermon, if ( ( rc = register_netdev ( netdev ) ) != 0 ) { DBGC ( hermon, "Hermon %p port %d could not register network " "device: %s\n", hermon, ibdev->port, strerror ( rc ) ); - return rc; + goto err_register_netdev; + } + + /* Register non-volatile options */ + if ( ( rc = register_nvo ( &port->nvo, + netdev_settings ( netdev ) ) ) != 0 ) { + DBGC ( hermon, "Hermon %p port %d could not register non-" + "volatile options: %s\n", + hermon, ibdev->port, strerror ( rc ) ); + goto err_register_nvo; } return 0; + + unregister_nvo ( &port->nvo ); + err_register_nvo: + unregister_netdev ( netdev ); + err_register_netdev: + err_query_port: + return rc; } /** @@ -3429,6 +3447,7 @@ static void hermon_unregister_netdev ( struct hermon *hermon __unused, struct hermon_port *port ) { struct net_device *netdev = port->netdev; + unregister_nvo ( &port->nvo ); unregister_netdev ( netdev ); } @@ -3822,6 +3841,15 @@ static int hermon_probe ( struct pci_device *pci ) { goto err_set_port_type; } + /* Initialise non-volatile storage */ + nvs_vpd_init ( &hermon->nvsvpd, pci ); + for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) { + port = &hermon->port[i]; + nvs_vpd_nvo_init ( &hermon->nvsvpd, + HERMON_VPD_FIELD ( port->ibdev->port ), + &port->nvo, NULL ); + } + /* Register devices */ for ( i = 0 ; i < hermon->cap.num_ports ; i++ ) { port = &hermon->port[i]; diff --git a/src/drivers/infiniband/hermon.h b/src/drivers/infiniband/hermon.h index 26940f6f..e0b028f2 100644 --- a/src/drivers/infiniband/hermon.h +++ b/src/drivers/infiniband/hermon.h @@ -13,6 +13,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include "mlx_bitops.h" #include "MT25408_PRM.h" @@ -135,6 +137,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define HERMON_MOD_STAT_CFG_SET 0x01 #define HERMON_MOD_STAT_CFG_QUERY 0x03 +#define HERMON_VPD_FIELD( port ) \ + PCI_VPD_FIELD ( PCI_VPD_TAG_RW, 'V', ( '5' + (port) - 1 ) ) + /* * Datatypes that seem to be missing from the autogenerated documentation * @@ -825,6 +830,8 @@ struct hermon_port { struct ib_queue_pair *eth_qp; /** Port type */ struct hermon_port_type *type; + /** Non-volatile option storage */ + struct nvo_block nvo; }; /** A Hermon device */ @@ -891,6 +898,9 @@ struct hermon { /** QPN base */ unsigned long qpn_base; + /** Non-volatile storage in PCI VPD */ + struct nvs_vpd_device nvsvpd; + /** Ports */ struct hermon_port port[HERMON_MAX_PORTS]; From 0c5e3df6d91961e05844678e70902f0537cb2a22 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 25 Oct 2012 16:09:09 -0700 Subject: [PATCH 185/250] [intel] Poll RX queue if hardware reports RX overflow The Intel NIC emulation in some versions of VMware seems to suffer from a flaw whereby the Interrupt Cause Register (ICR) fails to assert the usual "packet received" bit (ICR.RXT0) if a receive overflow (ICR.RXO) has also occurred. Work around this flaw by polling for completed descriptors whenever either ICR.RXT0 or ICR.RXO is asserted. Reported-by: Miroslav Halas Debugged-by: Miroslav Halas Tested-by: Miroslav Halas Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 0811ed91..399b5354 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -700,7 +700,7 @@ static void intel_poll ( struct net_device *netdev ) { intel_poll_tx ( netdev ); /* Poll for RX completions, if applicable */ - if ( icr & INTEL_IRQ_RXT0 ) + if ( icr & ( INTEL_IRQ_RXT0 | INTEL_IRQ_RXO ) ) intel_poll_rx ( netdev ); /* Report receive overruns */ From 6586e03fba2c04f066660c707a352b15ab99f33d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 29 Oct 2012 10:14:00 +0000 Subject: [PATCH 186/250] [forcedeth] Increase TX ring size to prevent dropped packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 947976d ("[netdevice] Do not force a poll on net_tx()") requires network devices to have TX rings that are sufficiently large to allow a transmitted response to all packets received during a single poll. Reported-by: Robin Smidsrød Tested-by: Robin Smidsrød Signed-off-by: Michael Brown --- src/drivers/net/forcedeth.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/net/forcedeth.h b/src/drivers/net/forcedeth.h index 8a095eab..e1cf6f71 100644 --- a/src/drivers/net/forcedeth.h +++ b/src/drivers/net/forcedeth.h @@ -55,7 +55,7 @@ struct ring_desc_ex { #define DESC_VER_3 3 #define RX_RING_SIZE 16 -#define TX_RING_SIZE 16 +#define TX_RING_SIZE 32 #define RXTX_RING_SIZE ( ( RX_RING_SIZE ) + ( TX_RING_SIZE ) ) #define RX_RING_MIN 128 #define TX_RING_MIN 64 From f008698c68618111babd2a5b7c5438110f69261e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 2 Nov 2012 13:21:52 +0000 Subject: [PATCH 187/250] [build] Use -maccumulate-outgoing-args if required by gcc Current versions of gcc require -maccumulate-outgoing-args if any sysv_abi functions call ms_abi functions. This requirement is likely to be lifted in future gcc versions, so test explicitly to see if the current version of gcc requires -maccumulate-outgoing-args. This problem is currently masked since the implied -fasynchronous-unwind-tables (which is the default in current gcc versions) implies -maccumulate-outgoing-args. Signed-off-by: Michael Brown --- src/arch/x86_64/Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/arch/x86_64/Makefile b/src/arch/x86_64/Makefile index d2c2ff53..b687f340 100644 --- a/src/arch/x86_64/Makefile +++ b/src/arch/x86_64/Makefile @@ -26,6 +26,18 @@ CFLAGS += -fshort-wchar # CFLAGS += -Ui386 +# Add -maccumulate-outgoing-args if required by this version of gcc +# +ifeq ($(CCTYPE),gcc) +MS_ABI_TEST_CODE := extern void __attribute__ (( ms_abi )) ms_abi(); \ + void sysv_abi ( void ) { ms_abi(); } +MS_ABI_TEST = $(ECHO) '$(MS_ABI_TEST_CODE)' | \ + $(CC) -m64 -mno-accumulate-outgoing-args -x c -c - -o /dev/null \ + >/dev/null 2>&1 +MS_ABI_FLAGS := $(shell $(MS_ABI_TEST) || $(ECHO) '-maccumulate-outgoing-args') +WORKAROUND_CFLAGS += $(MS_ABI_FLAGS) +endif + # x86_64-specific directories containing source files # SRCDIRS += arch/x86_64/prefix From 0932bc5156bd88f773936ee5dac5d574ff921287 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 2 Nov 2012 12:15:36 +0000 Subject: [PATCH 188/250] [build] Inhibit .eh_frame on newer gcc versions Using -fno-dwarf2-cfi-asm is not sufficient to prevent the .eh_frame section from being generated on newer versions of gcc. Add -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables; this is sufficient to inhibit the .eh_frame section on gcc 4.7.1. This does not affect the overall binary size, but does fix the numbers reported by "size" for individual object files. Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 1e05beba..fce49288 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -162,9 +162,12 @@ endif # output of "size". Inhibit this. # ifeq ($(CCTYPE),gcc) -CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -x c -c /dev/null \ +CFI_TEST = $(CC) -fno-dwarf2-cfi-asm -fno-exceptions -fno-unwind-tables \ + -fno-asynchronous-unwind-tables -x c -c /dev/null \ -o /dev/null >/dev/null 2>&1 -CFI_FLAGS := $(shell $(CFI_TEST) && $(ECHO) '-fno-dwarf2-cfi-asm') +CFI_FLAGS := $(shell $(CFI_TEST) && \ + $(ECHO) '-fno-dwarf2-cfi-asm -fno-exceptions ' \ + '-fno-unwind-tables -fno-asynchronous-unwind-tables') WORKAROUND_CFLAGS += $(CFI_FLAGS) endif From 4867085c0cd334004e8d67dff7bd53996f23ade6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 2 Nov 2012 14:46:39 +0000 Subject: [PATCH 189/250] [build] Include version number within only a single object file Signed-off-by: Michael Brown --- src/Makefile | 5 --- src/Makefile.housekeeping | 7 ++++ src/arch/i386/image/multiboot.c | 5 ++- src/arch/i386/image/nbi.c | 11 +++-- .../i386/interface/syslinux/comboot_call.c | 7 +++- src/core/main.c | 5 ++- src/core/version.c | 41 +++++++++++++++++++ src/include/ipxe/version.h | 16 ++++++++ src/interface/efi/efi_snp_hii.c | 3 +- src/net/tcp/httpcore.c | 5 ++- src/net/udp/dhcp.c | 3 -- 11 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 src/core/version.c create mode 100644 src/include/ipxe/version.h diff --git a/src/Makefile b/src/Makefile index a061f834..210c6aa5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -169,11 +169,6 @@ GITVERSION := $(shell git describe --always --abbrev=1 --match "" 2>/dev/null) ifneq ($(GITVERSION),) VERSION += ($(GITVERSION)) endif -CFLAGS += -DVERSION_MAJOR=$(VERSION_MAJOR) \ - -DVERSION_MINOR=$(VERSION_MINOR) \ - -DVERSION_PATCH=$(VERSION_PATCH) \ - -DVERSION="\"$(VERSION)\"" -IDENT = '$(@F) $(VERSION) (GPL) ipxe.org' version : @$(ECHO) "$(VERSION)" diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index fce49288..f607c4d3 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -653,6 +653,13 @@ $(BIN)/embedded.o : override CC := env CCACHE_DISABLE=1 $(CC) $(BIN)/clientcert.o : override CC := env CCACHE_DISABLE=1 $(CC) +# Version number +# +CFLAGS_version += -DVERSION_MAJOR=$(VERSION_MAJOR) \ + -DVERSION_MINOR=$(VERSION_MINOR) \ + -DVERSION_PATCH=$(VERSION_PATCH) \ + -DVERSION="\"$(VERSION)\"" + # We automatically generate rules for any file mentioned in AUTO_SRCS # using the following set of templates. It would be cleaner to use # $(eval ...), but this function exists only in GNU make >= 3.80. diff --git a/src/arch/i386/image/multiboot.c b/src/arch/i386/image/multiboot.c index 8b8959e1..3d6d2bf3 100644 --- a/src/arch/i386/image/multiboot.c +++ b/src/arch/i386/image/multiboot.c @@ -39,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 ); @@ -247,7 +248,7 @@ static struct multiboot_info __bss16 ( mbinfo ); #define mbinfo __use_data16 ( mbinfo ) /** The multiboot bootloader name */ -static char __data16_array ( mb_bootloader_name, [] ) = "iPXE " VERSION; +static char __bss16_array ( mb_bootloader_name, [32] ); #define mb_bootloader_name __use_data16 ( mb_bootloader_name ) /** The multiboot memory map */ @@ -420,6 +421,8 @@ static int multiboot_exec ( struct image *image ) { mbinfo.cmdline = multiboot_add_cmdline ( image ); mbinfo.mods_addr = virt_to_phys ( mbmodules ); mbinfo.mmap_addr = virt_to_phys ( mbmemmap ); + snprintf ( mb_bootloader_name, sizeof ( mb_bootloader_name ), + "iPXE %s", product_version ); mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name ); if ( ( rc = multiboot_add_modules ( image, max, &mbinfo, mbmodules, ( sizeof ( mbmodules ) / diff --git a/src/arch/i386/image/nbi.c b/src/arch/i386/image/nbi.c index c516bb2e..d3e523e9 100644 --- a/src/arch/i386/image/nbi.c +++ b/src/arch/i386/image/nbi.c @@ -10,6 +10,7 @@ #include #include #include +#include /** @file * @@ -94,12 +95,6 @@ struct ebinfo { uint16_t flags; /* Bit flags */ }; -/** Info passed to NBI image */ -static struct ebinfo loaderinfo = { - VERSION_MAJOR, VERSION_MINOR, - 0 -}; - /** * Prepare a segment for an NBI image * @@ -281,6 +276,10 @@ static int nbi_boot16 ( struct image *image, struct imgheader *imgheader ) { * @ret rc Return status code, if image returns */ static int nbi_boot32 ( struct image *image, struct imgheader *imgheader ) { + struct ebinfo loaderinfo = { + product_major_version, product_minor_version, + 0 + }; int discard_D, discard_S, discard_b; int rc; diff --git a/src/arch/i386/interface/syslinux/comboot_call.c b/src/arch/i386/interface/syslinux/comboot_call.c index 3eee584c..fbf605f3 100644 --- a/src/arch/i386/interface/syslinux/comboot_call.c +++ b/src/arch/i386/interface/syslinux/comboot_call.c @@ -39,12 +39,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include "config/console.h" #include "config/serial.h" /** The "SYSLINUX" version string */ -static char __data16_array ( syslinux_version, [] ) = "\r\niPXE " VERSION; +static char __bss16_array ( syslinux_version, [32] ); #define syslinux_version __use_data16 ( syslinux_version ) /** The "SYSLINUX" copyright string */ @@ -326,6 +327,10 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) { /* SYSLINUX derivative ID */ ix86->regs.dl = BZI_LOADER_TYPE_IPXE; + /* SYSLINUX version */ + snprintf ( syslinux_version, sizeof ( syslinux_version ), + "\r\niPXE %s", product_version ); + /* SYSLINUX version and copyright strings */ ix86->segs.es = rm_ds; ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) ); diff --git a/src/core/main.c b/src/core/main.c index 9ee31d2d..7b7755c9 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -82,10 +83,10 @@ __asmcall int main ( void ) { * do so. * */ - printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE " VERSION + printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE %s" NORMAL " -- Open Source Network Boot Firmware -- " CYAN "http://ipxe.org" NORMAL "\n" - "Features:" ); + "Features:", product_version ); for_each_table_entry ( feature, FEATURES ) printf ( " %s", feature->name ); printf ( "\n" ); diff --git a/src/core/version.c b/src/core/version.c new file mode 100644 index 00000000..1aa22d8e --- /dev/null +++ b/src/core/version.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Version number + * + */ + +#include +#include + +/** Version number feature */ +FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH ); + +/** Product major version */ +const int product_major_version = VERSION_MAJOR; + +/** Product minor version */ +const int product_minor_version = VERSION_MINOR; + +/** Product version string */ +const char *product_version = VERSION; diff --git a/src/include/ipxe/version.h b/src/include/ipxe/version.h new file mode 100644 index 00000000..aa894d7e --- /dev/null +++ b/src/include/ipxe/version.h @@ -0,0 +1,16 @@ +#ifndef _IPXE_VERSION_H +#define _IPXE_VERSION_H + +/** @file + * + * Version number + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +extern const int product_major_version; +extern const int product_minor_version; +extern const char *product_version; + +#endif /* _IPXE_VERSION_H */ diff --git a/src/interface/efi/efi_snp_hii.c b/src/interface/efi/efi_snp_hii.c index 90f94984..3a1193a3 100644 --- a/src/interface/efi/efi_snp_hii.c +++ b/src/interface/efi/efi_snp_hii.c @@ -54,6 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -196,7 +197,7 @@ efi_snp_hii_package_list ( struct efi_snp_device *snpdev ) { efi_ifr_text_op ( &ifr, efi_ifr_string ( &ifr, "Version" ), efi_ifr_string ( &ifr, "Firmware version" ), - efi_ifr_string ( &ifr, VERSION ) ); + efi_ifr_string ( &ifr, "%s", product_version ) ); efi_ifr_text_op ( &ifr, efi_ifr_string ( &ifr, "Driver" ), efi_ifr_string ( &ifr, "Firmware driver" ), diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 7f178cc8..bccb35f5 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -48,6 +48,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /* Disambiguate the various error causes */ @@ -1141,11 +1142,11 @@ static void http_step ( struct http_request *http ) { /* Send request */ if ( ( rc = xfer_printf ( &http->socket, "%s %s HTTP/1.1\r\n" - "User-Agent: iPXE/" VERSION "\r\n" + "User-Agent: iPXE/%s\r\n" "Host: %s%s%s\r\n" "%s%s%s" "\r\n", - method, uri, http->uri->host, + method, uri, product_version, http->uri->host, ( http->uri->port ? ":" : "" ), ( http->uri->port ? diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index e652503d..e63c3e42 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -91,9 +91,6 @@ static uint8_t dhcp_request_options_data[] = { DHCP_END }; -/** Version number feature */ -FEATURE_VERSION ( VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH ); - /** DHCP server address setting */ struct setting dhcp_server_setting __setting ( SETTING_MISC ) = { .name = "dhcp-server", From f68b4069b1aeeeff3cef33659efd001125adcb26 Mon Sep 17 00:00:00 2001 From: Thomas Miletich Date: Fri, 2 Nov 2012 15:00:09 +0000 Subject: [PATCH 190/250] [build] Make version.o depend on the git index The version number string is currently updated only if version.o happens to be rebuilt due to changes in its dependencies. Add a dependency upon the git index, so that the version number is updated after any checkout. Signed-off-by: Thomas Miletich Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/Makefile.housekeeping | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index f607c4d3..d40f226f 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -659,6 +659,10 @@ CFLAGS_version += -DVERSION_MAJOR=$(VERSION_MAJOR) \ -DVERSION_MINOR=$(VERSION_MINOR) \ -DVERSION_PATCH=$(VERSION_PATCH) \ -DVERSION="\"$(VERSION)\"" +# Make sure the version number gets updated on every git checkout +ifneq ($(GITVERSION),) +$(BIN)/version.o : ../.git/index +endif # We automatically generate rules for any file mentioned in AUTO_SRCS # using the following set of templates. It would be cleaner to use From 54a861a7bdfb2186239d520d5e4b0ce88c7604ab Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 2 Nov 2012 16:12:56 +0000 Subject: [PATCH 191/250] [list] Reduce overall code size by externalising many list functions Typical saving is 10-20 bytes in each file using list functions. Signed-off-by: Michael Brown --- src/core/list.c | 84 +++++++++++++ src/include/ipxe/list.h | 253 +++++++++++++++++++++------------------- 2 files changed, 215 insertions(+), 122 deletions(-) create mode 100644 src/core/list.c diff --git a/src/core/list.c b/src/core/list.c new file mode 100644 index 00000000..77579d69 --- /dev/null +++ b/src/core/list.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Linked lists + * + */ + +#include + +void extern_list_add ( struct list_head *new, struct list_head *head ) { + inline_list_add ( new, head ); +} + +void extern_list_add_tail ( struct list_head *new, struct list_head *head ) { + inline_list_add_tail ( new, head ); +} + +void extern_list_del ( struct list_head *list ) { + inline_list_del ( list ); +} + +int extern_list_empty ( const struct list_head *list ) { + return inline_list_empty ( list ); +} + +int extern_list_is_singular ( const struct list_head *list ) { + return inline_list_is_singular ( list ); +} + +int extern_list_is_last ( const struct list_head *list, + const struct list_head *head ) { + return inline_list_is_last ( list, head ); +} + +void extern_list_cut_position ( struct list_head *new, + struct list_head *list, + struct list_head *entry ) { + inline_list_cut_position ( new, list, entry ); +} + +void extern_list_splice ( const struct list_head *list, + struct list_head *entry ) { + inline_list_splice ( list, entry ); +} + +void extern_list_splice_tail ( const struct list_head *list, + struct list_head *entry ) { + inline_list_splice_tail ( list, entry ); +} + +void extern_list_splice_init ( struct list_head *list, + struct list_head *entry ) { + inline_list_splice_init ( list, entry ); +} + +void extern_list_splice_tail_init ( struct list_head *list, + struct list_head *entry ) { + inline_list_splice_tail_init ( list, entry ); +} + +int extern_list_contains ( struct list_head *entry, + struct list_head *head ) { + return inline_list_contains ( entry, head ); +} diff --git a/src/include/ipxe/list.h b/src/include/ipxe/list.h index b14a83d7..0d097307 100644 --- a/src/include/ipxe/list.h +++ b/src/include/ipxe/list.h @@ -42,9 +42,9 @@ struct list_head { * * @v list List head */ -#define INIT_LIST_HEAD( list ) do { \ - (list)->next = (list); \ - (list)->prev = (list); \ +#define INIT_LIST_HEAD( list ) do { \ + (list)->next = (list); \ + (list)->prev = (list); \ } while ( 0 ) /** @@ -52,43 +52,35 @@ struct list_head { * * @v list List entry or head */ -#define list_check( list ) ( { \ - assert ( (list) != NULL ); \ - assert ( (list)->prev != NULL ); \ - assert ( (list)->next != NULL ); \ - assert ( (list)->next->prev == (list) ); \ - assert ( (list)->prev->next == (list) ); \ +#define list_check( list ) ( { \ + assert ( (list) != NULL ); \ + assert ( (list)->prev != NULL ); \ + assert ( (list)->next != NULL ); \ + assert ( (list)->next->prev == (list) ); \ + assert ( (list)->prev->next == (list) ); \ } ) -/** - * Insert a list entry between two known consecutive entries - * - * @v new New list entry - * @v prev Previous list entry - * @v next Next list entry - */ -static inline void __list_add ( struct list_head *new, - struct list_head *prev, - struct list_head *next ) { - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - /** * Add a new entry to the head of a list * * @v new New entry to be added * @v head List head, or entry after which to add the new entry */ -static inline void list_add ( struct list_head *new, struct list_head *head ) { - __list_add ( new, head, head->next ); -} -#define list_add( new, head ) do { \ - list_check ( (head) ); \ - list_add ( (new), (head) ); \ +#define list_add( new, head ) do { \ + list_check ( (head) ); \ + extern_list_add ( (new), (head) ); \ } while ( 0 ) +static inline void inline_list_add ( struct list_head *new, + struct list_head *head ) { + struct list_head *prev = head; + struct list_head *next = head->next; + next->prev = (new); + (new)->next = next; + (new)->prev = prev; + prev->next = (new); +} +extern void extern_list_add ( struct list_head *new, + struct list_head *head ); /** * Add a new entry to the tail of a list @@ -96,26 +88,21 @@ static inline void list_add ( struct list_head *new, struct list_head *head ) { * @v new New entry to be added * @v head List head, or entry before which to add the new entry */ -static inline void list_add_tail ( struct list_head *new, - struct list_head *head ) { - __list_add ( new, head->prev, head ); -} -#define list_add_tail( new, head ) do { \ - list_check ( (head) ); \ - list_add_tail ( (new), (head) ); \ +#define list_add_tail( new, head ) do { \ + list_check ( (head) ); \ + extern_list_add_tail ( (new), (head) ); \ } while ( 0 ) - -/** - * Delete a list entry between two known consecutive entries - * - * @v prev Previous list entry - * @v next Next list entry - */ -static inline void __list_del ( struct list_head *prev, - struct list_head *next ) { - next->prev = prev; - prev->next = next; +static inline void inline_list_add_tail ( struct list_head *new, + struct list_head *head ) { + struct list_head *prev = head->prev; + struct list_head *next = head; + next->prev = (new); + (new)->next = next; + (new)->prev = prev; + prev->next = (new); } +extern void extern_list_add_tail ( struct list_head *new, + struct list_head *head ); /** * Delete an entry from a list @@ -125,37 +112,43 @@ static inline void __list_del ( struct list_head *prev, * Note that list_empty() on entry does not return true after this; * the entry is in an undefined state. */ -static inline void list_del ( struct list_head *list ) { - __list_del ( list->prev, list->next ); -} -#define list_del( list ) do { \ - list_check ( (list) ); \ - list_del ( (list) ); \ +#define list_del( list ) do { \ + list_check ( (list) ); \ + inline_list_del ( (list) ); \ } while ( 0 ) +static inline void inline_list_del ( struct list_head *list ) { + struct list_head *next = (list)->next; + struct list_head *prev = (list)->prev; + next->prev = prev; + prev->next = next; +} +extern void extern_list_del ( struct list_head *list ); /** * Test whether a list is empty * * @v list List head */ -static inline int list_empty ( const struct list_head *list ) { +#define list_empty( list ) ( { \ + list_check ( (list) ); \ + inline_list_empty ( (list) ); } ) +static inline int inline_list_empty ( const struct list_head *list ) { return ( list->next == list ); } -#define list_empty( list ) ( { \ - list_check ( (list) ); \ - list_empty ( (list) ); } ) +extern int extern_list_empty ( const struct list_head *list ); /** * Test whether a list has just one entry * * @v list List to test */ -static inline int list_is_singular ( const struct list_head *list ) { +#define list_is_singular( list ) ( { \ + list_check ( (list) ); \ + inline_list_is_singular ( (list) ); } ) +static inline int inline_list_is_singular ( const struct list_head *list ) { return ( ( ! list_empty ( list ) ) && ( list->next == list->prev ) ); } -#define list_is_singular( list ) ( { \ - list_check ( (list) ); \ - list_is_singular ( (list) ); } ) +extern int extern_list_is_singular ( const struct list_head *list ); /** * Test whether an entry is the last entry in list @@ -163,14 +156,16 @@ static inline int list_is_singular ( const struct list_head *list ) { * @v list List entry to test * @v head List head */ -static inline int list_is_last ( const struct list_head *list, - const struct list_head *head ) { +#define list_is_last( list, head ) ( { \ + list_check ( (list) ); \ + list_check ( (head) ); \ + inline_list_is_last ( (list), (head) ); } ) +static inline int inline_list_is_last ( const struct list_head *list, + const struct list_head *head ) { return ( list->next == head ); } -#define list_is_last( list, head ) ( { \ - list_check ( (list) ); \ - list_check ( (head) ); \ - list_is_last ( (list), (head) ); } ) +extern int extern_list_is_last ( const struct list_head *list, + const struct list_head *head ); /** * Cut a list into two @@ -183,9 +178,16 @@ static inline int list_is_last ( const struct list_head *list, * @c new, which should be an empty list. @c entry may be equal to @c * list, in which case no entries are moved. */ -static inline void list_cut_position ( struct list_head *new, - struct list_head *list, - struct list_head *entry ) { +#define list_cut_position( new, list, entry ) do { \ + list_check ( (new) ); \ + assert ( list_empty ( (new) ) ); \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_cut_position ( (new), (list), (entry) ); \ + } while ( 0 ) +static inline void inline_list_cut_position ( struct list_head *new, + struct list_head *list, + struct list_head *entry ) { struct list_head *first = entry->next; if ( list != entry ) { @@ -197,13 +199,9 @@ static inline void list_cut_position ( struct list_head *new, list->next->prev = list; } } -#define list_cut_position( new, list, entry ) do { \ - list_check ( (new) ); \ - assert ( list_empty ( (new) ) ); \ - list_check ( (list) ); \ - list_check ( (entry) ); \ - list_cut_position ( (new), (list), (entry) ); \ - } while ( 0 ) +extern void extern_list_cut_position ( struct list_head *new, + struct list_head *list, + struct list_head *entry ); /** * Move all entries from one list into another list @@ -215,8 +213,13 @@ static inline void list_cut_position ( struct list_head *new, * list is left in an undefined state; use @c list_splice_init() if * you want @c list to become an empty list. */ -static inline void list_splice ( const struct list_head *list, - struct list_head *entry ) { +#define list_splice( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice ( (list), (entry) ); \ + } while ( 0 ) +static inline void inline_list_splice ( const struct list_head *list, + struct list_head *entry ) { struct list_head *first = list->next; struct list_head *last = list->prev; @@ -227,11 +230,8 @@ static inline void list_splice ( const struct list_head *list, first->prev->next = first; } } -#define list_splice( list, entry ) do { \ - list_check ( (list) ); \ - list_check ( (entry) ); \ - list_splice ( (list), (entry) ); \ - } while ( 0 ) +extern void extern_list_splice ( const struct list_head *list, + struct list_head *entry ); /** * Move all entries from one list into another list @@ -243,8 +243,13 @@ static inline void list_splice ( const struct list_head *list, * list is left in an undefined state; use @c list_splice_tail_init() if * you want @c list to become an empty list. */ -static inline void list_splice_tail ( const struct list_head *list, - struct list_head *entry ) { +#define list_splice_tail( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice_tail ( (list), (entry) ); \ + } while ( 0 ) +static inline void inline_list_splice_tail ( const struct list_head *list, + struct list_head *entry ) { struct list_head *first = list->next; struct list_head *last = list->prev; @@ -255,11 +260,8 @@ static inline void list_splice_tail ( const struct list_head *list, last->next->prev = last; } } -#define list_splice_tail( list, entry ) do { \ - list_check ( (list) ); \ - list_check ( (entry) ); \ - list_splice_tail ( (list), (entry) ); \ - } while ( 0 ) +extern void extern_list_splice_tail ( const struct list_head *list, + struct list_head *entry ); /** * Move all entries from one list into another list and reinitialise empty list @@ -269,16 +271,18 @@ static inline void list_splice_tail ( const struct list_head *list, * * All entries from @c list are inserted after @c entry. */ -static inline void list_splice_init ( struct list_head *list, - struct list_head *entry ) { +#define list_splice_init( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice_init ( (list), (entry) ); \ + } while ( 0 ) +static inline void inline_list_splice_init ( struct list_head *list, + struct list_head *entry ) { list_splice ( list, entry ); INIT_LIST_HEAD ( list ); } -#define list_splice_init( list, entry ) do { \ - list_check ( (list) ); \ - list_check ( (entry) ); \ - list_splice_init ( (list), (entry) ); \ - } while ( 0 ) +extern void extern_list_splice_init ( struct list_head *list, + struct list_head *entry ); /** * Move all entries from one list into another list and reinitialise empty list @@ -288,16 +292,19 @@ static inline void list_splice_init ( struct list_head *list, * * All entries from @c list are inserted before @c entry. */ -static inline void list_splice_tail_init ( struct list_head *list, - struct list_head *entry ) { +#define list_splice_tail_init( list, entry ) do { \ + list_check ( (list) ); \ + list_check ( (entry) ); \ + extern_list_splice_tail_init ( (list), (entry) ); \ + } while ( 0 ) + +static inline void inline_list_splice_tail_init ( struct list_head *list, + struct list_head *entry ) { list_splice_tail ( list, entry ); INIT_LIST_HEAD ( list ); } -#define list_splice_tail_init( list, entry ) do { \ - list_check ( (list) ); \ - list_check ( (entry) ); \ - list_splice_tail_init ( (list), (entry) ); \ - } while ( 0 ) +extern void extern_list_splice_tail_init ( struct list_head *list, + struct list_head *entry ); /** * Get the container of a list entry @@ -307,8 +314,8 @@ static inline void list_splice_tail_init ( struct list_head *list, * @v member Name of list field within containing type * @ret container Containing object */ -#define list_entry( list, type, member ) ( { \ - list_check ( (list) ); \ +#define list_entry( list, type, member ) ( { \ + list_check ( (list) ); \ container_of ( list, type, member ); } ) /** @@ -319,9 +326,9 @@ static inline void list_splice_tail_init ( struct list_head *list, * @v member Name of list field within containing type * @ret first First list entry, or NULL */ -#define list_first_entry( list, type, member ) \ - ( list_empty ( (list) ) ? \ - ( type * ) NULL : \ +#define list_first_entry( list, type, member ) \ + ( list_empty ( (list) ) ? \ + ( type * ) NULL : \ list_entry ( (list)->next, type, member ) ) /** @@ -332,9 +339,9 @@ static inline void list_splice_tail_init ( struct list_head *list, * @v member Name of list field within containing type * @ret first First list entry, or NULL */ -#define list_last_entry( list, type, member ) \ - ( list_empty ( (list) ) ? \ - ( type * ) NULL : \ +#define list_last_entry( list, type, member ) \ + ( list_empty ( (list) ) ? \ + ( type * ) NULL : \ list_entry ( (list)->prev, type, member ) ) /** @@ -424,8 +431,12 @@ static inline void list_splice_tail_init ( struct list_head *list, * @v head List head * @ret present List contains specified entry */ -static inline int list_contains ( struct list_head *entry, - struct list_head *head ) { +#define list_contains( entry, head ) ( { \ + list_check ( (head) ); \ + list_check ( (entry) ); \ + extern_list_contains ( (entry), (head) ); } ) +static inline int inline_list_contains ( struct list_head *entry, + struct list_head *head ) { struct list_head *tmp; list_for_each ( tmp, head ) { @@ -434,10 +445,8 @@ static inline int list_contains ( struct list_head *entry, } return 0; } -#define list_contains( entry, head ) ( { \ - list_check ( (head) ); \ - list_check ( (entry) ); \ - list_contains ( (entry), (head) ); } ) +extern int extern_list_contains ( struct list_head *entry, + struct list_head *head ); /** * Test if list contains a specified entry @@ -446,7 +455,7 @@ static inline int list_contains ( struct list_head *entry, * @v head List head * @ret present List contains specified entry */ -#define list_contains_entry( entry, head, member ) \ +#define list_contains_entry( entry, head, member ) \ list_contains ( &(entry)->member, (head) ) /** From 1494d41d0a20a1facff7558ff825a2681b419e9d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 5 Nov 2012 16:09:38 +0000 Subject: [PATCH 192/250] [uaccess] Add userptr_sub() to find the difference between two user pointers Signed-off-by: Michael Brown --- src/arch/i386/include/librm.h | 6 ++++++ src/include/ipxe/efi/efi_uaccess.h | 6 ++++++ src/include/ipxe/linux/linux_uaccess.h | 6 ++++++ src/include/ipxe/uaccess.h | 21 +++++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/src/arch/i386/include/librm.h b/src/arch/i386/include/librm.h index c6992f64..801f586b 100644 --- a/src/arch/i386/include/librm.h +++ b/src/arch/i386/include/librm.h @@ -68,6 +68,12 @@ UACCESS_INLINE ( librm, userptr_add ) ( userptr_t userptr, off_t offset ) { return trivial_userptr_add ( userptr, offset ); } +static inline __always_inline off_t +UACCESS_INLINE ( librm, userptr_sub ) ( userptr_t userptr, + userptr_t subtrahend ) { + return trivial_userptr_sub ( userptr, subtrahend ); +} + static inline __always_inline void UACCESS_INLINE ( librm, memcpy_user ) ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, diff --git a/src/include/ipxe/efi/efi_uaccess.h b/src/include/ipxe/efi/efi_uaccess.h index dc226a3e..79c18972 100644 --- a/src/include/ipxe/efi/efi_uaccess.h +++ b/src/include/ipxe/efi/efi_uaccess.h @@ -56,6 +56,12 @@ UACCESS_INLINE ( efi, userptr_add ) ( userptr_t userptr, off_t offset ) { return trivial_userptr_add ( userptr, offset ); } +static inline __always_inline off_t +UACCESS_INLINE ( efi, userptr_sub ) ( userptr_t userptr, + userptr_t subtrahend ) { + return trivial_userptr_sub ( userptr, subtrahend ); +} + static inline __always_inline void UACCESS_INLINE ( efi, memcpy_user ) ( userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, diff --git a/src/include/ipxe/linux/linux_uaccess.h b/src/include/ipxe/linux/linux_uaccess.h index 1b496117..e4dfdd35 100644 --- a/src/include/ipxe/linux/linux_uaccess.h +++ b/src/include/ipxe/linux/linux_uaccess.h @@ -71,6 +71,12 @@ UACCESS_INLINE(linux, userptr_add)(userptr_t userptr, off_t offset) return trivial_userptr_add(userptr, offset); } +static inline __always_inline off_t +UACCESS_INLINE(linux, userptr_sub)(userptr_t userptr, userptr_t subtrahend) +{ + return trivial_userptr_sub ( userptr, subtrahend ); +} + static inline __always_inline void UACCESS_INLINE(linux, memcpy_user)(userptr_t dest, off_t dest_off, userptr_t src, off_t src_off, size_t len) { diff --git a/src/include/ipxe/uaccess.h b/src/include/ipxe/uaccess.h index b574c318..95e94367 100644 --- a/src/include/ipxe/uaccess.h +++ b/src/include/ipxe/uaccess.h @@ -82,6 +82,18 @@ trivial_userptr_add ( userptr_t userptr, off_t offset ) { return ( userptr + offset ); } +/** + * Subtract user pointers + * + * @v userptr User pointer + * @v subtrahend User pointer to be subtracted + * @ret offset Offset + */ +static inline __always_inline off_t +trivial_userptr_sub ( userptr_t userptr, userptr_t subtrahend ) { + return ( userptr - subtrahend ); +} + /** * Copy data between user buffers * @@ -239,6 +251,15 @@ void * user_to_virt ( userptr_t userptr, off_t offset ); */ userptr_t userptr_add ( userptr_t userptr, off_t offset ); +/** + * Subtract user pointers + * + * @v userptr User pointer + * @v subtrahend User pointer to be subtracted + * @ret offset Offset + */ +off_t userptr_sub ( userptr_t userptr, userptr_t subtrahend ); + /** * Convert virtual address to a physical address * From fd141fb6693520fd01b6f5a5d6b15379fb543254 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 5 Nov 2012 23:19:16 +0000 Subject: [PATCH 193/250] [umalloc] Split largest_memblock() function out from init_eheap() Signed-off-by: Michael Brown --- .../i386/interface/pcbios/memtop_umalloc.c | 57 ++----------- src/core/memblock.c | 81 +++++++++++++++++++ src/include/ipxe/memblock.h | 17 ++++ 3 files changed, 106 insertions(+), 49 deletions(-) create mode 100644 src/core/memblock.c create mode 100644 src/include/ipxe/memblock.h diff --git a/src/arch/i386/interface/pcbios/memtop_umalloc.c b/src/arch/i386/interface/pcbios/memtop_umalloc.c index 1821faf2..c382e3c3 100644 --- a/src/arch/i386/interface/pcbios/memtop_umalloc.c +++ b/src/arch/i386/interface/pcbios/memtop_umalloc.c @@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** Alignment of external allocated memory */ @@ -59,53 +60,14 @@ static size_t heap_size; /** * Initialise external heap * - * @ret rc Return status code */ -static int init_eheap ( void ) { - struct memory_map memmap; - unsigned int i; - - DBG ( "Allocating external heap\n" ); - - get_memmap ( &memmap ); - heap_size = 0; - for ( i = 0 ; i < memmap.count ; i++ ) { - struct memory_region *region = &memmap.regions[i]; - unsigned long r_start, r_end; - unsigned long r_size; - - DBG ( "Considering [%llx,%llx)\n", region->start, region->end); - - /* Truncate block to 4GB */ - if ( region->start > UINT_MAX ) { - DBG ( "...starts after 4GB\n" ); - continue; - } - r_start = region->start; - if ( region->end > UINT_MAX ) { - DBG ( "...end truncated to 4GB\n" ); - r_end = 0; /* =4GB, given the wraparound */ - } else { - r_end = region->end; - } - - /* Use largest block */ - r_size = ( r_end - r_start ); - if ( r_size > heap_size ) { - DBG ( "...new best block found\n" ); - top = bottom = phys_to_user ( r_end ); - heap_size = r_size; - } - } - - if ( ! heap_size ) { - DBG ( "No external heap available\n" ); - return -ENOMEM; - } +static void init_eheap ( void ) { + userptr_t base; + heap_size = largest_memblock ( &base ); + bottom = top = userptr_add ( base, heap_size ); DBG ( "External heap grows downwards from %lx (size %zx)\n", user_to_phys ( top, 0 ), heap_size ); - return 0; } /** @@ -144,13 +106,10 @@ static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) { struct external_memory extmem; userptr_t new = ptr; size_t align; - int rc; - /* Initialise external memory allocator if necessary */ - if ( bottom == top ) { - if ( ( rc = init_eheap() ) != 0 ) - return UNULL; - } + /* (Re)initialise external memory allocator if necessary */ + if ( bottom == top ) + init_eheap(); /* Get block properties into extmem */ if ( ptr && ( ptr != UNOWHERE ) ) { diff --git a/src/core/memblock.c b/src/core/memblock.c new file mode 100644 index 00000000..1fd89b87 --- /dev/null +++ b/src/core/memblock.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Largest memory block + * + */ + +#include +#include +#include +#include + +/** + * Find largest usable memory region + * + * @ret start Start of region + * @ret len Length of region + */ +size_t largest_memblock ( userptr_t *start ) { + struct memory_map memmap; + struct memory_region *region; + physaddr_t max = ~( ( physaddr_t ) 0 ); + physaddr_t region_start; + physaddr_t region_end; + size_t region_len; + unsigned int i; + size_t len = 0; + + /* Avoid returning uninitialised data on error */ + *start = UNULL; + + /* Scan through all memory regions */ + get_memmap ( &memmap ); + for ( i = 0 ; i < memmap.count ; i++ ) { + region = &memmap.regions[i]; + DBG ( "Considering [%llx,%llx)\n", region->start, region->end ); + + /* Truncate block to maximum physical address */ + if ( region->start > max ) { + DBG ( "...starts after maximum address %lx\n", max ); + continue; + } + region_start = region->start; + if ( region->end > max ) { + DBG ( "...end truncated to maximum address %lx\n", max); + region_end = 0; /* =max, given the wraparound */ + } else { + region_end = region->end; + } + region_len = ( region_end - region_start ); + + /* Use largest block */ + if ( region_len > len ) { + DBG ( "...new best block found\n" ); + *start = phys_to_user ( region_start ); + len = region_len; + } + } + + return len; +} diff --git a/src/include/ipxe/memblock.h b/src/include/ipxe/memblock.h new file mode 100644 index 00000000..13af3e43 --- /dev/null +++ b/src/include/ipxe/memblock.h @@ -0,0 +1,17 @@ +#ifndef _IPXE_MEMBLOCK_H +#define _IPXE_MEMBLOCK_H + +/** @file + * + * Largest memory block + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +extern size_t largest_memblock ( userptr_t *start ); + +#endif /* _IPXE_MEMBLOCK_H */ From 520323e36049f89ba0480cd5d0da2ade08197b0e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 12 Nov 2012 16:58:26 +0000 Subject: [PATCH 194/250] [test] Add self-tests for string functions Signed-off-by: Michael Brown --- src/tests/string_test.c | 133 ++++++++++++++++++++++++++++++++++++++++ src/tests/tests.c | 1 + 2 files changed, 134 insertions(+) create mode 100644 src/tests/string_test.c diff --git a/src/tests/string_test.c b/src/tests/string_test.c new file mode 100644 index 00000000..88181cc2 --- /dev/null +++ b/src/tests/string_test.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * String self-tests + * + * memcpy() tests are handled separately + */ + +/* Forcibly enable assertions */ +#undef NDEBUG + +#include +#include +#include +#include + +/** + * Perform string self-tests + * + */ +static void string_test_exec ( void ) { + + /* Test strlen() */ + ok ( strlen ( "" ) == 0 ); + ok ( strlen ( "Hello" ) == 5 ); + ok ( strlen ( "Hello world!" ) == 12 ); + ok ( strlen ( "Hello\0world!" ) == 5 ); + + /* Test strnlen() */ + ok ( strnlen ( "", 0 ) == 0 ); + ok ( strnlen ( "", 10 ) == 0 ); + ok ( strnlen ( "Hello", 0 ) == 0 ); + ok ( strnlen ( "Hello", 3 ) == 3 ); + ok ( strnlen ( "Hello", 5 ) == 5 ); + ok ( strnlen ( "Hello", 16 ) == 5 ); + ok ( strnlen ( "Hello world!", 5 ) == 5 ); + ok ( strnlen ( "Hello world!", 11 ) == 11 ); + ok ( strnlen ( "Hello world!", 16 ) == 12 ); + + /* Test strchr() */ + ok ( strchr ( "", 'a' ) == NULL ); + ok ( *(strchr ( "Testing", 'e' )) == 'e' ); + ok ( *(strchr ( "Testing", 'g' )) == 'g' ); + ok ( strchr ( "Testing", 'x' ) == NULL ); + + /* Test strcmp() */ + ok ( strcmp ( "", "" ) == 0 ); + ok ( strcmp ( "Hello", "Hello" ) == 0 ); + ok ( strcmp ( "Hello", "hello" ) != 0 ); + ok ( strcmp ( "Hello", "Hello world!" ) != 0 ); + ok ( strcmp ( "Hello world!", "Hello" ) != 0 ); + + /* Test strncmp() */ + ok ( strncmp ( "", "", 0 ) == 0 ); + ok ( strncmp ( "", "", 15 ) == 0 ); + ok ( strncmp ( "Goodbye", "Goodbye", 16 ) == 0 ); + ok ( strncmp ( "Goodbye", "Hello", 16 ) != 0 ); + ok ( strncmp ( "Goodbye", "Goodbye world", 32 ) != 0 ); + ok ( strncmp ( "Goodbye", "Goodbye world", 7 ) == 0 ); + + /* Test memcmp() */ + ok ( memcmp ( "", "", 0 ) == 0 ); + ok ( memcmp ( "Foo", "Foo", 3 ) == 0 ); + ok ( memcmp ( "Foo", "Bar", 3 ) != 0 ); + + /* Test memset() */ + { + static uint8_t test[7] = { '>', 1, 1, 1, 1, 1, '<' }; + static const uint8_t expected[7] = { '>', 0, 0, 0, 0, 0, '<' }; + memset ( ( test + 1 ), 0, ( sizeof ( test ) - 2 ) ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + { + static uint8_t test[4] = { '>', 0, 0, '<' }; + static const uint8_t expected[4] = { '>', 0xeb, 0xeb, '<' }; + memset ( ( test + 1 ), 0xeb, ( sizeof ( test ) - 2 ) ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + + /* Test memmove() */ + { + static uint8_t test[11] = + { '>', 1, 2, 3, 4, 5, 6, 7, 8, 9, '<' }; + static const uint8_t expected[11] = + { '>', 3, 4, 5, 6, 7, 8, 7, 8, 9, '<' }; + memmove ( ( test + 1 ), ( test + 3 ), 6 ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + { + static uint8_t test[12] = + { '>', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, '<' }; + static const uint8_t expected[12] = + { '>', 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, '<' }; + memmove ( ( test + 6 ), ( test + 1 ), 5 ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } + + /* Test memswap() */ + { + static uint8_t test[8] = + { '>', 1, 2, 3, 7, 8, 9, '<' }; + static const uint8_t expected[8] = + { '>', 7, 8, 9, 1, 2, 3, '<' }; + memswap ( ( test + 1 ), ( test + 4 ), 3 ); + ok ( memcmp ( test, expected, sizeof ( test ) ) == 0 ); + } +} + +/** String self-test */ +struct self_test string_test __self_test = { + .name = "string", + .exec = string_test_exec, +}; diff --git a/src/tests/tests.c b/src/tests/tests.c index a8d77788..af969ec8 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); /* Drag in all applicable self-tests */ REQUIRE_OBJECT ( memcpy_test ); +REQUIRE_OBJECT ( string_test ); REQUIRE_OBJECT ( list_test ); REQUIRE_OBJECT ( byteswap_test ); REQUIRE_OBJECT ( base64_test ); From 7cbac6859327296fba1c873d1f589fa90c1b9d91 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 4 Nov 2012 21:45:34 +0000 Subject: [PATCH 195/250] [libc] Remove obsolete implementation of memcpy() Signed-off-by: Michael Brown --- src/arch/x86/include/bits/string.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index f35cdab1..d9ebe306 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -27,18 +27,6 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); extern void * __memcpy ( void *dest, const void *src, size_t len ); -#if 0 -static inline __attribute__ (( always_inline )) void * -__memcpy ( void *dest, const void *src, size_t len ) { - int d0, d1, d2; - __asm__ __volatile__ ( "rep ; movsb" - : "=&c" ( d0 ), "=&S" ( d1 ), "=&D" ( d2 ) - : "0" ( len ), "1" ( src ), "2" ( dest ) - : "memory" ); - return dest; -} -#endif - static inline __attribute__ (( always_inline )) void * __constant_memcpy ( void *dest, const void *src, size_t len ) { union { From fc30b13b25d66c711778fee50ce2d5609ad361ee Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 4 Nov 2012 22:43:59 +0000 Subject: [PATCH 196/250] [libc] Reduce overall code size by externalising memmove() Typical saving is 15-20 bytes in each file using memmove(). Signed-off-by: Michael Brown --- src/arch/x86/core/x86_string.c | 50 +++++++++++++++++++++++++++++- src/arch/x86/include/bits/string.h | 48 ++++++++++++++-------------- 2 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 698dbe2e..59e0eaae 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -35,7 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); * @v len Length * @ret dest Destination address */ -void * __memcpy ( void *dest, const void *src, size_t len ) { +void * __attribute__ (( noinline )) __memcpy ( void *dest, const void *src, + size_t len ) { void *edi = dest; const void *esi = src; int discard_ecx; @@ -56,3 +57,50 @@ void * __memcpy ( void *dest, const void *src, size_t len ) { : "memory" ); return dest; } + +/** + * Copy memory area backwards + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * __attribute__ (( noinline )) __memcpy_reverse ( void *dest, + const void *src, + size_t len ) { + void *edi = ( dest + len - 1 ); + const void *esi = ( src + len - 1 ); + int discard_ecx; + + /* Assume memmove() is not performance-critical, and perform a + * bytewise copy for simplicity. + */ + __asm__ __volatile__ ( "std\n\t" + "rep movsb\n\t" + "cld\n\t" + : "=&D" ( edi ), "=&S" ( esi ), + "=&c" ( discard_ecx ) + : "0" ( edi ), "1" ( esi ), + "2" ( len ) + : "memory" ); + return dest; +} + + +/** + * Copy (possibly overlapping) memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * __memmove ( void *dest, const void *src, size_t len ) { + + if ( dest <= src ) { + return __memcpy ( dest, src, len ); + } else { + return __memcpy_reverse ( dest, src, len ); + } +} diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index d9ebe306..e5850ed9 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -26,6 +26,7 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); #define __HAVE_ARCH_MEMCPY extern void * __memcpy ( void *dest, const void *src, size_t len ); +extern void * __memcpy_reverse ( void *dest, const void *src, size_t len ); static inline __attribute__ (( always_inline )) void * __constant_memcpy ( void *dest, const void *src, size_t len ) { @@ -144,29 +145,30 @@ __constant_memcpy ( void *dest, const void *src, size_t len ) { __memcpy ( (dest), (src), (len) ) ) #define __HAVE_ARCH_MEMMOVE -static inline void * memmove(void * dest,const void * src, size_t n) -{ -int d0, d1, d2; -if (dest Date: Sun, 4 Nov 2012 22:50:27 +0000 Subject: [PATCH 197/250] [libc] Convert memcpy() from a macro to an inline function Signed-off-by: Michael Brown --- src/arch/x86/include/bits/string.h | 28 ++++++++++++++++++++++++---- src/include/string.h | 1 + 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index e5850ed9..f0d3c965 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -28,6 +28,14 @@ FILE_LICENCE ( PUBLIC_DOMAIN ); extern void * __memcpy ( void *dest, const void *src, size_t len ); extern void * __memcpy_reverse ( void *dest, const void *src, size_t len ); +/** + * Copy memory area (where length is a compile-time constant) + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ static inline __attribute__ (( always_inline )) void * __constant_memcpy ( void *dest, const void *src, size_t len ) { union { @@ -139,10 +147,22 @@ __constant_memcpy ( void *dest, const void *src, size_t len ) { return dest; } -#define memcpy( dest, src, len ) \ - ( __builtin_constant_p ( (len) ) ? \ - __constant_memcpy ( (dest), (src), (len) ) : \ - __memcpy ( (dest), (src), (len) ) ) +/** + * Copy memory area + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +static inline __attribute__ (( always_inline )) void * +memcpy ( void *dest, const void *src, size_t len ) { + if ( __builtin_constant_p ( len ) ) { + return __constant_memcpy ( dest, src, len ); + } else { + return __memcpy ( dest, src, len ); + } +} #define __HAVE_ARCH_MEMMOVE diff --git a/src/include/string.h b/src/include/string.h index 2fd6acf1..3482e1b2 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -37,6 +37,7 @@ char * __pure strpbrk(const char * cs,const char * ct) __nonnull; char * strtok(char * s,const char * ct) __nonnull; char * strsep(char **s, const char *ct) __nonnull; void * memset(void * s,int c,size_t count) __nonnull; +void * memcpy ( void *dest, const void *src, size_t len ) __nonnull; void * memmove(void * dest,const void *src,size_t count) __nonnull; int __pure memcmp(const void * cs,const void * ct, size_t count) __nonnull; From f8ece72fc9b441c8a72635558a18bca98b211081 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 4 Nov 2012 22:58:42 +0000 Subject: [PATCH 198/250] [libc] Remove unnecessary "cld" instruction from memset() Saving is one byte per call to memset(). Signed-off-by: Michael Brown --- src/arch/x86/include/bits/string.h | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index f0d3c965..5736295a 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -192,17 +192,24 @@ memmove ( void *dest, const void *src, size_t len ) { } #define __HAVE_ARCH_MEMSET -static inline void * memset(void *s, int c,size_t count) -{ -int d0, d1; -__asm__ __volatile__( - "cld\n\t" - "rep\n\t" - "stosb" - : "=&c" (d0), "=&D" (d1) - :"a" (c),"1" (s),"0" (count) - :"memory"); -return s; + +/** + * Fill memory region + * + * @v dest Destination address + * @v fill Fill pattern + * @v len Length + * @ret dest Destination address + */ +static inline void * memset ( void *dest, int fill, size_t len ) { + void *discard_D; + size_t discard_c; + + __asm__ __volatile__ ( "rep stosb" + : "=&D" ( discard_D ), "=&c" ( discard_c ) + : "0" ( dest ), "1" ( len ), "a" ( fill ) + : "memory" ); + return dest; } #define __HAVE_ARCH_MEMSWAP From 06766875ada566a95ff22aef2d6c7fadec4da4b8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 4 Nov 2012 23:53:59 +0000 Subject: [PATCH 199/250] [libc] Reduce overall code size by externalising strncmp() Typical saving is 20-30 bytes in each file using strncmp(). Signed-off-by: Michael Brown --- src/arch/x86/core/x86_string.c | 38 ++++++++++++++++++++++++++++++ src/arch/x86/include/bits/string.h | 23 ++---------------- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 59e0eaae..962a7d84 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -104,3 +104,41 @@ void * __memmove ( void *dest, const void *src, size_t len ) { return __memcpy_reverse ( dest, src, len ); } } + +/** + * Compare strings (up to a specified length) + * + * @v str1 First string + * @v str2 Second string + * @v len Maximum length + * @ret diff Difference + */ +int strncmp ( const char *str1, const char *str2, size_t len ) { + const void *discard_S; + const void *discard_D; + size_t discard_c; + int diff; + + __asm__ __volatile__ ( "\n1:\n\t" + "dec %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %b3, %b3\n\t" + "jnz 1b\n\t" + /* Equal */ + "\n2:\n\t" + "xor %3, %3\n\t" + "jmp 4f\n\t" + /* Not equal; CF indicates difference */ + "\n3:\n\t" + "sbb %3, %3\n\t" + "orb $1, %b3\n\t" + "\n4:\n\t" + : "=&S" ( discard_S ), "=&D" ( discard_D ), + "=&c" ( discard_c ), "=&a" ( diff ) + : "0" ( str1 ), "1" ( str2 ), "2" ( len ) ); + + return diff; +} diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index 5736295a..75a1f01a 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -230,27 +230,8 @@ return dest; } #define __HAVE_ARCH_STRNCMP -static inline int strncmp(const char * cs,const char * ct,size_t count) -{ -register int __res; -int d0, d1, d2; -__asm__ __volatile__( - "1:\tdecl %3\n\t" - "js 2f\n\t" - "lodsb\n\t" - "scasb\n\t" - "jne 3f\n\t" - "testb %%al,%%al\n\t" - "jne 1b\n" - "2:\txorl %%eax,%%eax\n\t" - "jmp 4f\n" - "3:\tsbbl %%eax,%%eax\n\t" - "orb $1,%%al\n" - "4:" - :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) - :"1" (cs),"2" (ct),"3" (count)); -return __res; -} + +extern int strncmp ( const char *str1, const char *str2, size_t len ); #define __HAVE_ARCH_STRLEN static inline size_t strlen(const char * s) From de20c526e68f7ec1155cdb7dcaeb2ff4c8c2c580 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 5 Nov 2012 00:25:25 +0000 Subject: [PATCH 200/250] [libc] Reduce overall code size by externalising strlen() Typical saving is 5-20 bytes in each file using strlen(). Signed-off-by: Michael Brown --- src/arch/x86/core/x86_string.c | 18 ++++++++++++++++++ src/arch/x86/include/bits/string.h | 14 ++------------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 962a7d84..69c73f70 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -105,6 +105,24 @@ void * __memmove ( void *dest, const void *src, size_t len ) { } } +/** + * Calculate length of string + * + * @v string String + * @ret len Length (excluding NUL) + */ +size_t strlen ( const char *string ) { + const char *discard_D; + size_t len_plus_one; + + __asm__ __volatile__ ( "repne scasb\n\t" + "not %1\n\t" + : "=&D" ( discard_D ), "=&c" ( len_plus_one ) + : "0" ( string ), "1" ( -1UL ), "a" ( 0 ) ); + + return ( len_plus_one - 1 ); +} + /** * Compare strings (up to a specified length) * diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index 75a1f01a..249dd543 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -234,17 +234,7 @@ return dest; extern int strncmp ( const char *str1, const char *str2, size_t len ); #define __HAVE_ARCH_STRLEN -static inline size_t strlen(const char * s) -{ -int d0; -register int __res; -__asm__ __volatile__( - "repne\n\t" - "scasb\n\t" - "notl %0\n\t" - "decl %0" - :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); -return __res; -} + +extern size_t strlen ( const char *string ); #endif /* ETHERBOOT_BITS_STRING_H */ From 53f3deee06366dacd38974af7beb89aa7ce6c45e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 5 Nov 2012 00:58:20 +0000 Subject: [PATCH 201/250] [libc] Fix and externalise memswap() Make memswap() behave correctly if called with a length of zero. Signed-off-by: Michael Brown --- src/arch/x86/core/x86_string.c | 28 ++++++++++++++++++++++++++++ src/arch/x86/include/bits/string.h | 17 ++--------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/arch/x86/core/x86_string.c b/src/arch/x86/core/x86_string.c index 69c73f70..d48347c9 100644 --- a/src/arch/x86/core/x86_string.c +++ b/src/arch/x86/core/x86_string.c @@ -105,6 +105,34 @@ void * __memmove ( void *dest, const void *src, size_t len ) { } } +/** + * Swap memory areas + * + * @v dest Destination address + * @v src Source address + * @v len Length + * @ret dest Destination address + */ +void * memswap ( void *dest, void *src, size_t len ) { + size_t discard_c; + int discard; + + __asm__ __volatile__ ( "\n1:\n\t" + "dec %2\n\t" + "js 2f\n\t" + "movb (%0,%2), %b3\n\t" + "xchgb (%1,%2), %b3\n\t" + "movb %b3, (%0,%2)\n\t" + "jmp 1b\n\t" + "2:\n\t" + : "=r" ( src ), "=r" ( dest ), + "=&c" ( discard_c ), "=&q" ( discard ) + : "0" ( src ), "1" ( dest ), "2" ( len ) + : "memory" ); + + return dest; +} + /** * Calculate length of string * diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index 249dd543..4d44c722 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -213,21 +213,8 @@ static inline void * memset ( void *dest, int fill, size_t len ) { } #define __HAVE_ARCH_MEMSWAP -static inline void * memswap(void *dest, void *src, size_t n) -{ -long d0, d1, d2, d3; -__asm__ __volatile__( - "\n1:\t" - "movb (%2),%%al\n\t" - "xchgb (%1),%%al\n\t" - "inc %1\n\t" - "stosb\n\t" - "loop 1b" - : "=&c" (d0), "=&S" (d1), "=&D" (d2), "=&a" (d3) - : "0" (n), "1" (src), "2" (dest) - : "memory" ); -return dest; -} + +extern void * memswap ( void *dest, void *src, size_t len ); #define __HAVE_ARCH_STRNCMP From 603455bb0699f31c9485b98aff2749680c19a671 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 5 Nov 2012 01:01:12 +0000 Subject: [PATCH 202/250] [libc] Relicense x86 string.h No code from the original source remains within this file; relicense under GPL2+ with a new copyright notice. Signed-off-by: Michael Brown --- src/arch/x86/include/bits/string.h | 45 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/arch/x86/include/bits/string.h b/src/arch/x86/include/bits/string.h index 4d44c722..dce99498 100644 --- a/src/arch/x86/include/bits/string.h +++ b/src/arch/x86/include/bits/string.h @@ -1,27 +1,32 @@ -#ifndef ETHERBOOT_BITS_STRING_H -#define ETHERBOOT_BITS_STRING_H -/* - * Taken from Linux /usr/include/asm/string.h - * All except memcpy, memmove, memset and memcmp removed. - * - * Non-standard memswap() function added because it saves quite a bit - * of code (mbrown@fensystems.co.uk). - */ +#ifndef X86_BITS_STRING_H +#define X86_BITS_STRING_H /* - * This string-include defines all string functions as inline - * functions. Use gcc. It also assumes ds=es=data space, this should be - * normal. Most of the string-functions are rather heavily hand-optimized, - * see especially strtok,strstr,str[c]spn. They should work, but are not - * very easy to understand. Everything is done entirely within the register - * set, making the functions fast and clean. String instructions have been - * used through-out, making for "slightly" unclear code :-) + * Copyright (C) 2007 Michael Brown . * - * NO Copyright (C) 1991, 1992 Linus Torvalds, - * consider these trivial functions to be PD. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. */ -FILE_LICENCE ( PUBLIC_DOMAIN ); +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Optimised string operations + * + */ #define __HAVE_ARCH_MEMCPY @@ -224,4 +229,4 @@ extern int strncmp ( const char *str1, const char *str2, size_t len ); extern size_t strlen ( const char *string ); -#endif /* ETHERBOOT_BITS_STRING_H */ +#endif /* X86_BITS_STRING_H */ From 4ca98693b9622934b934e9bb0c421690316376f7 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 12 Nov 2012 13:08:16 +0000 Subject: [PATCH 203/250] [initrd] Add ability to reshuffle initrds into image list order Signed-off-by: Michael Brown --- src/arch/i386/image/initrd.c | 300 ++++++++++++++++++++++++++++ src/arch/i386/include/initrd.h | 29 +++ src/arch/x86/include/bits/errfile.h | 1 + 3 files changed, 330 insertions(+) create mode 100644 src/arch/i386/image/initrd.c create mode 100644 src/arch/i386/include/initrd.h diff --git a/src/arch/i386/image/initrd.c b/src/arch/i386/image/initrd.c new file mode 100644 index 00000000..eaba3a64 --- /dev/null +++ b/src/arch/i386/image/initrd.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include +#include +#include +#include +#include + +/** @file + * + * Initial ramdisk (initrd) reshuffling + * + */ + +/** Maximum address available for initrd */ +userptr_t initrd_top; + +/** Minimum address available for initrd */ +userptr_t initrd_bottom; + +/** + * Squash initrds as high as possible in memory + * + * @v top Highest possible address + * @ret used Lowest address used by initrds + */ +static userptr_t initrd_squash_high ( userptr_t top ) { + userptr_t current = top; + struct image *initrd; + struct image *highest; + size_t len; + + /* Squash up any initrds already within or below the region */ + while ( 1 ) { + + /* Find the highest image not yet in its final position */ + highest = NULL; + for_each_image ( initrd ) { + if ( ( userptr_sub ( initrd->data, current ) < 0 ) && + ( ( highest == NULL ) || + ( userptr_sub ( initrd->data, + highest->data ) > 0 ) ) ) { + highest = initrd; + } + } + if ( ! highest ) + break; + + /* Move this image to its final position */ + len = ( ( highest->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + current = userptr_sub ( current, len ); + DBGC ( &images, "INITRD squashing %s [%#08lx,%#08lx)->" + "[%#08lx,%#08lx)\n", highest->name, + user_to_phys ( highest->data, 0 ), + user_to_phys ( highest->data, highest->len ), + user_to_phys ( current, 0 ), + user_to_phys ( current, highest->len ) ); + memmove_user ( current, 0, highest->data, 0, highest->len ); + highest->data = current; + } + + /* Copy any remaining initrds (e.g. embedded images) to the region */ + for_each_image ( initrd ) { + if ( userptr_sub ( initrd->data, top ) >= 0 ) { + len = ( ( initrd->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + current = userptr_sub ( current, len ); + DBGC ( &images, "INITRD copying %s [%#08lx,%#08lx)->" + "[%#08lx,%#08lx)\n", initrd->name, + user_to_phys ( initrd->data, 0 ), + user_to_phys ( initrd->data, initrd->len ), + user_to_phys ( current, 0 ), + user_to_phys ( current, initrd->len ) ); + memcpy_user ( current, 0, initrd->data, 0, + initrd->len ); + initrd->data = current; + } + } + + return current; +} + +/** + * Swap position of two adjacent initrds + * + * @v low Lower initrd + * @v high Higher initrd + * @v free Free space + * @v free_len Length of free space + */ +static void initrd_swap ( struct image *low, struct image *high, + userptr_t free, size_t free_len ) { + size_t len = 0; + size_t frag_len; + size_t new_len; + + DBGC ( &images, "INITRD swapping %s [%#08lx,%#08lx)<->[%#08lx,%#08lx) " + "%s\n", low->name, user_to_phys ( low->data, 0 ), + user_to_phys ( low->data, low->len ), + user_to_phys ( high->data, 0 ), + user_to_phys ( high->data, high->len ), high->name ); + + /* Round down length of free space */ + free_len &= ~( INITRD_ALIGN - 1 ); + assert ( free_len > 0 ); + + /* Swap image data */ + while ( len < high->len ) { + + /* Calculate maximum fragment length */ + frag_len = ( high->len - len ); + if ( frag_len > free_len ) + frag_len = free_len; + new_len = ( ( len + frag_len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + + /* Swap fragments */ + memcpy_user ( free, 0, high->data, len, frag_len ); + memmove_user ( low->data, new_len, low->data, len, low->len ); + memcpy_user ( low->data, len, free, 0, frag_len ); + len = new_len; + } + + /* Adjust data pointers */ + high->data = low->data; + low->data = userptr_add ( low->data, len ); +} + +/** + * Swap position of any two adjacent initrds not currently in the correct order + * + * @v free Free space + * @v free_len Length of free space + * @ret swapped A pair of initrds was swapped + */ +static int initrd_swap_any ( userptr_t free, size_t free_len ) { + struct image *low; + struct image *high; + size_t padded_len; + userptr_t adjacent; + + /* Find any pair of initrds that can be swapped */ + for_each_image ( low ) { + + /* Calculate location of adjacent image (if any) */ + padded_len = ( ( low->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ); + adjacent = userptr_add ( low->data, padded_len ); + + /* Search for adjacent image */ + for_each_image ( high ) { + + /* If we have found the adjacent image, swap and exit */ + if ( high->data == adjacent ) { + initrd_swap ( low, high, free, free_len ); + return 1; + } + + /* Stop search if all remaining potential + * adjacent images are already in the correct + * order. + */ + if ( high == low ) + break; + } + } + + /* Nothing swapped */ + return 0; +} + +/** + * Dump initrd locations (for debug) + * + */ +static void initrd_dump ( void ) { + struct image *initrd; + + /* Do nothing unless debugging is enabled */ + if ( ! DBG_LOG ) + return; + + /* Dump initrd locations */ + for_each_image ( initrd ) { + DBGC ( &images, "INITRD %s at [%#08lx,%#08lx)\n", + initrd->name, user_to_phys ( initrd->data, 0 ), + user_to_phys ( initrd->data, initrd->len ) ); + DBGC2_MD5A ( &images, user_to_phys ( initrd->data, 0 ), + user_to_virt ( initrd->data, 0 ), initrd->len ); + } +} + +/** + * Reshuffle initrds into desired order at top of memory + * + * @v bottom Lowest address available for initrds + * + * After this function returns, the initrds have been rearranged in + * memory and the external heap structures will have been corrupted. + * Reshuffling must therefore take place immediately prior to jumping + * to the loaded OS kernel; no further execution within iPXE is + * permitted. + */ +void initrd_reshuffle ( userptr_t bottom ) { + userptr_t top; + userptr_t used; + userptr_t free; + size_t free_len; + + /* Calculate limits of available space for initrds */ + top = initrd_top; + if ( userptr_sub ( initrd_bottom, bottom ) > 0 ) + bottom = initrd_bottom; + + /* Debug */ + DBGC ( &images, "INITRD region [%#08lx,%#08lx)\n", + user_to_phys ( bottom, 0 ), user_to_phys ( top, 0 ) ); + initrd_dump(); + + /* Squash initrds as high as possible in memory */ + used = initrd_squash_high ( top ); + + /* Calculate available free space */ + free = bottom; + free_len = userptr_sub ( used, free ); + + /* Bubble-sort initrds into desired order */ + while ( initrd_swap_any ( free, free_len ) ) {} + + /* Debug */ + initrd_dump(); +} + +/** + * Check that there is enough space to reshuffle initrds + * + * @v len Total length of initrds (including padding) + * @v bottom Lowest address available for initrds + * @ret rc Return status code + */ +int initrd_reshuffle_check ( size_t len, userptr_t bottom ) { + userptr_t top; + size_t available; + + /* Calculate limits of available space for initrds */ + top = initrd_top; + if ( userptr_sub ( initrd_bottom, bottom ) > 0 ) + bottom = initrd_bottom; + available = userptr_sub ( top, bottom ); + + /* Allow for a sensible minimum amount of free space */ + len += INITRD_MIN_FREE_LEN; + + /* Check for available space */ + return ( ( len < available ) ? 0 : -ENOBUFS ); +} + +/** + * initrd startup function + * + */ +static void initrd_startup ( void ) { + size_t len; + + /* Record largest memory block available. Do this after any + * allocations made during driver startup (e.g. large host + * memory blocks for Infiniband devices, which may still be in + * use at the time of rearranging if a SAN device is hooked) + * but before any allocations for downloaded images (which we + * can safely reuse when rearranging). + */ + len = largest_memblock ( &initrd_bottom ); + initrd_top = userptr_add ( initrd_bottom, len ); +} + +/** initrd startup function */ +struct startup_fn startup_initrd __startup_fn ( STARTUP_LATE ) = { + .startup = initrd_startup, +}; diff --git a/src/arch/i386/include/initrd.h b/src/arch/i386/include/initrd.h new file mode 100644 index 00000000..c25d0924 --- /dev/null +++ b/src/arch/i386/include/initrd.h @@ -0,0 +1,29 @@ +#ifndef _INITRD_H +#define _INITRD_H + +/** @file + * + * Initial ramdisk (initrd) reshuffling + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** Minimum alignment for initrds + * + * Chosen to maximise memcpy() speeds + */ +#define INITRD_ALIGN 4 + +/** Minimum free space required to reshuffle initrds + * + * Chosen to avoid absurdly long reshuffling times + */ +#define INITRD_MIN_FREE_LEN ( 512 * 1024 ) + +extern void initrd_reshuffle ( userptr_t bottom ); +extern int initrd_reshuffle_check ( size_t len, userptr_t bottom ); + +#endif /* _INITRD_H */ diff --git a/src/arch/x86/include/bits/errfile.h b/src/arch/x86/include/bits/errfile.h index 25e070e8..7b9f3702 100644 --- a/src/arch/x86/include/bits/errfile.h +++ b/src/arch/x86/include/bits/errfile.h @@ -32,6 +32,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define ERRFILE_comboot_resolv ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00090000 ) #define ERRFILE_comboot_call ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000a0000 ) #define ERRFILE_sdi ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000b0000 ) +#define ERRFILE_initrd ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x000c0000 ) #define ERRFILE_undi ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 ) #define ERRFILE_undiload ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 ) From d6b0b76a05d6507d14abdf29f7730b324b920b4d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 12 Nov 2012 16:16:31 +0000 Subject: [PATCH 204/250] [bzimage] Allow initrds to be rearranged in place At present, loading a bzImage via iPXE requires enough RAM to hold two copies of each initrd file. Remove this constraint by rearranging the initrds in place. Signed-off-by: Michael Brown --- src/arch/i386/image/bzimage.c | 227 ++++++++++++++++++++++------------ 1 file changed, 147 insertions(+), 80 deletions(-) diff --git a/src/arch/i386/image/bzimage.c b/src/arch/i386/image/bzimage.c index 9c22685b..12be1779 100644 --- a/src/arch/i386/image/bzimage.c +++ b/src/arch/i386/image/bzimage.c @@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -304,11 +305,10 @@ static int bzimage_parse_cmdline ( struct image *image, * @v image bzImage image * @v bzimg bzImage context * @v cmdline Kernel command line - * @ret rc Return status code */ -static int bzimage_set_cmdline ( struct image *image, - struct bzimage_context *bzimg, - const char *cmdline ) { +static void bzimage_set_cmdline ( struct image *image, + struct bzimage_context *bzimg, + const char *cmdline ) { size_t cmdline_len; /* Copy command line down to real-mode portion */ @@ -318,8 +318,6 @@ static int bzimage_set_cmdline ( struct image *image, copy_to_user ( bzimg->rm_kernel, bzimg->rm_cmdline, cmdline, cmdline_len ); DBGC ( image, "bzImage %p command line \"%s\"\n", image, cmdline ); - - return 0; } /** @@ -354,7 +352,7 @@ static void bzimage_parse_cpio_cmdline ( struct image *image, * @v image bzImage image * @v initrd initrd image * @v address Address at which to load, or UNULL - * @ret len Length of loaded image, rounded up to 4 bytes + * @ret len Length of loaded image, rounded up to INITRD_ALIGN */ static size_t bzimage_load_initrd ( struct image *image, struct image *initrd, @@ -364,6 +362,7 @@ static size_t bzimage_load_initrd ( struct image *image, struct cpio_header cpio; size_t offset = 0; size_t name_len; + size_t pad_len; /* Do not include kernel image itself as an initrd */ if ( initrd == image ) @@ -371,8 +370,6 @@ static size_t bzimage_load_initrd ( struct image *image, /* Create cpio header before non-prebuilt images */ if ( filename && filename[0] ) { - DBGC ( image, "bzImage %p inserting initrd %p as %s\n", - image, initrd, filename ); cmdline = strchr ( filename, ' ' ); name_len = ( ( cmdline ? ( ( size_t ) ( cmdline - filename ) ) : strlen ( filename ) ) + 1 /* NUL */ ); @@ -402,17 +399,82 @@ static size_t bzimage_load_initrd ( struct image *image, /* Copy in initrd image body */ if ( address ) - memcpy_user ( address, offset, initrd->data, 0, initrd->len ); - offset += initrd->len; + memmove_user ( address, offset, initrd->data, 0, initrd->len ); if ( address ) { - DBGC ( image, "bzImage %p has initrd %p at [%lx,%lx)\n", - image, initrd, user_to_phys ( address, 0 ), - user_to_phys ( address, offset ) ); + DBGC ( image, "bzImage %p initrd %p [%#08lx,%#08lx,%#08lx)" + "%s%s\n", image, initrd, user_to_phys ( address, 0 ), + user_to_phys ( address, offset ), + user_to_phys ( address, ( offset + initrd->len ) ), + ( filename ? " " : "" ), ( filename ? filename : "" ) ); + DBGC2_MD5A ( image, user_to_phys ( address, offset ), + user_to_virt ( address, offset ), initrd->len ); + } + offset += initrd->len; + + /* Round up to multiple of INITRD_ALIGN and zero-pad */ + pad_len = ( ( -offset ) & ( INITRD_ALIGN - 1 ) ); + if ( address ) + memset_user ( address, offset, 0, pad_len ); + offset += pad_len; + + return offset; +} + +/** + * Check that initrds can be loaded + * + * @v image bzImage image + * @v bzimg bzImage context + * @ret rc Return status code + */ +static int bzimage_check_initrds ( struct image *image, + struct bzimage_context *bzimg ) { + struct image *initrd; + userptr_t bottom; + size_t len = 0; + int rc; + + /* Calculate total loaded length of initrds */ + for_each_image ( initrd ) { + + /* Skip kernel */ + if ( initrd == image ) + continue; + + /* Calculate length */ + len += bzimage_load_initrd ( image, initrd, UNULL ); + + DBGC ( image, "bzImage %p initrd %p from [%#08lx,%#08lx)%s%s\n", + image, initrd, user_to_phys ( initrd->data, 0 ), + user_to_phys ( initrd->data, initrd->len ), + ( initrd->cmdline ? " " : "" ), + ( initrd->cmdline ? initrd->cmdline : "" ) ); + DBGC2_MD5A ( image, user_to_phys ( initrd->data, 0 ), + user_to_virt ( initrd->data, 0 ), initrd->len ); } - /* Round up to 4-byte boundary */ - offset = ( ( offset + 0x03 ) & ~0x03 ); - return offset; + /* Calculate lowest usable address */ + bottom = userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ); + + /* Check that total length fits within space available for + * reshuffling. This is a conservative check, since CPIO + * headers are not present during reshuffling, but this + * doesn't hurt and keeps the code simple. + */ + if ( ( rc = initrd_reshuffle_check ( len, bottom ) ) != 0 ) { + DBGC ( image, "bzImage %p failed reshuffle check: %s\n", + image, strerror ( rc ) ); + return rc; + } + + /* Check that total length fits within kernel's memory limit */ + if ( user_to_phys ( bottom, len ) > bzimg->mem_limit ) { + DBGC ( image, "bzImage %p not enough space for initrds\n", + image ); + return -ENOBUFS; + } + + return 0; } /** @@ -420,62 +482,63 @@ static size_t bzimage_load_initrd ( struct image *image, * * @v image bzImage image * @v bzimg bzImage context - * @ret rc Return status code */ -static int bzimage_load_initrds ( struct image *image, - struct bzimage_context *bzimg ) { +static void bzimage_load_initrds ( struct image *image, + struct bzimage_context *bzimg ) { struct image *initrd; - size_t total_len = 0; - physaddr_t address; - int rc; + struct image *highest = NULL; + struct image *other; + userptr_t top; + userptr_t dest; + size_t len; - /* Add up length of all initrd images */ - for_each_image ( initrd ) - total_len += bzimage_load_initrd ( image, initrd, UNULL ); + /* Reshuffle initrds into desired order */ + initrd_reshuffle ( userptr_add ( bzimg->pm_kernel, bzimg->pm_sz ) ); - /* Give up if no initrd images found */ - if ( ! total_len ) - return 0; - - /* Find a suitable start address. Try 1MB boundaries, - * starting from the downloaded kernel image itself and - * working downwards until we hit an available region. - */ - for ( address = ( user_to_phys ( image->data, 0 ) & ~0xfffff ) ; ; - address -= 0x100000 ) { - /* Check that we're not going to overwrite the - * kernel itself. This check isn't totally - * accurate, but errs on the side of caution. - */ - if ( address <= ( BZI_LOAD_HIGH_ADDR + image->len ) ) { - DBGC ( image, "bzImage %p could not find a location " - "for initrd\n", image ); - return -ENOBUFS; - } - /* Check that we are within the kernel's range */ - if ( ( address + total_len - 1 ) > bzimg->mem_limit ) - continue; - /* Prepare and verify segment */ - if ( ( rc = prep_segment ( phys_to_user ( address ), 0, - total_len ) ) != 0 ) - continue; - /* Use this address */ - break; - } - - /* Record initrd location */ - bzimg->ramdisk_image = address; - bzimg->ramdisk_size = total_len; - - /* Construct initrd */ - DBGC ( image, "bzImage %p constructing initrd at [%lx,%lx)\n", - image, address, ( address + total_len ) ); + /* Find highest initrd */ for_each_image ( initrd ) { - address += bzimage_load_initrd ( image, initrd, - phys_to_user ( address ) ); + if ( ( highest == NULL ) || + ( userptr_sub ( initrd->data, highest->data ) > 0 ) ) { + highest = initrd; + } } - return 0; + /* Do nothing if there are no initrds */ + if ( ! highest ) + return; + + /* Find highest usable address */ + top = userptr_add ( highest->data, + ( ( highest->len + INITRD_ALIGN - 1 ) & + ~( INITRD_ALIGN - 1 ) ) ); + if ( user_to_phys ( top, 0 ) > bzimg->mem_limit ) + top = phys_to_user ( bzimg->mem_limit ); + DBGC ( image, "bzImage %p loading initrds from %#08lx downwards\n", + image, user_to_phys ( top, 0 ) ); + + /* Load initrds in order */ + for_each_image ( initrd ) { + + /* Calculate cumulative length of following + * initrds (including padding). + */ + len = 0; + for_each_image ( other ) { + if ( other == initrd ) + len = 0; + len += bzimage_load_initrd ( image, other, UNULL ); + } + + /* Load initrd at this address */ + dest = userptr_add ( top, -len ); + bzimage_load_initrd ( image, initrd, dest ); + + /* Record initrd location */ + if ( ! bzimg->ramdisk_image ) { + bzimg->ramdisk_image = user_to_phys ( dest, 0 ); + bzimg->ramdisk_size = len; + } + } } /** @@ -508,33 +571,37 @@ static int bzimage_exec ( struct image *image ) { return rc; } + /* Parse command line for bootloader parameters */ + if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0) + return rc; + + /* Check that initrds can be loaded */ + if ( ( rc = bzimage_check_initrds ( image, &bzimg ) ) != 0 ) + return rc; + + /* Remove kernel from image list (without invalidating image pointer) */ + unregister_image ( image_get ( image ) ); + /* Load segments */ memcpy_user ( bzimg.rm_kernel, 0, image->data, 0, bzimg.rm_filesz ); memcpy_user ( bzimg.pm_kernel, 0, image->data, bzimg.rm_filesz, bzimg.pm_sz ); - /* Update and write out header */ - bzimage_update_header ( image, &bzimg, bzimg.rm_kernel ); - - /* Parse command line for bootloader parameters */ - if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0) - return rc; - /* Store command line */ - if ( ( rc = bzimage_set_cmdline ( image, &bzimg, cmdline ) ) != 0 ) - return rc; + bzimage_set_cmdline ( image, &bzimg, cmdline ); + + /* Prepare for exiting. Must do this before loading initrds, + * since loading the initrds will corrupt the external heap. + */ + shutdown_boot(); /* Load any initrds */ - if ( ( rc = bzimage_load_initrds ( image, &bzimg ) ) != 0 ) - return rc; + bzimage_load_initrds ( image, &bzimg ); /* Update kernel header */ bzimage_update_header ( image, &bzimg, bzimg.rm_kernel ); - /* Prepare for exiting */ - shutdown_boot(); - DBGC ( image, "bzImage %p jumping to RM kernel at %04x:0000 " "(stack %04x:%04zx)\n", image, ( bzimg.rm_kernel_seg + 0x20 ), bzimg.rm_kernel_seg, bzimg.rm_heap ); From 1a79f6f37a4a3bf1876cbfa3162dfe903da212cc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 21 Nov 2012 02:37:55 +0000 Subject: [PATCH 205/250] [efi] Delegate to child device's EFI_COMPONENT_NAME2_PROTOCOL, if present EFI's device naming model requires drivers to provide names for child devices. Allow the driver's GetControllerName() method to delegate to an instance of EFI_COMPONENT_NAME2_PROTOCOL installed on the child device itself (if present); this allows the SNP device to expose its own device name via the PCI driver's GetControllerName() method. Signed-off-by: Michael Brown --- src/interface/efi/efi_driver.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/interface/efi/efi_driver.c b/src/interface/efi/efi_driver.c index 476b3c32..deb3cf2c 100644 --- a/src/interface/efi/efi_driver.c +++ b/src/interface/efi/efi_driver.c @@ -90,12 +90,29 @@ efi_driver_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf, */ static EFI_STATUS EFIAPI efi_driver_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *wtf __unused, - EFI_HANDLE device __unused, - EFI_HANDLE child __unused, - CHAR8 *language __unused, - CHAR16 **controller_name __unused ) { + EFI_HANDLE device, EFI_HANDLE child, + CHAR8 *language, CHAR16 **controller_name ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + union { + EFI_COMPONENT_NAME2_PROTOCOL *name2; + void *interface; + } name2; + EFI_STATUS efirc; - /* Just let EFI use the default Device Path Name */ + /* Delegate to the EFI_COMPONENT_NAME2_PROTOCOL instance + * installed on child handle, if present. + */ + if ( ( child != NULL ) && + ( ( efirc = bs->OpenProtocol ( + child, &efi_component_name2_protocol_guid, + &name2.interface, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) == 0 ) ) { + return name2.name2->GetControllerName ( name2.name2, device, + child, language, + controller_name ); + } + + /* Otherwise, let EFI use the default Device Path Name */ return EFI_UNSUPPORTED; } From 717279a294e414218deb1c89d33422b209574053 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 21 Nov 2012 03:36:07 +0000 Subject: [PATCH 206/250] [efi] Include product short name in EFI SNP device names Signed-off-by: Michael Brown --- src/interface/efi/efi_snp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index c48572e8..20027596 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** EFI simple network protocol GUID */ static EFI_GUID efi_simple_network_protocol_guid @@ -849,11 +850,12 @@ static int efi_snp_probe ( struct net_device *netdev ) { /* Populate the component name structure */ efi_snprintf ( snpdev->driver_name, ( sizeof ( snpdev->driver_name ) / - sizeof ( snpdev->driver_name[0] ) ), "%s", - netdev->dev->driver_name ); + sizeof ( snpdev->driver_name[0] ) ), + PRODUCT_SHORT_NAME " %s", netdev->dev->driver_name ); efi_snprintf ( snpdev->controller_name, ( sizeof ( snpdev->controller_name ) / - sizeof ( snpdev->controller_name[0] ) ), "%s (%s)", + sizeof ( snpdev->controller_name[0] ) ), + PRODUCT_SHORT_NAME " %s (%s)", netdev->name, netdev_addr ( netdev ) ); snpdev->name2.GetDriverName = efi_snp_get_driver_name; snpdev->name2.GetControllerName = efi_snp_get_controller_name; From 3fcb8cf8dceb45f8b01e1d69d43cfd99df43b78a Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 3 Jan 2013 15:12:32 +0000 Subject: [PATCH 207/250] [src] Fix spelling in comments, debug messages and local variable names Fixes in comments and debug messages: existance -> existence unecessary -> unnecessary occured -> occurred decriptor -> descriptor neccessary -> necessary addres, adress -> address initilize -> initialize sucessfully -> successfully paramter -> parameter acess -> access upto -> up to likelyhood ->likelihood thru -> through substracting -> subtracting lenght -> length isnt -> isn't interupt -> interrupt publically -> publicly (this one was not wrong, but unusual) recieve -> receive accessable -> accessible seperately -> separately pacet -> packet controled -> controlled dectect -> detect indicies -> indices extremly -> extremely boundry -> boundary usefull -> useful unuseable -> unusable auxilliary -> auxiliary embeded -> embedded enviroment -> environment sturcture -> structure complier -> compiler constructes -> constructs supress -> suppress intruduced -> introduced compatability -> compatibility verfication -> verification ths -> the reponse -> response Fixes in local variable names: retreive -> retrieve Most of these fixes were made using codespell. Signed-off-by: Stefan Weil Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/drivers/net/3c509.h | 2 +- src/drivers/net/3c515.c | 2 +- src/drivers/net/3c595.c | 2 +- src/drivers/net/amd8111e.h | 2 +- src/drivers/net/cs89x0.c | 2 +- src/drivers/net/davicom.c | 8 ++++---- src/drivers/net/dmfe.c | 20 ++++++++++---------- src/drivers/net/eepro100.c | 2 +- src/drivers/net/epic100.c | 4 ++-- src/drivers/net/epic100.h | 2 +- src/drivers/net/etherfabric.c | 8 ++++---- src/drivers/net/forcedeth.c | 2 +- src/drivers/net/myri10ge.c | 2 +- src/drivers/net/p80211hdr.h | 2 +- src/drivers/net/pcnet32.c | 2 +- src/drivers/net/sis190.h | 4 ++-- src/drivers/net/sis900.c | 10 +++++----- src/drivers/net/skge.h | 8 ++++---- src/drivers/net/sky2.c | 2 +- src/drivers/net/sky2.h | 6 +++--- src/drivers/net/smc9000.h | 4 ++-- src/drivers/net/sundance.c | 6 +++--- src/drivers/net/tlan.c | 6 +++--- src/drivers/net/via-rhine.c | 10 +++++----- src/drivers/net/via-velocity.c | 2 +- src/drivers/net/via-velocity.h | 2 +- src/drivers/net/virtio-net.c | 2 +- src/drivers/net/vxge/vxge_main.c | 2 +- src/include/ipxe/iscsi.h | 2 +- src/include/ipxe/pci.h | 2 +- src/net/udp/dns.c | 2 +- 31 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/drivers/net/3c509.h b/src/drivers/net/3c509.h index f030d4ba..25e4a88d 100644 --- a/src/drivers/net/3c509.h +++ b/src/drivers/net/3c509.h @@ -77,7 +77,7 @@ FILE_LICENCE ( BSD3 ); /************************************************************************** * * These define the EEPROM data structure. They are used in the probe - * function to verify the existance of the adapter after having sent + * function to verify the existence of the adapter after having sent * the ID_Sequence. * * There are others but only the ones we use are defined here. diff --git a/src/drivers/net/3c515.c b/src/drivers/net/3c515.c index f345bb96..0aa68b1a 100644 --- a/src/drivers/net/3c515.c +++ b/src/drivers/net/3c515.c @@ -656,7 +656,7 @@ static int corkscrew_found_device(int ioaddr, int irq, int product_index, int options, struct nic *nic) { - /* Direct copy from Becker 3c515.c with unecessary parts removed */ + /* Direct copy from Becker 3c515.c with unnecessary parts removed */ vp->product_name = "3c515"; vp->options = options; if (options >= 0) { diff --git a/src/drivers/net/3c595.c b/src/drivers/net/3c595.c index 3178178a..1aa8ed64 100644 --- a/src/drivers/net/3c595.c +++ b/src/drivers/net/3c595.c @@ -127,7 +127,7 @@ static void t595_reset(struct nic *nic) S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); /* - * Attempt to get rid of any stray interrupts that occured during + * Attempt to get rid of any stray interrupts that occurred during * configuration. On the i386 this isn't possible because one may * already be queued. However, a single stray interrupt is * unimportant. diff --git a/src/drivers/net/amd8111e.h b/src/drivers/net/amd8111e.h index 7898deb6..2000df15 100644 --- a/src/drivers/net/amd8111e.h +++ b/src/drivers/net/amd8111e.h @@ -574,7 +574,7 @@ typedef enum { #define CSTATE 1 #define SSTATE 2 -/* amd8111e decriptor flag definitions */ +/* amd8111e descriptor flag definitions */ typedef enum { OWN_BIT = (1 << 15), diff --git a/src/drivers/net/cs89x0.c b/src/drivers/net/cs89x0.c index 876b8785..17b7157a 100644 --- a/src/drivers/net/cs89x0.c +++ b/src/drivers/net/cs89x0.c @@ -58,7 +58,7 @@ FILE_LICENCE ( GPL2_ONLY ); Fri Nov 22 23:00:00 1996 Markus Gutschke * read the manuals for the CS89x0 chipsets and took note of all the - changes that will be neccessary in order to adapt Russel Nelson's code + changes that will be necessary in order to adapt Russel Nelson's code to the requirements of a BOOT-Prom * 6 diff --git a/src/drivers/net/davicom.c b/src/drivers/net/davicom.c index 14117742..a4870a72 100644 --- a/src/drivers/net/davicom.c +++ b/src/drivers/net/davicom.c @@ -213,11 +213,11 @@ static int phy_read(int location) phy_write_1bit(io_dcr9, PHY_DATA_1); phy_write_1bit(io_dcr9, PHY_DATA_0); - /* Send Phy addres */ + /* Send Phy address */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0); - /* Send register addres */ + /* Send register address */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); @@ -257,11 +257,11 @@ static void phy_write(int location, u16 phy_data) phy_write_1bit(io_dcr9, PHY_DATA_0); phy_write_1bit(io_dcr9, PHY_DATA_1); - /* Send Phy addres */ + /* Send Phy address */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0); - /* Send register addres */ + /* Send register address */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); diff --git a/src/drivers/net/dmfe.c b/src/drivers/net/dmfe.c index edc15941..aae40fce 100644 --- a/src/drivers/net/dmfe.c +++ b/src/drivers/net/dmfe.c @@ -261,15 +261,15 @@ static void dmfe_reset(struct nic *nic) db->cr0_data = 0; db->dm910x_chk_mode = 1; /* Enter the check mode */ } - /* Initilize DM910X board */ + /* Initialize DM910X board */ dmfe_init_dm910x(nic); return; } -/* Initilize DM910X board +/* Initialize DM910X board * Reset DM910X board - * Initilize TX/Rx descriptor chain structure + * Initialize TX/Rx descriptor chain structure * Send the set-up frame * Enable Tx/Rx machine */ @@ -307,7 +307,7 @@ static void dmfe_init_dm910x(struct nic *nic) if (!(db->media_mode & DMFE_AUTO)) db->op_mode = db->media_mode; /* Force Mode */ - /* Initiliaze Transmit/Receive decriptor and CR3/4 */ + /* Initiliaze Transmit/Receive descriptor and CR3/4 */ dmfe_descriptor_init(nic, ioaddr); /* tx descriptor start pointer */ @@ -572,7 +572,7 @@ static void update_cr6(u32 cr6_data, unsigned long ioaddr) /* * Send a setup frame for DM9132 - * This setup frame initilize DM910X addres filter mode + * This setup frame initialize DM910X address filter mode */ static void dm9132_id_table(struct nic *nic __unused) @@ -623,7 +623,7 @@ static void dm9132_id_table(struct nic *nic __unused) /* * Send a setup frame for DM9102/DM9102A - * This setup frame initilize DM910X addres filter mode + * This setup frame initialize DM910X address filter mode */ static void send_filter_frame(struct nic *nic) @@ -903,13 +903,13 @@ static void phy_write(unsigned long iobase, u8 phy_addr, u8 offset, phy_write_1bit(ioaddr, PHY_DATA_0); phy_write_1bit(ioaddr, PHY_DATA_1); - /* Send Phy addres */ + /* Send Phy address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); - /* Send register addres */ + /* Send register address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : @@ -959,13 +959,13 @@ static u16 phy_read(unsigned long iobase, u8 phy_addr, u8 offset, phy_write_1bit(ioaddr, PHY_DATA_1); phy_write_1bit(ioaddr, PHY_DATA_0); - /* Send Phy addres */ + /* Send Phy address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, phy_addr & i ? PHY_DATA_1 : PHY_DATA_0); - /* Send register addres */ + /* Send register address */ for (i = 0x10; i > 0; i = i >> 1) phy_write_1bit(ioaddr, offset & i ? PHY_DATA_1 : diff --git a/src/drivers/net/eepro100.c b/src/drivers/net/eepro100.c index b98b745d..ede0a1a4 100644 --- a/src/drivers/net/eepro100.c +++ b/src/drivers/net/eepro100.c @@ -910,7 +910,7 @@ static void ifec_refill_rx_ring ( struct net_device *netdev ) * Initial allocation & initialization of the rx ring. * * @v netdev Device of rx ring. - * @ret rc Non-zero if error occured + * @ret rc Non-zero if error occurred */ static int ifec_rx_setup ( struct net_device *netdev ) { diff --git a/src/drivers/net/epic100.c b/src/drivers/net/epic100.c index 884eb722..8e31a3bf 100644 --- a/src/drivers/net/epic100.c +++ b/src/drivers/net/epic100.c @@ -250,7 +250,7 @@ epic100_open(void) outl(tmp, txcon); - /* Give adress of RX and TX ring to the chip */ + /* Give address of RX and TX ring to the chip */ outl(virt_to_le32desc(&rx_ring), prcdar); outl(virt_to_le32desc(&tx_ring), ptcdar); @@ -365,7 +365,7 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type, * Arguments: none * * returns: 1 if a packet was received. - * 0 if no pacet was received. + * 0 if no packet was received. * side effects: * returns the packet in the array nic->packet. * returns the length of the packet in nic->packetlen. diff --git a/src/drivers/net/epic100.h b/src/drivers/net/epic100.h index f290b103..806c4bda 100644 --- a/src/drivers/net/epic100.h +++ b/src/drivers/net/epic100.h @@ -64,7 +64,7 @@ enum epic100_registers { #define INTR_RX_STATUS_OK (0x00008000) /* rx status valid. NI */ #define INTR_PCI_TGT_ABT (0x00004000) /* PCI Target abort */ #define INTR_PCI_MASTER_ABT (0x00002000) /* PCI Master abort */ -#define INTR_PCI_PARITY_ERR (0x00001000) /* PCI adress parity error */ +#define INTR_PCI_PARITY_ERR (0x00001000) /* PCI address parity error */ #define INTR_PCI_DATA_ERR (0x00000800) /* PCI data parity error */ #define INTR_RX_THR_CROSSED (0x00000400) /* rx copy threshold crossed */ #define INTR_CNTFULL (0x00000200) /* Counter overflow */ diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c index a0a009cb..6036d321 100644 --- a/src/drivers/net/etherfabric.c +++ b/src/drivers/net/etherfabric.c @@ -1566,7 +1566,7 @@ falcon_gmii_wait ( struct efab_nic *efab ) efab_dword_t md_stat; int count; - /* wait upto 10ms */ + /* wait up to 10ms */ for (count = 0; count < 1000; count++) { falcon_readl ( efab, &md_stat, FCN_MD_STAT_REG_KER ); if ( EFAB_DWORD_FIELD ( md_stat, FCN_MD_BSY ) == 0 ) { @@ -2195,7 +2195,7 @@ falcon_reset_xaui ( struct efab_nic *efab ) falcon_xmac_writel ( efab, ®, FCN_XX_PWR_RST_REG_MAC ); /* Give some time for the link to establish */ - for (count = 0; count < 1000; count++) { /* wait upto 10ms */ + for (count = 0; count < 1000; count++) { /* wait up to 10ms */ falcon_xmac_readl ( efab, ®, FCN_XX_PWR_RST_REG_MAC ); if ( EFAB_DWORD_FIELD ( reg, FCN_XX_RST_XX_EN ) == 0 ) { falcon_setup_xaui ( efab ); @@ -3395,7 +3395,7 @@ falcon_init_sram ( struct efab_nic *efab ) falcon_read ( efab, ®, FCN_SRM_CFG_REG_KER ); if ( !EFAB_OWORD_FIELD ( reg, FCN_SRAM_OOB_BT_INIT_EN ) ) return 0; - } while (++count < 20); /* wait upto 0.4 sec */ + } while (++count < 20); /* wait up to 0.4 sec */ EFAB_ERR ( "timed out waiting for SRAM reset\n"); return -ETIMEDOUT; @@ -3426,7 +3426,7 @@ falcon_setup_nic ( struct efab_nic *efab ) falcon_write ( efab, ®, FCN_RX_DC_CFG_REG_KER ); /* Set number of RSS CPUs - * bug7244: Increase filter depth to reduce RX_RESET likelyhood + * bug7244: Increase filter depth to reduce RX_RESET likelihood */ EFAB_POPULATE_OWORD_5 ( reg, FCN_NUM_KER, 0, diff --git a/src/drivers/net/forcedeth.c b/src/drivers/net/forcedeth.c index 47e2c5e8..d8ece9a7 100644 --- a/src/drivers/net/forcedeth.c +++ b/src/drivers/net/forcedeth.c @@ -998,7 +998,7 @@ forcedeth_poll ( struct net_device *netdev ) DBG ( "forcedeth_poll: status = %#04x\n", status ); - /* Link change interrupt occured. Call always if link is down, + /* Link change interrupt occurred. Call always if link is down, * to give auto-neg a chance to finish */ if ( ( status & NVREG_IRQ_LINK ) || ! ( netdev_link_ok ( netdev ) ) ) forcedeth_link_status ( netdev ); diff --git a/src/drivers/net/myri10ge.c b/src/drivers/net/myri10ge.c index 1b6835de..ae6b6c21 100644 --- a/src/drivers/net/myri10ge.c +++ b/src/drivers/net/myri10ge.c @@ -719,7 +719,7 @@ static int myri10ge_nv_init ( struct myri10ge_private *priv ) return 0; } - /* Initilize NonVolatile Storage state. */ + /* Initialize NonVolatile Storage state. */ priv->nvs.word_len_log2 = 0; priv->nvs.size = hdr.eeprom_len; diff --git a/src/drivers/net/p80211hdr.h b/src/drivers/net/p80211hdr.h index 83546712..110905c5 100644 --- a/src/drivers/net/p80211hdr.h +++ b/src/drivers/net/p80211hdr.h @@ -258,7 +258,7 @@ typedef union p80211_hdr /*================================================================*/ /* Function Declarations */ -/* Frame and header lenght macros */ +/* Frame and header length macros */ #define WLAN_CTL_FRAMELEN(fstype) (\ (fstype) == WLAN_FSTYPE_BLOCKACKREQ ? 24 : \ diff --git a/src/drivers/net/pcnet32.c b/src/drivers/net/pcnet32.c index 28fd583d..26633a24 100644 --- a/src/drivers/net/pcnet32.c +++ b/src/drivers/net/pcnet32.c @@ -407,7 +407,7 @@ pcnet32_chip_detect ( struct pcnet32_private *priv ) /* * On selected chips turn on the BCR18:NOUFLO bit. This stops transmit * starting until the packet is loaded. Strike one for reliability, lose - * one for latency - although on PCI this isnt a big loss. Older chips + * one for latency - although on PCI this isn't a big loss. Older chips * have FIFO's smaller than a packet, so you can't do this. * Turn on BCR18:BurstRdEn and BCR18:BurstWrEn. */ diff --git a/src/drivers/net/sis190.h b/src/drivers/net/sis190.h index fc6cb4b6..0551333d 100644 --- a/src/drivers/net/sis190.h +++ b/src/drivers/net/sis190.h @@ -77,7 +77,7 @@ enum sis190_registers { IntrStatus = 0x20, IntrMask = 0x24, IntrControl = 0x28, - IntrTimer = 0x2c, // unused (Interupt Timer) + IntrTimer = 0x2c, // unused (Interrupt Timer) PMControl = 0x30, // unused (Power Mgmt Control/Status) rsv2 = 0x34, // reserved ROMControl = 0x38, @@ -218,7 +218,7 @@ enum _DescStatusBit { RxSizeMask = 0x0000ffff /* * The asic could apparently do vlan, TSO, jumbo (sis191 only) and - * provide two (unused with Linux) Tx queues. No publically + * provide two (unused with Linux) Tx queues. No publicly * available documentation alas. */ }; diff --git a/src/drivers/net/sis900.c b/src/drivers/net/sis900.c index 92eb5ce2..75e9ef96 100644 --- a/src/drivers/net/sis900.c +++ b/src/drivers/net/sis900.c @@ -328,7 +328,7 @@ static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic * * Side effects: * leaves the ioaddress of the sis900 chip in the variable ioaddr. - * leaves the sis900 initialized, and ready to recieve packets. + * leaves the sis900 initialized, and ready to receive packets. * * Returns: struct nic *: pointer to NIC data structure */ @@ -394,7 +394,7 @@ static int sis900_probe ( struct nic *nic, struct pci_device *pci ) { mii_status = sis900_mdio_read(phy_addr, MII_STATUS); if (mii_status == 0xffff || mii_status == 0x0000) - /* the mii is not accessable, try next one */ + /* the mii is not accessible, try next one */ continue; phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0); @@ -508,7 +508,7 @@ static u16 sis900_read_eeprom(int location) /* Read and write the MII management registers using software-generated serial MDIO protocol. Note that the command bits and data bits are - send out seperately + sent out separately */ static void sis900_mdio_idle(long mdio_addr) @@ -1171,8 +1171,8 @@ sis900_transmit(struct nic *nic, * * Arguments: struct nic *nic: NIC data structure * - * Returns: 1 if a packet was recieved. - * 0 if no pacet was recieved. + * Returns: 1 if a packet was received. + * 0 if no packet was received. * * Side effects: * Returns (copies) the packet to the array nic->packet. diff --git a/src/drivers/net/skge.h b/src/drivers/net/skge.h index 8a6ba6b2..d9e91457 100755 --- a/src/drivers/net/skge.h +++ b/src/drivers/net/skge.h @@ -1095,7 +1095,7 @@ enum { PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ - PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */ + PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ @@ -1778,8 +1778,8 @@ enum { GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ - GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */ - GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */ + GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ + GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ @@ -2284,7 +2284,7 @@ enum { XM_ST_BC = 1<<7, /* Bit 7: Broadcast packet */ XM_ST_MC = 1<<6, /* Bit 6: Multicast packet */ XM_ST_UC = 1<<5, /* Bit 5: Unicast packet */ - XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occured */ + XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occurred */ XM_ST_CS_ERR = 1<<3, /* Bit 3: Carrier Sense Error */ XM_ST_LAT_COL = 1<<2, /* Bit 2: Late Collision Error */ XM_ST_MUL_COL = 1<<1, /* Bit 1: Multiple Collisions */ diff --git a/src/drivers/net/sky2.c b/src/drivers/net/sky2.c index eed9b5cb..35ff66c6 100644 --- a/src/drivers/net/sky2.c +++ b/src/drivers/net/sky2.c @@ -783,7 +783,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); - /* On chips without ram buffer, pause is controled by MAC level */ + /* On chips without ram buffer, pause is controlled by MAC level */ if (!(hw->flags & SKY2_HW_RAM_BUFFER)) { sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); diff --git a/src/drivers/net/sky2.h b/src/drivers/net/sky2.h index 3e86b1de..9bb63010 100644 --- a/src/drivers/net/sky2.h +++ b/src/drivers/net/sky2.h @@ -1056,7 +1056,7 @@ enum { PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ - PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */ + PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ @@ -1587,8 +1587,8 @@ enum { GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ - GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */ - GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */ + GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ + GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ diff --git a/src/drivers/net/smc9000.h b/src/drivers/net/smc9000.h index 22b0e189..02b1c831 100644 --- a/src/drivers/net/smc9000.h +++ b/src/drivers/net/smc9000.h @@ -107,7 +107,7 @@ typedef unsigned long int dword; #define RPC_LED_10 (0x02) // LED = 10Mbps link detect #define RPC_LED_FD (0x03) // LED = Full Duplex Mode #define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred -#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect +#define RPC_LED_100 (0x05) // LED = 100Mbps link detect #define RPC_LED_TX (0x06) // LED = TX packet occurred #define RPC_LED_RX (0x07) // LED = RX packet occurred #define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) @@ -125,7 +125,7 @@ typedef unsigned long int dword; #define RPC_LED_10 (0x02) // LED = 10Mbps link detect #define RPC_LED_FD (0x03) // LED = Full Duplex Mode #define RPC_LED_TX_RX (0x04) // LED = TX or RX packet occurred -#define RPC_LED_100 (0x05) // LED = 100Mbps link dectect +#define RPC_LED_100 (0x05) // LED = 100Mbps link detect #define RPC_LED_TX (0x06) // LED = TX packet occurred #define RPC_LED_RX (0x07) // LED = RX packet occurred #define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX) diff --git a/src/drivers/net/sundance.c b/src/drivers/net/sundance.c index 4d276105..eef7c9c7 100644 --- a/src/drivers/net/sundance.c +++ b/src/drivers/net/sundance.c @@ -258,7 +258,7 @@ static struct sundance_private { const char *nic_name; /* Frequently used values */ - unsigned int cur_rx; /* Producer/consumer ring indicies */ + unsigned int cur_rx; /* Producer/consumer ring indices */ unsigned int mtu; /* These values keep track of the tranceiver/media in use */ @@ -441,7 +441,7 @@ static void sundance_irq ( struct nic *nic, irq_action_t action ) { /************************************************************************** POLL - Wait for a frame ***************************************************************************/ -static int sundance_poll(struct nic *nic, int retreive) +static int sundance_poll(struct nic *nic, int retrieve) { /* return true if there's an ethernet packet ready to read */ /* nic->packet should contain data on return */ @@ -455,7 +455,7 @@ static int sundance_poll(struct nic *nic, int retreive) return 0; /* There is a packet ready */ - if(!retreive) + if(!retrieve) return 1; intr_status = inw(nic->ioaddr + IntrStatus); diff --git a/src/drivers/net/tlan.c b/src/drivers/net/tlan.c index 927bfce8..74398df4 100644 --- a/src/drivers/net/tlan.c +++ b/src/drivers/net/tlan.c @@ -202,7 +202,7 @@ static struct tlan_private { unsigned short vendor_id; /* PCI Vendor code */ unsigned short dev_id; /* PCI Device code */ const char *nic_name; - unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indicies */ + unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned rx_buf_sz; /* Based on mtu + Slack */ struct TLanList *txList; u32 txHead; @@ -1085,11 +1085,11 @@ These routines are based on the information in Chap. 2 of the * for this device. * phy The address of the PHY to be queried. * reg The register whose contents are to be -* retreived. +* retrieved. * val A pointer to a variable to store the * retrieved value. * -* This function uses the TLAN's MII bus to retreive the contents +* This function uses the TLAN's MII bus to retrieve the contents * of a given register on a PHY. It sends the appropriate info * and then reads the 16-bit register value from the MII bus via * the TLAN SIO register. diff --git a/src/drivers/net/via-rhine.c b/src/drivers/net/via-rhine.c index 439a4a5d..f3bb4e01 100644 --- a/src/drivers/net/via-rhine.c +++ b/src/drivers/net/via-rhine.c @@ -288,7 +288,7 @@ static const char *version = "rhine.c v1.0.2 2004-10-29\n"; */ #define EECSR_EEPR 0x80 /* eeprom programed status, 73h means programed */ -#define EECSR_EMBP 0x40 /* eeprom embeded programming */ +#define EECSR_EMBP 0x40 /* eeprom embedded programming */ #define EECSR_AUTOLD 0x20 /* eeprom content reload */ #define EECSR_DPM 0x10 /* eeprom direct programming */ #define EECSR_CS 0x08 /* eeprom CS pin */ @@ -322,7 +322,7 @@ static const char *version = "rhine.c v1.0.2 2004-10-29\n"; * Bits in the CFGA register */ -#define CFGA_EELOAD 0x80 /* enable eeprom embeded and direct programming */ +#define CFGA_EELOAD 0x80 /* enable eeprom embedded and direct programming */ #define CFGA_JUMPER 0x40 #define CFGA_MTGPIO 0x08 #define CFGA_T10EN 0x02 @@ -693,7 +693,7 @@ static void MIIDelay (void); static void rhine_init_ring (struct nic *dev); static void rhine_disable (struct nic *nic); static void rhine_reset (struct nic *nic); -static int rhine_poll (struct nic *nic, int retreive); +static int rhine_poll (struct nic *nic, int retrieve); static void rhine_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p); static void reload_eeprom(int ioaddr); @@ -1286,7 +1286,7 @@ rhine_reset (struct nic *nic) #define IOSYNC do { inb(nic->ioaddr + StationAddr); } while (0) static int -rhine_poll (struct nic *nic, int retreive) +rhine_poll (struct nic *nic, int retrieve) { struct rhine_private *tp = (struct rhine_private *) nic->priv_data; int rxstatus, good = 0;; @@ -1295,7 +1295,7 @@ rhine_poll (struct nic *nic, int retreive) { unsigned int intr_status; /* There is a packet ready */ - if(!retreive) + if(!retrieve) return 1; intr_status = inw(nic->ioaddr + IntrStatus); diff --git a/src/drivers/net/via-velocity.c b/src/drivers/net/via-velocity.c index f50b1590..9ba0b093 100644 --- a/src/drivers/net/via-velocity.c +++ b/src/drivers/net/via-velocity.c @@ -125,7 +125,7 @@ VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging"); /* IP_byte_align[] is used for IP header DWORD byte aligned 0: indicate the IP header won't be DWORD byte aligned.(Default) . 1: indicate the IP header will be DWORD byte aligned. - In some enviroment, the IP header should be DWORD byte aligned, + In some environment, the IP header should be DWORD byte aligned, or the packet will be droped when we receive it. (eg: IPVS) */ VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned"); diff --git a/src/drivers/net/via-velocity.h b/src/drivers/net/via-velocity.h index b657224d..753fe445 100644 --- a/src/drivers/net/via-velocity.h +++ b/src/drivers/net/via-velocity.h @@ -878,7 +878,7 @@ enum { * Bits in the EECSR register */ -#define EECSR_EMBP 0x40 /* eeprom embeded programming */ +#define EECSR_EMBP 0x40 /* eeprom embedded programming */ #define EECSR_RELOAD 0x20 /* eeprom content reload */ #define EECSR_DPM 0x10 /* eeprom direct programming */ #define EECSR_ECS 0x08 /* eeprom CS pin */ diff --git a/src/drivers/net/virtio-net.c b/src/drivers/net/virtio-net.c index 54e962d1..d5fd8197 100644 --- a/src/drivers/net/virtio-net.c +++ b/src/drivers/net/virtio-net.c @@ -69,7 +69,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * Linux source. */ -/* Virtqueue indicies */ +/* Virtqueue indices */ enum { RX_INDEX = 0, TX_INDEX, diff --git a/src/drivers/net/vxge/vxge_main.c b/src/drivers/net/vxge/vxge_main.c index b8533d31..130eab61 100644 --- a/src/drivers/net/vxge/vxge_main.c +++ b/src/drivers/net/vxge/vxge_main.c @@ -252,7 +252,7 @@ static void vxge_poll(struct net_device *ndev) /* * vxge_irq - enable or Disable interrupts * - * @netdev netdevice sturcture reference + * @netdev netdevice structure reference * @action requested interrupt action */ static void vxge_irq(struct net_device *netdev __unused, int action) diff --git a/src/include/ipxe/iscsi.h b/src/include/ipxe/iscsi.h index b4de793a..be71360a 100644 --- a/src/include/ipxe/iscsi.h +++ b/src/include/ipxe/iscsi.h @@ -36,7 +36,7 @@ union iscsi_segment_lengths { */ uint8_t data_len[3]; } bytes; - /** Ths data length (measured in bytes), in network byte + /** The data length (measured in bytes), in network byte * order, with ahs_len as the first byte. */ uint32_t ahs_and_data_len; diff --git a/src/include/ipxe/pci.h b/src/include/ipxe/pci.h index 520c8a02..a6ed484f 100644 --- a/src/include/ipxe/pci.h +++ b/src/include/ipxe/pci.h @@ -172,7 +172,7 @@ FILE_LICENCE ( GPL2_ONLY ); #define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ #define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */ #define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ -#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */ +#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxiliary power support mask */ #define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ #define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ #define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index efe0d2e0..613541f5 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -428,7 +428,7 @@ static int dns_xfer_deliver ( struct dns_request *dns, } /* Determine what to do next based on the type of query we - * issued and the reponse we received + * issued and the response we received */ switch ( qtype ) { From 0acc52519de732f4f010e1029e1308cee825eaed Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 30 Jan 2013 16:58:17 +0000 Subject: [PATCH 208/250] [tls] Concatenate received non-data records before processing Allow non-data records to be split across multiple received I/O buffers, to accommodate large certificate chains. Reported-by: Nicola Volpini Tested-by: Nicola Volpini Signed-off-by: Michael Brown --- src/core/iobuf.c | 42 ++++++++++++++++++++++++++++++++++++++++ src/include/ipxe/iobuf.h | 1 + src/net/tls.c | 22 ++++++++++----------- 3 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/core/iobuf.c b/src/core/iobuf.c index 3f67d2f5..afc91d15 100644 --- a/src/core/iobuf.c +++ b/src/core/iobuf.c @@ -158,3 +158,45 @@ int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) { return -ENOBUFS; } +/** + * Concatenate I/O buffers into a single buffer + * + * @v list List of I/O buffers + * @ret iobuf Concatenated I/O buffer, or NULL on allocation failure + * + * After a successful concatenation, the list will be empty. + */ +struct io_buffer * iob_concatenate ( struct list_head *list ) { + struct io_buffer *iobuf; + struct io_buffer *tmp; + struct io_buffer *concatenated; + size_t len = 0; + + /* If the list contains only a single entry, avoid an + * unnecessary additional allocation. + */ + if ( list_is_singular ( list ) ) { + iobuf = list_first_entry ( list, struct io_buffer, list ); + INIT_LIST_HEAD ( list ); + return iobuf; + } + + /* Calculate total length */ + list_for_each_entry ( iobuf, list, list ) + len += iob_len ( iobuf ); + + /* Allocate new I/O buffer */ + concatenated = alloc_iob_raw ( len, __alignof__ ( *iobuf ), 0 ); + if ( ! concatenated ) + return NULL; + + /* Move data to new I/O buffer */ + list_for_each_entry_safe ( iobuf, tmp, list, list ) { + list_del ( &iobuf->list ); + memcpy ( iob_put ( concatenated, iob_len ( iobuf ) ), + iobuf->data, iob_len ( iobuf ) ); + free_iob ( iobuf ); + } + + return concatenated; +} diff --git a/src/include/ipxe/iobuf.h b/src/include/ipxe/iobuf.h index 65a8e80d..b2b0cb44 100644 --- a/src/include/ipxe/iobuf.h +++ b/src/include/ipxe/iobuf.h @@ -216,5 +216,6 @@ extern struct io_buffer * __malloc alloc_iob ( size_t len ); extern void free_iob ( struct io_buffer *iobuf ); extern void iob_pad ( struct io_buffer *iobuf, size_t min_len ); extern int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ); +extern struct io_buffer * iob_concatenate ( struct list_head *list ); #endif /* _IPXE_IOBUF_H */ diff --git a/src/net/tls.c b/src/net/tls.c index 4ad131c8..5e18f726 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -105,10 +105,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_EINVAL_MAC \ __einfo_uniqify ( EINFO_EINVAL, 0x0d, \ "Invalid MAC" ) -#define EINVAL_NON_DATA __einfo_error ( EINFO_EINVAL_NON_DATA ) -#define EINFO_EINVAL_NON_DATA \ - __einfo_uniqify ( EINFO_EINVAL, 0x0e, \ - "Overlength non-data record" ) #define EIO_ALERT __einfo_error ( EINFO_EIO_ALERT ) #define EINFO_EIO_ALERT \ __einfo_uniqify ( EINFO_EINVAL, 0x01, \ @@ -137,6 +133,10 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_ENOMEM_RX_DATA \ __einfo_uniqify ( EINFO_ENOMEM, 0x07, \ "Not enough space for received data" ) +#define ENOMEM_RX_CONCAT __einfo_error ( EINFO_ENOMEM_RX_CONCAT ) +#define EINFO_ENOMEM_RX_CONCAT \ + __einfo_uniqify ( EINFO_ENOMEM, 0x08, \ + "Not enough space to concatenate received data" ) #define ENOTSUP_CIPHER __einfo_error ( EINFO_ENOTSUP_CIPHER ) #define EINFO_ENOTSUP_CIPHER \ __einfo_uniqify ( EINFO_ENOTSUP, 0x01, \ @@ -1743,14 +1743,12 @@ static int tls_new_record ( struct tls_session *tls, unsigned int type, return 0; } - /* For all other records, fail unless we have exactly one I/O buffer */ - iobuf = list_first_entry ( rx_data, struct io_buffer, list ); - assert ( iobuf != NULL ); - list_del ( &iobuf->list ); - if ( ! list_empty ( rx_data ) ) { - DBGC ( tls, "TLS %p overlength non-data record\n", tls ); - free_iob ( iobuf ); - return -EINVAL_NON_DATA; + /* For all other records, merge into a single I/O buffer */ + iobuf = iob_concatenate ( rx_data ); + if ( ! iobuf ) { + DBGC ( tls, "TLS %p could not concatenate non-data record " + "type %d\n", tls, type ); + return -ENOMEM_RX_CONCAT; } /* Determine handler */ From b757df7756dd06a03cb810701b2c61f5faaea4f6 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 31 Jan 2013 10:12:58 +0000 Subject: [PATCH 209/250] [build] Include self-tests within "make everything" Signed-off-by: Michael Brown --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 210c6aa5..e240f4ce 100644 --- a/src/Makefile +++ b/src/Makefile @@ -143,7 +143,8 @@ everything : bin-i386-efi/ipxe.efirom \ bin-x86_64-efi/ipxe.efi bin-x86_64-efi/ipxe.efidrv \ bin-x86_64-efi/ipxe.efirom \ - bin-i386-linux/tap.linux bin-x86_64-linux/tap.linux + bin-i386-linux/tap.linux bin-x86_64-linux/tap.linux \ + bin-i386-linux/tests.linux bin-x86_64-linux/tests.linux ############################################################################### # From 3c29c8ecc187b2fdd38c87df42080dc7c5a25b81 Mon Sep 17 00:00:00 2001 From: Jens Rottmann Date: Wed, 6 Feb 2013 14:25:05 +0100 Subject: [PATCH 210/250] [intel] Add Intel I210 Gigabit Ethernet PCI ID Signed-off-by: Jens Rottmann Signed-off-by: Michael Brown --- src/drivers/net/intel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/drivers/net/intel.c b/src/drivers/net/intel.c index 399b5354..ce17e9f2 100644 --- a/src/drivers/net/intel.c +++ b/src/drivers/net/intel.c @@ -945,6 +945,7 @@ static struct pci_device_id intel_nics[] = { PCI_ROM ( 0x8086, 0x1525, "82567v-4", "82567V-4", 0 ), PCI_ROM ( 0x8086, 0x1526, "82576-5", "82576", 0 ), PCI_ROM ( 0x8086, 0x1527, "82580-f2", "82580 Fiber", 0 ), + PCI_ROM ( 0x8086, 0x1533, "i210", "I210", 0 ), PCI_ROM ( 0x8086, 0x294c, "82566dc-2", "82566DC-2", 0 ), PCI_ROM ( 0x8086, 0x2e6e, "cemedia", "CE Media Processor", 0 ), }; From 09c5109b8585178172c7608de8d52e9d9af0b680 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 25 Feb 2013 17:22:01 +0000 Subject: [PATCH 211/250] [efi] Ensure EFI binaries comply with Authenticode requirements Authenticode requires that the size of the raw file must equal the size of the OptionalHeader.SizeOfHeaders plus the sum of all sections' SizeOfRawData. Signed-off-by: Michael Brown --- src/util/elf2efi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c index 007453e2..b28c7ef3 100644 --- a/src/util/elf2efi.c +++ b/src/util/elf2efi.c @@ -614,8 +614,11 @@ static void write_pe_file ( struct pe_header *pe_header, struct pe_section *section; unsigned long fpos = 0; + /* Align length of headers */ + fpos = pe_header->nt.OptionalHeader.SizeOfHeaders = + efi_file_align ( pe_header->nt.OptionalHeader.SizeOfHeaders ); + /* Assign raw data pointers */ - fpos = efi_file_align ( pe_header->nt.OptionalHeader.SizeOfHeaders ); for ( section = pe_sections ; section ; section = section->next ) { if ( section->hdr.SizeOfRawData ) { section->hdr.PointerToRawData = fpos; From 7426177d631c0fd8b2ef3ffae4449637d5bca32a Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 1 Mar 2013 16:32:15 +0100 Subject: [PATCH 212/250] [netdevice] Add vlan_tag() to get the VLAN tag of a network device The iBFT has a VLAN field that should be filled in. Add the vlan_tag() function to extract the VLAN tag of a network device. Since VLAN support is optional, define a weak function that returns 0 when iPXE is built without VLAN support. Signed-off-by: Stefan Hajnoczi Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/include/ipxe/vlan.h | 1 + src/net/netdevice.c | 11 +++++++++++ src/net/vlan.c | 17 +++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/src/include/ipxe/vlan.h b/src/include/ipxe/vlan.h index d9f4484e..083c2191 100644 --- a/src/include/ipxe/vlan.h +++ b/src/include/ipxe/vlan.h @@ -61,6 +61,7 @@ struct vlan_header { extern struct net_device * vlan_find ( struct net_device *trunk, unsigned int tag ); +extern unsigned int vlan_tag ( struct net_device *netdev ); extern int vlan_can_be_trunk ( struct net_device *trunk ); extern int vlan_create ( struct net_device *trunk, unsigned int tag, unsigned int priority ); diff --git a/src/net/netdevice.c b/src/net/netdevice.c index ec3456a9..a7166630 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -33,6 +33,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include /** @file @@ -783,5 +784,15 @@ static void net_step ( struct process *process __unused ) { net_poll(); } +/** + * Get the VLAN tag (when VLAN support is not present) + * + * @v netdev Network device + * @ret tag 0, indicating that device is not a VLAN device + */ +__weak unsigned int vlan_tag ( struct net_device *netdev __unused ) { + return 0; +} + /** Networking stack process */ PERMANENT_PROCESS ( net_process, net_step ); diff --git a/src/net/vlan.c b/src/net/vlan.c index f7281f5d..1a2a0862 100644 --- a/src/net/vlan.c +++ b/src/net/vlan.c @@ -282,6 +282,23 @@ struct net_protocol vlan_protocol __net_protocol = { .rx = vlan_rx, }; +/** + * Get the VLAN tag + * + * @v netdev Network device + * @ret tag VLAN tag, or 0 if device is not a VLAN device + */ +unsigned int vlan_tag ( struct net_device *netdev ) { + struct vlan_device *vlan; + + if ( netdev->op == &vlan_operations ) { + vlan = netdev->priv; + return vlan->tag; + } else { + return 0; + } +} + /** * Check if network device can be used as a VLAN trunk device * From 7d64abbc5d0b5dfe4810883f372b905a359f2697 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 1 Mar 2013 16:32:16 +0100 Subject: [PATCH 213/250] [iscsi] Include 802.1Q VLAN identifier in iBFT The iBFT NIC section has a VLAN field which must be filled in so that iSCSI booting works over VLANs. Unfortunately it is unclear from the IBM specification linked in ibft.c whether the VLAN field is just the 802.1Q VLAN Identifier or the full 802.1Q TCI. For now just fill in the VID, the Priority Code Point and Drop Eligible Indicator could be set in the future if it turns out they should be present too. Signed-off-by: Stefan Hajnoczi Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/drivers/block/ibft.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/drivers/block/ibft.c b/src/drivers/block/ibft.c index f1609637..75ca51a9 100644 --- a/src/drivers/block/ibft.c +++ b/src/drivers/block/ibft.c @@ -37,6 +37,7 @@ FILE_LICENCE ( BSD2 ); #include #include #include +#include #include #include #include @@ -264,6 +265,8 @@ static int ibft_fill_nic ( struct ibft_nic *nic, DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix ); /* Extract values from net-device configuration */ + nic->vlan = cpu_to_le16 ( vlan_tag ( netdev ) ); + DBG ( "iBFT NIC VLAN = %02x\n", le16_to_cpu ( nic->vlan ) ); if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr, nic->mac_address ) ) != 0 ) { DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) ); From 77f64b11f764e721f4f8704b7b90317e52d85fc3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 1 Mar 2013 16:32:29 +0000 Subject: [PATCH 214/250] [netdevice] Separate VLAN support from presence of VLAN-supporting drivers Some NICs (e.g. Hermon) provide hardware support for stripping the VLAN tag, but do not provide any way for this support to be disabled. Drivers for this hardware must therefore call vlan_find() to identify a suitable receiving network device. Provide a weak version of vlan_find() which will always return NULL if VLAN support has not been enabled (either directly, or by enabling a feature such as FCoE which requires VLAN support). This allows the VLAN code to be omitted from builds where the user has not requested support for VLANs. Inspired-by: Stefan Hajnoczi Signed-off-by: Michael Brown --- src/net/netdevice.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/net/netdevice.c b/src/net/netdevice.c index a7166630..e9cbb9e9 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -794,5 +794,17 @@ __weak unsigned int vlan_tag ( struct net_device *netdev __unused ) { return 0; } +/** + * Identify VLAN device (when VLAN support is not present) + * + * @v trunk Trunk network device + * @v tag VLAN tag + * @ret netdev VLAN device, if any + */ +__weak struct net_device * vlan_find ( struct net_device *trunk __unused, + unsigned int tag __unused ) { + return NULL; +} + /** Networking stack process */ PERMANENT_PROCESS ( net_process, net_step ); From e27803e40f9134ca7c05c7bf94f3ccd9bbb8edb4 Mon Sep 17 00:00:00 2001 From: Kevin Tran Date: Mon, 4 Mar 2013 21:56:24 +0000 Subject: [PATCH 215/250] [tg3] Fix various tg3 issues Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/drivers/net/tg3/tg3.h | 6 ++++++ src/drivers/net/tg3/tg3_hw.c | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/drivers/net/tg3/tg3.h b/src/drivers/net/tg3/tg3.h index e84eed87..66036839 100644 --- a/src/drivers/net/tg3/tg3.h +++ b/src/drivers/net/tg3/tg3.h @@ -298,6 +298,7 @@ #define ASIC_REV_57780 0x57780 #define ASIC_REV_5717 0x5717 #define ASIC_REV_57765 0x57785 +#define ASIC_REV_57766 0x57766 #define ASIC_REV_5719 0x5719 #define ASIC_REV_5720 0x5720 #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) @@ -1215,6 +1216,8 @@ #define TG3_CPMU_LNK_AWARE_PWRMD 0x00003610 #define CPMU_LNK_AWARE_MACCLK_MASK 0x001f0000 #define CPMU_LNK_AWARE_MACCLK_6_25 0x00130000 + +#define TG3_CPMU_D0_CLCK_POLICY 0x00003614 /* 0x3614 --> 0x361c unused */ #define TG3_CPMU_HST_ACC 0x0000361c @@ -1225,6 +1228,9 @@ #define TG3_CPMU_CLCK_ORIDE 0x00003624 #define CPMU_CLCK_ORIDE_MAC_ORIDE_EN 0x80000000 +#define TG3_CPMU_CLCK_ORIDE_EN 0x00003628 +#define CPMU_CLCK_ORIDE_MAC_CLCK_ORIDE_EN 0x00002000 + #define TG3_CPMU_CLCK_STAT 0x00003630 #define CPMU_CLCK_STAT_MAC_CLCK_MASK 0x001f0000 #define CPMU_CLCK_STAT_MAC_CLCK_62_5 0x00000000 diff --git a/src/drivers/net/tg3/tg3_hw.c b/src/drivers/net/tg3/tg3_hw.c index 9ae007c2..3a481aba 100644 --- a/src/drivers/net/tg3/tg3_hw.c +++ b/src/drivers/net/tg3/tg3_hw.c @@ -322,7 +322,7 @@ static void tg3_get_eeprom_hw_cfg(struct tg3 *tp) } if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) && - tg3_flag(tp, 5750_PLUS)) + tg3_flag(tp, ENABLE_ASF)) tg3_flag_set(tp, ENABLE_APE); if (cfg2 & (1 << 17)) @@ -466,6 +466,7 @@ int tg3_get_invariants(struct tg3 *tp) tg3_flag_set(tp, 5717_PLUS); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57766 || tg3_flag(tp, 5717_PLUS)) tg3_flag_set(tp, 57765_PLUS); @@ -1465,6 +1466,13 @@ static int tg3_chip_reset(struct tg3 *tp) tw32(TG3_CPMU_CLCK_ORIDE, val & ~CPMU_CLCK_ORIDE_MAC_ORIDE_EN); } + if (tg3_flag(tp, CPMU_PRESENT)) { + tw32(TG3_CPMU_D0_CLCK_POLICY, 0); + val = tr32(TG3_CPMU_CLCK_ORIDE_EN); + tw32(TG3_CPMU_CLCK_ORIDE_EN, + val | CPMU_CLCK_ORIDE_MAC_CLCK_ORIDE_EN); + } + return 0; } From 9373ca8ea2928097e41da1888280a435b54ff1e0 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 5 Mar 2013 14:22:53 +0000 Subject: [PATCH 216/250] [undi] Work around specific devices with known broken interrupt behaviour Some PXE stacks are known to claim that IRQs are supported, but then never generate interrupts. No satisfactory solution has been found to this problem; the workaround is to add the PCI vendor and device IDs to a list of devices which will be treated as simply not supporting interrupts. This is something of a hack, since it will generate false positives for identical devices with a working PXE stack (e.g. those that have been reflashed with iPXE), but it's an improvement on the current situation. Reported-by: Richard Moore Signed-off-by: Michael Brown --- src/arch/i386/drivers/net/undinet.c | 52 +++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index 6205c809..e956b989 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -531,6 +531,53 @@ static struct net_device_operations undinet_operations = { .irq = undinet_irq, }; +/** A device with broken support for generating interrupts */ +struct undinet_irq_broken { + /** PCI vendor ID */ + uint16_t pci_vendor; + /** PCI device ID */ + uint16_t pci_device; +}; + +/** + * List of devices with broken support for generating interrupts + * + * Some PXE stacks are known to claim that IRQs are supported, but + * then never generate interrupts. No satisfactory solution has been + * found to this problem; the workaround is to add the PCI vendor and + * device IDs to this list. This is something of a hack, since it + * will generate false positives for identical devices with a working + * PXE stack (e.g. those that have been reflashed with iPXE), but it's + * an improvement on the current situation. + */ +static const struct undinet_irq_broken undinet_irq_broken_list[] = { + /* HP XX70x laptops */ + { .pci_vendor = 0x8086, .pci_device = 0x1502 }, + { .pci_vendor = 0x8086, .pci_device = 0x1503 }, +}; + +/** + * Check for devices with broken support for generating interrupts + * + * @v undi UNDI device + * @ret irq_is_broken Interrupt support is broken; no interrupts are generated + */ +static int undinet_irq_is_broken ( struct undi_device *undi ) { + const struct undinet_irq_broken *broken; + unsigned int i; + + for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) / + sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) { + broken = &undinet_irq_broken_list[i]; + if ( ( undi->dev.desc.bus_type == BUS_TYPE_PCI ) && + ( undi->dev.desc.vendor == broken->pci_vendor ) && + ( undi->dev.desc.device == broken->pci_device ) ) { + return 1; + } + } + return 0; +} + /** * Probe UNDI device * @@ -647,6 +694,11 @@ int undinet_probe ( struct undi_device *undi ) { undinic ); undinic->hacks |= UNDI_HACK_EB54; } + if ( undinet_irq_is_broken ( undi ) ) { + DBGC ( undinic, "UNDINIC %p forcing polling mode due to " + "broken interrupts\n", undinic ); + undinic->irq_supported = 0; + } /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) From eb5a2ba5962579e514b377f5fdab7292be0fb2a7 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 5 Mar 2013 15:18:20 +0000 Subject: [PATCH 217/250] [zbin] Fix size used for memset in alloc_output_file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The output->buf field is a pointer, not an array, so sizeof() is not applicable. We must use the allocated string length instead. Identified by gcc: util/zbin.c: In function ‘alloc_output_file’: util/zbin.c:146:37: warning: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to dereference it? [-Wsizeof-pointer-memaccess] memset ( output->buf, 0xff, sizeof ( output->buf ) ); Signed-off-by: Daniel P. Berrange Signed-off-by: Michael Brown --- src/util/zbin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/zbin.c b/src/util/zbin.c index 0dabaf1e..3b7cf95b 100644 --- a/src/util/zbin.c +++ b/src/util/zbin.c @@ -143,7 +143,7 @@ static int alloc_output_file ( size_t max_len, struct output_file *output ) { max_len ); return -1; } - memset ( output->buf, 0xff, sizeof ( output->buf ) ); + memset ( output->buf, 0xff, max_len ); return 0; } From b8cbdbbb53512ff35515b3da78b8451b6b8906ae Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Mar 2013 14:41:46 +0000 Subject: [PATCH 218/250] [menu] Prevent character code zero from acting as a shortcut key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unrecognised keys may be returned by getkey() as character code zero, which currently matches against the first menu item with no shortcut key defined. Prevent this unintended behaviour by explicitly checking that the menu item has a defined shortcut key. Reported-by: Ján ONDREJ (SAL) Signed-off-by: Michael Brown --- src/hci/tui/menu_ui.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c index dfa1d2e7..49740795 100644 --- a/src/hci/tui/menu_ui.c +++ b/src/hci/tui/menu_ui.c @@ -247,7 +247,8 @@ static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) { i = 0; list_for_each_entry ( item, &ui->menu->items, list ) { - if ( item->shortcut == key ) { + if ( item->shortcut && + ( item->shortcut == key ) ) { ui->selected = i; chosen = 1; break; From c08025137be3109adb008a4dfd8f023ae3845519 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Mar 2013 15:05:30 +0000 Subject: [PATCH 219/250] [menu] Prevent separators with shortcut keys from being selected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing currently prevents a menu separator from being assigned a shortcut key, and then from being selected using that shortcut key. This produces an inconsistency in the user interface, since separators cannot be selected by other means of menu navigation (arrow keys, page up/down, etc). It would be trivial to prevent separators from being assigned shortcut keys, but this would eliminate one potentially useful use case: having a large menu and using shortcut keys to jump to a section within the menu. Fix by treating a shortcut key on a separator as equivalent to "select the separator, then press the down arrow key". This has the effect of moving to the first non-separator menu item following the specified separator, which is probably the most intuitive behaviour. (The existing logic for moving the selection already handles the various nasty corner cases such as a menu ending with one or more separators.) Reported-by: Ján ONDREJ (SAL) Signed-off-by: Michael Brown --- src/hci/tui/menu_ui.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c index 49740795..d5636f8b 100644 --- a/src/hci/tui/menu_ui.c +++ b/src/hci/tui/menu_ui.c @@ -247,13 +247,17 @@ static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) { i = 0; list_for_each_entry ( item, &ui->menu->items, list ) { - if ( item->shortcut && - ( item->shortcut == key ) ) { - ui->selected = i; - chosen = 1; - break; + if ( ! ( item->shortcut && + ( item->shortcut == key ) ) ) { + i++; + continue; + } + ui->selected = i; + if ( item->label ) { + chosen = 1; + } else { + move = +1; } - i++; } break; } @@ -284,12 +288,10 @@ static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) { draw_menu_item ( ui, ui->selected ); } - /* Refuse to choose unlabelled items (i.e. separators) */ - item = menu_item ( ui->menu, ui->selected ); - if ( ! item->label ) - chosen = 0; - /* Record selection */ + item = menu_item ( ui->menu, ui->selected ); + assert ( item != NULL ); + assert ( item->label != NULL ); *selected = item; } while ( ( rc == 0 ) && ! chosen ); From 02b914e8129c55a1b8766de0ab49928929392e89 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Mar 2013 17:35:30 +0000 Subject: [PATCH 220/250] [tftp] Allow TFTP block size to be controlled via the PXE TFTP API The PXE TFTP API allows the caller to request a particular TFTP block size. Since mid-2008, iPXE has appended a "?blksize=xxx" parameter to the TFTP URI constructed internally; nothing has ever parsed this parameter. Nobody seems to have cared that this parameter has been ignored for almost five years. Fix by using xfer_window(), which provides a fairly natural way to convey the block size information from the PXE TFTP API to the TFTP protocol layer. Signed-off-by: Michael Brown --- src/arch/i386/interface/pxe/pxe_tftp.c | 27 ++++++++++++++++++------- src/include/ipxe/tftp.h | 2 -- src/net/udp/tftp.c | 28 ++++++++------------------ 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/arch/i386/interface/pxe/pxe_tftp.c b/src/arch/i386/interface/pxe/pxe_tftp.c index aab376e8..f4801bad 100644 --- a/src/arch/i386/interface/pxe/pxe_tftp.c +++ b/src/arch/i386/interface/pxe/pxe_tftp.c @@ -71,6 +71,17 @@ static void pxe_tftp_close ( struct pxe_tftp_connection *pxe_tftp, int rc ) { pxe_tftp->rc = rc; } +/** + * Check flow control window + * + * @v pxe_tftp PXE TFTP connection + * @ret len Length of window + */ +static size_t pxe_tftp_xfer_window ( struct pxe_tftp_connection *pxe_tftp ) { + + return pxe_tftp->blksize; +} + /** * Receive new data * @@ -128,6 +139,8 @@ static int pxe_tftp_xfer_deliver ( struct pxe_tftp_connection *pxe_tftp, static struct interface_operation pxe_tftp_xfer_ops[] = { INTF_OP ( xfer_deliver, struct pxe_tftp_connection *, pxe_tftp_xfer_deliver ), + INTF_OP ( xfer_window, struct pxe_tftp_connection *, + pxe_tftp_xfer_window ), INTF_OP ( intf_close, struct pxe_tftp_connection *, pxe_tftp_close ), }; @@ -167,19 +180,19 @@ static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port, /* Reset PXE TFTP connection structure */ memset ( &pxe_tftp, 0, sizeof ( pxe_tftp ) ); intf_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_desc, NULL ); + if ( blksize < TFTP_DEFAULT_BLKSIZE ) + blksize = TFTP_DEFAULT_BLKSIZE; + pxe_tftp.blksize = blksize; pxe_tftp.rc = -EINPROGRESS; /* Construct URI string */ address.s_addr = ipaddress; if ( ! port ) port = htons ( TFTP_PORT ); - if ( blksize < TFTP_DEFAULT_BLKSIZE ) - blksize = TFTP_DEFAULT_BLKSIZE; - snprintf ( uri_string, sizeof ( uri_string ), - "tftp%s://%s:%d%s%s?blksize=%zd", - sizeonly ? "size" : "", - inet_ntoa ( address ), ntohs ( port ), - ( ( filename[0] == '/' ) ? "" : "/" ), filename, blksize ); + snprintf ( uri_string, sizeof ( uri_string ), "tftp%s://%s:%d%s%s", + sizeonly ? "size" : "", inet_ntoa ( address ), + ntohs ( port ), ( ( filename[0] == '/' ) ? "" : "/" ), + filename ); DBG ( " %s", uri_string ); /* Open PXE TFTP connection */ diff --git a/src/include/ipxe/tftp.h b/src/include/ipxe/tftp.h index 38be0d4d..aecafa2a 100644 --- a/src/include/ipxe/tftp.h +++ b/src/include/ipxe/tftp.h @@ -80,6 +80,4 @@ union tftp_any { struct tftp_oack oack; }; -extern void tftp_set_request_blksize ( unsigned int blksize ); - #endif /* _IPXE_TFTP_H */ diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c index a6c64b4a..d686aac9 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -287,24 +287,6 @@ static int tftp_presize ( struct tftp_request *tftp, size_t filesize ) { return 0; } -/** - * TFTP requested blocksize - * - * This is treated as a global configuration parameter. - */ -static unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE; - -/** - * Set TFTP request blocksize - * - * @v blksize Requested block size - */ -void tftp_set_request_blksize ( unsigned int blksize ) { - if ( blksize < TFTP_DEFAULT_BLKSIZE ) - blksize = TFTP_DEFAULT_BLKSIZE; - tftp_request_blksize = blksize; -} - /** * MTFTP multicast receive address * @@ -345,6 +327,7 @@ static int tftp_send_rrq ( struct tftp_request *tftp ) { const char *path; size_t len; struct io_buffer *iobuf; + size_t blksize; /* Strip initial '/' if present. If we were opened via the * URI interface, then there will be an initial '/', since a @@ -370,6 +353,11 @@ static int tftp_send_rrq ( struct tftp_request *tftp ) { if ( ! iobuf ) return -ENOMEM; + /* Determine block size */ + blksize = xfer_window ( &tftp->xfer ); + if ( blksize > TFTP_MAX_BLKSIZE ) + blksize = TFTP_MAX_BLKSIZE; + /* Build request */ rrq = iob_put ( iobuf, sizeof ( *rrq ) ); rrq->opcode = htons ( TFTP_RRQ ); @@ -378,8 +366,8 @@ static int tftp_send_rrq ( struct tftp_request *tftp ) { if ( tftp->flags & TFTP_FL_RRQ_SIZES ) { iob_put ( iobuf, snprintf ( iobuf->tail, iob_tailroom ( iobuf ), - "blksize%c%d%ctsize%c0", 0, - tftp_request_blksize, 0, 0 ) + 1 ); + "blksize%c%zd%ctsize%c0", + 0, blksize, 0, 0 ) + 1 ); } if ( tftp->flags & TFTP_FL_RRQ_MULTICAST ) { iob_put ( iobuf, snprintf ( iobuf->tail, From 3a8dbd9cdff9994d6e75d8aea99ab216ee5a74a3 Mon Sep 17 00:00:00 2001 From: Brandon Penglase Date: Sun, 4 Nov 2012 13:48:08 -0500 Subject: [PATCH 221/250] [build] Add vmware build target Add "make vmware" build target, to build all of the ROMs used with VMware. Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Makefile b/src/Makefile index e240f4ce..207369a9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -146,6 +146,23 @@ everything : bin-i386-linux/tap.linux bin-x86_64-linux/tap.linux \ bin-i386-linux/tests.linux bin-x86_64-linux/tests.linux +############################################################################### +# +# VMware build target: all ROMs used with VMware +# +vmware : bin/8086100f.mrom bin/808610d3.mrom bin/10222000.rom bin/15ad07b0.rom + @$(ECHO) '===========================================================' + @$(ECHO) + @$(ECHO) 'Available ROMs:' + @$(ECHO) ' bin/8086100f.mrom -- intel/e1000' + @$(ECHO) ' bin/808610d3.mrom -- intel/e1000e' + @$(ECHO) ' bin/10222000.rom -- vlance/pcnet32' + @$(ECHO) ' bin/15ad07b0.rom -- vmxnet3' + @$(ECHO) + @$(ECHO) 'For more information, see http://ipxe.org/howto/vmware' + @$(ECHO) + @$(ECHO) '===========================================================' + ############################################################################### # # Build targets that do nothing but might be tried by users From b33082a52b093ad91d2de55be5fe258630985562 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 8 Mar 2013 12:22:56 +0000 Subject: [PATCH 222/250] [pcbios] Add extra debugging messages when unhiding iPXE from memory Signed-off-by: Michael Brown --- src/arch/i386/firmware/pcbios/hidemem.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/arch/i386/firmware/pcbios/hidemem.c b/src/arch/i386/firmware/pcbios/hidemem.c index c1788b3a..8f3069e1 100644 --- a/src/arch/i386/firmware/pcbios/hidemem.c +++ b/src/arch/i386/firmware/pcbios/hidemem.c @@ -190,6 +190,8 @@ static void hide_etherboot ( void ) { * possible. */ static void unhide_etherboot ( int flags __unused ) { + struct memory_map memmap; + int rc; /* If we have more than one hooked interrupt at this point, it * means that some other vector is still hooked, in which case @@ -203,15 +205,23 @@ static void unhide_etherboot ( int flags __unused ) { return; } - /* Try to unhook INT 15. If it fails, then just leave it - * hooked; it takes care of protecting itself. :) - */ - unhook_bios_interrupt ( 0x15, ( unsigned int ) int15, - &int15_vector ); + /* Try to unhook INT 15 */ + if ( ( rc = unhook_bios_interrupt ( 0x15, ( unsigned int ) int15, + &int15_vector ) ) != 0 ) { + DBG ( "Cannot unhook INT15: %s\n", strerror ( rc ) ); + /* Leave it hooked; there's nothing else we can do, + * and it should be intrinsically safe (though + * wasteful of RAM). + */ + } /* Unhook fake E820 map, if used */ if ( FAKE_E820 ) unfake_e820(); + + /* Dump memory map after unhiding */ + DBG ( "Unhidden iPXE from system memory map\n" ); + get_memmap ( &memmap ); } /** Hide Etherboot startup function */ From c7694acb51be7a3676d1b30fd1b0ba34bce09f39 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 8 Mar 2013 13:23:58 +0000 Subject: [PATCH 223/250] [nbiprefix] Set up real-mode stack before jumping to .text16 Signed-off-by: Michael Brown --- src/arch/i386/prefix/nbiprefix.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/arch/i386/prefix/nbiprefix.S b/src/arch/i386/prefix/nbiprefix.S index 20d224d6..06e7df5b 100644 --- a/src/arch/i386/prefix/nbiprefix.S +++ b/src/arch/i386/prefix/nbiprefix.S @@ -54,6 +54,10 @@ _nbi_start: /* Install iPXE */ call install + /* Set up real-mode stack */ + movw %bx, %ss + movw $_estack16, %sp + /* Jump to .text16 segment */ pushw %ax pushw $1f From 0d4a760ffc6561ea69cddcba47c34e98147d30f4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 8 Mar 2013 13:26:22 +0000 Subject: [PATCH 224/250] [prefix] Use %cs as implicit parameter to uninstall() romprefix.S currently calls uninstall() with an invalid value in %ax. Consequently, base memory is not freed after a ROM boot attempt (or after entering iPXE during POST). The uninstall() function is physically present in .text16, and so can use %cs to determine the .text16 segment address. The .data16 segment address is not required, since uninstall() is called only by code paths which set up .data16 to immediately follow .text16. Signed-off-by: Michael Brown --- src/arch/i386/prefix/libprefix.S | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S index 2f8fc4e1..0bd80b0a 100644 --- a/src/arch/i386/prefix/libprefix.S +++ b/src/arch/i386/prefix/libprefix.S @@ -545,8 +545,7 @@ alloc_basemem: * Free space allocated with alloc_basemem. * * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address + * none (.text16 segment address is implicit in %cs) * Returns: * %ax : 0 if successfully freed * Corrupts: @@ -559,14 +558,14 @@ alloc_basemem: free_basemem: /* Preserve registers */ pushw %fs + pushw %ax /* Check FBMS counter */ - pushw %ax + movw %cs, %ax shrw $6, %ax pushw $0x40 popw %fs cmpw %ax, %fs:0x13 - popw %ax jne 1f /* Check hooked interrupt count */ @@ -574,6 +573,7 @@ free_basemem: jne 1f /* OK to free memory */ + movw %cs, %ax addw $_text16_memsz_pgh, %ax addw $_data16_memsz_pgh, %ax shrw $6, %ax @@ -581,6 +581,7 @@ free_basemem: xorw %ax, %ax 1: /* Restore registers and return */ + popw %ax popw %fs ret .size free_basemem, . - free_basemem @@ -872,8 +873,7 @@ close_payload: * Uninstall all text and data segments. * * Parameters: - * %ax : .text16 segment address - * %bx : .data16 segment address + * none (.text16 segment address is implicit in %cs) * Returns: * none * Corrupts: From 2629b7e2cd8975f02a159db461d2460b9275545e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 11 Mar 2013 00:50:52 +0000 Subject: [PATCH 225/250] [pcbios] Inhibit all calls to INT 15,e820 and INT 15,e801 during POST Many BIOSes do not construct the full system memory map until after calling the option ROM initialisation entry points. For several years, we have added sanity checks and workarounds to accommodate charming quirks such as BIOSes which report the entire 32-bit address space (including all memory-mapped PCI BARs) as being usable RAM. The IBM x3650 takes quirky behaviour to a new extreme. Calling either INT 15,e820 or INT 15,e801 during POST doesn't just get you invalid data. We could cope with invalid data. Instead, these nominally read-only API calls manage to trash some internal BIOS state, with the result that the system memory map is _never_ constructed. This tends to confuse subsequent bootloaders and operating systems. [ GRUB 0.97 fails in a particularly amusing way. Someone thought it would be a good idea for memcpy() to check that the destination memory region is a valid part of the system memory map; if not, then memcpy() will sulk, fail, and return NULL. This breaks pretty much every use of memcpy() including, for example, those inserted implicitly by gcc to copy non-const initialisers. Debugging is _fun_ when a simple call to printf() manages to create an infinite recursion, exhaust the available stack space, and shut down the CPU. ] Fix by completely inhibiting calls to INT 15,e820 and INT 15,e801 during POST. We do now allow relocation during POST up to the maximum address returned by INT 15,88 (which seems so far to always be safe). This allows us to continue to have a reasonable size of external heap, even if the PMM allocation is close to the 1MB mark. The downside of allowing relocation during POST is that we may overwrite PMM-allocated memory in use by other option ROMs. However, the downside of inhibiting relocation, when combined with also inhibiting calls to INT 15,e820 and INT 15,e801, would be that we might have no external heap available: this would make booting an OS impossible and could prevent some devices from even completing initialisation. On balance, the lesser evil is probably to allow relocation during POST (up to the limit provided by INT 15,88). Entering iPXE during POST is a rare operation; on the even rarer systems where doing so happens to overwrite a PMM-allocated region, then there exists a fairly simple workaround: if the user enters iPXE during POST and wishes to exit iPXE, then the user must reboot. This is an acceptable cost, given the rarity of the situation and the simplicity of the workaround. Signed-off-by: Michael Brown --- src/arch/i386/core/relocate.c | 8 +++++--- src/arch/i386/firmware/pcbios/memmap.c | 16 ++++++++++++++++ src/arch/i386/prefix/exeprefix.S | 2 +- src/arch/i386/prefix/libprefix.S | 13 +++++++++++-- src/arch/i386/prefix/romprefix.S | 6 +++--- src/arch/i386/prefix/undiloader.S | 2 +- 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/arch/i386/core/relocate.c b/src/arch/i386/core/relocate.c index b9b02944..5fbf2d2c 100644 --- a/src/arch/i386/core/relocate.c +++ b/src/arch/i386/core/relocate.c @@ -33,8 +33,10 @@ extern char _etextdata[]; /** * Relocate iPXE * - * @v ix86 x86 register dump from prefix - * @ret ix86 x86 registers to return to prefix + * @v ebp Maximum address to use for relocation + * @ret esi Current physical address + * @ret edi New physical address + * @ret ecx Length to copy * * This finds a suitable location for iPXE near the top of 32-bit * address space, and returns the physical address of the new location @@ -59,7 +61,7 @@ __asmcall void relocate ( struct i386_all_regs *ix86 ) { /* Determine maximum usable address */ max = MAX_ADDR; - if ( ix86->regs.ebp && ( ix86->regs.ebp < max ) ) { + if ( ix86->regs.ebp < max ) { max = ix86->regs.ebp; DBG ( "Limiting relocation to [0,%lx)\n", max ); } diff --git a/src/arch/i386/firmware/pcbios/memmap.c b/src/arch/i386/firmware/pcbios/memmap.c index cf659226..0937a7ce 100644 --- a/src/arch/i386/firmware/pcbios/memmap.c +++ b/src/arch/i386/firmware/pcbios/memmap.c @@ -63,6 +63,10 @@ struct e820_entry { static struct e820_entry __bss16 ( e820buf ); #define e820buf __use_data16 ( e820buf ) +/** We are running during POST; inhibit INT 15,e820 and INT 15,e801 */ +uint8_t __bss16 ( memmap_post ); +#define memmap_post __use_data16 ( memmap_post ) + /** * Get size of extended memory via INT 15,e801 * @@ -74,6 +78,12 @@ static unsigned int extmemsize_e801 ( void ) { unsigned int flags; unsigned int extmem; + /* Inhibit INT 15,e801 during POST */ + if ( memmap_post ) { + DBG ( "INT 15,e801 not available during POST\n" ); + return 0; + } + __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" "int $0x15\n\t" "pushfw\n\t" @@ -164,6 +174,12 @@ static int meme820 ( struct memory_map *memmap ) { unsigned int flags; unsigned int discard_D; + /* Inhibit INT 15,e820 during POST */ + if ( memmap_post ) { + DBG ( "INT 15,e820 not available during POST\n" ); + return -ENOTTY; + } + /* Clear the E820 buffer. Do this once before starting, * rather than on each call; some BIOSes rely on the contents * being preserved between calls. diff --git a/src/arch/i386/prefix/exeprefix.S b/src/arch/i386/prefix/exeprefix.S index acd3f83c..cb61287d 100644 --- a/src/arch/i386/prefix/exeprefix.S +++ b/src/arch/i386/prefix/exeprefix.S @@ -114,7 +114,7 @@ _exe_start: call alloc_basemem xorl %esi, %esi movl $EXE_DECOMPRESS_ADDRESS, %edi - xorl %ebp, %ebp + orl $0xffffffff, %ebp /* Allow arbitrary relocation */ call install_prealloc /* Set up real-mode stack */ diff --git a/src/arch/i386/prefix/libprefix.S b/src/arch/i386/prefix/libprefix.S index 0bd80b0a..197a86bc 100644 --- a/src/arch/i386/prefix/libprefix.S +++ b/src/arch/i386/prefix/libprefix.S @@ -622,7 +622,7 @@ install: /* Image destination = default */ xorl %edi, %edi /* Allow arbitrary relocation */ - xorl %ebp, %ebp + orl $0xffffffff, %ebp /* Install text and data segments */ call install_prealloc /* Restore registers and return */ @@ -642,7 +642,9 @@ install: * %bx : .data16 segment address * %esi : Image source physical address (or zero for %cs:0000) * %edi : Decompression temporary area physical address (or zero for default) - * %ebp : Maximum end address for relocation (or zero for no maximum) + * %ebp : Maximum end address for relocation + * - 0xffffffff for no maximum + * - 0x00000000 to inhibit use of INT 15,e820 and INT 15,e801 * Corrupts: * none **************************************************************************** @@ -796,6 +798,13 @@ payload_death_message: movw %ax, (init_librm_vector+2) lcall *init_librm_vector + /* Inhibit INT 15,e820 and INT 15,e801 if applicable */ + testl %ebp, %ebp + jnz 1f + incb memmap_post + decl %ebp +1: + /* Call relocate() to determine target address for relocation. * relocate() will return with %esi, %edi and %ecx set up * ready for the copy to the new location. diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 35d037ef..18fef75e 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -445,7 +445,7 @@ no_pmm: * picked up by the initial shell prompt, and we will drop * into a shell. */ - movl $0xa0000, %ebp /* Inhibit relocation during POST */ + xorl %ebp, %ebp /* Inhibit use of INT 15,e820 and INT 15,e801 */ pushw %cs call exec 2: @@ -630,7 +630,7 @@ decompress_to: * Called by the PnP BIOS when it wants to boot us. */ bev_entry: - xorl %ebp, %ebp /* Allow relocation */ + orl $0xffffffff, %ebp /* Allow arbitrary relocation */ pushw %cs call exec lret @@ -665,7 +665,7 @@ int19_entry: /* Leave keypress in buffer and start iPXE. The keypress will * cause the usual initial Ctrl-B prompt to be skipped. */ - xorl %ebp, %ebp /* Allow relocation */ + orl $0xffffffff, %ebp /* Allow arbitrary relocation */ pushw %cs call exec 1: /* Try to call original INT 19 vector */ diff --git a/src/arch/i386/prefix/undiloader.S b/src/arch/i386/prefix/undiloader.S index bb3d469b..ccdd816e 100644 --- a/src/arch/i386/prefix/undiloader.S +++ b/src/arch/i386/prefix/undiloader.S @@ -31,7 +31,7 @@ undiloader: movw %es:14(%di), %ax movl image_source, %esi movl decompress_to, %edi - xorl %ebp, %ebp /* Allow relocation */ + orl $0xffffffff, %ebp /* Allow arbitrary relocation */ call install_prealloc popw %di /* Call UNDI loader C code */ From cb37d92ff6915b511163e0160b5587cce4d9bb1c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 11 Mar 2013 01:43:12 +0000 Subject: [PATCH 226/250] [romprefix] Display only one "Ctrl-B" prompt per PCI device during POST If a multifunction PCI device exposes an iPXE ROM via each function, then each function will display a "Press Ctrl-B to configure iPXE" prompt, and delay for two seconds. Since a single instance of iPXE can drive all functions on the multifunction device, this simply adds unnecessary delay to the boot process. Fix by inhibiting the "Press Ctrl-B" prompt for all except the first function on a PCI device. Signed-off-by: Michael Brown --- src/arch/i386/prefix/romprefix.S | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S index 18fef75e..091673d3 100644 --- a/src/arch/i386/prefix/romprefix.S +++ b/src/arch/i386/prefix/romprefix.S @@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER ) ( PMM_HANDLE_BASE | 0x00001000 ) #define PMM_HANDLE_BASE_DECOMPRESS_TO \ ( PMM_HANDLE_BASE | 0x00002000 ) +#define PCI_FUNC_MASK 0x07 /* ROM banner timeout. Based on the configurable BANNER_TIMEOUT in * config.h, but converted to a number of (18Hz) timer ticks, and @@ -422,6 +423,9 @@ no_pmm: xorw %di, %di cs rep movsb + /* Skip prompt if this is not the first PCI function */ + testb $PCI_FUNC_MASK, init_pci_busdevfn + jnz no_shell /* Prompt for POST-time shell */ movw $init_message_prompt, %si xorw %di, %di @@ -440,7 +444,7 @@ no_pmm: movw $init_message_done, %si call print_message popf - jnz 2f + jnz no_shell /* Ctrl-B was pressed: invoke iPXE. The keypress will be * picked up by the initial shell prompt, and we will drop * into a shell. @@ -448,7 +452,11 @@ no_pmm: xorl %ebp, %ebp /* Inhibit use of INT 15,e820 and INT 15,e801 */ pushw %cs call exec -2: +no_shell: + movb $( '\n' ), %al + xorw %di, %di + call print_character + /* Restore registers */ popw %gs popw %fs @@ -595,7 +603,7 @@ init_message_done: * */ init_pci_busdevfn: - .word 0xffff + .word 0 .size init_pci_busdevfn, . - init_pci_busdevfn /* Image source area From 1025835d802978a16af456deca7a95265ba13af9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 13 Mar 2013 22:23:42 +0000 Subject: [PATCH 227/250] [efi] Update to latest EDK2 headers Signed-off-by: Michael Brown --- src/include/ipxe/efi/Guid/WinCertificate.h | 4 +- src/include/ipxe/efi/IndustryStandard/Pci22.h | 12 ++- src/include/ipxe/efi/Library/BaseLib.h | 52 ++++++++-- src/include/ipxe/efi/Pi/PiBootMode.h | 5 +- .../ipxe/efi/Protocol/SimpleTextInEx.h | 6 +- .../efi/Uefi/UefiInternalFormRepresentation.h | 10 +- src/include/ipxe/efi/Uefi/UefiSpec.h | 94 ++++++++++--------- src/include/ipxe/efi/import.pl | 15 ++- 8 files changed, 125 insertions(+), 73 deletions(-) diff --git a/src/include/ipxe/efi/Guid/WinCertificate.h b/src/include/ipxe/efi/Guid/WinCertificate.h index 75fc642f..cf0a7c25 100644 --- a/src/include/ipxe/efi/Guid/WinCertificate.h +++ b/src/include/ipxe/efi/Guid/WinCertificate.h @@ -1,7 +1,7 @@ /** @file GUID for UEFI WIN_CERTIFICATE structure. - Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -76,7 +76,7 @@ typedef struct { typedef struct { /// /// This is the standard WIN_CERTIFICATE header, where - /// wCertificateType is set to WIN_CERT_TYPE_UEFI_GUID. + /// wCertificateType is set to WIN_CERT_TYPE_EFI_GUID. /// WIN_CERTIFICATE Hdr; /// diff --git a/src/include/ipxe/efi/IndustryStandard/Pci22.h b/src/include/ipxe/efi/IndustryStandard/Pci22.h index b57059a9..53654ee4 100644 --- a/src/include/ipxe/efi/IndustryStandard/Pci22.h +++ b/src/include/ipxe/efi/IndustryStandard/Pci22.h @@ -6,7 +6,7 @@ PCI-to-PCI Bridge Architecture Specification, Revision 1.2 PC Card Standard, 8.0 - Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -221,7 +221,7 @@ typedef struct { #define PCI_IF_16550_MODEM 0x02 #define PCI_IF_16650_MODEM 0x03 #define PCI_IF_16750_MODEM 0x04 -#define PCI_SUBCLASS_SCC_OTHER 0x80 +#define PCI_SUBCLASS_SCC_OTHER 0x80 #define PCI_CLASS_SYSTEM_PERIPHERAL 0x08 #define PCI_SUBCLASS_PIC 0x00 @@ -240,7 +240,7 @@ typedef struct { #define PCI_IF_EISA_TIMER 0x02 #define PCI_SUBCLASS_RTC 0x03 #define PCI_IF_GENERIC_RTC 0x00 -#define PCI_IF_ISA_RTC 0x00 +#define PCI_IF_ISA_RTC 0x01 #define PCI_SUBCLASS_PNP_CONTROLLER 0x04 ///< HotPlug Controller #define PCI_SUBCLASS_PERIPHERAL_OTHER 0x80 @@ -251,10 +251,12 @@ typedef struct { #define PCI_SUBCLASS_SCAN_CONTROLLER 0x03 #define PCI_SUBCLASS_GAMEPORT 0x04 #define PCI_IF_GAMEPORT 0x00 -#define PCI_IF_GAMEPORT1 0x01 +#define PCI_IF_GAMEPORT1 0x10 #define PCI_SUBCLASS_INPUT_OTHER 0x80 #define PCI_CLASS_DOCKING_STATION 0x0A +#define PCI_SUBCLASS_DOCKING_GENERIC 0x00 +#define PCI_SUBCLASS_DOCKING_OTHER 0x80 #define PCI_CLASS_PROCESSOR 0x0B #define PCI_SUBCLASS_PROC_386 0x00 @@ -282,7 +284,7 @@ typedef struct { #define PCI_CLASS_WIRELESS 0x0D #define PCI_SUBCLASS_IRDA 0x00 #define PCI_SUBCLASS_IR 0x01 -#define PCI_SUBCLASS_RF 0x02 +#define PCI_SUBCLASS_RF 0x10 #define PCI_SUBCLASS_WIRELESS_OTHER 0x80 #define PCI_CLASS_INTELLIGENT_IO 0x0E diff --git a/src/include/ipxe/efi/Library/BaseLib.h b/src/include/ipxe/efi/Library/BaseLib.h index af4c8743..be521f96 100644 --- a/src/include/ipxe/efi/Library/BaseLib.h +++ b/src/include/ipxe/efi/Library/BaseLib.h @@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef __BASE_LIB__ #define __BASE_LIB__ +FILE_LICENCE ( BSD3 ); + // // Definitions for architecture-specific types // @@ -1291,7 +1293,7 @@ InitializeListHead ( If Entry is NULL, then ASSERT(). If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number + If PcdMaximumLinkedListLength is not zero, and prior to insertion the number of nodes in ListHead, including the ListHead node, is greater than or equal to PcdMaximumLinkedListLength, then ASSERT(). @@ -1321,7 +1323,7 @@ InsertHeadList ( If Entry is NULL, then ASSERT(). If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and prior to insertion the number + If PcdMaximumLinkedListLength is not zero, and prior to insertion the number of nodes in ListHead, including the ListHead node, is greater than or equal to PcdMaximumLinkedListLength, then ASSERT(). @@ -1350,7 +1352,7 @@ InsertTailList ( If List is NULL, then ASSERT(). If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and the number of nodes + If PcdMaximumLinkedListLength is not zero, and the number of nodes in List, including the List node, is greater than or equal to PcdMaximumLinkedListLength, then ASSERT(). @@ -1378,8 +1380,8 @@ GetFirstNode ( If Node is NULL, then ASSERT(). If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and List contains more than - PcdMaximumLinkedListLenth nodes, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). @param List A pointer to the head node of a doubly linked list. @@ -1407,8 +1409,8 @@ GetNextNode ( If Node is NULL, then ASSERT(). If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and List contains more than - PcdMaximumLinkedListLenth nodes, then ASSERT(). + If PcdMaximumLinkedListLength is not zero, and List contains more than + PcdMaximumLinkedListLength nodes, then ASSERT(). If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). @param List A pointer to the head node of a doubly linked list. @@ -1434,7 +1436,7 @@ GetPreviousNode ( If ListHead is NULL, then ASSERT(). If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and the number of nodes + If PcdMaximumLinkedListLength is not zero, and the number of nodes in List, including the List node, is greater than or equal to PcdMaximumLinkedListLength, then ASSERT(). @@ -1464,7 +1466,7 @@ IsListEmpty ( If Node is NULL, then ASSERT(). If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and the number of nodes + If PcdMaximumLinkedListLength is not zero, and the number of nodes in List, including the List node, is greater than or equal to PcdMaximumLinkedListLength, then ASSERT(). If PcdVerifyNodeInList is TRUE and Node is not a node in List the and Node is not equal @@ -1496,7 +1498,7 @@ IsNull ( If Node is NULL, then ASSERT(). If List was not initialized with INTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead(), then ASSERT(). - If PcdMaximumLinkedListLenth is not zero, and the number of nodes + If PcdMaximumLinkedListLength is not zero, and the number of nodes in List, including the List node, is greater than or equal to PcdMaximumLinkedListLength, then ASSERT(). If PcdVerifyNodeInList is TRUE and Node is not a node in List, then ASSERT(). @@ -2343,6 +2345,7 @@ BitFieldRead8 ( If StartBit is greater than 7, then ASSERT(). If EndBit is greater than 7, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2376,6 +2379,7 @@ BitFieldWrite8 ( If StartBit is greater than 7, then ASSERT(). If EndBit is greater than 7, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2409,6 +2413,7 @@ BitFieldOr8 ( If StartBit is greater than 7, then ASSERT(). If EndBit is greater than 7, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2443,6 +2448,8 @@ BitFieldAnd8 ( If StartBit is greater than 7, then ASSERT(). If EndBit is greater than 7, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2505,6 +2512,7 @@ BitFieldRead16 ( If StartBit is greater than 15, then ASSERT(). If EndBit is greater than 15, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2538,6 +2546,7 @@ BitFieldWrite16 ( If StartBit is greater than 15, then ASSERT(). If EndBit is greater than 15, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2571,6 +2580,7 @@ BitFieldOr16 ( If StartBit is greater than 15, then ASSERT(). If EndBit is greater than 15, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2605,6 +2615,8 @@ BitFieldAnd16 ( If StartBit is greater than 15, then ASSERT(). If EndBit is greater than 15, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2667,6 +2679,7 @@ BitFieldRead32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2700,6 +2713,7 @@ BitFieldWrite32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2733,6 +2747,7 @@ BitFieldOr32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2767,6 +2782,8 @@ BitFieldAnd32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2829,6 +2846,7 @@ BitFieldRead64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2862,6 +2880,7 @@ BitFieldWrite64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2895,6 +2914,7 @@ BitFieldOr64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -2929,6 +2949,8 @@ BitFieldAnd64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Operand Operand on which to perform the bitfield operation. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5380,6 +5402,7 @@ AsmMsrBitFieldRead32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5416,6 +5439,7 @@ AsmMsrBitFieldWrite32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5452,6 +5476,7 @@ AsmMsrBitFieldOr32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5490,6 +5515,8 @@ AsmMsrBitFieldAnd32 ( If StartBit is greater than 31, then ASSERT(). If EndBit is greater than 31, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5684,6 +5711,7 @@ AsmMsrBitFieldRead64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If Value is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5720,6 +5748,7 @@ AsmMsrBitFieldWrite64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5756,6 +5785,7 @@ AsmMsrBitFieldOr64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. @@ -5793,6 +5823,8 @@ AsmMsrBitFieldAnd64 ( If StartBit is greater than 63, then ASSERT(). If EndBit is greater than 63, then ASSERT(). If EndBit is less than StartBit, then ASSERT(). + If AndData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). + If OrData is larger than the bitmask value range specified by StartBit and EndBit, then ASSERT(). @param Index The 32-bit MSR index to write. @param StartBit The ordinal of the least significant bit in the bit field. diff --git a/src/include/ipxe/efi/Pi/PiBootMode.h b/src/include/ipxe/efi/Pi/PiBootMode.h index 30fd4437..f462f7aa 100644 --- a/src/include/ipxe/efi/Pi/PiBootMode.h +++ b/src/include/ipxe/efi/Pi/PiBootMode.h @@ -1,7 +1,7 @@ /** @file Present the boot mode values in PI. - Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -11,7 +11,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. @par Revision Reference: - PI Version 1.0 + PI Version 1.2.1A **/ @@ -35,6 +35,7 @@ typedef UINT32 EFI_BOOT_MODE; #define BOOT_WITH_DEFAULT_SETTINGS 0x04 #define BOOT_ON_S4_RESUME 0x05 #define BOOT_ON_S5_RESUME 0x06 +#define BOOT_WITH_MFG_MODE_SETTINGS 0x07 #define BOOT_ON_S2_RESUME 0x10 #define BOOT_ON_S3_RESUME 0x11 #define BOOT_ON_FLASH_UPDATE 0x12 diff --git a/src/include/ipxe/efi/Protocol/SimpleTextInEx.h b/src/include/ipxe/efi/Protocol/SimpleTextInEx.h index 71d3463b..9a9f5ab5 100644 --- a/src/include/ipxe/efi/Protocol/SimpleTextInEx.h +++ b/src/include/ipxe/efi/Protocol/SimpleTextInEx.h @@ -5,7 +5,7 @@ which exposes much more state and modifier information from the input device, also allows one to register a notification for a particular keystroke. - Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -276,7 +276,7 @@ EFI_STATUS IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN EFI_KEY_DATA *KeyData, IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, - OUT EFI_HANDLE *NotifyHandle + OUT VOID **NotifyHandle ); /** @@ -298,7 +298,7 @@ typedef EFI_STATUS (EFIAPI *EFI_UNREGISTER_KEYSTROKE_NOTIFY)( IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, - IN EFI_HANDLE NotificationHandle + IN VOID *NotificationHandle ); diff --git a/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h b/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h index fb20d763..e792473c 100644 --- a/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h +++ b/src/include/ipxe/efi/Uefi/UefiInternalFormRepresentation.h @@ -887,9 +887,9 @@ typedef struct _EFI_IFR_IMAGE { EFI_IMAGE_ID Id; } EFI_IFR_IMAGE; -typedef struct _EFI_IFR_MODAL { +typedef struct _EFI_IFR_MODAL_TAG { EFI_IFR_OP_HEADER Header; -} EFI_IFR_MODAL; +} EFI_IFR_MODAL_TAG; typedef struct _EFI_IFR_LOCKED { EFI_IFR_OP_HEADER Header; @@ -907,6 +907,12 @@ typedef struct _EFI_IFR_DEFAULT { EFI_IFR_TYPE_VALUE Value; } EFI_IFR_DEFAULT; +typedef struct _EFI_IFR_DEFAULT_2 { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; +} EFI_IFR_DEFAULT_2; + typedef struct _EFI_IFR_VALUE { EFI_IFR_OP_HEADER Header; } EFI_IFR_VALUE; diff --git a/src/include/ipxe/efi/Uefi/UefiSpec.h b/src/include/ipxe/efi/Uefi/UefiSpec.h index 4887157c..141bccd7 100644 --- a/src/include/ipxe/efi/Uefi/UefiSpec.h +++ b/src/include/ipxe/efi/Uefi/UefiSpec.h @@ -283,7 +283,9 @@ EFI_STATUS @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances present in the system. 2) No drivers were connected to ControllerHandle. - + @retval EFI_SECURITY_VIOLATION + The user has no permission to start UEFI device drivers on the device path + associated with the ControllerHandle or specified by the RemainingDevicePath. **/ typedef EFI_STATUS @@ -850,8 +852,9 @@ EFI_STATUS @param ExitData The pointer to a pointer to a data buffer that includes a Null-terminated string, optionally followed by additional binary data. - @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image handle or the image - has already been initialized with StartImage. + @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image handle or the image + has already been initialized with StartImage. + @retval EFI_SECURITY_VIOLATION The current platform policy specifies that the image should not be started. @return Exit code from image **/ @@ -1138,8 +1141,8 @@ EFI_STATUS /** Installs one or more protocol interfaces into the boot services environment. - @param Handle The handle to install the new protocol interfaces on, or NULL if a new - handle is to be allocated. + @param Handle The pointer to a handle to install the new protocol interfaces on, + or a pointer to NULL if a new handle is to be allocated. @param ... A variable argument list containing pairs of protocol GUIDs and protocol interfaces. @@ -1722,6 +1725,10 @@ EFI_STATUS OUT UINT64 *MaximumVariableSize ); +// +// Firmware should stop at a firmware user interface on next boot +// +#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 // // EFI Runtime Services Table @@ -2006,50 +2013,46 @@ EFI_STATUS /// /// EFI Boot Key Data /// -typedef union { - struct { - /// - /// Indicates the revision of the EFI_KEY_OPTION structure. This revision level should be 0. - /// - UINT32 Revision : 8; - /// - /// Either the left or right Shift keys must be pressed (1) or must not be pressed (0). - /// - UINT32 ShiftPressed : 1; - /// - /// Either the left or right Control keys must be pressed (1) or must not be pressed (0). - /// - UINT32 ControlPressed : 1; - /// - /// Either the left or right Alt keys must be pressed (1) or must not be pressed (0). - /// - UINT32 AltPressed : 1; - /// - /// Either the left or right Logo keys must be pressed (1) or must not be pressed (0). - /// - UINT32 LogoPressed : 1; - /// - /// The Menu key must be pressed (1) or must not be pressed (0). - /// - UINT32 MenuPressed : 1; - /// - /// The SysReq key must be pressed (1) or must not be pressed (0). - /// - UINT32 SysReqPressed : 1; - UINT32 Reserved : 16; - /// - /// Specifies the actual number of entries in EFI_KEY_OPTION.Keys, from 0-3. If - /// zero, then only the shift state is considered. If more than one, then the boot option will - /// only be launched if all of the specified keys are pressed with the same shift state. - /// - UINT32 InputKeyCount : 2; - } Options; - UINT32 PackedValue; -} EFI_BOOT_KEY_DATA; +typedef UINT32 EFI_BOOT_KEY_DATA; +/// +/// Indicates the revision of the EFI_KEY_OPTION structure. This revision level should be 0. +/// +#define EFI_KEY_OPTION_REVISION_MASK 0x000000FF +/// +/// Either the left or right Shift keys must be pressed (1) or must not be pressed (0). +/// +#define EFI_KEY_OPTION_SHIFT_PRESSED_MASK BIT8 +/// +/// Either the left or right Control keys must be pressed (1) or must not be pressed (0). +/// +#define EFI_KEY_OPTION_CONTROL_PRESSED_MASK BIT9 +/// +/// Either the left or right Alt keys must be pressed (1) or must not be pressed (0). +/// +#define EFI_KEY_OPTION_ALT_PRESSED_MASK BIT10 +/// +/// Either the left or right Logo keys must be pressed (1) or must not be pressed (0). +/// +#define EFI_KEY_OPTION_LOGO_PRESSED_MASK BIT11 +/// +/// The Menu key must be pressed (1) or must not be pressed (0). +/// +#define EFI_KEY_OPTION_MENU_PRESSED_MASK BIT12 +/// +/// The SysReq key must be pressed (1) or must not be pressed (0). +/// +#define EFI_KEY_OPTION_SYS_REQ_PRESSED_MASK BIT13 +/// +/// Specifies the actual number of entries in EFI_KEY_OPTION.Keys, from 0-3. If +/// zero, then only the shift state is considered. If more than one, then the boot option will +/// only be launched if all of the specified keys are pressed with the same shift state. +/// +#define EFI_KEY_OPTION_INPUT_KEY_COUNT_MASK (BIT30 | BIT31) /// /// EFI Key Option. /// +#pragma pack(1) typedef struct { /// /// Specifies options about how the key will be processed. @@ -2073,6 +2076,7 @@ typedef struct { /// //EFI_INPUT_KEY Keys[]; } EFI_KEY_OPTION; +#pragma pack() // // EFI File location to boot from on removable media devices diff --git a/src/include/ipxe/efi/import.pl b/src/include/ipxe/efi/import.pl index 2b5d3e93..99551468 100755 --- a/src/include/ipxe/efi/import.pl +++ b/src/include/ipxe/efi/import.pl @@ -59,6 +59,7 @@ sub try_import_file { open my $outfh, ">$outfile" or die "Could not open $outfile: $!\n"; my @dependencies = (); my $licence; + my $maybe_guard; my $guard; while ( <$infh> ) { # Strip CR and trailing whitespace @@ -77,10 +78,16 @@ sub try_import_file { # Write out line print $outfh "$_\n"; # Apply FILE_LICENCE() immediately after include guard - if ( /^\#define\s+_?_\S+_H_?_$/ ) { - die "Duplicate header guard detected in $infile\n" if $guard; - $guard = 1; - print $outfh "\nFILE_LICENCE ( $licence );\n" if $licence; + if ( defined $maybe_guard ) { + if ( /^\#define\s+_?_${maybe_guard}_?_$/ ) { + die "Duplicate header guard detected in $infile\n" if $guard; + $guard = $maybe_guard; + print $outfh "\nFILE_LICENCE ( $licence );\n" if $licence; + } + undef $maybe_guard; + } + if ( /^#ifndef\s+_?_(\S+)_?_/ ) { + $maybe_guard = $1; } } close $outfh; From 033f4c92ca86834e44cb3c2a75cdc87cdef80cf9 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 11 Mar 2013 18:38:42 +0000 Subject: [PATCH 228/250] [autoboot] Split main control flow out of main() into a new function ipxe() Signed-off-by: Michael Brown --- src/core/main.c | 84 +-------------------------------- src/include/usr/autoboot.h | 1 + src/usr/autoboot.c | 95 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 82 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 7b7755c9..8ad912d4 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -14,56 +14,18 @@ Literature dealing with the network protocols: FILE_LICENCE ( GPL2_OR_LATER ); +#include #include -#include #include -#include -#include -#include -#include -#include -#include #include #include -#define NORMAL "\033[0m" -#define BOLD "\033[1m" -#define CYAN "\033[36m" - -/** The "scriptlet" setting */ -struct setting scriptlet_setting __setting ( SETTING_MISC ) = { - .name = "scriptlet", - .description = "Boot scriptlet", - .tag = DHCP_EB_SCRIPTLET, - .type = &setting_type_string, -}; - -/** - * Prompt for shell entry - * - * @ret enter_shell User wants to enter shell - */ -static int shell_banner ( void ) { - - /* Skip prompt if timeout is zero */ - if ( BANNER_TIMEOUT <= 0 ) - return 0; - - /* Prompt user */ - printf ( "\n" ); - return ( prompt ( "Press Ctrl-B for the iPXE command line...", - ( BANNER_TIMEOUT * 100 ), CTRL_B ) == 0 ); -} - /** * Main entry point * * @ret rc Return status code */ __asmcall int main ( void ) { - struct feature *feature; - struct image *image; - char *scriptlet; /* Some devices take an unreasonably long time to initialise */ printf ( PRODUCT_SHORT_NAME " initialising devices..." ); @@ -71,49 +33,7 @@ __asmcall int main ( void ) { startup(); printf ( "ok\n" ); - /* - * Print welcome banner - * - * - * If you wish to brand this build of iPXE, please do so by - * defining the string PRODUCT_NAME in config/general.h. - * - * While nothing in the GPL prevents you from removing all - * references to iPXE or http://ipxe.org, we prefer you not to - * do so. - * - */ - printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE %s" - NORMAL " -- Open Source Network Boot Firmware -- " - CYAN "http://ipxe.org" NORMAL "\n" - "Features:", product_version ); - for_each_table_entry ( feature, FEATURES ) - printf ( " %s", feature->name ); - printf ( "\n" ); - - /* Boot system */ - if ( ( image = first_image() ) != NULL ) { - /* We have an embedded image; execute it */ - image_exec ( image ); - } else if ( shell_banner() ) { - /* User wants shell; just give them a shell */ - shell(); - } else { - fetch_string_setting_copy ( NULL, &scriptlet_setting, - &scriptlet ); - if ( scriptlet ) { - /* User has defined a scriptlet; execute it */ - system ( scriptlet ); - free ( scriptlet ); - } else { - /* Try booting. If booting fails, offer the - * user another chance to enter the shell. - */ - autoboot(); - if ( shell_banner() ) - shell(); - } - } + ipxe ( NULL ); shutdown_exit(); diff --git a/src/include/usr/autoboot.h b/src/include/usr/autoboot.h index 25b9f073..cfa4c41e 100644 --- a/src/include/usr/autoboot.h +++ b/src/include/usr/autoboot.h @@ -31,6 +31,7 @@ extern struct uri * fetch_next_server_and_filename ( struct settings *settings ); extern int netboot ( struct net_device *netdev ); extern int autoboot ( void ); +extern void ipxe ( struct net_device *netdev ); extern int pxe_menu_boot ( struct net_device *netdev ); diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 0587f204..b2d288ea 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -30,11 +30,18 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include +#include +#include +#include #include #include #include #include +#include #include +#include /** @file * @@ -47,6 +54,18 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define EINFO_ENOENT_BOOT \ __einfo_uniqify ( EINFO_ENOENT, 0x01, "Nothing to boot" ) +#define NORMAL "\033[0m" +#define BOLD "\033[1m" +#define CYAN "\033[36m" + +/** The "scriptlet" setting */ +struct setting scriptlet_setting __setting ( SETTING_MISC ) = { + .name = "scriptlet", + .description = "Boot scriptlet", + .tag = DHCP_EB_SCRIPTLET, + .type = &setting_type_string, +}; + /** * Perform PXE menu boot when PXE stack is not available */ @@ -423,3 +442,79 @@ int autoboot ( void ) { printf ( "No more network devices\n" ); return rc; } + +/** + * Prompt for shell entry + * + * @ret enter_shell User wants to enter shell + */ +static int shell_banner ( void ) { + + /* Skip prompt if timeout is zero */ + if ( BANNER_TIMEOUT <= 0 ) + return 0; + + /* Prompt user */ + printf ( "\n" ); + return ( prompt ( "Press Ctrl-B for the iPXE command line...", + ( BANNER_TIMEOUT * 100 ), CTRL_B ) == 0 ); +} + +/** + * Main iPXE flow of execution + * + * @v netdev Network device, or NULL + */ +void ipxe ( struct net_device *netdev ) { + struct feature *feature; + struct image *image; + char *scriptlet; + + /* + * Print welcome banner + * + * + * If you wish to brand this build of iPXE, please do so by + * defining the string PRODUCT_NAME in config/general.h. + * + * While nothing in the GPL prevents you from removing all + * references to iPXE or http://ipxe.org, we prefer you not to + * do so. + * + */ + printf ( NORMAL "\n\n" PRODUCT_NAME "\n" BOLD "iPXE %s" + NORMAL " -- Open Source Network Boot Firmware -- " + CYAN "http://ipxe.org" NORMAL "\n" + "Features:", product_version ); + for_each_table_entry ( feature, FEATURES ) + printf ( " %s", feature->name ); + printf ( "\n" ); + + /* Boot system */ + if ( ( image = first_image() ) != NULL ) { + /* We have an embedded image; execute it */ + image_exec ( image ); + } else if ( shell_banner() ) { + /* User wants shell; just give them a shell */ + shell(); + } else { + fetch_string_setting_copy ( NULL, &scriptlet_setting, + &scriptlet ); + if ( scriptlet ) { + /* User has defined a scriptlet; execute it */ + system ( scriptlet ); + free ( scriptlet ); + } else { + /* Try booting. If booting fails, offer the + * user another chance to enter the shell. + */ + if ( netdev ) { + netboot ( netdev ); + } else { + autoboot(); + } + if ( shell_banner() ) + shell(); + } + } +} From db014f3c23be19e11964d48f2bcb25b54a9bf722 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 13 Mar 2013 22:34:06 +0000 Subject: [PATCH 229/250] [efi] Add last_opened_snpdev() Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi_snp.h | 1 + src/interface/efi/efi_snp.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/include/ipxe/efi/efi_snp.h b/src/include/ipxe/efi/efi_snp.h index c8676090..074d1b27 100644 --- a/src/include/ipxe/efi/efi_snp.h +++ b/src/include/ipxe/efi/efi_snp.h @@ -71,5 +71,6 @@ struct efi_snp_device { extern int efi_snp_hii_install ( struct efi_snp_device *snpdev ); extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ); +extern struct efi_snp_device * last_opened_snpdev ( void ); #endif /* _IPXE_EFI_SNP_H */ diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 20027596..48a6f397 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -1005,3 +1005,18 @@ struct net_driver efi_snp_driver __net_driver = { .notify = efi_snp_notify, .remove = efi_snp_remove, }; + +/** + * Get most recently opened SNP device + * + * @ret snpdev Most recently opened SNP device, or NULL + */ +struct efi_snp_device * last_opened_snpdev ( void ) { + struct net_device *netdev; + + netdev = last_opened_netdev(); + if ( ! netdev ) + return NULL; + + return efi_snp_demux ( netdev ); +} From fc87adb46c1395b09302085e9d15fcd8ab3c31fe Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 13 Mar 2013 22:36:32 +0000 Subject: [PATCH 230/250] [efi] Expose downloaded images via EFI_SIMPLE_FILE_SYSTEM_PROTOCOL Expose iPXE's images as a UEFI file system, allowing the booted image to access all images downloaded by iPXE. This functionality is complementary to the custom iPXE download protocol. The iPXE download protocol allows a booted image to utilise iPXE to download arbitrary URIs, but requires the booted image to specifically support the custom iPXE download protocol. The new functionality limits the booted image to accessing only files that were already downloaded by iPXE (e.g. as part of a script), but can work with any generic UEFI image (e.g. the UEFI shell). Both protocols are provided simultaneously, and are attached to the SNP device handle. Signed-off-by: Michael Brown --- src/image/efi_image.c | 231 ++++--- src/include/ipxe/efi/Guid/FileInfo.h | 73 +++ src/include/ipxe/efi/Guid/FileSystemInfo.h | 65 ++ src/include/ipxe/efi/Protocol/BlockIo.h | 243 +++++++ .../ipxe/efi/Protocol/SimpleFileSystem.h | 403 ++++++++++++ src/include/ipxe/efi/efi.h | 2 - .../efi/{ipxe_download.h => efi_download.h} | 3 + src/include/ipxe/efi/efi_file.h | 13 + src/interface/efi/efi_download.c | 34 +- src/interface/efi/efi_file.c | 594 ++++++++++++++++++ 10 files changed, 1546 insertions(+), 115 deletions(-) create mode 100644 src/include/ipxe/efi/Guid/FileInfo.h create mode 100644 src/include/ipxe/efi/Guid/FileSystemInfo.h create mode 100644 src/include/ipxe/efi/Protocol/BlockIo.h create mode 100644 src/include/ipxe/efi/Protocol/SimpleFileSystem.h rename src/include/ipxe/efi/{ipxe_download.h => efi_download.h} (97%) create mode 100644 src/include/ipxe/efi/efi_file.h create mode 100644 src/interface/efi/efi_file.c diff --git a/src/image/efi_image.c b/src/image/efi_image.c index bee966e7..4b04d36f 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -21,7 +21,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include #include +#include +#include +#include +#include +#include #include #include #include @@ -34,79 +40,75 @@ static EFI_GUID efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; /** - * Create a Unicode command line for the image + * Create device path for image + * + * @v image EFI image + * @v parent Parent device path + * @ret path Device path, or NULL on failure + * + * The caller must eventually free() the device path. + */ +static EFI_DEVICE_PATH_PROTOCOL * efi_image_path ( struct image *image, + EFI_DEVICE_PATH *parent ) { + EFI_DEVICE_PATH_PROTOCOL *path; + FILEPATH_DEVICE_PATH *filepath; + EFI_DEVICE_PATH_PROTOCOL *end; + size_t name_len; + size_t prefix_len; + size_t filepath_len; + size_t len; + + /* Calculate device path lengths */ + end = efi_devpath_end ( parent ); + prefix_len = ( ( void * ) end - ( void * ) parent ); + name_len = strlen ( image->name ); + filepath_len = ( SIZE_OF_FILEPATH_DEVICE_PATH + + ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) ); + len = ( prefix_len + filepath_len + sizeof ( *end ) ); + + /* Allocate device path */ + path = zalloc ( len ); + if ( ! path ) + return NULL; + + /* Construct device path */ + memcpy ( path, parent, prefix_len ); + filepath = ( ( ( void * ) path ) + prefix_len ); + filepath->Header.Type = MEDIA_DEVICE_PATH; + filepath->Header.SubType = MEDIA_FILEPATH_DP; + filepath->Header.Length[0] = ( filepath_len & 0xff ); + filepath->Header.Length[1] = ( filepath_len >> 8 ); + efi_snprintf ( filepath->PathName, ( name_len + 1 /* NUL */ ), + "%s", image->name ); + end = ( ( ( void * ) filepath ) + filepath_len ); + end->Type = END_DEVICE_PATH_TYPE; + end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + end->Length[0] = sizeof ( *end ); + + return path; +} + +/** + * Create command line for image * * @v image EFI image - * @v devpath_out Device path to pass to image (output) - * @v cmdline_out Unicode command line (output) - * @v cmdline_len_out Length of command line in bytes (output) - * @ret rc Return status code + * @ret cmdline Command line, or NULL on failure */ -static int efi_image_make_cmdline ( struct image *image, - EFI_DEVICE_PATH **devpath_out, - VOID **cmdline_out, - UINT32 *cmdline_len_out ) { - char *uri; - size_t uri_len; - FILEPATH_DEVICE_PATH *devpath; - EFI_DEVICE_PATH *endpath; - size_t devpath_len; - CHAR16 *cmdline; - UINT32 cmdline_len; - size_t args_len = 0; - UINT32 i; +static wchar_t * efi_image_cmdline ( struct image *image ) { + wchar_t *cmdline; + size_t len; - /* Get the URI string of the image */ - uri_len = unparse_uri ( NULL, 0, image->uri, URI_ALL ) + 1; - - /* Compute final command line length */ - if ( image->cmdline ) { - args_len = strlen ( image->cmdline ) + 1; - } - cmdline_len = args_len + uri_len; - - /* Allocate space for the uri, final command line and device path */ - cmdline = malloc ( cmdline_len * sizeof ( CHAR16 ) + uri_len - + SIZE_OF_FILEPATH_DEVICE_PATH - + uri_len * sizeof ( CHAR16 ) - + sizeof ( EFI_DEVICE_PATH ) ); + len = ( strlen ( image->name ) + + ( image->cmdline ? + ( 1 /* " " */ + strlen ( image->cmdline ) ) : 0 ) ); + cmdline = zalloc ( ( len + 1 /* NUL */ ) * sizeof ( wchar_t ) ); if ( ! cmdline ) - return -ENOMEM; - uri = (char *) ( cmdline + cmdline_len ); - devpath = (FILEPATH_DEVICE_PATH *) ( uri + uri_len ); - endpath = (EFI_DEVICE_PATH *) ( (char *) devpath - + SIZE_OF_FILEPATH_DEVICE_PATH - + uri_len * sizeof ( CHAR16 ) ); - - /* Build the iPXE device path */ - devpath->Header.Type = MEDIA_DEVICE_PATH; - devpath->Header.SubType = MEDIA_FILEPATH_DP; - devpath_len = SIZE_OF_FILEPATH_DEVICE_PATH - + uri_len * sizeof ( CHAR16 ); - devpath->Header.Length[0] = devpath_len & 0xFF; - devpath->Header.Length[1] = devpath_len >> 8; - endpath->Type = END_DEVICE_PATH_TYPE; - endpath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; - endpath->Length[0] = 4; - endpath->Length[1] = 0; - unparse_uri ( uri, uri_len, image->uri, URI_ALL ); - - /* Convert to Unicode */ - for ( i = 0 ; i < uri_len ; i++ ) { - cmdline[i] = uri[i]; - devpath->PathName[i] = uri[i]; - } - if ( image->cmdline ) { - cmdline[uri_len - 1] = ' '; - } - for ( i = 0 ; i < args_len ; i++ ) { - cmdline[i + uri_len] = image->cmdline[i]; - } - - *devpath_out = &devpath->Header; - *cmdline_out = cmdline; - *cmdline_len_out = cmdline_len * sizeof ( CHAR16 ); - return 0; + return NULL; + efi_snprintf ( cmdline, ( len + 1 /* NUL */ ), "%s%s%s", + image->name, + ( image->cmdline ? " " : "" ), + ( image->cmdline ? image->cmdline : "" ) ); + return cmdline; } /** @@ -117,19 +119,60 @@ static int efi_image_make_cmdline ( struct image *image, */ static int efi_image_exec ( struct image *image ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + struct efi_snp_device *snpdev; + EFI_DEVICE_PATH_PROTOCOL *path; union { EFI_LOADED_IMAGE_PROTOCOL *image; void *interface; } loaded; EFI_HANDLE handle; - EFI_HANDLE device_handle = NULL; - UINTN exit_data_size; - CHAR16 *exit_data; + wchar_t *cmdline; EFI_STATUS efirc; int rc; + /* Find an appropriate device handle to use */ + snpdev = last_opened_snpdev(); + if ( ! snpdev ) { + DBGC ( image, "EFIIMAGE %p could not identify SNP device\n", + image ); + rc = -ENODEV; + goto err_no_snpdev; + } + + /* Install file I/O protocols */ + if ( ( rc = efi_file_install ( &snpdev->handle ) ) != 0 ) { + DBGC ( image, "EFIIMAGE %p could not install file protocol: " + "%s\n", image, strerror ( rc ) ); + goto err_file_install; + } + + /* Install iPXE download protocol */ + if ( ( rc = efi_download_install ( &snpdev->handle ) ) != 0 ) { + DBGC ( image, "EFIIMAGE %p could not install iPXE download " + "protocol: %s\n", image, strerror ( rc ) ); + goto err_download_install; + } + + /* Create device path for image */ + path = efi_image_path ( image, &snpdev->path ); + if ( ! path ) { + DBGC ( image, "EFIIMAGE %p could not create device path\n", + image ); + rc = -ENOMEM; + goto err_image_path; + } + + /* Create command line for image */ + cmdline = efi_image_cmdline ( image ); + if ( ! cmdline ) { + DBGC ( image, "EFIIMAGE %p could not create command line\n", + image ); + rc = -ENOMEM; + goto err_cmdline; + } + /* Attempt loading image */ - if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL, + if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, path, user_to_virt ( image->data, 0 ), image->len, &handle ) ) != 0 ) { /* Not an EFI image */ @@ -149,22 +192,19 @@ static int efi_image_exec ( struct image *image ) { goto err_open_protocol; } - /* Pass an iPXE download protocol to the image */ - if ( ( rc = efi_download_install ( &device_handle ) ) != 0 ) { - DBGC ( image, "EFIIMAGE %p could not install iPXE download " - "protocol: %s\n", image, strerror ( rc ) ); - goto err_download_install; - } - loaded.image->DeviceHandle = device_handle; - loaded.image->ParentHandle = efi_loaded_image; - if ( ( rc = efi_image_make_cmdline ( image, &loaded.image->FilePath, - &loaded.image->LoadOptions, - &loaded.image->LoadOptionsSize ) ) != 0 ) - goto err_make_cmdline; + /* Sanity checks */ + assert ( loaded.image->ParentHandle == efi_image_handle ); + assert ( loaded.image->DeviceHandle == snpdev->handle ); + assert ( loaded.image->LoadOptionsSize == 0 ); + assert ( loaded.image->LoadOptions == NULL ); + + /* Set command line */ + loaded.image->LoadOptions = cmdline; + loaded.image->LoadOptionsSize = + ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) ); /* Start the image */ - if ( ( efirc = bs->StartImage ( handle, &exit_data_size, - &exit_data ) ) != 0 ) { + if ( ( efirc = bs->StartImage ( handle, 0, NULL ) ) != 0 ) { DBGC ( image, "EFIIMAGE %p returned with status %s\n", image, efi_strerror ( efirc ) ); rc = EFIRC_TO_RC ( efirc ); @@ -175,17 +215,24 @@ static int efi_image_exec ( struct image *image ) { rc = 0; err_start_image: - free ( loaded.image->LoadOptions ); - err_make_cmdline: - efi_download_uninstall ( device_handle ); - err_download_install: err_open_protocol: /* Unload the image. We can't leave it loaded, because we * have no "unload" operation. */ - bs->UnloadImage ( handle ); + if ( ( efirc = bs->UnloadImage ( handle ) ) != 0 ) { + DBGC ( image, "EFIIMAGE %p could not unload: %s\n", + image, efi_strerror ( efirc ) ); + } err_load_image: - + free ( cmdline ); + err_cmdline: + free ( path ); + err_image_path: + efi_download_uninstall ( snpdev->handle ); + err_download_install: + efi_file_uninstall ( snpdev->handle ); + err_file_install: + err_no_snpdev: return rc; } diff --git a/src/include/ipxe/efi/Guid/FileInfo.h b/src/include/ipxe/efi/Guid/FileInfo.h new file mode 100644 index 00000000..21fd3890 --- /dev/null +++ b/src/include/ipxe/efi/Guid/FileInfo.h @@ -0,0 +1,73 @@ +/** @file + Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.SetInfo() + and EFI_FILE_PROTOCOL.GetInfo() to set or get generic file information. + This GUID is defined in UEFI specification. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __FILE_INFO_H__ +#define __FILE_INFO_H__ + +FILE_LICENCE ( BSD3 ); + +#define EFI_FILE_INFO_ID \ + { \ + 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct { + /// + /// The size of the EFI_FILE_INFO structure, including the Null-terminated FileName string. + /// + UINT64 Size; + /// + /// The size of the file in bytes. + /// + UINT64 FileSize; + /// + /// PhysicalSize The amount of physical space the file consumes on the file system volume. + /// + UINT64 PhysicalSize; + /// + /// The time the file was created. + /// + EFI_TIME CreateTime; + /// + /// The time when the file was last accessed. + /// + EFI_TIME LastAccessTime; + /// + /// The time when the file's contents were last modified. + /// + EFI_TIME ModificationTime; + /// + /// The attribute bits for the file. + /// + UINT64 Attribute; + /// + /// The Null-terminated name of the file. + /// + CHAR16 FileName[1]; +} EFI_FILE_INFO; + +/// +/// The FileName field of the EFI_FILE_INFO data structure is variable length. +/// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to +/// be the size of the data structure without the FileName field. The following macro +/// computes this size correctly no matter how big the FileName array is declared. +/// This is required to make the EFI_FILE_INFO data structure ANSI compilant. +/// +#define SIZE_OF_EFI_FILE_INFO OFFSET_OF (EFI_FILE_INFO, FileName) + +extern EFI_GUID gEfiFileInfoGuid; + +#endif diff --git a/src/include/ipxe/efi/Guid/FileSystemInfo.h b/src/include/ipxe/efi/Guid/FileSystemInfo.h new file mode 100644 index 00000000..504b7938 --- /dev/null +++ b/src/include/ipxe/efi/Guid/FileSystemInfo.h @@ -0,0 +1,65 @@ +/** @file + Provides a GUID and a data structure that can be used with EFI_FILE_PROTOCOL.GetInfo() + or EFI_FILE_PROTOCOL.SetInfo() to get or set information about the system's volume. + This GUID is defined in UEFI specification. + +Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __FILE_SYSTEM_INFO_H__ +#define __FILE_SYSTEM_INFO_H__ + +FILE_LICENCE ( BSD3 ); + +#define EFI_FILE_SYSTEM_INFO_ID \ + { \ + 0x9576e93, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct { + /// + /// The size of the EFI_FILE_SYSTEM_INFO structure, including the Null-terminated VolumeLabel string. + /// + UINT64 Size; + /// + /// TRUE if the volume only supports read access. + /// + BOOLEAN ReadOnly; + /// + /// The number of bytes managed by the file system. + /// + UINT64 VolumeSize; + /// + /// The number of available bytes for use by the file system. + /// + UINT64 FreeSpace; + /// + /// The nominal block size by which files are typically grown. + /// + UINT32 BlockSize; + /// + /// The Null-terminated string that is the volume's label. + /// + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_INFO; + +/// +/// The VolumeLabel field of the EFI_FILE_SYSTEM_INFO data structure is variable length. +/// Whenever code needs to know the size of the EFI_FILE_SYSTEM_INFO data structure, it needs +/// to be the size of the data structure without the VolumeLable field. The following macro +/// computes this size correctly no matter how big the VolumeLable array is declared. +/// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant. +/// +#define SIZE_OF_EFI_FILE_SYSTEM_INFO OFFSET_OF (EFI_FILE_SYSTEM_INFO, VolumeLabel) + +extern EFI_GUID gEfiFileSystemInfoGuid; + +#endif diff --git a/src/include/ipxe/efi/Protocol/BlockIo.h b/src/include/ipxe/efi/Protocol/BlockIo.h new file mode 100644 index 00000000..f45154bb --- /dev/null +++ b/src/include/ipxe/efi/Protocol/BlockIo.h @@ -0,0 +1,243 @@ +/** @file + Block IO protocol as defined in the UEFI 2.0 specification. + + The Block IO protocol is used to abstract block devices like hard drives, + DVD-ROMs and floppy drives. + + Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __BLOCK_IO_H__ +#define __BLOCK_IO_H__ + +FILE_LICENCE ( BSD3 ); + +#define EFI_BLOCK_IO_PROTOCOL_GUID \ + { \ + 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL; + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL_GUID + +/// +/// Protocol defined in EFI1.1. +/// +typedef EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO; + +/** + Reset the Block Device. + + @param This Indicates a pointer to the calling context. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_RESET)( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Read BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId Id of the media, changes every time the media is replaced. + @param Lba The starting Logical Block Address to read from + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer A pointer to the destination buffer for the data. The caller is + responsible for either having implicit or explicit ownership of the buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_READ)( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Write BufferSize bytes from Lba into Buffer. + + @param This Indicates a pointer to the calling context. + @param MediaId The media ID that the write request is for. + @param Lba The starting logical block address to be written. The caller is + responsible for writing to only legitimate locations. + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer A pointer to the source buffer for the data. + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_WRITE)( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flush the Block Device. + + @param This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding data was written to the device + @retval EFI_DEVICE_ERROR The device reported an error while writting back the data + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_FLUSH)( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +/** + Block IO read only mode data and updated only via members of BlockIO +**/ +typedef struct { + /// + /// The curent media Id. If the media changes, this value is changed. + /// + UINT32 MediaId; + + /// + /// TRUE if the media is removable; otherwise, FALSE. + /// + BOOLEAN RemovableMedia; + + /// + /// TRUE if there is a media currently present in the device; + /// othersise, FALSE. THis field shows the media present status + /// as of the most recent ReadBlocks() or WriteBlocks() call. + /// + BOOLEAN MediaPresent; + + /// + /// TRUE if LBA 0 is the first block of a partition; otherwise + /// FALSE. For media with only one partition this would be TRUE. + /// + BOOLEAN LogicalPartition; + + /// + /// TRUE if the media is marked read-only otherwise, FALSE. + /// This field shows the read-only status as of the most recent WriteBlocks () call. + /// + BOOLEAN ReadOnly; + + /// + /// TRUE if the WriteBlock () function caches write data. + /// + BOOLEAN WriteCaching; + + /// + /// The intrinsic block size of the device. If the media changes, then + /// this field is updated. + /// + UINT32 BlockSize; + + /// + /// Supplies the alignment requirement for any buffer to read or write block(s). + /// + UINT32 IoAlign; + + /// + /// The last logical block address on the device. + /// If the media changes, then this field is updated. + /// + EFI_LBA LastBlock; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the first LBA is aligned to + /// a physical block boundary. + /// + EFI_LBA LowestAlignedLba; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION2. Returns the number of logical blocks + /// per physical block. + /// + UINT32 LogicalBlocksPerPhysicalBlock; + + /// + /// Only present if EFI_BLOCK_IO_PROTOCOL.Revision is greater than or equal to + /// EFI_BLOCK_IO_PROTOCOL_REVISION3. Returns the optimal transfer length + /// granularity as a number of logical blocks. + /// + UINT32 OptimalTransferLengthGranularity; +} EFI_BLOCK_IO_MEDIA; + +#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000 +#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 +#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031 + +/// +/// Revision defined in EFI1.1. +/// +#define EFI_BLOCK_IO_INTERFACE_REVISION EFI_BLOCK_IO_PROTOCOL_REVISION + +/// +/// This protocol provides control over block devices. +/// +struct _EFI_BLOCK_IO_PROTOCOL { + /// + /// The revision to which the block IO interface adheres. All future + /// revisions must be backwards compatible. If a future version is not + /// back wards compatible, it is not the same GUID. + /// + UINT64 Revision; + /// + /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device. + /// + EFI_BLOCK_IO_MEDIA *Media; + + EFI_BLOCK_RESET Reset; + EFI_BLOCK_READ ReadBlocks; + EFI_BLOCK_WRITE WriteBlocks; + EFI_BLOCK_FLUSH FlushBlocks; + +}; + +extern EFI_GUID gEfiBlockIoProtocolGuid; + +#endif diff --git a/src/include/ipxe/efi/Protocol/SimpleFileSystem.h b/src/include/ipxe/efi/Protocol/SimpleFileSystem.h new file mode 100644 index 00000000..19818086 --- /dev/null +++ b/src/include/ipxe/efi/Protocol/SimpleFileSystem.h @@ -0,0 +1,403 @@ +/** @file + SimpleFileSystem protocol as defined in the UEFI 2.0 specification. + + The SimpleFileSystem protocol is the programmatic access to the FAT (12,16,32) + file system specified in UEFI 2.0. It can also be used to abstract a file + system other than FAT. + + UEFI 2.0 can boot from any valid EFI image contained in a SimpleFileSystem. + +Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __SIMPLE_FILE_SYSTEM_H__ +#define __SIMPLE_FILE_SYSTEM_H__ + +FILE_LICENCE ( BSD3 ); + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { \ + 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; + +typedef struct _EFI_FILE_PROTOCOL EFI_FILE_PROTOCOL; +typedef struct _EFI_FILE_PROTOCOL *EFI_FILE_HANDLE; + +/// +/// Protocol GUID name defined in EFI1.1. +/// +#define SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID + +/// +/// Protocol name defined in EFI1.1. +/// +typedef EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_FILE_IO_INTERFACE; +typedef EFI_FILE_PROTOCOL EFI_FILE; + +/** + Open the root directory on a volume. + + @param This A pointer to the volume to open the root directory. + @param Root A pointer to the location to return the opened file handle for the + root directory. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_UNSUPPORTED This volume does not support the requested file system type. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. Any existing file handles for this volume are + no longer valid. To access the files on the new medium, the + volume must be reopened with OpenVolume(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **Root + ); + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 + +/// +/// Revision defined in EFI1.1 +/// +#define EFI_FILE_IO_INTERFACE_REVISION EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION + +struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + /// + /// The version of the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. The version + /// specified by this specification is 0x00010000. All future revisions + /// must be backwards compatible. + /// + UINT64 Revision; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume; +}; + +/** + Opens a new file relative to the source file's location. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to the source location. This would typically be an open + handle to a directory. + @param NewHandle A pointer to the location to return the opened handle for the new + file. + @param FileName The Null-terminated string of the name of the file to be opened. + The file name may contain the following path modifiers: "\", ".", + and "..". + @param OpenMode The mode to open the file. The only valid combinations that the + file may be opened with are: Read, Read/Write, or Create/Read/Write. + @param Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the + attribute bits for the newly created file. + + @retval EFI_SUCCESS The file was opened. + @retval EFI_NOT_FOUND The specified file could not be found on the device. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write + when the media is write-protected. + @retval EFI_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_OPEN)( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +// +// Open modes +// +#define EFI_FILE_MODE_READ 0x0000000000000001ULL +#define EFI_FILE_MODE_WRITE 0x0000000000000002ULL +#define EFI_FILE_MODE_CREATE 0x8000000000000000ULL + +// +// File attributes +// +#define EFI_FILE_READ_ONLY 0x0000000000000001ULL +#define EFI_FILE_HIDDEN 0x0000000000000002ULL +#define EFI_FILE_SYSTEM 0x0000000000000004ULL +#define EFI_FILE_RESERVED 0x0000000000000008ULL +#define EFI_FILE_DIRECTORY 0x0000000000000010ULL +#define EFI_FILE_ARCHIVE 0x0000000000000020ULL +#define EFI_FILE_VALID_ATTR 0x0000000000000037ULL + +/** + Closes a specified file handle. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to close. + + @retval EFI_SUCCESS The file was closed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_CLOSE)( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Close and delete the file handle. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the + handle to the file to delete. + + @retval EFI_SUCCESS The file was closed and deleted, and the handle was closed. + @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_DELETE)( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Reads data from a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to read data from. + @param BufferSize On input, the size of the Buffer. On output, the amount of data + returned in Buffer. In both cases, the size is measured in bytes. + @param Buffer The buffer into which the data is read. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file. + @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TO_SMALL The BufferSize is too small to read the current directory + entry. BufferSize has been updated with the size + needed to complete the request. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_READ)( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Writes data to a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to write data to. + @param BufferSize On input, the size of the Buffer. On output, the amount of data + actually written. In both cases, the size is measured in bytes. + @param Buffer The buffer of data to write. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Writes to open directory files are not supported. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write-protected. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_WRITE)( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Sets a file's current position. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the + file handle to set the requested position on. + @param Position The byte position from the start of the file to set. + + @retval EFI_SUCCESS The position was set. + @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open + directories. + @retval EFI_DEVICE_ERROR An attempt was made to set the position of a deleted file. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_POSITION)( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ); + +/** + Returns a file's current position. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to get the current position on. + @param Position The address to return the file's current position value. + + @retval EFI_SUCCESS The position was returned. + @retval EFI_UNSUPPORTED The request is not valid on open directories. + @retval EFI_DEVICE_ERROR An attempt was made to get the position from a deleted file. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_POSITION)( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ); + +/** + Returns information about a file. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle the requested information is for. + @param InformationType The type identifier for the information being requested. + @param BufferSize On input, the size of Buffer. On output, the amount of data + returned in Buffer. In both cases, the size is measured in bytes. + @param Buffer A pointer to the data buffer to return. The buffer's type is + indicated by InformationType. + + @retval EFI_SUCCESS The information was returned. + @retval EFI_UNSUPPORTED The InformationType is not known. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry. + BufferSize has been updated with the size needed to complete + the request. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_INFO)( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Sets information about a file. + + @param File A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle the information is for. + @param InformationType The type identifier for the information being set. + @param BufferSize The size, in bytes, of Buffer. + @param Buffer A pointer to the data buffer to write. The buffer's type is + indicated by InformationType. + + @retval EFI_SUCCESS The information was set. + @retval EFI_UNSUPPORTED The InformationType is not known. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_INFO_ID and the media is + read-only. + @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_PROTOCOL_SYSTEM_INFO_ID + and the media is read only. + @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_SYSTEM_VOLUME_LABEL_ID + and the media is read-only. + @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file to a + file that is already present. + @retval EFI_ACCESS_DENIED An attempt is being made to change the EFI_FILE_DIRECTORY + Attribute. + @retval EFI_ACCESS_DENIED An attempt is being made to change the size of a directory. + @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the file was opened + read-only and an attempt is being made to modify a field + other than Attribute. + @retval EFI_VOLUME_FULL The volume is full. + @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type indicated + by InformationType. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_INFO)( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flushes all modified data associated with a file to a device. + + @param This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to flush. + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_NO_MEDIA The device has no medium. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. + @retval EFI_WRITE_PROTECTED The file or medium is write-protected. + @retval EFI_ACCESS_DENIED The file was opened read-only. + @retval EFI_VOLUME_FULL The volume is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_FLUSH)( + IN EFI_FILE_PROTOCOL *This + ); + +#define EFI_FILE_PROTOCOL_REVISION 0x00010000 +// +// Revision defined in EFI1.1. +// +#define EFI_FILE_REVISION EFI_FILE_PROTOCOL_REVISION + +/// +/// The EFI_FILE_PROTOCOL provides file IO access to supported file systems. +/// An EFI_FILE_PROTOCOL provides access to a file's or directory's contents, +/// and is also a reference to a location in the directory tree of the file system +/// in which the file resides. With any given file handle, other files may be opened +/// relative to this file's location, yielding new file handles. +/// +struct _EFI_FILE_PROTOCOL { + /// + /// The version of the EFI_FILE_PROTOCOL interface. The version specified + /// by this specification is 0x00010000. Future versions are required + /// to be backward compatible to version 1.0. + /// + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; +}; + + +extern EFI_GUID gEfiSimpleFileSystemProtocolGuid; + +#endif diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index b5ce7df9..8a216b53 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -142,7 +142,5 @@ extern EFI_SYSTEM_TABLE *efi_systab; extern const char * efi_strerror ( EFI_STATUS efirc ); extern EFI_STATUS efi_init ( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab ); -extern int efi_download_install ( EFI_HANDLE *device_handle ); -extern void efi_download_uninstall ( EFI_HANDLE device_handle ); #endif /* _IPXE_EFI_H */ diff --git a/src/include/ipxe/efi/ipxe_download.h b/src/include/ipxe/efi/efi_download.h similarity index 97% rename from src/include/ipxe/efi/ipxe_download.h rename to src/include/ipxe/efi/efi_download.h index 22e3cef0..3ce49722 100644 --- a/src/include/ipxe/efi/ipxe_download.h +++ b/src/include/ipxe/efi/efi_download.h @@ -151,4 +151,7 @@ struct _IPXE_DOWNLOAD_PROTOCOL { 0x3eaeaebd, 0xdecf, 0x493b, { 0x9b, 0xd1, 0xcd, 0xb2, 0xde, 0xca, 0xe7, 0x19 } \ } +extern int efi_download_install ( EFI_HANDLE *device ); +extern void efi_download_uninstall ( EFI_HANDLE device ); + #endif /* _IPXE_DOWNLOAD_H */ diff --git a/src/include/ipxe/efi/efi_file.h b/src/include/ipxe/efi/efi_file.h new file mode 100644 index 00000000..0d75cf5b --- /dev/null +++ b/src/include/ipxe/efi/efi_file.h @@ -0,0 +1,13 @@ +#ifndef _IPXE_EFI_FILE_H +#define _IPXE_EFI_FILE_H + +/** @file + * + * EFI file protocols + * + */ + +extern int efi_file_install ( EFI_HANDLE *handle ); +extern void efi_file_uninstall ( EFI_HANDLE handle ); + +#endif /* _IPXE_EFI_FILE_H */ diff --git a/src/interface/efi/efi_download.c b/src/interface/efi/efi_download.c index 250946e2..7b19ad3a 100644 --- a/src/interface/efi/efi_download.c +++ b/src/interface/efi/efi_download.c @@ -25,7 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include +#include /** iPXE download protocol GUID */ static EFI_GUID ipxe_download_protocol_guid @@ -187,47 +187,39 @@ static IPXE_DOWNLOAD_PROTOCOL ipxe_download_protocol_interface = { }; /** - * Create a new device handle with a iPXE download protocol attached to it. + * Install iPXE download protocol * - * @v device_handle Newly created device handle (output) + * @v handle EFI handle * @ret rc Return status code */ -int efi_download_install ( EFI_HANDLE *device_handle ) { +int efi_download_install ( EFI_HANDLE *handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_STATUS efirc; - EFI_HANDLE handle = NULL; - if (efi_loaded_image->DeviceHandle) { /* TODO: ensure handle is the NIC (maybe efi_image has a better way to indicate the handle doing SNP?) */ - handle = efi_loaded_image->DeviceHandle; - } - DBG ( "Installing ipxe protocol interface (%p)... ", - &ipxe_download_protocol_interface ); efirc = bs->InstallMultipleProtocolInterfaces ( - &handle, + handle, &ipxe_download_protocol_guid, &ipxe_download_protocol_interface, NULL ); if ( efirc ) { - DBG ( "failed (%s)\n", efi_strerror ( efirc ) ); + DBG ( "Could not install download protocol: %s\n", + efi_strerror ( efirc ) ); return EFIRC_TO_RC ( efirc ); } - DBG ( "success (%p)\n", handle ); - *device_handle = handle; return 0; } /** - * Remove the iPXE download protocol from the given handle, and if nothing - * else is attached, destroy the handle. + * Uninstall iPXE download protocol * - * @v device_handle EFI device handle to remove from + * @v handle EFI handle */ -void efi_download_uninstall ( EFI_HANDLE device_handle ) { +void efi_download_uninstall ( EFI_HANDLE handle ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; bs->UninstallMultipleProtocolInterfaces ( - device_handle, - ipxe_download_protocol_guid, - ipxe_download_protocol_interface ); + handle, + &ipxe_download_protocol_guid, + &ipxe_download_protocol_interface, NULL ); } diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c new file mode 100644 index 00000000..ffe25fd6 --- /dev/null +++ b/src/interface/efi/efi_file.c @@ -0,0 +1,594 @@ +/* + * Copyright (C) 2013 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @file + * + * EFI file protocols + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** EFI simple file system protocol GUID */ +static EFI_GUID efi_simple_file_system_protocol_guid + = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + +/** EFI file information GUID */ +static EFI_GUID efi_file_info_id = EFI_FILE_INFO_ID; + +/** EFI file system information GUID */ +static EFI_GUID efi_file_system_info_id = EFI_FILE_SYSTEM_INFO_ID; + +/** EFI block I/O protocol GUID */ +static EFI_GUID efi_block_io_protocol_guid + = EFI_BLOCK_IO_PROTOCOL_GUID; + +/** EFI media ID */ +#define EFI_MEDIA_ID_MAGIC 0x69505845 + +/** An image exposed as an EFI file */ +struct efi_file { + /** EFI file protocol */ + EFI_FILE_PROTOCOL file; + /** Image */ + struct image *image; + /** Current file position */ + size_t pos; +}; + +static struct efi_file efi_file_root; + +/** + * Get EFI file name (for debugging) + * + * @v file EFI file + * @ret name Name + */ +static const char * efi_file_name ( struct efi_file *file ) { + + return ( file->image ? file->image->name : "" ); +} + +/** + * Open file + * + * @v this EFI file + * @ret new New EFI file + * @v wname Filename + * @v mode File mode + * @v attributes File attributes (for newly-created files) + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new, + CHAR16 *wname, UINT64 mode __unused, + UINT64 attributes __unused ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + char name[ wcslen ( wname ) + 1 /* NUL */ ]; + struct efi_file *new_file; + struct image *image; + + /* Initial '\' indicates opening from the root directory */ + while ( *wname == L'\\' ) { + file = &efi_file_root; + wname++; + } + + /* Allow root directory itself to be opened */ + if ( ( wname[0] == L'\0' ) || ( wname[0] == L'.' ) ) { + *new = &efi_file_root.file; + return 0; + } + + /* Fail unless opening from the root */ + if ( file->image ) { + DBGC ( file, "EFIFILE %s is not a directory\n", + efi_file_name ( file ) ); + return EFI_NOT_FOUND; + } + + /* Identify image */ + snprintf ( name, sizeof ( name ), "%ls", wname ); + image = find_image ( name ); + if ( ! image ) { + DBGC ( file, "EFIFILE \"%s\" does not exist\n", name ); + return EFI_NOT_FOUND; + } + + /* Fail unless opening read-only */ + if ( mode != EFI_FILE_MODE_READ ) { + DBGC ( file, "EFIFILE %s cannot be opened in mode %#08llx\n", + image->name, mode ); + return EFI_WRITE_PROTECTED; + } + + /* Allocate and initialise file */ + new_file = zalloc ( sizeof ( *new_file ) ); + memcpy ( &new_file->file, &efi_file_root.file, + sizeof ( new_file->file ) ); + new_file->image = image_get ( image ); + *new = &new_file->file; + DBGC ( new_file, "EFIFILE %s opened\n", efi_file_name ( new_file ) ); + + return 0; +} + +/** + * Close file + * + * @v this EFI file + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_close ( EFI_FILE_PROTOCOL *this ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + + /* Do nothing if this is the root */ + if ( ! file->image ) + return 0; + + /* Close file */ + DBGC ( file, "EFIFILE %s closed\n", efi_file_name ( file ) ); + image_put ( file->image ); + free ( file ); + + return 0; +} + +/** + * Close and delete file + * + * @v this EFI file + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_delete ( EFI_FILE_PROTOCOL *this ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + + DBGC ( file, "EFIFILE %s cannot be deleted\n", efi_file_name ( file ) ); + + /* Close file */ + efi_file_close ( this ); + + /* Warn of failure to delete */ + return EFI_WARN_DELETE_FAILURE; +} + +/** + * Return variable-length data structure + * + * @v base Base data structure (starting with UINT64) + * @v base_len Length of base data structure + * @v name Name to append to base data structure + * @v len Length of data buffer + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS efi_file_varlen ( UINT64 *base, size_t base_len, + const char *name, UINTN *len, VOID *data ) { + size_t name_len; + + /* Calculate structure length */ + name_len = strlen ( name ); + *base = ( base_len + ( name_len + 1 /* NUL */ ) * sizeof ( wchar_t ) ); + if ( *len < *base ) { + *len = *base; + return EFI_BUFFER_TOO_SMALL; + } + + /* Copy data to buffer */ + *len = *base; + memcpy ( data, base, base_len ); + efi_snprintf ( ( data + base_len ), ( name_len + 1 /* NUL */ ), + "%s", name ); + + return 0; +} + +/** + * Return file information structure + * + * @v image Image, or NULL for the root directory + * @v len Length of data buffer + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS efi_file_info ( struct image *image, UINTN *len, + VOID *data ) { + EFI_FILE_INFO info; + const char *name; + + /* Populate file information */ + memset ( &info, 0, sizeof ( info ) ); + if ( image ) { + info.FileSize = image->len; + info.PhysicalSize = image->len; + info.Attribute = EFI_FILE_READ_ONLY; + name = image->name; + } else { + info.Attribute = ( EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY ); + name = ""; + } + + return efi_file_varlen ( &info.Size, SIZE_OF_EFI_FILE_INFO, name, + len, data ); +} + +/** + * Read directory entry + * + * @v file EFI file + * @v len Length to read + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS efi_file_read_dir ( struct efi_file *file, UINTN *len, + VOID *data ) { + EFI_STATUS efirc; + struct image *image; + unsigned int index; + + /* Construct directory entry at current position */ + index = file->pos; + for_each_image ( image ) { + if ( index-- == 0 ) { + efirc = efi_file_info ( image, len, data ); + if ( efirc == 0 ) + file->pos++; + return efirc; + } + } + + /* No more entries */ + *len = 0; + return 0; +} + +/** + * Read from file + * + * @v this EFI file + * @v len Length to read + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_read ( EFI_FILE_PROTOCOL *this, + UINTN *len, VOID *data ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + size_t remaining; + + /* If this is the root directory, then construct a directory entry */ + if ( ! file->image ) + return efi_file_read_dir ( file, len, data ); + + /* Read from the file */ + remaining = ( file->image->len - file->pos ); + if ( *len > remaining ) + *len = remaining; + DBGC ( file, "EFIFILE %s read [%#08zx,%#08zx)\n", + efi_file_name ( file ), file->pos, + ( ( size_t ) ( file->pos + *len ) ) ); + copy_from_user ( data, file->image->data, file->pos, *len ); + file->pos += *len; + return 0; +} + +/** + * Write to file + * + * @v this EFI file + * @v len Length to write + * @v data Data buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_write ( EFI_FILE_PROTOCOL *this, + UINTN *len, VOID *data __unused ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + + DBGC ( file, "EFIFILE %s cannot write [%#08zx, %#08zx)\n", + efi_file_name ( file ), file->pos, + ( ( size_t ) ( file->pos + *len ) ) ); + return EFI_WRITE_PROTECTED; +} + +/** + * Set file position + * + * @v this EFI file + * @v position New file position + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_set_position ( EFI_FILE_PROTOCOL *this, + UINT64 position ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + + /* If this is the root directory, reset to the start */ + if ( ! file->image ) { + DBGC ( file, "EFIFILE root directory rewound\n" ); + file->pos = 0; + return 0; + } + + /* Check for the magic end-of-file value */ + if ( position == 0xffffffffffffffffULL ) + position = file->image->len; + + /* Fail if we attempt to seek past the end of the file (since + * we do not support writes). + */ + if ( position > file->image->len ) { + DBGC ( file, "EFIFILE %s cannot seek to %#08llx of %#08zx\n", + efi_file_name ( file ), position, file->image->len ); + return EFI_UNSUPPORTED; + } + + /* Set position */ + file->pos = position; + DBGC ( file, "EFIFILE %s position set to %#08zx\n", + efi_file_name ( file ), file->pos ); + + return 0; +} + +/** + * Get file position + * + * @v this EFI file + * @ret position New file position + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_get_position ( EFI_FILE_PROTOCOL *this, + UINT64 *position ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + + *position = file->pos; + return 0; +} + +/** + * Get file information + * + * @v this EFI file + * @v type Type of information + * @v len Buffer size + * @v data Buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_get_info ( EFI_FILE_PROTOCOL *this, + EFI_GUID *type, + UINTN *len, VOID *data ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + EFI_FILE_SYSTEM_INFO fsinfo; + struct image *image; + + /* Determine information to return */ + if ( memcmp ( type, &efi_file_info_id, sizeof ( *type ) ) == 0 ) { + + /* Get file information */ + DBGC ( file, "EFIFILE %s get file information\n", + efi_file_name ( file ) ); + return efi_file_info ( file->image, len, data ); + + } else if ( memcmp ( type, &efi_file_system_info_id, + sizeof ( *type ) ) == 0 ) { + + /* Get file system information */ + DBGC ( file, "EFIFILE %s get file system information\n", + efi_file_name ( file ) ); + memset ( &fsinfo, 0, sizeof ( fsinfo ) ); + fsinfo.ReadOnly = 1; + for_each_image ( image ) + fsinfo.VolumeSize += image->len; + return efi_file_varlen ( &fsinfo.Size, + SIZE_OF_EFI_FILE_SYSTEM_INFO, "iPXE", + len, data ); + } else { + + DBGC ( file, "EFIFILE %s cannot get information of type %s\n", + efi_file_name ( file ), + uuid_ntoa ( ( union uuid * ) type ) ); + return EFI_UNSUPPORTED; + } +} + +/** + * Set file information + * + * @v this EFI file + * @v type Type of information + * @v len Buffer size + * @v data Buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_file_set_info ( EFI_FILE_PROTOCOL *this, EFI_GUID *type, + UINTN len __unused, VOID *data __unused ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + + DBGC ( file, "EFIFILE %s cannot set information of type %s\n", + efi_file_name ( file ), uuid_ntoa ( ( union uuid * ) type ) ); + return EFI_WRITE_PROTECTED; +} + +/** + * Flush file modified data + * + * @v this EFI file + * @v type Type of information + * @v len Buffer size + * @v data Buffer + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI efi_file_flush ( EFI_FILE_PROTOCOL *this ) { + struct efi_file *file = container_of ( this, struct efi_file, file ); + + DBGC ( file, "EFIFILE %s flushed\n", efi_file_name ( file ) ); + return 0; +} + +/** Root directory */ +static struct efi_file efi_file_root = { + .file = { + .Revision = EFI_FILE_PROTOCOL_REVISION, + .Open = efi_file_open, + .Close = efi_file_close, + .Delete = efi_file_delete, + .Read = efi_file_read, + .Write = efi_file_write, + .GetPosition = efi_file_get_position, + .SetPosition = efi_file_set_position, + .GetInfo = efi_file_get_info, + .SetInfo = efi_file_set_info, + .Flush = efi_file_flush, + }, + .image = NULL, +}; + +/** + * Open root directory + * + * @v filesystem EFI simple file system + * @ret file EFI file handle + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_file_open_volume ( EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *filesystem __unused, + EFI_FILE_PROTOCOL **file ) { + + *file = &efi_file_root.file; + return 0; +} + +/** EFI simple file system protocol */ +static EFI_SIMPLE_FILE_SYSTEM_PROTOCOL efi_simple_file_system_protocol = { + .Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, + .OpenVolume = efi_file_open_volume, +}; + +/** Dummy block I/O reset */ +static EFI_STATUS EFIAPI +efi_block_io_reset ( EFI_BLOCK_IO_PROTOCOL *this __unused, + BOOLEAN extended __unused ) { + return 0; +} + +/** Dummy block I/O read */ +static EFI_STATUS EFIAPI +efi_block_io_read_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused, + UINT32 MediaId __unused, EFI_LBA lba __unused, + UINTN len __unused, VOID *data __unused ) { + return EFI_DEVICE_ERROR; +} + +/** Dummy block I/O write */ +static EFI_STATUS EFIAPI +efi_block_io_write_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused, + UINT32 MediaId __unused, EFI_LBA lba __unused, + UINTN len __unused, VOID *data __unused ) { + return EFI_DEVICE_ERROR; +} + +/** Dummy block I/O flush */ +static EFI_STATUS EFIAPI +efi_block_io_flush_blocks ( EFI_BLOCK_IO_PROTOCOL *this __unused ) { + return 0; +} + +/** Dummy block I/O media */ +static EFI_BLOCK_IO_MEDIA efi_block_io_media = { + .MediaId = EFI_MEDIA_ID_MAGIC, + .MediaPresent = 1, + .ReadOnly = 1, + .BlockSize = 1, +}; + +/** Dummy EFI block I/O protocol */ +static EFI_BLOCK_IO_PROTOCOL efi_block_io_protocol = { + .Revision = EFI_BLOCK_IO_PROTOCOL_REVISION, + .Media = &efi_block_io_media, + .Reset = efi_block_io_reset, + .ReadBlocks = efi_block_io_read_blocks, + .WriteBlocks = efi_block_io_write_blocks, + .FlushBlocks = efi_block_io_flush_blocks, +}; + +/** + * Install EFI simple file system protocol + * + * @v handle EFI handle + * @ret rc Return status code + */ +int efi_file_install ( EFI_HANDLE *handle ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_STATUS efirc; + + /* Install the simple file system protocol and the block I/O + * protocol. We don't have a block device, but large parts of + * the EDK2 codebase make the assumption that file systems are + * normally attached to block devices, and so we create a + * dummy block device on the same handle just to keep things + * looking normal. + */ + if ( ( efirc = bs->InstallMultipleProtocolInterfaces ( + handle, + &efi_block_io_protocol_guid, + &efi_block_io_protocol, + &efi_simple_file_system_protocol_guid, + &efi_simple_file_system_protocol, NULL ) ) != 0 ) { + DBGC ( handle, "Could not install simple file system protocol: " + "%s\n", efi_strerror ( efirc ) ); + return EFIRC_TO_RC ( efirc ); + } + + return 0; +} + +/** + * Uninstall EFI simple file system protocol + * + * @v handle EFI handle + */ +void efi_file_uninstall ( EFI_HANDLE handle ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + + /* We must install the file system protocol first, since + * otherwise the EDK2 code will attempt to helpfully uninstall + * it when the block I/O protocol is uninstalled, leading to a + * system lock-up. + */ + bs->UninstallMultipleProtocolInterfaces ( + handle, + &efi_simple_file_system_protocol_guid, + &efi_simple_file_system_protocol, + &efi_block_io_protocol_guid, + &efi_block_io_protocol, NULL ); +} From c7c3d839fc9120aee28de9aabe452dc85ad91502 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 13 Mar 2013 22:42:26 +0000 Subject: [PATCH 231/250] [efi] Add our own EFI_LOAD_FILE_PROTOCOL implementation When iPXE is used as a UEFI driver, the UEFI PXE base code currently provides the TCP/IP stack, network protocols, and user interface. This represents a substantial downgrade from the standard BIOS iPXE user experience. Fix by installing our own EFI_LOAD_FILE_PROTOCOL implementation which initiates the standard iPXE boot procedure. This upgrades the UEFI iPXE user experience to match the standard BIOS iPXE user experience. Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi_snp.h | 3 ++ src/interface/efi/efi_snp.c | 57 +++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/include/ipxe/efi/efi_snp.h b/src/include/ipxe/efi/efi_snp.h index 074d1b27..37916459 100644 --- a/src/include/ipxe/efi/efi_snp.h +++ b/src/include/ipxe/efi/efi_snp.h @@ -16,6 +16,7 @@ #include #include #include +#include /** An SNP device */ struct efi_snp_device { @@ -49,6 +50,8 @@ struct efi_snp_device { EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL nii; /** Component name protocol */ EFI_COMPONENT_NAME2_PROTOCOL name2; + /** Load file protocol handle */ + EFI_LOAD_FILE_PROTOCOL load_file; /** HII configuration access protocol */ EFI_HII_CONFIG_ACCESS_PROTOCOL hii; /** HII package list */ diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 48a6f397..95e39b7d 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -34,6 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /** EFI simple network protocol GUID */ static EFI_GUID efi_simple_network_protocol_guid @@ -57,10 +58,14 @@ static EFI_GUID efi_nii31_protocol_guid = { { 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 } }; -/** EFI component name protocol */ +/** EFI component name protocol GUID */ static EFI_GUID efi_component_name2_protocol_guid = EFI_COMPONENT_NAME2_PROTOCOL_GUID; +/** EFI load file protocol GUID */ +static EFI_GUID efi_load_file_protocol_guid + = EFI_LOAD_FILE_PROTOCOL_GUID; + /** List of SNP devices */ static LIST_HEAD ( efi_snp_devices ); @@ -754,6 +759,49 @@ efi_snp_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2, return 0; } +/****************************************************************************** + * + * Load file protocol + * + ****************************************************************************** + */ + +/** + * Load file + * + * @v loadfile Load file protocol + * @v path File path + * @v booting Loading as part of a boot attempt + * @ret efirc EFI status code + */ +static EFI_STATUS EFIAPI +efi_snp_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file, + EFI_DEVICE_PATH_PROTOCOL *path __unused, + BOOLEAN booting, UINTN *len __unused, + VOID *data __unused ) { + struct efi_snp_device *snpdev = + container_of ( load_file, struct efi_snp_device, load_file ); + struct net_device *netdev = snpdev->netdev; + + /* Fail unless this is a boot attempt */ + if ( ! booting ) { + DBGC ( snpdev, "SNPDEV %p cannot load non-boot file\n", + snpdev ); + return EFI_UNSUPPORTED; + } + + /* Boot from network device */ + ipxe ( netdev ); + + /* Assume boot process was aborted */ + return EFI_ABORTED; +} + +/** Load file protocol */ +static EFI_LOAD_FILE_PROTOCOL efi_snp_load_file_protocol = { + .LoadFile = efi_snp_load_file, +}; + /****************************************************************************** * * iPXE network driver @@ -861,6 +909,10 @@ static int efi_snp_probe ( struct net_device *netdev ) { snpdev->name2.GetControllerName = efi_snp_get_controller_name; snpdev->name2.SupportedLanguages = "en"; + /* Populate the load file protocol structure */ + memcpy ( &snpdev->load_file, &efi_snp_load_file_protocol, + sizeof ( snpdev->load_file ) ); + /* Populate the device name */ efi_snprintf ( snpdev->name, ( sizeof ( snpdev->name ) / sizeof ( snpdev->name[0] ) ), @@ -890,6 +942,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, &efi_component_name2_protocol_guid, &snpdev->name2, + &efi_load_file_protocol_guid, &snpdev->load_file, NULL ) ) != 0 ) { DBGC ( snpdev, "SNPDEV %p could not install protocols: " "%s\n", snpdev, efi_strerror ( efirc ) ); @@ -931,6 +984,7 @@ static int efi_snp_probe ( struct net_device *netdev ) { &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, &efi_component_name2_protocol_guid, &snpdev->name2, + &efi_load_file_protocol_guid, &snpdev->load_file, NULL ); err_install_protocol_interface: bs->CloseEvent ( snpdev->snp.WaitForPacket ); @@ -992,6 +1046,7 @@ static void efi_snp_remove ( struct net_device *netdev ) { &efi_nii_protocol_guid, &snpdev->nii, &efi_nii31_protocol_guid, &snpdev->nii, &efi_component_name2_protocol_guid, &snpdev->name2, + &efi_load_file_protocol_guid, &snpdev->load_file, NULL ); bs->CloseEvent ( snpdev->snp.WaitForPacket ); netdev_put ( snpdev->netdev ); From e63f6c9241394eca5bfbc962704c19dff1448e37 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 14 Mar 2013 00:20:04 +0000 Subject: [PATCH 232/250] [efi] Fix building with newer binutils Newer versions of bfd.h require definitions for the PACKAGE and PACKAGE_VERSION macros used by autotools. Work around this by manually defining these macros before including bfd.h. Originally-fixed-by: Brandon Penglase Tested-by: Brandon Penglase Signed-off-by: Michael Brown --- src/util/elf2efi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c index b28c7ef3..45d53957 100644 --- a/src/util/elf2efi.c +++ b/src/util/elf2efi.c @@ -18,6 +18,8 @@ */ #define _GNU_SOURCE +#define PACKAGE "elf2efi" +#define PACKAGE_VERSION "1" #include #include #include From 747e9eb6f39c4e755b5f3ed0cbc82e1d04b0124a Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 15 Mar 2013 15:22:57 +0000 Subject: [PATCH 233/250] [lkrnprefix] Allow relocation when no initrd is present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 2629b7e ("[pcbios] Inhibit all calls to INT 15,e820 and INT 15,e801 during POST") introduced a regression into .lkrn images when used with no corresponding initrd. Specifically, the semantics of the "maximum address for relocation" value passed to install_prealloc() in %ebp changed so that zero became a special value meaning "inhibit use of INT 15,e820 and INT 15,e801". The %ebp value meaing "no upper limit on relocation" was changed from zero to 0xffffffff, and all prefixes providing fixed values for %ebp were updated to match the new semantics. The .lkrn prefix provides the initrd base address as the maximum address for relocation. When no initrd is present, this address will be zero, and so will unintentionally trigger the "inhibit INT 15,e820 and INT 15,e801" behaviour. Fix by explicitly setting %ebp to 0xffffffff if no initrd is present before calling install_prealloc(). Reported-by: Ján ONDREJ (SAL) Tested-by: Ján ONDREJ (SAL) Signed-off-by: Michael Brown --- src/arch/i386/prefix/lkrnprefix.S | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/arch/i386/prefix/lkrnprefix.S b/src/arch/i386/prefix/lkrnprefix.S index 76890332..690031f0 100644 --- a/src/arch/i386/prefix/lkrnprefix.S +++ b/src/arch/i386/prefix/lkrnprefix.S @@ -231,9 +231,12 @@ run_ipxe: movzwl %sp, %edx no_cmd_line: - /* Retrieve initrd pointer and size */ - movl %ds:ramdisk_image, %ebp - movl %ds:ramdisk_size, %ecx + /* Calculate maximum relocation address */ + movl ramdisk_image, %ebp + testl %ebp, %ebp + jnz 1f + orl $0xffffffff, %ebp /* Allow arbitrary relocation if no initrd */ +1: /* Install iPXE */ call alloc_basemem @@ -251,6 +254,10 @@ no_cmd_line: lret .section ".text16", "awx", @progbits 1: + /* Retrieve initrd pointer and size */ + movl ramdisk_image, %ebp + movl ramdisk_size, %ecx + /* Set up %ds for access to .data16 */ movw %bx, %ds From e05dcf0e017f7dbd6f0859ce250cdbbbef16103e Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 19 Mar 2013 23:16:09 +0000 Subject: [PATCH 234/250] [efi] Fix minor typos in efi_image.c Signed-off-by: Michael Brown --- src/image/efi_image.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/image/efi_image.c b/src/image/efi_image.c index 4b04d36f..0368b82c 100644 --- a/src/image/efi_image.c +++ b/src/image/efi_image.c @@ -48,8 +48,8 @@ static EFI_GUID efi_loaded_image_protocol_guid = * * The caller must eventually free() the device path. */ -static EFI_DEVICE_PATH_PROTOCOL * efi_image_path ( struct image *image, - EFI_DEVICE_PATH *parent ) { +static EFI_DEVICE_PATH_PROTOCOL * +efi_image_path ( struct image *image, EFI_DEVICE_PATH_PROTOCOL *parent ) { EFI_DEVICE_PATH_PROTOCOL *path; FILEPATH_DEVICE_PATH *filepath; EFI_DEVICE_PATH_PROTOCOL *end; @@ -204,7 +204,7 @@ static int efi_image_exec ( struct image *image ) { ( ( wcslen ( cmdline ) + 1 /* NUL */ ) * sizeof ( wchar_t ) ); /* Start the image */ - if ( ( efirc = bs->StartImage ( handle, 0, NULL ) ) != 0 ) { + if ( ( efirc = bs->StartImage ( handle, NULL, NULL ) ) != 0 ) { DBGC ( image, "EFIIMAGE %p returned with status %s\n", image, efi_strerror ( efirc ) ); rc = EFIRC_TO_RC ( efirc ); From 6b9b44319fa1c50d9c91c80cd266b15cbd173ada Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 15 Mar 2013 19:09:45 +0000 Subject: [PATCH 235/250] [efi] Add EFI-specific debugging macros Signed-off-by: Michael Brown --- .../ipxe/efi/Protocol/DevicePathToText.h | 87 +++++++++++++++++ src/include/ipxe/efi/efi.h | 34 +++++++ src/interface/efi/efi_debug.c | 95 +++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 src/include/ipxe/efi/Protocol/DevicePathToText.h create mode 100644 src/interface/efi/efi_debug.c diff --git a/src/include/ipxe/efi/Protocol/DevicePathToText.h b/src/include/ipxe/efi/Protocol/DevicePathToText.h new file mode 100644 index 00000000..edca965b --- /dev/null +++ b/src/include/ipxe/efi/Protocol/DevicePathToText.h @@ -0,0 +1,87 @@ +/** @file + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL as defined in UEFI 2.0. + This protocol provides service to convert device nodes and paths to text. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DEVICE_PATH_TO_TEXT_PROTOCOL_H__ +#define __DEVICE_PATH_TO_TEXT_PROTOCOL_H__ + +FILE_LICENCE ( BSD3 ); + +/// +/// Device Path To Text protocol +/// +#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ + { \ + 0x8b843e20, 0x8132, 0x4852, {0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c } \ + } + +/** + Convert a device node to its text representation. + + @param DeviceNode Points to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @retval a_pointer a pointer to the allocated text representation of the device node data + @retval NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_NODE)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/** + Convert a device path to its text representation. + + @param DevicePath Points to the device path to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts The AllowShortcuts is FALSE, then the shortcut forms of + text representation for a device node cannot be used. + + @retval a_pointer a pointer to the allocated text representation of the device node. + @retval NULL if DevicePath is NULL or there was insufficient memory. + +**/ +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_PATH)( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ); + +/// +/// This protocol converts device paths and device nodes to text. +/// +typedef struct { + EFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText; + EFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText; +} EFI_DEVICE_PATH_TO_TEXT_PROTOCOL; + +extern EFI_GUID gEfiDevicePathToTextProtocolGuid; + +#endif + + diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index 8a216b53..880872aa 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -140,6 +140,40 @@ extern EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; extern EFI_SYSTEM_TABLE *efi_systab; extern const char * efi_strerror ( EFI_STATUS efirc ); + +extern void dbg_efi_protocols ( EFI_HANDLE handle ); +extern void dbg_efi_devpath ( EFI_DEVICE_PATH_PROTOCOL *path ); + +#define DBG_EFI_PROTOCOLS_IF( level, handle ) do { \ + if ( DBG_ ## level ) { \ + dbg_efi_protocols ( handle ); \ + } \ + } while ( 0 ) + +#define DBG_EFI_DEVPATH_IF( level, path ) do { \ + if ( DBG_ ## level ) { \ + dbg_efi_devpath ( path ); \ + } \ + } while ( 0 ) + +#define DBGC_EFI_PROTOCOLS_IF( level, id, ... ) do { \ + DBG_AC_IF ( level, id ); \ + DBG_EFI_PROTOCOLS_IF ( level, __VA_ARGS__ ); \ + DBG_DC_IF ( level ); \ + } while ( 0 ) + +#define DBGC_EFI_DEVPATH_IF( level, id, ... ) do { \ + DBG_AC_IF ( level, id ); \ + DBG_EFI_DEVPATH_IF ( level, __VA_ARGS__ ); \ + DBG_DC_IF ( level ); \ + } while ( 0 ) + +#define DBGC_EFI_PROTOCOLS( ... ) \ + DBGC_EFI_PROTOCOLS_IF( LOG, ##__VA_ARGS__ ) + +#define DBGC_EFI_DEVPATH( ... ) \ + DBGC_EFI_DEVPATH_IF( LOG, ##__VA_ARGS__ ) + extern EFI_STATUS efi_init ( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab ); diff --git a/src/interface/efi/efi_debug.c b/src/interface/efi/efi_debug.c new file mode 100644 index 00000000..7f3c115d --- /dev/null +++ b/src/interface/efi/efi_debug.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2013 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @file + * + * EFI debugging utilities + * + */ + +#include +#include +#include +#include +#include + +/** Device path to text protocol */ +static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *efidpt; +EFI_REQUIRE_PROTOCOL ( EFI_DEVICE_PATH_TO_TEXT_PROTOCOL, &efidpt ); + +/** + * Print list of protocol handlers attached to a handle + * + * @v handle EFI handle + */ +void dbg_efi_protocols ( EFI_HANDLE handle ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_GUID **protocols; + UINTN count; + unsigned int i; + EFI_STATUS efirc; + + /* Retrieve list of protocols */ + if ( ( efirc = bs->ProtocolsPerHandle ( handle, &protocols, + &count ) ) != 0 ) { + printf ( "EFI could not retrieve protocols for %p: %s\n", + handle, efi_strerror ( efirc ) ); + return; + } + + /* Dump list of protocols */ + for ( i = 0 ; i < count ; i++ ) { + printf ( "%s\n", uuid_ntoa ( ( union uuid * ) protocols[i] ) ); + } + + /* Free list */ + bs->FreePool ( protocols ); +} + +/** + * Print device path + * + * @v path Device path + */ +void dbg_efi_devpath ( EFI_DEVICE_PATH_PROTOCOL *path ) { + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; + EFI_DEVICE_PATH_PROTOCOL *end; + CHAR16 *text; + size_t len; + + /* Convert path to a textual representation */ + text = efidpt->ConvertDevicePathToText ( path, TRUE, FALSE ); + if ( ! text ) { + printf ( ":\n" ); + end = efi_devpath_end ( path ); + len = ( ( ( void * ) end ) - ( ( void * ) path ) + + sizeof ( *end ) ); + dbg_hex_dump_da ( 0, path, len ); + return; + } + + /* Print path */ + printf ( "%ls", text ); + + /* Free path */ + bs->FreePool ( text ); +} From 2ec0c1ea48fa0244599c6b87da7838730dde585b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 18 Mar 2013 15:05:43 +0000 Subject: [PATCH 236/250] [int13] Split out ISO9660 and El Torito definitions to separate header files Signed-off-by: Michael Brown --- src/arch/i386/include/int13.h | 116 ------------------------- src/arch/i386/interface/pcbios/int13.c | 2 + src/include/ipxe/eltorito.h | 103 ++++++++++++++++++++++ src/include/ipxe/iso9660.h | 44 ++++++++++ 4 files changed, 149 insertions(+), 116 deletions(-) create mode 100644 src/include/ipxe/eltorito.h create mode 100644 src/include/ipxe/iso9660.h diff --git a/src/arch/i386/include/int13.h b/src/arch/i386/include/int13.h index 5d36b637..e337ca1d 100644 --- a/src/arch/i386/include/int13.h +++ b/src/arch/i386/include/int13.h @@ -291,122 +291,6 @@ struct master_boot_record { /** MBR magic signature */ #define INT13_MBR_MAGIC 0xaa55 -/** ISO9660 block size */ -#define ISO9660_BLKSIZE 2048 - -/** An ISO9660 Primary Volume Descriptor (fixed portion) */ -struct iso9660_primary_descriptor_fixed { - /** Descriptor type */ - uint8_t type; - /** Identifier ("CD001") */ - uint8_t id[5]; -} __attribute__ (( packed )); - -/** An ISO9660 Primary Volume Descriptor */ -struct iso9660_primary_descriptor { - /** Fixed portion */ - struct iso9660_primary_descriptor_fixed fixed; -} __attribute__ (( packed )); - -/** ISO9660 Primary Volume Descriptor type */ -#define ISO9660_TYPE_PRIMARY 0x01 - -/** ISO9660 identifier */ -#define ISO9660_ID "CD001" - -/** ISO9660 Primary Volume Descriptor block address */ -#define ISO9660_PRIMARY_LBA 16 - -/** An El Torito Boot Record Volume Descriptor (fixed portion) */ -struct eltorito_descriptor_fixed { - /** Descriptor type */ - uint8_t type; - /** Identifier ("CD001") */ - uint8_t id[5]; - /** Version, must be 1 */ - uint8_t version; - /** Boot system indicator; must be "EL TORITO SPECIFICATION" */ - uint8_t system_id[32]; -} __attribute__ (( packed )); - -/** An El Torito Boot Record Volume Descriptor */ -struct eltorito_descriptor { - /** Fixed portion */ - struct eltorito_descriptor_fixed fixed; - /** Unused */ - uint8_t unused[32]; - /** Boot catalog sector */ - uint32_t sector; -} __attribute__ (( packed )); - -/** ISO9660 Boot Volume Descriptor type */ -#define ISO9660_TYPE_BOOT 0x00 - -/** El Torito Boot Record Volume Descriptor block address */ -#define ELTORITO_LBA 17 - -/** An El Torito Boot Catalog Validation Entry */ -struct eltorito_validation_entry { - /** Header ID; must be 1 */ - uint8_t header_id; - /** Platform ID - * - * 0 = 80x86 - * 1 = PowerPC - * 2 = Mac - */ - uint8_t platform_id; - /** Reserved */ - uint16_t reserved; - /** ID string */ - uint8_t id_string[24]; - /** Checksum word */ - uint16_t checksum; - /** Signature; must be 0xaa55 */ - uint16_t signature; -} __attribute__ (( packed )); - -/** El Torito platform IDs */ -enum eltorito_platform_id { - ELTORITO_PLATFORM_X86 = 0x00, - ELTORITO_PLATFORM_POWERPC = 0x01, - ELTORITO_PLATFORM_MAC = 0x02, -}; - -/** A bootable entry in the El Torito Boot Catalog */ -struct eltorito_boot_entry { - /** Boot indicator - * - * Must be @c ELTORITO_BOOTABLE for a bootable ISO image - */ - uint8_t indicator; - /** Media type - * - */ - uint8_t media_type; - /** Load segment */ - uint16_t load_segment; - /** System type */ - uint8_t filesystem; - /** Unused */ - uint8_t reserved_a; - /** Sector count */ - uint16_t length; - /** Starting sector */ - uint32_t start; - /** Unused */ - uint8_t reserved_b[20]; -} __attribute__ (( packed )); - -/** Boot indicator for a bootable ISO image */ -#define ELTORITO_BOOTABLE 0x88 - -/** El Torito media types */ -enum eltorito_media_type { - /** No emulation */ - ELTORITO_NO_EMULATION = 0, -}; - /** A floppy disk geometry */ struct int13_fdd_geometry { /** Number of tracks */ diff --git a/src/arch/i386/interface/pcbios/int13.c b/src/arch/i386/interface/pcbios/int13.c index 263f861e..1c7a8128 100644 --- a/src/arch/i386/interface/pcbios/int13.c +++ b/src/arch/i386/interface/pcbios/int13.c @@ -38,6 +38,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include +#include #include #include #include diff --git a/src/include/ipxe/eltorito.h b/src/include/ipxe/eltorito.h new file mode 100644 index 00000000..3302b38b --- /dev/null +++ b/src/include/ipxe/eltorito.h @@ -0,0 +1,103 @@ +#ifndef _IPXE_ELTORITO_H +#define _IPXE_ELTORITO_H + +/** + * @file + * + * El Torito bootable CD-ROM specification + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +/** An El Torito Boot Record Volume Descriptor (fixed portion) */ +struct eltorito_descriptor_fixed { + /** Descriptor type */ + uint8_t type; + /** Identifier ("CD001") */ + uint8_t id[5]; + /** Version, must be 1 */ + uint8_t version; + /** Boot system indicator; must be "EL TORITO SPECIFICATION" */ + uint8_t system_id[32]; +} __attribute__ (( packed )); + +/** An El Torito Boot Record Volume Descriptor */ +struct eltorito_descriptor { + /** Fixed portion */ + struct eltorito_descriptor_fixed fixed; + /** Unused */ + uint8_t unused[32]; + /** Boot catalog sector */ + uint32_t sector; +} __attribute__ (( packed )); + +/** El Torito Boot Record Volume Descriptor block address */ +#define ELTORITO_LBA 17 + +/** An El Torito Boot Catalog Validation Entry */ +struct eltorito_validation_entry { + /** Header ID; must be 1 */ + uint8_t header_id; + /** Platform ID + * + * 0 = 80x86 + * 1 = PowerPC + * 2 = Mac + */ + uint8_t platform_id; + /** Reserved */ + uint16_t reserved; + /** ID string */ + uint8_t id_string[24]; + /** Checksum word */ + uint16_t checksum; + /** Signature; must be 0xaa55 */ + uint16_t signature; +} __attribute__ (( packed )); + +/** El Torito platform IDs */ +enum eltorito_platform_id { + ELTORITO_PLATFORM_X86 = 0x00, + ELTORITO_PLATFORM_POWERPC = 0x01, + ELTORITO_PLATFORM_MAC = 0x02, +}; + +/** A bootable entry in the El Torito Boot Catalog */ +struct eltorito_boot_entry { + /** Boot indicator + * + * Must be @c ELTORITO_BOOTABLE for a bootable ISO image + */ + uint8_t indicator; + /** Media type + * + */ + uint8_t media_type; + /** Load segment */ + uint16_t load_segment; + /** System type */ + uint8_t filesystem; + /** Unused */ + uint8_t reserved_a; + /** Sector count */ + uint16_t length; + /** Starting sector */ + uint32_t start; + /** Unused */ + uint8_t reserved_b[20]; +} __attribute__ (( packed )); + +/** Boot indicator for a bootable ISO image */ +#define ELTORITO_BOOTABLE 0x88 + +/** El Torito media types */ +enum eltorito_media_type { + /** No emulation */ + ELTORITO_NO_EMULATION = 0, +}; + +#endif /* _IPXE_ELTORITO_H */ diff --git a/src/include/ipxe/iso9660.h b/src/include/ipxe/iso9660.h new file mode 100644 index 00000000..02c2ae37 --- /dev/null +++ b/src/include/ipxe/iso9660.h @@ -0,0 +1,44 @@ +#ifndef _IPXE_ISO9660_H +#define _IPXE_ISO9660_H + +/** + * @file + * + * ISO9660 CD-ROM specification + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +/** ISO9660 block size */ +#define ISO9660_BLKSIZE 2048 + +/** An ISO9660 Primary Volume Descriptor (fixed portion) */ +struct iso9660_primary_descriptor_fixed { + /** Descriptor type */ + uint8_t type; + /** Identifier ("CD001") */ + uint8_t id[5]; +} __attribute__ (( packed )); + +/** An ISO9660 Primary Volume Descriptor */ +struct iso9660_primary_descriptor { + /** Fixed portion */ + struct iso9660_primary_descriptor_fixed fixed; +} __attribute__ (( packed )); + +/** ISO9660 Primary Volume Descriptor type */ +#define ISO9660_TYPE_PRIMARY 0x01 + +/** ISO9660 Primary Volume Descriptor block address */ +#define ISO9660_PRIMARY_LBA 16 + +/** ISO9660 Boot Volume Descriptor type */ +#define ISO9660_TYPE_BOOT 0x00 + +/** ISO9660 identifier */ +#define ISO9660_ID "CD001" + +#endif /* _IPXE_ISO9660_H */ From 4f742bcd95373425fde52b0d3b354bb020446542 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Mar 2013 00:12:30 +0000 Subject: [PATCH 237/250] [smbios] Provide SMBIOS version number via smbios_version() Signed-off-by: Michael Brown --- src/arch/i386/interface/pcbios/bios_smbios.c | 2 ++ src/include/ipxe/smbios.h | 12 ++++++++++++ src/interface/efi/efi_smbios.c | 2 ++ src/interface/smbios/smbios.c | 17 +++++++++++++++++ 4 files changed, 33 insertions(+) diff --git a/src/arch/i386/interface/pcbios/bios_smbios.c b/src/arch/i386/interface/pcbios/bios_smbios.c index 2ecc24ea..76a32e93 100644 --- a/src/arch/i386/interface/pcbios/bios_smbios.c +++ b/src/arch/i386/interface/pcbios/bios_smbios.c @@ -77,6 +77,8 @@ static int bios_find_smbios ( struct smbios *smbios ) { smbios->address = phys_to_user ( u.entry.smbios_address ); smbios->len = u.entry.smbios_len; smbios->count = u.entry.smbios_count; + smbios->version = + SMBIOS_VERSION ( u.entry.major, u.entry.minor ); return 0; } diff --git a/src/include/ipxe/smbios.h b/src/include/ipxe/smbios.h index fcf149ea..0765c4e4 100644 --- a/src/include/ipxe/smbios.h +++ b/src/include/ipxe/smbios.h @@ -148,8 +148,19 @@ struct smbios { size_t len; /** Number of SMBIOS structures */ unsigned int count; + /** SMBIOS version */ + uint16_t version; }; +/** + * Calculate SMBIOS version + * + * @v major Major version + * @v minor Minor version + * @ret version SMBIOS version + */ +#define SMBIOS_VERSION( major, minor ) ( ( (major) << 8 ) | (minor) ) + extern int find_smbios ( struct smbios *smbios ); extern int find_smbios_structure ( unsigned int type, struct smbios_structure *structure ); @@ -158,5 +169,6 @@ extern int read_smbios_structure ( struct smbios_structure *structure, extern int read_smbios_string ( struct smbios_structure *structure, unsigned int index, void *data, size_t len ); +extern int smbios_version ( void ); #endif /* _IPXE_SMBIOS_H */ diff --git a/src/interface/efi/efi_smbios.c b/src/interface/efi/efi_smbios.c index 506b04e7..304f95a5 100644 --- a/src/interface/efi/efi_smbios.c +++ b/src/interface/efi/efi_smbios.c @@ -55,6 +55,8 @@ static int efi_find_smbios ( struct smbios *smbios ) { smbios->address = phys_to_user ( smbios_entry->smbios_address ); smbios->len = smbios_entry->smbios_len; smbios->count = smbios_entry->smbios_count; + smbios->version = + SMBIOS_VERSION ( smbios_entry->major, smbios_entry->minor ); DBG ( "Found SMBIOS v%d.%d entry point at %p (%x+%zx)\n", smbios_entry->major, smbios_entry->minor, smbios_entry, smbios_entry->smbios_address, smbios->len ); diff --git a/src/interface/smbios/smbios.c b/src/interface/smbios/smbios.c index 8ed24dd6..2adaa53d 100644 --- a/src/interface/smbios/smbios.c +++ b/src/interface/smbios/smbios.c @@ -179,3 +179,20 @@ int read_smbios_string ( struct smbios_structure *structure, DBG ( "SMBIOS string index %d not found\n", index ); return -ENOENT; } + +/** + * Get SMBIOS version + * + * @ret version Version, or negative error + */ +int smbios_version ( void ) { + int rc; + + /* Find SMBIOS */ + if ( ( smbios.address == UNULL ) && + ( ( rc = find_smbios ( &smbios ) ) != 0 ) ) + return rc; + assert ( smbios.address != UNULL ); + + return smbios.version; +} From 9e896d0eeaa07d47b2bed4c92072fd638ce3eb55 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Mar 2013 00:14:38 +0000 Subject: [PATCH 238/250] [smbios] Mangle UUIDs for SMBIOS version 2.6 and newer iPXE treats UUIDs as being in network byte order (big-endian). The SMBIOS specification version 2.6 states that UUIDs are stored with little-endian values in the first three fields; earlier versions did not specify an endianness. This results in some inconsistency between the BIOS, vendor PXE, iPXE, and operating system interpretations of the SMBIOS UUID. dmidecode assumes that the byte order is little-endian if and only if the SMBIOS version is 2.6 or higher. Choose to match this behaviour. Reported-by: Matthew Helton Reported-by: Alexandru Bordei Signed-off-by: Michael Brown --- src/interface/smbios/smbios_settings.c | 42 ++++++++++++++++++++------ 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 893b958e..4ca14476 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include #include @@ -112,14 +113,16 @@ static int smbios_fetch ( struct settings *settings __unused, { uint8_t buf[structure.header.len]; + const void *raw; + union uuid uuid; /* Read SMBIOS structure */ if ( ( rc = read_smbios_structure ( &structure, buf, sizeof ( buf ) ) ) != 0 ) return rc; + /* A tag length of zero indicates a string */ if ( tag_len == 0 ) { - /* String */ if ( ( rc = read_smbios_string ( &structure, buf[tag_offset], data, len ) ) < 0 ) { @@ -128,15 +131,36 @@ static int smbios_fetch ( struct settings *settings __unused, if ( ! setting->type ) setting->type = &setting_type_string; return rc; - } else { - /* Raw data */ - if ( len > tag_len ) - len = tag_len; - memcpy ( data, &buf[tag_offset], len ); - if ( ! setting->type ) - setting->type = &setting_type_hex; - return tag_len; } + + /* Mangle UUIDs if necessary. iPXE treats UUIDs as + * being in network byte order (big-endian). SMBIOS + * specification version 2.6 states that UUIDs are + * stored with little-endian values in the first three + * fields; earlier versions did not specify an + * endianness. dmidecode assumes that the byte order + * is little-endian if and only if the SMBIOS version + * is 2.6 or higher; we match this behaviour. + */ + raw = &buf[tag_offset]; + if ( ( setting->type == &setting_type_uuid ) && + ( tag_len == sizeof ( uuid ) ) && + ( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) { + DBG ( "SMBIOS detected mangled UUID\n" ); + memcpy ( &uuid, &buf[tag_offset], sizeof ( uuid ) ); + __bswap_32s ( &uuid.canonical.a ); + __bswap_16s ( &uuid.canonical.b ); + __bswap_16s ( &uuid.canonical.c ); + raw = &uuid; + } + + /* Return data */ + if ( len > tag_len ) + len = tag_len; + memcpy ( data, raw, len ); + if ( ! setting->type ) + setting->type = &setting_type_hex; + return tag_len; } } From a9b63ecda55ea24df7d51d59cc7fd7b3234bc135 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Mar 2013 00:54:42 +0000 Subject: [PATCH 239/250] [dhcp] Use PXE byte ordering for UUID in DHCP option 97 The PXE spec does not specify a byte ordering for UUIDs, but RFC4578 suggests that it follows the EFI spec, in which the first three fields are little-endian. Signed-off-by: Michael Brown --- src/net/udp/dhcp.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index e63c3e42..3f2c451e 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -1041,10 +1041,17 @@ int dhcp_create_request ( struct dhcp_packet *dhcppkt, return rc; } - /* Add client UUID, if we have one. Required for PXE. */ + /* Add client UUID, if we have one. Required for PXE. The + * PXE spec does not specify a byte ordering for UUIDs, but + * RFC4578 suggests that it follows the EFI spec, in which the + * first three fields are little-endian. + */ client_uuid.type = DHCP_CLIENT_UUID_TYPE; if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting, &client_uuid.uuid ) ) >= 0 ) { + __bswap_32s ( &client_uuid.uuid.canonical.a ); + __bswap_16s ( &client_uuid.uuid.canonical.b ); + __bswap_16s ( &client_uuid.uuid.canonical.c ); if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID, &client_uuid, sizeof ( client_uuid ) ) ) != 0 ) { From d938e50136b0bd7dbc56b250cd4363646e59c9fc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Mar 2013 15:06:40 +0000 Subject: [PATCH 240/250] [uuid] Abstract UUID mangling code out to a separate uuid_mangle() function Signed-off-by: Michael Brown --- src/include/ipxe/uuid.h | 19 +++++++++++++++++++ src/interface/smbios/smbios_settings.c | 5 +---- src/net/udp/dhcp.c | 4 +--- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/include/ipxe/uuid.h b/src/include/ipxe/uuid.h index 5de56b94..ad515d0c 100644 --- a/src/include/ipxe/uuid.h +++ b/src/include/ipxe/uuid.h @@ -9,6 +9,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include +#include /** A universally unique ID */ union uuid { @@ -28,6 +29,24 @@ union uuid { uint8_t raw[16]; }; +/** + * Change UUID endianness + * + * @v uuid UUID + * + * RFC4122 defines UUIDs as being encoded in network byte order, but + * leaves some wriggle room for "explicit application or presentation + * protocol specification to the contrary". PXE, EFI and SMBIOS + * (versions 2.6 and above) treat the first three fields as being + * little-endian. + */ +static inline void uuid_mangle ( union uuid *uuid ) { + + __bswap_32s ( &uuid->canonical.a ); + __bswap_16s ( &uuid->canonical.b ); + __bswap_16s ( &uuid->canonical.c ); +} + extern char * uuid_ntoa ( const union uuid *uuid ); #endif /* _IPXE_UUID_H */ diff --git a/src/interface/smbios/smbios_settings.c b/src/interface/smbios/smbios_settings.c index 4ca14476..663da968 100644 --- a/src/interface/smbios/smbios_settings.c +++ b/src/interface/smbios/smbios_settings.c @@ -22,7 +22,6 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include -#include #include #include #include @@ -148,9 +147,7 @@ static int smbios_fetch ( struct settings *settings __unused, ( smbios_version() >= SMBIOS_VERSION ( 2, 6 ) ) ) { DBG ( "SMBIOS detected mangled UUID\n" ); memcpy ( &uuid, &buf[tag_offset], sizeof ( uuid ) ); - __bswap_32s ( &uuid.canonical.a ); - __bswap_16s ( &uuid.canonical.b ); - __bswap_16s ( &uuid.canonical.c ); + uuid_mangle ( &uuid ); raw = &uuid; } diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 3f2c451e..762ae732 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -1049,9 +1049,7 @@ int dhcp_create_request ( struct dhcp_packet *dhcppkt, client_uuid.type = DHCP_CLIENT_UUID_TYPE; if ( ( len = fetch_uuid_setting ( NULL, &uuid_setting, &client_uuid.uuid ) ) >= 0 ) { - __bswap_32s ( &client_uuid.uuid.canonical.a ); - __bswap_16s ( &client_uuid.uuid.canonical.b ); - __bswap_16s ( &client_uuid.uuid.canonical.c ); + uuid_mangle ( &client_uuid.uuid ); if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID, &client_uuid, sizeof ( client_uuid ) ) ) != 0 ) { From 1920aa43764981597da57616cdb75c040d730712 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Mar 2013 15:25:16 +0000 Subject: [PATCH 241/250] [efi] Provide efi_guid_ntoa() for printing EFI GUIDs Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi.h | 19 +++++-------------- src/interface/efi/efi_debug.c | 25 ++++++++++++++++++++++--- src/interface/efi/efi_file.c | 5 ++--- src/interface/efi/efi_init.c | 13 +++++++------ 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index 880872aa..46b66690 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -54,12 +54,7 @@ /** An EFI protocol used by iPXE */ struct efi_protocol { /** GUID */ - union { - /** EFI protocol GUID */ - EFI_GUID guid; - /** UUID structure understood by iPXE */ - union uuid uuid; - } u; + EFI_GUID guid; /** Variable containing pointer to protocol structure */ void **protocol; }; @@ -77,7 +72,7 @@ struct efi_protocol { */ #define EFI_REQUIRE_PROTOCOL( _protocol, _ptr ) \ struct efi_protocol __ ## _protocol __efi_protocol = { \ - .u.guid = _protocol ## _GUID, \ + .guid = _protocol ## _GUID, \ .protocol = ( ( void ** ) ( void * ) \ ( ( (_ptr) == ( ( _protocol ** ) (_ptr) ) ) ? \ (_ptr) : (_ptr) ) ), \ @@ -86,12 +81,7 @@ struct efi_protocol { /** An EFI configuration table used by iPXE */ struct efi_config_table { /** GUID */ - union { - /** EFI configuration table GUID */ - EFI_GUID guid; - /** UUID structure understood by iPXE */ - union uuid uuid; - } u; + EFI_GUID guid; /** Variable containing pointer to configuration table */ void **table; /** Table is required for operation */ @@ -113,7 +103,7 @@ struct efi_config_table { */ #define EFI_USE_TABLE( _table, _ptr, _required ) \ struct efi_config_table __ ## _table __efi_config_table = { \ - .u.guid = _table ## _GUID, \ + .guid = _table ## _GUID, \ .table = ( ( void ** ) ( void * ) (_ptr) ), \ .required = (_required), \ } @@ -140,6 +130,7 @@ extern EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; extern EFI_SYSTEM_TABLE *efi_systab; extern const char * efi_strerror ( EFI_STATUS efirc ); +extern const char * efi_guid_ntoa ( EFI_GUID *guid ); extern void dbg_efi_protocols ( EFI_HANDLE handle ); extern void dbg_efi_devpath ( EFI_DEVICE_PATH_PROTOCOL *path ); diff --git a/src/interface/efi/efi_debug.c b/src/interface/efi/efi_debug.c index 7f3c115d..a7ba7e2e 100644 --- a/src/interface/efi/efi_debug.c +++ b/src/interface/efi/efi_debug.c @@ -27,6 +27,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ #include +#include +#include #include #include #include @@ -36,6 +38,24 @@ FILE_LICENCE ( GPL2_OR_LATER ); static EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *efidpt; EFI_REQUIRE_PROTOCOL ( EFI_DEVICE_PATH_TO_TEXT_PROTOCOL, &efidpt ); +/** + * Convert GUID to a printable string + * + * @v guid GUID + * @ret string Printable string + */ +const char * efi_guid_ntoa ( EFI_GUID *guid ) { + union { + union uuid uuid; + EFI_GUID guid; + } u; + + /* Convert GUID to standard endianness */ + memcpy ( &u.guid, guid, sizeof ( u.guid ) ); + uuid_mangle ( &u.uuid ); + return uuid_ntoa ( &u.uuid ); +} + /** * Print list of protocol handlers attached to a handle * @@ -57,9 +77,8 @@ void dbg_efi_protocols ( EFI_HANDLE handle ) { } /* Dump list of protocols */ - for ( i = 0 ; i < count ; i++ ) { - printf ( "%s\n", uuid_ntoa ( ( union uuid * ) protocols[i] ) ); - } + for ( i = 0 ; i < count ; i++ ) + printf ( "%s\n", efi_guid_ntoa ( protocols[i] ) ); /* Free list */ bs->FreePool ( protocols ); diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c index ffe25fd6..6f9d44f8 100644 --- a/src/interface/efi/efi_file.c +++ b/src/interface/efi/efi_file.c @@ -414,8 +414,7 @@ static EFI_STATUS EFIAPI efi_file_get_info ( EFI_FILE_PROTOCOL *this, } else { DBGC ( file, "EFIFILE %s cannot get information of type %s\n", - efi_file_name ( file ), - uuid_ntoa ( ( union uuid * ) type ) ); + efi_file_name ( file ), efi_guid_ntoa ( type ) ); return EFI_UNSUPPORTED; } } @@ -435,7 +434,7 @@ efi_file_set_info ( EFI_FILE_PROTOCOL *this, EFI_GUID *type, struct efi_file *file = container_of ( this, struct efi_file, file ); DBGC ( file, "EFIFILE %s cannot set information of type %s\n", - efi_file_name ( file ), uuid_ntoa ( ( union uuid * ) type ) ); + efi_file_name ( file ), efi_guid_ntoa ( type ) ); return EFI_WRITE_PROTECTED; } diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index aaf89471..48cac538 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -121,13 +121,14 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, /* Look up used protocols */ for_each_table_entry ( prot, EFI_PROTOCOLS ) { - if ( ( efirc = bs->LocateProtocol ( &prot->u.guid, NULL, + if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL, prot->protocol ) ) == 0 ) { DBGC ( systab, "EFI protocol %s is at %p\n", - uuid_ntoa ( &prot->u.uuid ), *(prot->protocol)); + efi_guid_ntoa ( &prot->guid ), + *(prot->protocol) ); } else { DBGC ( systab, "EFI does not provide protocol %s\n", - uuid_ntoa ( &prot->u.uuid ) ); + efi_guid_ntoa ( &prot->guid ) ); /* All protocols are required */ return efirc; } @@ -135,12 +136,12 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, /* Look up used configuration tables */ for_each_table_entry ( tab, EFI_CONFIG_TABLES ) { - if ( ( *(tab->table) = efi_find_table ( &tab->u.guid ) ) ) { + if ( ( *(tab->table) = efi_find_table ( &tab->guid ) ) ) { DBGC ( systab, "EFI configuration table %s is at %p\n", - uuid_ntoa ( &tab->u.uuid ), *(tab->table) ); + efi_guid_ntoa ( &tab->guid ), *(tab->table) ); } else { DBGC ( systab, "EFI does not provide configuration " - "table %s\n", uuid_ntoa ( &tab->u.uuid ) ); + "table %s\n", efi_guid_ntoa ( &tab->guid ) ); if ( tab->required ) return EFI_NOT_AVAILABLE_YET; } From 11ad0bafbf137a874f88ac810520acb90fa9a990 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Wed, 20 Mar 2013 16:34:17 +0800 Subject: [PATCH 242/250] [build] Avoid strict-aliasing warning for gcc 4.3 Signed-off-by: Bo Yang Signed-off-by: Michael Brown --- src/arch/i386/include/bits/byteswap.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/i386/include/bits/byteswap.h b/src/arch/i386/include/bits/byteswap.h index f3d30a25..0d9cb967 100644 --- a/src/arch/i386/include/bits/byteswap.h +++ b/src/arch/i386/include/bits/byteswap.h @@ -53,8 +53,8 @@ __bswap_variable_64 ( uint64_t x ) { static inline __attribute__ (( always_inline )) void __bswap_64s ( uint64_t *x ) { struct { - uint32_t low; - uint32_t high; + uint32_t __attribute__ (( may_alias )) low; + uint32_t __attribute__ (( may_alias )) high; } __attribute__ (( may_alias )) *dwords = ( ( void * ) x ); uint32_t discard; From 71cd50883896dc043f1025a3b96f3c0c7f3b2184 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 22 Mar 2013 13:42:16 +0000 Subject: [PATCH 243/250] [efi] Add "reboot" command for EFI Abstract out the ability to reboot the system to a separate reboot() function (with platform-specific implementations), add an EFI implementation, and make the existing "reboot" command available under EFI. Signed-off-by: Michael Brown --- src/arch/i386/include/bits/reboot.h | 14 +++++ src/arch/i386/include/ipxe/bios_reboot.h | 18 ++++++ src/arch/i386/interface/pcbios/bios_reboot.c | 41 +++++++++++++ src/arch/x86_64/include/bits/reboot.h | 12 ++++ src/config/defaults/efi.h | 3 + src/config/defaults/linux.h | 1 + src/config/defaults/pcbios.h | 1 + src/config/reboot.h | 16 ++++++ src/core/null_reboot.c | 42 ++++++++++++++ src/{arch/i386 => }/hci/commands/reboot_cmd.c | 4 +- src/include/ipxe/efi/efi_reboot.h | 18 ++++++ src/include/ipxe/null_reboot.h | 18 ++++++ src/include/ipxe/reboot.h | 57 +++++++++++++++++++ src/interface/efi/efi_reboot.c | 43 ++++++++++++++ 14 files changed, 286 insertions(+), 2 deletions(-) create mode 100644 src/arch/i386/include/bits/reboot.h create mode 100644 src/arch/i386/include/ipxe/bios_reboot.h create mode 100644 src/arch/i386/interface/pcbios/bios_reboot.c create mode 100644 src/arch/x86_64/include/bits/reboot.h create mode 100644 src/config/reboot.h create mode 100644 src/core/null_reboot.c rename src/{arch/i386 => }/hci/commands/reboot_cmd.c (94%) create mode 100644 src/include/ipxe/efi/efi_reboot.h create mode 100644 src/include/ipxe/null_reboot.h create mode 100644 src/include/ipxe/reboot.h create mode 100644 src/interface/efi/efi_reboot.c diff --git a/src/arch/i386/include/bits/reboot.h b/src/arch/i386/include/bits/reboot.h new file mode 100644 index 00000000..5b09e95f --- /dev/null +++ b/src/arch/i386/include/bits/reboot.h @@ -0,0 +1,14 @@ +#ifndef _BITS_REBOOT_H +#define _BITS_REBOOT_H + +/** @file + * + * i386-specific reboot API implementations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +#endif /* _BITS_REBOOT_H */ diff --git a/src/arch/i386/include/ipxe/bios_reboot.h b/src/arch/i386/include/ipxe/bios_reboot.h new file mode 100644 index 00000000..a0845328 --- /dev/null +++ b/src/arch/i386/include/ipxe/bios_reboot.h @@ -0,0 +1,18 @@ +#ifndef _IPXE_BIOS_REBOOT_H +#define _IPXE_BIOS_REBOOT_H + +/** @file + * + * Standard PC-BIOS reboot mechanism + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#ifdef REBOOT_PCBIOS +#define REBOOT_PREFIX_pcbios +#else +#define REBOOT_PREFIX_pcbios __pcbios_ +#endif + +#endif /* _IPXE_BIOS_REBOOT_H */ diff --git a/src/arch/i386/interface/pcbios/bios_reboot.c b/src/arch/i386/interface/pcbios/bios_reboot.c new file mode 100644 index 00000000..86f4e3eb --- /dev/null +++ b/src/arch/i386/interface/pcbios/bios_reboot.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Standard PC-BIOS reboot mechanism + * + */ + +#include +#include + +/** + * Reboot system + * + */ +static void bios_reboot ( void ) { + + /* Jump to system reset vector */ + __asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : ); +} + +PROVIDE_REBOOT ( pcbios, reboot, bios_reboot ); diff --git a/src/arch/x86_64/include/bits/reboot.h b/src/arch/x86_64/include/bits/reboot.h new file mode 100644 index 00000000..f1bce054 --- /dev/null +++ b/src/arch/x86_64/include/bits/reboot.h @@ -0,0 +1,12 @@ +#ifndef _BITS_REBOOT_H +#define _BITS_REBOOT_H + +/** @file + * + * x86_64-specific reboot API implementations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#endif /* _BITS_REBOOT_H */ diff --git a/src/config/defaults/efi.h b/src/config/defaults/efi.h index 923360ae..c453e89a 100644 --- a/src/config/defaults/efi.h +++ b/src/config/defaults/efi.h @@ -19,8 +19,11 @@ #define BOFM_EFI #define ENTROPY_NULL #define TIME_NULL +#define REBOOT_EFI #define IMAGE_EFI /* EFI image support */ #define IMAGE_SCRIPT /* iPXE script image support */ +#define REBOOT_CMD /* Reboot command */ + #endif /* CONFIG_DEFAULTS_EFI_H */ diff --git a/src/config/defaults/linux.h b/src/config/defaults/linux.h index 50897560..666db6b8 100644 --- a/src/config/defaults/linux.h +++ b/src/config/defaults/linux.h @@ -16,6 +16,7 @@ #define SANBOOT_NULL #define ENTROPY_LINUX #define TIME_LINUX +#define REBOOT_NULL #define DRIVERS_LINUX diff --git a/src/config/defaults/pcbios.h b/src/config/defaults/pcbios.h index c52fca97..7debc8d2 100644 --- a/src/config/defaults/pcbios.h +++ b/src/config/defaults/pcbios.h @@ -20,6 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define SANBOOT_PCBIOS #define ENTROPY_RTC #define TIME_RTC +#define REBOOT_PCBIOS #define IMAGE_ELF /* ELF image support */ #define IMAGE_MULTIBOOT /* MultiBoot image support */ diff --git a/src/config/reboot.h b/src/config/reboot.h new file mode 100644 index 00000000..240ef87b --- /dev/null +++ b/src/config/reboot.h @@ -0,0 +1,16 @@ +#ifndef CONFIG_REBOOT_H +#define CONFIG_REBOOT_H + +/** @file + * + * Reboot API configuration + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include + +#include + +#endif /* CONFIG_REBOOT_H */ diff --git a/src/core/null_reboot.c b/src/core/null_reboot.c new file mode 100644 index 00000000..b7e55bce --- /dev/null +++ b/src/core/null_reboot.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @file + * + * Null reboot mechanism + * + */ + +#include +#include + +/** + * Reboot system + * + */ +static void null_reboot ( void ) { + + printf ( "Cannot reboot; not implemented\n" ); + while ( 1 ) {} +} + +PROVIDE_REBOOT ( null, reboot, null_reboot ); diff --git a/src/arch/i386/hci/commands/reboot_cmd.c b/src/hci/commands/reboot_cmd.c similarity index 94% rename from src/arch/i386/hci/commands/reboot_cmd.c rename to src/hci/commands/reboot_cmd.c index 74c69c94..19d3d6df 100644 --- a/src/arch/i386/hci/commands/reboot_cmd.c +++ b/src/hci/commands/reboot_cmd.c @@ -17,9 +17,9 @@ * 02110-1301, USA. */ -#include #include #include +#include FILE_LICENCE ( GPL2_OR_LATER ); @@ -55,7 +55,7 @@ static int reboot_exec ( int argc, char **argv ) { return rc; /* Reboot system */ - __asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : ); + reboot(); return 0; } diff --git a/src/include/ipxe/efi/efi_reboot.h b/src/include/ipxe/efi/efi_reboot.h new file mode 100644 index 00000000..33921b91 --- /dev/null +++ b/src/include/ipxe/efi/efi_reboot.h @@ -0,0 +1,18 @@ +#ifndef _IPXE_EFI_REBOOT_H +#define _IPXE_EFI_REBOOT_H + +/** @file + * + * iPXE reboot API for EFI + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#ifdef REBOOT_EFI +#define REBOOT_PREFIX_efi +#else +#define REBOOT_PREFIX_efi __efi_ +#endif + +#endif /* _IPXE_EFI_REBOOT_H */ diff --git a/src/include/ipxe/null_reboot.h b/src/include/ipxe/null_reboot.h new file mode 100644 index 00000000..3de36c5b --- /dev/null +++ b/src/include/ipxe/null_reboot.h @@ -0,0 +1,18 @@ +#ifndef _IPXE_NULL_REBOOT_H +#define _IPXE_NULL_REBOOT_H + +/** @file + * + * iPXE do-nothing reboot API + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#ifdef REBOOT_NULL +#define REBOOT_PREFIX_null +#else +#define REBOOT_PREFIX_null __null_ +#endif + +#endif /* _IPXE_NULL_REBOOT_H */ diff --git a/src/include/ipxe/reboot.h b/src/include/ipxe/reboot.h new file mode 100644 index 00000000..043c5e10 --- /dev/null +++ b/src/include/ipxe/reboot.h @@ -0,0 +1,57 @@ +#ifndef _IPXE_REBOOT_H +#define _IPXE_REBOOT_H + +/** @file + * + * iPXE reboot API + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +/** + * Calculate static inline reboot API function name + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @ret _subsys_func Subsystem API function + */ +#define REBOOT_INLINE( _subsys, _api_func ) \ + SINGLE_API_INLINE ( REBOOT_PREFIX_ ## _subsys, _api_func ) + +/** + * Provide an reboot API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @v _func Implementing function + */ +#define PROVIDE_REBOOT( _subsys, _api_func, _func ) \ + PROVIDE_SINGLE_API ( REBOOT_PREFIX_ ## _subsys, _api_func, _func ) + +/** + * Provide a static inline reboot API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + */ +#define PROVIDE_REBOOT_INLINE( _subsys, _api_func ) \ + PROVIDE_SINGLE_API_INLINE ( REBOOT_PREFIX_ ## _subsys, _api_func ) + +/* Include all architecture-independent reboot API headers */ +#include +#include + +/* Include all architecture-dependent reboot API headers */ +#include + +/** + * Reboot system + * + */ +void reboot ( void ); + +#endif /* _IPXE_REBOOT_H */ diff --git a/src/interface/efi/efi_reboot.c b/src/interface/efi/efi_reboot.c new file mode 100644 index 00000000..1ecccc46 --- /dev/null +++ b/src/interface/efi/efi_reboot.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** + * @file + * + * EFI reboot mechanism + * + */ + +#include +#include + +/** + * Reboot system + * + */ +static void efi_reboot ( void ) { + EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices; + + /* Use runtime services to reset system */ + rs->ResetSystem ( EfiResetCold, 0, 0, NULL ); +} + +PROVIDE_REBOOT ( efi, reboot, efi_reboot ); From e68a6ca225115a8796e6d63ffc32856043e25886 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 22 Mar 2013 13:54:44 +0000 Subject: [PATCH 244/250] [cmdline] Add ability to perform a warm reboot Signed-off-by: Michael Brown --- src/arch/i386/include/bios.h | 2 ++ src/arch/i386/interface/pcbios/bios_reboot.c | 9 ++++++++- src/core/null_reboot.c | 3 ++- src/hci/commands/reboot_cmd.c | 15 +++++++++++---- src/include/ipxe/reboot.h | 3 ++- src/interface/efi/efi_reboot.c | 5 +++-- 6 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/arch/i386/include/bios.h b/src/arch/i386/include/bios.h index fadb9f1b..3e6a845e 100644 --- a/src/arch/i386/include/bios.h +++ b/src/arch/i386/include/bios.h @@ -6,6 +6,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define BDA_SEG 0x0040 #define BDA_EQUIPMENT_WORD 0x0010 #define BDA_FBMS 0x0013 +#define BDA_REBOOT 0x0072 +#define BDA_REBOOT_WARM 0x1234 #define BDA_NUM_DRIVES 0x0075 #endif /* BIOS_H */ diff --git a/src/arch/i386/interface/pcbios/bios_reboot.c b/src/arch/i386/interface/pcbios/bios_reboot.c index 86f4e3eb..68546b2e 100644 --- a/src/arch/i386/interface/pcbios/bios_reboot.c +++ b/src/arch/i386/interface/pcbios/bios_reboot.c @@ -27,12 +27,19 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include +#include /** * Reboot system * + * @v warm Perform a warm reboot */ -static void bios_reboot ( void ) { +static void bios_reboot ( int warm ) { + uint16_t flag; + + /* Configure BIOS for cold/warm reboot */ + flag = ( warm ? BDA_REBOOT_WARM : 0 ); + put_real ( flag, BDA_SEG, BDA_REBOOT ); /* Jump to system reset vector */ __asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : ); diff --git a/src/core/null_reboot.c b/src/core/null_reboot.c index b7e55bce..8e3ed0bb 100644 --- a/src/core/null_reboot.c +++ b/src/core/null_reboot.c @@ -32,8 +32,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** * Reboot system * + * @v warm Perform a warm reboot */ -static void null_reboot ( void ) { +static void null_reboot ( int warm __unused ) { printf ( "Cannot reboot; not implemented\n" ); while ( 1 ) {} diff --git a/src/hci/commands/reboot_cmd.c b/src/hci/commands/reboot_cmd.c index 19d3d6df..44dcfc71 100644 --- a/src/hci/commands/reboot_cmd.c +++ b/src/hci/commands/reboot_cmd.c @@ -17,6 +17,7 @@ * 02110-1301, USA. */ +#include #include #include #include @@ -30,14 +31,20 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ /** "reboot" options */ -struct reboot_options {}; +struct reboot_options { + /** Perform a warm reboot */ + int warm; +}; /** "reboot" option list */ -static struct option_descriptor reboot_opts[] = {}; +static struct option_descriptor reboot_opts[] = { + OPTION_DESC ( "warm", 'w', no_argument, + struct reboot_options, warm, parse_flag ), +}; /** "reboot" command descriptor */ static struct command_descriptor reboot_cmd = - COMMAND_DESC ( struct reboot_options, reboot_opts, 0, 0, "" ); + COMMAND_DESC ( struct reboot_options, reboot_opts, 0, 0, "[--warm]" ); /** * The "reboot" command @@ -55,7 +62,7 @@ static int reboot_exec ( int argc, char **argv ) { return rc; /* Reboot system */ - reboot(); + reboot ( opts.warm ); return 0; } diff --git a/src/include/ipxe/reboot.h b/src/include/ipxe/reboot.h index 043c5e10..5d882d3d 100644 --- a/src/include/ipxe/reboot.h +++ b/src/include/ipxe/reboot.h @@ -51,7 +51,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** * Reboot system * + * @v warm Perform a warm reboot */ -void reboot ( void ); +void reboot ( int warm ); #endif /* _IPXE_REBOOT_H */ diff --git a/src/interface/efi/efi_reboot.c b/src/interface/efi/efi_reboot.c index 1ecccc46..bfee36aa 100644 --- a/src/interface/efi/efi_reboot.c +++ b/src/interface/efi/efi_reboot.c @@ -32,12 +32,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); /** * Reboot system * + * @v warm Perform a warm reboot */ -static void efi_reboot ( void ) { +static void efi_reboot ( int warm ) { EFI_RUNTIME_SERVICES *rs = efi_systab->RuntimeServices; /* Use runtime services to reset system */ - rs->ResetSystem ( EfiResetCold, 0, 0, NULL ); + rs->ResetSystem ( ( warm ? EfiResetWarm : EfiResetCold ), 0, 0, NULL ); } PROVIDE_REBOOT ( efi, reboot, efi_reboot ); From 9f75ee9ddba3b9b6760700287267d300fad5e136 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 22 Mar 2013 13:58:54 +0000 Subject: [PATCH 245/250] [efi] Enable "cpuid" command by default for EFI Signed-off-by: Michael Brown --- src/config/defaults/efi.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/defaults/efi.h b/src/config/defaults/efi.h index c453e89a..7385aeab 100644 --- a/src/config/defaults/efi.h +++ b/src/config/defaults/efi.h @@ -25,5 +25,6 @@ #define IMAGE_SCRIPT /* iPXE script image support */ #define REBOOT_CMD /* Reboot command */ +#define CPUID_CMD /* x86 CPU feature detection command */ #endif /* CONFIG_DEFAULTS_EFI_H */ From b2c9730da7ecd50515aadb24a98dbf63ed650a22 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 25 Mar 2013 18:01:53 +0000 Subject: [PATCH 246/250] [cs89x0] Remove conflicting macro definitions Remove macros which aren't used anywhere in the driver, and which conflict with macros of the same name used in the EFI headers. Signed-off-by: Michael Brown --- src/drivers/net/cs89x0.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/drivers/net/cs89x0.h b/src/drivers/net/cs89x0.h index 432fe94e..aca790fd 100644 --- a/src/drivers/net/cs89x0.h +++ b/src/drivers/net/cs89x0.h @@ -471,9 +471,6 @@ FILE_LICENCE ( GPL2_ONLY ); #define PNP_CNF_DMA 0x74 #define PNP_CNF_MEM 0x48 -#define BIT0 1 -#define BIT15 0x8000 - /* * Local variables: * c-basic-offset: 8 From dab7910beb348853da73c8e73904d1c87708ab22 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 25 Mar 2013 18:02:09 +0000 Subject: [PATCH 247/250] [igbvf] Remove conflicting macro definitions Remove macros which aren't used anywhere in the driver, and which conflict with macros of the same name used in the EFI headers. Signed-off-by: Michael Brown --- src/drivers/net/igbvf/igbvf_osdep.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/drivers/net/igbvf/igbvf_osdep.h b/src/drivers/net/igbvf/igbvf_osdep.h index 259b9ec3..8ac179de 100644 --- a/src/drivers/net/igbvf/igbvf_osdep.h +++ b/src/drivers/net/igbvf/igbvf_osdep.h @@ -56,9 +56,6 @@ typedef enum { true = 1 } boolean_t; -#define TRUE 1 -#define FALSE 0 - #define usec_delay(x) udelay(x) #define msec_delay(x) mdelay(x) #define msec_delay_irq(x) mdelay(x) From 8a49782eebc66c3529578735386f03c262e1995b Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 25 Mar 2013 18:02:20 +0000 Subject: [PATCH 248/250] [prism2] Use standard type names Avoid using UINT16 and similar typedefs, which are non-standard in the iPXE codebase and generate conflicts when trying to include any of the EFI headers. Also fix trailing whitespace in the affected files, to prevent complaints from git. Signed-off-by: Michael Brown --- src/drivers/net/hfa384x.h | 2382 ++++++++++++++++----------------- src/drivers/net/p80211hdr.h | 100 +- src/drivers/net/prism2.c | 190 +-- src/drivers/net/wlan_compat.h | 46 +- 4 files changed, 1348 insertions(+), 1370 deletions(-) diff --git a/src/drivers/net/hfa384x.h b/src/drivers/net/hfa384x.h index 2e3ccf52..d33704e6 100644 --- a/src/drivers/net/hfa384x.h +++ b/src/drivers/net/hfa384x.h @@ -39,7 +39,7 @@ * * -------------------------------------------------------------------- * -* Portions of the development of this software were funded by +* Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development. * * -------------------------------------------------------------------- @@ -65,18 +65,18 @@ FILE_LICENCE ( GPL2_ONLY ); /*------ Constants --------------------------------------------*/ /*--- Mins & Maxs -----------------------------------*/ -#define HFA384x_CMD_ALLOC_LEN_MIN ((UINT16)4) -#define HFA384x_CMD_ALLOC_LEN_MAX ((UINT16)2400) -#define HFA384x_BAP_DATALEN_MAX ((UINT16)4096) -#define HFA384x_BAP_OFFSET_MAX ((UINT16)4096) -#define HFA384x_PORTID_MAX ((UINT16)7) -#define HFA384x_NUMPORTS_MAX ((UINT16)(HFA384x_PORTID_MAX+1)) -#define HFA384x_PDR_LEN_MAX ((UINT16)512) /* in bytes, from EK */ -#define HFA384x_PDA_RECS_MAX ((UINT16)200) /* a guess */ -#define HFA384x_PDA_LEN_MAX ((UINT16)1024) /* in bytes, from EK */ -#define HFA384x_SCANRESULT_MAX ((UINT16)31) -#define HFA384x_HSCANRESULT_MAX ((UINT16)31) -#define HFA384x_CHINFORESULT_MAX ((UINT16)16) +#define HFA384x_CMD_ALLOC_LEN_MIN ((uint16_t)4) +#define HFA384x_CMD_ALLOC_LEN_MAX ((uint16_t)2400) +#define HFA384x_BAP_DATALEN_MAX ((uint16_t)4096) +#define HFA384x_BAP_OFFSET_MAX ((uint16_t)4096) +#define HFA384x_PORTID_MAX ((uint16_t)7) +#define HFA384x_NUMPORTS_MAX ((uint16_t)(HFA384x_PORTID_MAX+1)) +#define HFA384x_PDR_LEN_MAX ((uint16_t)512) /* in bytes, from EK */ +#define HFA384x_PDA_RECS_MAX ((uint16_t)200) /* a guess */ +#define HFA384x_PDA_LEN_MAX ((uint16_t)1024) /* in bytes, from EK */ +#define HFA384x_SCANRESULT_MAX ((uint16_t)31) +#define HFA384x_HSCANRESULT_MAX ((uint16_t)31) +#define HFA384x_CHINFORESULT_MAX ((uint16_t)16) #define HFA384x_DRVR_FIDSTACKLEN_MAX (10) #define HFA384x_DRVR_TXBUF_MAX (sizeof(hfa384x_tx_frame_t) + \ WLAN_DATA_MAXLEN - \ @@ -86,63 +86,63 @@ FILE_LICENCE ( GPL2_ONLY ); #define HFA384x_INFODATA_MAXLEN (sizeof(hfa384x_infodata_t)) #define HFA384x_INFOFRM_MAXLEN (sizeof(hfa384x_InfFrame_t)) #define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */ -#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN +#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN #define HFA384x_USB_RWMEM_MAXLEN 2048 /*--- Support Constants -----------------------------*/ -#define HFA384x_BAP_PROC ((UINT16)0) -#define HFA384x_BAP_INT ((UINT16)1) -#define HFA384x_PORTTYPE_IBSS ((UINT16)0) -#define HFA384x_PORTTYPE_BSS ((UINT16)1) -#define HFA384x_PORTTYPE_WDS ((UINT16)2) -#define HFA384x_PORTTYPE_PSUEDOIBSS ((UINT16)3) -#define HFA384x_PORTTYPE_HOSTAP ((UINT16)6) -#define HFA384x_WEPFLAGS_PRIVINVOKED ((UINT16)BIT0) -#define HFA384x_WEPFLAGS_EXCLUDE ((UINT16)BIT1) -#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((UINT16)BIT4) -#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((UINT16)BIT7) -#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((UINT16)BIT11) -#define HFA384x_WEPFLAGS_IV_INTERVAL1 ((UINT16)0) -#define HFA384x_WEPFLAGS_IV_INTERVAL10 ((UINT16)BIT5) -#define HFA384x_WEPFLAGS_IV_INTERVAL50 ((UINT16)BIT6) -#define HFA384x_WEPFLAGS_IV_INTERVAL100 ((UINT16)(BIT5 | BIT6)) -#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((UINT16)BIT8) -#define HFA384x_WEPFLAGS_HOST_MIC ((UINT16)BIT9) -#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((UINT16)1) -#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((UINT16)2) -#define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((UINT16)3) -#define HFA384x_PORTSTATUS_DISABLED ((UINT16)1) -#define HFA384x_PORTSTATUS_INITSRCH ((UINT16)2) -#define HFA384x_PORTSTATUS_CONN_IBSS ((UINT16)3) -#define HFA384x_PORTSTATUS_CONN_ESS ((UINT16)4) -#define HFA384x_PORTSTATUS_OOR_ESS ((UINT16)5) -#define HFA384x_PORTSTATUS_CONN_WDS ((UINT16)6) -#define HFA384x_PORTSTATUS_HOSTAP ((UINT16)8) -#define HFA384x_RATEBIT_1 ((UINT16)1) -#define HFA384x_RATEBIT_2 ((UINT16)2) -#define HFA384x_RATEBIT_5dot5 ((UINT16)4) -#define HFA384x_RATEBIT_11 ((UINT16)8) +#define HFA384x_BAP_PROC ((uint16_t)0) +#define HFA384x_BAP_int ((uint16_t)1) +#define HFA384x_PORTTYPE_IBSS ((uint16_t)0) +#define HFA384x_PORTTYPE_BSS ((uint16_t)1) +#define HFA384x_PORTTYPE_WDS ((uint16_t)2) +#define HFA384x_PORTTYPE_PSUEDOIBSS ((uint16_t)3) +#define HFA384x_PORTTYPE_HOSTAP ((uint16_t)6) +#define HFA384x_WEPFLAGS_PRIVINVOKED ((uint16_t)BIT0) +#define HFA384x_WEPFLAGS_EXCLUDE ((uint16_t)BIT1) +#define HFA384x_WEPFLAGS_DISABLE_TXCRYPT ((uint16_t)BIT4) +#define HFA384x_WEPFLAGS_DISABLE_RXCRYPT ((uint16_t)BIT7) +#define HFA384x_WEPFLAGS_DISALLOW_MIXED ((uint16_t)BIT11) +#define HFA384x_WEPFLAGS_IV_INTERVAL1 ((uint16_t)0) +#define HFA384x_WEPFLAGS_IV_INTERVAL10 ((uint16_t)BIT5) +#define HFA384x_WEPFLAGS_IV_INTERVAL50 ((uint16_t)BIT6) +#define HFA384x_WEPFLAGS_IV_INTERVAL100 ((uint16_t)(BIT5 | BIT6)) +#define HFA384x_WEPFLAGS_FIRMWARE_WPA ((uint16_t)BIT8) +#define HFA384x_WEPFLAGS_HOST_MIC ((uint16_t)BIT9) +#define HFA384x_ROAMMODE_FWSCAN_FWROAM ((uint16_t)1) +#define HFA384x_ROAMMODE_FWSCAN_HOSTROAM ((uint16_t)2) +#define HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM ((uint16_t)3) +#define HFA384x_PORTSTATUS_DISABLED ((uint16_t)1) +#define HFA384x_PORTSTATUS_INITSRCH ((uint16_t)2) +#define HFA384x_PORTSTATUS_CONN_IBSS ((uint16_t)3) +#define HFA384x_PORTSTATUS_CONN_ESS ((uint16_t)4) +#define HFA384x_PORTSTATUS_OOR_ESS ((uint16_t)5) +#define HFA384x_PORTSTATUS_CONN_WDS ((uint16_t)6) +#define HFA384x_PORTSTATUS_HOSTAP ((uint16_t)8) +#define HFA384x_RATEBIT_1 ((uint16_t)1) +#define HFA384x_RATEBIT_2 ((uint16_t)2) +#define HFA384x_RATEBIT_5dot5 ((uint16_t)4) +#define HFA384x_RATEBIT_11 ((uint16_t)8) /*--- Just some symbolic names for legibility -------*/ -#define HFA384x_TXCMD_NORECL ((UINT16)0) -#define HFA384x_TXCMD_RECL ((UINT16)1) +#define HFA384x_TXCMD_NORECL ((uint16_t)0) +#define HFA384x_TXCMD_RECL ((uint16_t)1) /*--- MAC Internal memory constants and macros ------*/ /* masks and macros used to manipulate MAC internal memory addresses. */ -/* MAC internal memory addresses are 23 bit quantities. The MAC uses - * a paged address space where the upper 16 bits are the page number - * and the lower 7 bits are the offset. There are various Host API - * elements that require two 16-bit quantities to specify a MAC - * internal memory address. Unfortunately, some of the API's use a - * page/offset format where the offset value is JUST the lower seven - * bits and the page is the remaining 16 bits. Some of the API's - * assume that the 23 bit address has been split at the 16th bit. We - * refer to these two formats as AUX format and CMD format. The +/* MAC internal memory addresses are 23 bit quantities. The MAC uses + * a paged address space where the upper 16 bits are the page number + * and the lower 7 bits are the offset. There are various Host API + * elements that require two 16-bit quantities to specify a MAC + * internal memory address. Unfortunately, some of the API's use a + * page/offset format where the offset value is JUST the lower seven + * bits and the page is the remaining 16 bits. Some of the API's + * assume that the 23 bit address has been split at the 16th bit. We + * refer to these two formats as AUX format and CMD format. The * macros below help handle some of this. - */ + */ /* Handy constant */ -#define HFA384x_ADDR_AUX_OFF_MAX ((UINT16)0x007f) +#define HFA384x_ADDR_AUX_OFF_MAX ((uint16_t)0x007f) /* Mask bits for discarding unwanted pieces in a flat address */ #define HFA384x_ADDR_FLAT_AUX_PAGE_MASK (0x007fff80) @@ -160,25 +160,25 @@ FILE_LICENCE ( GPL2_ONLY ); /* Make a 32-bit flat address from AUX format 16-bit page and offset */ #define HFA384x_ADDR_AUX_MKFLAT(p,o) \ - (((UINT32)(((UINT16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \ - ((UINT32)(((UINT16)(o))&HFA384x_ADDR_AUX_OFF_MASK)) + (((uint32_t)(((uint16_t)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) <<7) | \ + ((uint32_t)(((uint16_t)(o))&HFA384x_ADDR_AUX_OFF_MASK)) /* Make a 32-bit flat address from CMD format 16-bit page and offset */ #define HFA384x_ADDR_CMD_MKFLAT(p,o) \ - (((UINT32)(((UINT16)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \ - ((UINT32)(((UINT16)(o))&HFA384x_ADDR_CMD_OFF_MASK)) + (((uint32_t)(((uint16_t)(p))&HFA384x_ADDR_CMD_PAGE_MASK)) <<16) | \ + ((uint32_t)(((uint16_t)(o))&HFA384x_ADDR_CMD_OFF_MASK)) /* Make AUX format offset and page from a 32-bit flat address */ #define HFA384x_ADDR_AUX_MKPAGE(f) \ - ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7)) + ((uint16_t)((((uint32_t)(f))&HFA384x_ADDR_FLAT_AUX_PAGE_MASK)>>7)) #define HFA384x_ADDR_AUX_MKOFF(f) \ - ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_AUX_OFF_MASK)) + ((uint16_t)(((uint32_t)(f))&HFA384x_ADDR_FLAT_AUX_OFF_MASK)) /* Make CMD format offset and page from a 32-bit flat address */ #define HFA384x_ADDR_CMD_MKPAGE(f) \ - ((UINT16)((((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) + ((uint16_t)((((uint32_t)(f))&HFA384x_ADDR_FLAT_CMD_PAGE_MASK)>>16)) #define HFA384x_ADDR_CMD_MKOFF(f) \ - ((UINT16)(((UINT32)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK)) + ((uint16_t)(((uint32_t)(f))&HFA384x_ADDR_FLAT_CMD_OFF_MASK)) /*--- Aux register masks/tests ----------------------*/ /* Some of the upper bits of the AUX offset register are used to */ @@ -190,7 +190,7 @@ FILE_LICENCE ( GPL2_ONLY ); /* Make AUX register offset and page values from a flat address */ #define HFA384x_AUX_MKOFF(f, c) \ - (HFA384x_ADDR_AUX_MKOFF(f) | (((UINT16)(c))<<12)) + (HFA384x_ADDR_AUX_MKOFF(f) | (((uint16_t)(c))<<12)) #define HFA384x_AUX_MKPAGE(f) HFA384x_ADDR_AUX_MKPAGE(f) @@ -284,91 +284,91 @@ FILE_LICENCE ( GPL2_ONLY ); #endif /*--- Register Field Masks --------------------------*/ -#define HFA384x_CMD_BUSY ((UINT16)BIT15) -#define HFA384x_CMD_AINFO ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) -#define HFA384x_CMD_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) -#define HFA384x_CMD_RECL ((UINT16)BIT8) -#define HFA384x_CMD_WRITE ((UINT16)BIT8) -#define HFA384x_CMD_PROGMODE ((UINT16)(BIT9 | BIT8)) -#define HFA384x_CMD_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) +#define HFA384x_CMD_BUSY ((uint16_t)BIT15) +#define HFA384x_CMD_AINFO ((uint16_t)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) +#define HFA384x_CMD_MACPORT ((uint16_t)(BIT10 | BIT9 | BIT8)) +#define HFA384x_CMD_RECL ((uint16_t)BIT8) +#define HFA384x_CMD_WRITE ((uint16_t)BIT8) +#define HFA384x_CMD_PROGMODE ((uint16_t)(BIT9 | BIT8)) +#define HFA384x_CMD_CMDCODE ((uint16_t)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) -#define HFA384x_STATUS_RESULT ((UINT16)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) -#define HFA384x_STATUS_CMDCODE ((UINT16)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) +#define HFA384x_STATUS_RESULT ((uint16_t)(BIT14 | BIT13 | BIT12 | BIT11 | BIT10 | BIT9 | BIT8)) +#define HFA384x_STATUS_CMDCODE ((uint16_t)(BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0)) -#define HFA384x_OFFSET_BUSY ((UINT16)BIT15) -#define HFA384x_OFFSET_ERR ((UINT16)BIT14) -#define HFA384x_OFFSET_DATAOFF ((UINT16)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1)) +#define HFA384x_OFFSET_BUSY ((uint16_t)BIT15) +#define HFA384x_OFFSET_ERR ((uint16_t)BIT14) +#define HFA384x_OFFSET_DATAOFF ((uint16_t)(BIT11 | BIT10 | BIT9 | BIT8 | BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1)) -#define HFA384x_EVSTAT_TICK ((UINT16)BIT15) -#define HFA384x_EVSTAT_WTERR ((UINT16)BIT14) -#define HFA384x_EVSTAT_INFDROP ((UINT16)BIT13) -#define HFA384x_EVSTAT_INFO ((UINT16)BIT7) -#define HFA384x_EVSTAT_DTIM ((UINT16)BIT5) -#define HFA384x_EVSTAT_CMD ((UINT16)BIT4) -#define HFA384x_EVSTAT_ALLOC ((UINT16)BIT3) -#define HFA384x_EVSTAT_TXEXC ((UINT16)BIT2) -#define HFA384x_EVSTAT_TX ((UINT16)BIT1) -#define HFA384x_EVSTAT_RX ((UINT16)BIT0) +#define HFA384x_EVSTAT_TICK ((uint16_t)BIT15) +#define HFA384x_EVSTAT_WTERR ((uint16_t)BIT14) +#define HFA384x_EVSTAT_INFDROP ((uint16_t)BIT13) +#define HFA384x_EVSTAT_INFO ((uint16_t)BIT7) +#define HFA384x_EVSTAT_DTIM ((uint16_t)BIT5) +#define HFA384x_EVSTAT_CMD ((uint16_t)BIT4) +#define HFA384x_EVSTAT_ALLOC ((uint16_t)BIT3) +#define HFA384x_EVSTAT_TXEXC ((uint16_t)BIT2) +#define HFA384x_EVSTAT_TX ((uint16_t)BIT1) +#define HFA384x_EVSTAT_RX ((uint16_t)BIT0) #define HFA384x_INT_BAP_OP (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC) #define HFA384x_INT_NORMAL (HFA384x_EVSTAT_INFO|HFA384x_EVSTAT_RX|HFA384x_EVSTAT_TX|HFA384x_EVSTAT_TXEXC|HFA384x_EVSTAT_INFDROP|HFA384x_EVSTAT_ALLOC|HFA384x_EVSTAT_DTIM) -#define HFA384x_INTEN_TICK ((UINT16)BIT15) -#define HFA384x_INTEN_WTERR ((UINT16)BIT14) -#define HFA384x_INTEN_INFDROP ((UINT16)BIT13) -#define HFA384x_INTEN_INFO ((UINT16)BIT7) -#define HFA384x_INTEN_DTIM ((UINT16)BIT5) -#define HFA384x_INTEN_CMD ((UINT16)BIT4) -#define HFA384x_INTEN_ALLOC ((UINT16)BIT3) -#define HFA384x_INTEN_TXEXC ((UINT16)BIT2) -#define HFA384x_INTEN_TX ((UINT16)BIT1) -#define HFA384x_INTEN_RX ((UINT16)BIT0) +#define HFA384x_INTEN_TICK ((uint16_t)BIT15) +#define HFA384x_INTEN_WTERR ((uint16_t)BIT14) +#define HFA384x_INTEN_INFDROP ((uint16_t)BIT13) +#define HFA384x_INTEN_INFO ((uint16_t)BIT7) +#define HFA384x_INTEN_DTIM ((uint16_t)BIT5) +#define HFA384x_INTEN_CMD ((uint16_t)BIT4) +#define HFA384x_INTEN_ALLOC ((uint16_t)BIT3) +#define HFA384x_INTEN_TXEXC ((uint16_t)BIT2) +#define HFA384x_INTEN_TX ((uint16_t)BIT1) +#define HFA384x_INTEN_RX ((uint16_t)BIT0) -#define HFA384x_EVACK_TICK ((UINT16)BIT15) -#define HFA384x_EVACK_WTERR ((UINT16)BIT14) -#define HFA384x_EVACK_INFDROP ((UINT16)BIT13) -#define HFA384x_EVACK_INFO ((UINT16)BIT7) -#define HFA384x_EVACK_DTIM ((UINT16)BIT5) -#define HFA384x_EVACK_CMD ((UINT16)BIT4) -#define HFA384x_EVACK_ALLOC ((UINT16)BIT3) -#define HFA384x_EVACK_TXEXC ((UINT16)BIT2) -#define HFA384x_EVACK_TX ((UINT16)BIT1) -#define HFA384x_EVACK_RX ((UINT16)BIT0) +#define HFA384x_EVACK_TICK ((uint16_t)BIT15) +#define HFA384x_EVACK_WTERR ((uint16_t)BIT14) +#define HFA384x_EVACK_INFDROP ((uint16_t)BIT13) +#define HFA384x_EVACK_INFO ((uint16_t)BIT7) +#define HFA384x_EVACK_DTIM ((uint16_t)BIT5) +#define HFA384x_EVACK_CMD ((uint16_t)BIT4) +#define HFA384x_EVACK_ALLOC ((uint16_t)BIT3) +#define HFA384x_EVACK_TXEXC ((uint16_t)BIT2) +#define HFA384x_EVACK_TX ((uint16_t)BIT1) +#define HFA384x_EVACK_RX ((uint16_t)BIT0) -#define HFA384x_CONTROL_AUXEN ((UINT16)(BIT15 | BIT14)) +#define HFA384x_CONTROL_AUXEN ((uint16_t)(BIT15 | BIT14)) /*--- Command Code Constants --------------------------*/ /*--- Controller Commands --------------------------*/ -#define HFA384x_CMDCODE_INIT ((UINT16)0x00) -#define HFA384x_CMDCODE_ENABLE ((UINT16)0x01) -#define HFA384x_CMDCODE_DISABLE ((UINT16)0x02) -#define HFA384x_CMDCODE_DIAG ((UINT16)0x03) +#define HFA384x_CMDCODE_INIT ((uint16_t)0x00) +#define HFA384x_CMDCODE_ENABLE ((uint16_t)0x01) +#define HFA384x_CMDCODE_DISABLE ((uint16_t)0x02) +#define HFA384x_CMDCODE_DIAG ((uint16_t)0x03) /*--- Buffer Mgmt Commands --------------------------*/ -#define HFA384x_CMDCODE_ALLOC ((UINT16)0x0A) -#define HFA384x_CMDCODE_TX ((UINT16)0x0B) -#define HFA384x_CMDCODE_CLRPRST ((UINT16)0x12) +#define HFA384x_CMDCODE_ALLOC ((uint16_t)0x0A) +#define HFA384x_CMDCODE_TX ((uint16_t)0x0B) +#define HFA384x_CMDCODE_CLRPRST ((uint16_t)0x12) /*--- Regulate Commands --------------------------*/ -#define HFA384x_CMDCODE_NOTIFY ((UINT16)0x10) -#define HFA384x_CMDCODE_INQ ((UINT16)0x11) +#define HFA384x_CMDCODE_NOTIFY ((uint16_t)0x10) +#define HFA384x_CMDCODE_INQ ((uint16_t)0x11) /*--- Configure Commands --------------------------*/ -#define HFA384x_CMDCODE_ACCESS ((UINT16)0x21) -#define HFA384x_CMDCODE_DOWNLD ((UINT16)0x22) +#define HFA384x_CMDCODE_ACCESS ((uint16_t)0x21) +#define HFA384x_CMDCODE_DOWNLD ((uint16_t)0x22) /*--- Debugging Commands -----------------------------*/ -#define HFA384x_CMDCODE_MONITOR ((UINT16)(0x38)) -#define HFA384x_MONITOR_ENABLE ((UINT16)(0x0b)) -#define HFA384x_MONITOR_DISABLE ((UINT16)(0x0f)) +#define HFA384x_CMDCODE_MONITOR ((uint16_t)(0x38)) +#define HFA384x_MONITOR_ENABLE ((uint16_t)(0x0b)) +#define HFA384x_MONITOR_DISABLE ((uint16_t)(0x0f)) /*--- Result Codes --------------------------*/ -#define HFA384x_SUCCESS ((UINT16)(0x00)) -#define HFA384x_CARD_FAIL ((UINT16)(0x01)) -#define HFA384x_NO_BUFF ((UINT16)(0x05)) -#define HFA384x_CMD_ERR ((UINT16)(0x7F)) +#define HFA384x_SUCCESS ((uint16_t)(0x00)) +#define HFA384x_CARD_FAIL ((uint16_t)(0x01)) +#define HFA384x_NO_BUFF ((uint16_t)(0x05)) +#define HFA384x_CMD_ERR ((uint16_t)(0x7F)) /*--- Programming Modes -------------------------- MODE 0: Disable programming @@ -376,408 +376,408 @@ FILE_LICENCE ( GPL2_ONLY ); MODE 2: Enable non-volatile memory programming MODE 3: Program non-volatile memory section --------------------------------------------------*/ -#define HFA384x_PROGMODE_DISABLE ((UINT16)0x00) -#define HFA384x_PROGMODE_RAM ((UINT16)0x01) -#define HFA384x_PROGMODE_NV ((UINT16)0x02) -#define HFA384x_PROGMODE_NVWRITE ((UINT16)0x03) +#define HFA384x_PROGMODE_DISABLE ((uint16_t)0x00) +#define HFA384x_PROGMODE_RAM ((uint16_t)0x01) +#define HFA384x_PROGMODE_NV ((uint16_t)0x02) +#define HFA384x_PROGMODE_NVWRITE ((uint16_t)0x03) /*--- AUX register enable --------------------------*/ -#define HFA384x_AUXPW0 ((UINT16)0xfe01) -#define HFA384x_AUXPW1 ((UINT16)0xdc23) -#define HFA384x_AUXPW2 ((UINT16)0xba45) +#define HFA384x_AUXPW0 ((uint16_t)0xfe01) +#define HFA384x_AUXPW1 ((uint16_t)0xdc23) +#define HFA384x_AUXPW2 ((uint16_t)0xba45) -#define HFA384x_CONTROL_AUX_ISDISABLED ((UINT16)0x0000) -#define HFA384x_CONTROL_AUX_ISENABLED ((UINT16)0xc000) -#define HFA384x_CONTROL_AUX_DOENABLE ((UINT16)0x8000) -#define HFA384x_CONTROL_AUX_DODISABLE ((UINT16)0x4000) +#define HFA384x_CONTROL_AUX_ISDISABLED ((uint16_t)0x0000) +#define HFA384x_CONTROL_AUX_ISENABLED ((uint16_t)0xc000) +#define HFA384x_CONTROL_AUX_DOENABLE ((uint16_t)0x8000) +#define HFA384x_CONTROL_AUX_DODISABLE ((uint16_t)0x4000) /*--- Record ID Constants --------------------------*/ /*-------------------------------------------------------------------- Configuration RIDs: Network Parameters, Static Configuration Entities --------------------------------------------------------------------*/ -#define HFA384x_RID_CNFPORTTYPE ((UINT16)0xFC00) -#define HFA384x_RID_CNFOWNMACADDR ((UINT16)0xFC01) -#define HFA384x_RID_CNFDESIREDSSID ((UINT16)0xFC02) -#define HFA384x_RID_CNFOWNCHANNEL ((UINT16)0xFC03) -#define HFA384x_RID_CNFOWNSSID ((UINT16)0xFC04) -#define HFA384x_RID_CNFOWNATIMWIN ((UINT16)0xFC05) -#define HFA384x_RID_CNFSYSSCALE ((UINT16)0xFC06) -#define HFA384x_RID_CNFMAXDATALEN ((UINT16)0xFC07) -#define HFA384x_RID_CNFWDSADDR ((UINT16)0xFC08) -#define HFA384x_RID_CNFPMENABLED ((UINT16)0xFC09) -#define HFA384x_RID_CNFPMEPS ((UINT16)0xFC0A) -#define HFA384x_RID_CNFMULTICASTRX ((UINT16)0xFC0B) -#define HFA384x_RID_CNFMAXSLEEPDUR ((UINT16)0xFC0C) -#define HFA384x_RID_CNFPMHOLDDUR ((UINT16)0xFC0D) -#define HFA384x_RID_CNFOWNNAME ((UINT16)0xFC0E) -#define HFA384x_RID_CNFOWNDTIMPER ((UINT16)0xFC10) -#define HFA384x_RID_CNFWDSADDR1 ((UINT16)0xFC11) -#define HFA384x_RID_CNFWDSADDR2 ((UINT16)0xFC12) -#define HFA384x_RID_CNFWDSADDR3 ((UINT16)0xFC13) -#define HFA384x_RID_CNFWDSADDR4 ((UINT16)0xFC14) -#define HFA384x_RID_CNFWDSADDR5 ((UINT16)0xFC15) -#define HFA384x_RID_CNFWDSADDR6 ((UINT16)0xFC16) -#define HFA384x_RID_CNFMCASTPMBUFF ((UINT16)0xFC17) +#define HFA384x_RID_CNFPORTTYPE ((uint16_t)0xFC00) +#define HFA384x_RID_CNFOWNMACADDR ((uint16_t)0xFC01) +#define HFA384x_RID_CNFDESIREDSSID ((uint16_t)0xFC02) +#define HFA384x_RID_CNFOWNCHANNEL ((uint16_t)0xFC03) +#define HFA384x_RID_CNFOWNSSID ((uint16_t)0xFC04) +#define HFA384x_RID_CNFOWNATIMWIN ((uint16_t)0xFC05) +#define HFA384x_RID_CNFSYSSCALE ((uint16_t)0xFC06) +#define HFA384x_RID_CNFMAXDATALEN ((uint16_t)0xFC07) +#define HFA384x_RID_CNFWDSADDR ((uint16_t)0xFC08) +#define HFA384x_RID_CNFPMENABLED ((uint16_t)0xFC09) +#define HFA384x_RID_CNFPMEPS ((uint16_t)0xFC0A) +#define HFA384x_RID_CNFMULTICASTRX ((uint16_t)0xFC0B) +#define HFA384x_RID_CNFMAXSLEEPDUR ((uint16_t)0xFC0C) +#define HFA384x_RID_CNFPMHOLDDUR ((uint16_t)0xFC0D) +#define HFA384x_RID_CNFOWNNAME ((uint16_t)0xFC0E) +#define HFA384x_RID_CNFOWNDTIMPER ((uint16_t)0xFC10) +#define HFA384x_RID_CNFWDSADDR1 ((uint16_t)0xFC11) +#define HFA384x_RID_CNFWDSADDR2 ((uint16_t)0xFC12) +#define HFA384x_RID_CNFWDSADDR3 ((uint16_t)0xFC13) +#define HFA384x_RID_CNFWDSADDR4 ((uint16_t)0xFC14) +#define HFA384x_RID_CNFWDSADDR5 ((uint16_t)0xFC15) +#define HFA384x_RID_CNFWDSADDR6 ((uint16_t)0xFC16) +#define HFA384x_RID_CNFMCASTPMBUFF ((uint16_t)0xFC17) /*-------------------------------------------------------------------- Configuration RID lengths: Network Params, Static Config Entities - This is the length of JUST the DATA part of the RID (does not + This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ /* TODO: fill in the rest of these */ -#define HFA384x_RID_CNFPORTTYPE_LEN ((UINT16)2) -#define HFA384x_RID_CNFOWNMACADDR_LEN ((UINT16)6) -#define HFA384x_RID_CNFDESIREDSSID_LEN ((UINT16)34) -#define HFA384x_RID_CNFOWNCHANNEL_LEN ((UINT16)2) -#define HFA384x_RID_CNFOWNSSID_LEN ((UINT16)34) -#define HFA384x_RID_CNFOWNATIMWIN_LEN ((UINT16)2) -#define HFA384x_RID_CNFSYSSCALE_LEN ((UINT16)0) -#define HFA384x_RID_CNFMAXDATALEN_LEN ((UINT16)0) -#define HFA384x_RID_CNFWDSADDR_LEN ((UINT16)6) -#define HFA384x_RID_CNFPMENABLED_LEN ((UINT16)0) -#define HFA384x_RID_CNFPMEPS_LEN ((UINT16)0) -#define HFA384x_RID_CNFMULTICASTRX_LEN ((UINT16)0) -#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0) -#define HFA384x_RID_CNFPMHOLDDUR_LEN ((UINT16)0) -#define HFA384x_RID_CNFOWNNAME_LEN ((UINT16)34) -#define HFA384x_RID_CNFOWNDTIMPER_LEN ((UINT16)0) -#define HFA384x_RID_CNFWDSADDR1_LEN ((UINT16)6) -#define HFA384x_RID_CNFWDSADDR2_LEN ((UINT16)6) -#define HFA384x_RID_CNFWDSADDR3_LEN ((UINT16)6) -#define HFA384x_RID_CNFWDSADDR4_LEN ((UINT16)6) -#define HFA384x_RID_CNFWDSADDR5_LEN ((UINT16)6) -#define HFA384x_RID_CNFWDSADDR6_LEN ((UINT16)6) -#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((UINT16)0) -#define HFA384x_RID_CNFAUTHENTICATION_LEN ((UINT16)sizeof(UINT16)) -#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((UINT16)0) +#define HFA384x_RID_CNFPORTTYPE_LEN ((uint16_t)2) +#define HFA384x_RID_CNFOWNMACADDR_LEN ((uint16_t)6) +#define HFA384x_RID_CNFDESIREDSSID_LEN ((uint16_t)34) +#define HFA384x_RID_CNFOWNCHANNEL_LEN ((uint16_t)2) +#define HFA384x_RID_CNFOWNSSID_LEN ((uint16_t)34) +#define HFA384x_RID_CNFOWNATIMWIN_LEN ((uint16_t)2) +#define HFA384x_RID_CNFSYSSCALE_LEN ((uint16_t)0) +#define HFA384x_RID_CNFMAXDATALEN_LEN ((uint16_t)0) +#define HFA384x_RID_CNFWDSADDR_LEN ((uint16_t)6) +#define HFA384x_RID_CNFPMENABLED_LEN ((uint16_t)0) +#define HFA384x_RID_CNFPMEPS_LEN ((uint16_t)0) +#define HFA384x_RID_CNFMULTICASTRX_LEN ((uint16_t)0) +#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((uint16_t)0) +#define HFA384x_RID_CNFPMHOLDDUR_LEN ((uint16_t)0) +#define HFA384x_RID_CNFOWNNAME_LEN ((uint16_t)34) +#define HFA384x_RID_CNFOWNDTIMPER_LEN ((uint16_t)0) +#define HFA384x_RID_CNFWDSADDR1_LEN ((uint16_t)6) +#define HFA384x_RID_CNFWDSADDR2_LEN ((uint16_t)6) +#define HFA384x_RID_CNFWDSADDR3_LEN ((uint16_t)6) +#define HFA384x_RID_CNFWDSADDR4_LEN ((uint16_t)6) +#define HFA384x_RID_CNFWDSADDR5_LEN ((uint16_t)6) +#define HFA384x_RID_CNFWDSADDR6_LEN ((uint16_t)6) +#define HFA384x_RID_CNFMCASTPMBUFF_LEN ((uint16_t)0) +#define HFA384x_RID_CNFAUTHENTICATION_LEN ((uint16_t)sizeof(uint16_t)) +#define HFA384x_RID_CNFMAXSLEEPDUR_LEN ((uint16_t)0) /*-------------------------------------------------------------------- Configuration RIDs: Network Parameters, Dynamic Configuration Entities --------------------------------------------------------------------*/ -#define HFA384x_RID_GROUPADDR ((UINT16)0xFC80) -#define HFA384x_RID_CREATEIBSS ((UINT16)0xFC81) -#define HFA384x_RID_FRAGTHRESH ((UINT16)0xFC82) -#define HFA384x_RID_RTSTHRESH ((UINT16)0xFC83) -#define HFA384x_RID_TXRATECNTL ((UINT16)0xFC84) -#define HFA384x_RID_PROMISCMODE ((UINT16)0xFC85) -#define HFA384x_RID_FRAGTHRESH0 ((UINT16)0xFC90) -#define HFA384x_RID_FRAGTHRESH1 ((UINT16)0xFC91) -#define HFA384x_RID_FRAGTHRESH2 ((UINT16)0xFC92) -#define HFA384x_RID_FRAGTHRESH3 ((UINT16)0xFC93) -#define HFA384x_RID_FRAGTHRESH4 ((UINT16)0xFC94) -#define HFA384x_RID_FRAGTHRESH5 ((UINT16)0xFC95) -#define HFA384x_RID_FRAGTHRESH6 ((UINT16)0xFC96) -#define HFA384x_RID_RTSTHRESH0 ((UINT16)0xFC97) -#define HFA384x_RID_RTSTHRESH1 ((UINT16)0xFC98) -#define HFA384x_RID_RTSTHRESH2 ((UINT16)0xFC99) -#define HFA384x_RID_RTSTHRESH3 ((UINT16)0xFC9A) -#define HFA384x_RID_RTSTHRESH4 ((UINT16)0xFC9B) -#define HFA384x_RID_RTSTHRESH5 ((UINT16)0xFC9C) -#define HFA384x_RID_RTSTHRESH6 ((UINT16)0xFC9D) -#define HFA384x_RID_TXRATECNTL0 ((UINT16)0xFC9E) -#define HFA384x_RID_TXRATECNTL1 ((UINT16)0xFC9F) -#define HFA384x_RID_TXRATECNTL2 ((UINT16)0xFCA0) -#define HFA384x_RID_TXRATECNTL3 ((UINT16)0xFCA1) -#define HFA384x_RID_TXRATECNTL4 ((UINT16)0xFCA2) -#define HFA384x_RID_TXRATECNTL5 ((UINT16)0xFCA3) -#define HFA384x_RID_TXRATECNTL6 ((UINT16)0xFCA4) +#define HFA384x_RID_GROUPADDR ((uint16_t)0xFC80) +#define HFA384x_RID_CREATEIBSS ((uint16_t)0xFC81) +#define HFA384x_RID_FRAGTHRESH ((uint16_t)0xFC82) +#define HFA384x_RID_RTSTHRESH ((uint16_t)0xFC83) +#define HFA384x_RID_TXRATECNTL ((uint16_t)0xFC84) +#define HFA384x_RID_PROMISCMODE ((uint16_t)0xFC85) +#define HFA384x_RID_FRAGTHRESH0 ((uint16_t)0xFC90) +#define HFA384x_RID_FRAGTHRESH1 ((uint16_t)0xFC91) +#define HFA384x_RID_FRAGTHRESH2 ((uint16_t)0xFC92) +#define HFA384x_RID_FRAGTHRESH3 ((uint16_t)0xFC93) +#define HFA384x_RID_FRAGTHRESH4 ((uint16_t)0xFC94) +#define HFA384x_RID_FRAGTHRESH5 ((uint16_t)0xFC95) +#define HFA384x_RID_FRAGTHRESH6 ((uint16_t)0xFC96) +#define HFA384x_RID_RTSTHRESH0 ((uint16_t)0xFC97) +#define HFA384x_RID_RTSTHRESH1 ((uint16_t)0xFC98) +#define HFA384x_RID_RTSTHRESH2 ((uint16_t)0xFC99) +#define HFA384x_RID_RTSTHRESH3 ((uint16_t)0xFC9A) +#define HFA384x_RID_RTSTHRESH4 ((uint16_t)0xFC9B) +#define HFA384x_RID_RTSTHRESH5 ((uint16_t)0xFC9C) +#define HFA384x_RID_RTSTHRESH6 ((uint16_t)0xFC9D) +#define HFA384x_RID_TXRATECNTL0 ((uint16_t)0xFC9E) +#define HFA384x_RID_TXRATECNTL1 ((uint16_t)0xFC9F) +#define HFA384x_RID_TXRATECNTL2 ((uint16_t)0xFCA0) +#define HFA384x_RID_TXRATECNTL3 ((uint16_t)0xFCA1) +#define HFA384x_RID_TXRATECNTL4 ((uint16_t)0xFCA2) +#define HFA384x_RID_TXRATECNTL5 ((uint16_t)0xFCA3) +#define HFA384x_RID_TXRATECNTL6 ((uint16_t)0xFCA4) /*-------------------------------------------------------------------- Configuration RID Lengths: Network Param, Dynamic Config Entities - This is the length of JUST the DATA part of the RID (does not + This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ /* TODO: fill in the rest of these */ -#define HFA384x_RID_GROUPADDR_LEN ((UINT16)16 * WLAN_ADDR_LEN) -#define HFA384x_RID_CREATEIBSS_LEN ((UINT16)0) -#define HFA384x_RID_FRAGTHRESH_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL_LEN ((UINT16)4) -#define HFA384x_RID_PROMISCMODE_LEN ((UINT16)2) -#define HFA384x_RID_FRAGTHRESH0_LEN ((UINT16)0) -#define HFA384x_RID_FRAGTHRESH1_LEN ((UINT16)0) -#define HFA384x_RID_FRAGTHRESH2_LEN ((UINT16)0) -#define HFA384x_RID_FRAGTHRESH3_LEN ((UINT16)0) -#define HFA384x_RID_FRAGTHRESH4_LEN ((UINT16)0) -#define HFA384x_RID_FRAGTHRESH5_LEN ((UINT16)0) -#define HFA384x_RID_FRAGTHRESH6_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH0_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH1_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH2_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH3_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH4_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH5_LEN ((UINT16)0) -#define HFA384x_RID_RTSTHRESH6_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL0_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL1_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL2_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL3_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL4_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL5_LEN ((UINT16)0) -#define HFA384x_RID_TXRATECNTL6_LEN ((UINT16)0) +#define HFA384x_RID_GROUPADDR_LEN ((uint16_t)16 * WLAN_ADDR_LEN) +#define HFA384x_RID_CREATEIBSS_LEN ((uint16_t)0) +#define HFA384x_RID_FRAGTHRESH_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL_LEN ((uint16_t)4) +#define HFA384x_RID_PROMISCMODE_LEN ((uint16_t)2) +#define HFA384x_RID_FRAGTHRESH0_LEN ((uint16_t)0) +#define HFA384x_RID_FRAGTHRESH1_LEN ((uint16_t)0) +#define HFA384x_RID_FRAGTHRESH2_LEN ((uint16_t)0) +#define HFA384x_RID_FRAGTHRESH3_LEN ((uint16_t)0) +#define HFA384x_RID_FRAGTHRESH4_LEN ((uint16_t)0) +#define HFA384x_RID_FRAGTHRESH5_LEN ((uint16_t)0) +#define HFA384x_RID_FRAGTHRESH6_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH0_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH1_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH2_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH3_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH4_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH5_LEN ((uint16_t)0) +#define HFA384x_RID_RTSTHRESH6_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL0_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL1_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL2_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL3_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL4_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL5_LEN ((uint16_t)0) +#define HFA384x_RID_TXRATECNTL6_LEN ((uint16_t)0) /*-------------------------------------------------------------------- Configuration RIDs: Behavior Parameters --------------------------------------------------------------------*/ -#define HFA384x_RID_ITICKTIME ((UINT16)0xFCE0) +#define HFA384x_RID_ITICKTIME ((uint16_t)0xFCE0) /*-------------------------------------------------------------------- Configuration RID Lengths: Behavior Parameters - This is the length of JUST the DATA part of the RID (does not + This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ -#define HFA384x_RID_ITICKTIME_LEN ((UINT16)2) +#define HFA384x_RID_ITICKTIME_LEN ((uint16_t)2) /*---------------------------------------------------------------------- Information RIDs: NIC Information --------------------------------------------------------------------*/ -#define HFA384x_RID_MAXLOADTIME ((UINT16)0xFD00) -#define HFA384x_RID_DOWNLOADBUFFER ((UINT16)0xFD01) -#define HFA384x_RID_PRIIDENTITY ((UINT16)0xFD02) -#define HFA384x_RID_PRISUPRANGE ((UINT16)0xFD03) -#define HFA384x_RID_PRI_CFIACTRANGES ((UINT16)0xFD04) -#define HFA384x_RID_NICSERIALNUMBER ((UINT16)0xFD0A) -#define HFA384x_RID_NICIDENTITY ((UINT16)0xFD0B) -#define HFA384x_RID_MFISUPRANGE ((UINT16)0xFD0C) -#define HFA384x_RID_CFISUPRANGE ((UINT16)0xFD0D) -#define HFA384x_RID_CHANNELLIST ((UINT16)0xFD10) -#define HFA384x_RID_REGULATORYDOMAINS ((UINT16)0xFD11) -#define HFA384x_RID_TEMPTYPE ((UINT16)0xFD12) -#define HFA384x_RID_CIS ((UINT16)0xFD13) -#define HFA384x_RID_STAIDENTITY ((UINT16)0xFD20) -#define HFA384x_RID_STASUPRANGE ((UINT16)0xFD21) -#define HFA384x_RID_STA_MFIACTRANGES ((UINT16)0xFD22) -#define HFA384x_RID_STA_CFIACTRANGES ((UINT16)0xFD23) -#define HFA384x_RID_BUILDSEQ ((UINT16)0xFFFE) -#define HFA384x_RID_FWID ((UINT16)0xFFFF) +#define HFA384x_RID_MAXLOADTIME ((uint16_t)0xFD00) +#define HFA384x_RID_DOWNLOADBUFFER ((uint16_t)0xFD01) +#define HFA384x_RID_PRIIDENTITY ((uint16_t)0xFD02) +#define HFA384x_RID_PRISUPRANGE ((uint16_t)0xFD03) +#define HFA384x_RID_PRI_CFIACTRANGES ((uint16_t)0xFD04) +#define HFA384x_RID_NICSERIALNUMBER ((uint16_t)0xFD0A) +#define HFA384x_RID_NICIDENTITY ((uint16_t)0xFD0B) +#define HFA384x_RID_MFISUPRANGE ((uint16_t)0xFD0C) +#define HFA384x_RID_CFISUPRANGE ((uint16_t)0xFD0D) +#define HFA384x_RID_CHANNELLIST ((uint16_t)0xFD10) +#define HFA384x_RID_REGULATORYDOMAINS ((uint16_t)0xFD11) +#define HFA384x_RID_TEMPTYPE ((uint16_t)0xFD12) +#define HFA384x_RID_CIS ((uint16_t)0xFD13) +#define HFA384x_RID_STAIDENTITY ((uint16_t)0xFD20) +#define HFA384x_RID_STASUPRANGE ((uint16_t)0xFD21) +#define HFA384x_RID_STA_MFIACTRANGES ((uint16_t)0xFD22) +#define HFA384x_RID_STA_CFIACTRANGES ((uint16_t)0xFD23) +#define HFA384x_RID_BUILDSEQ ((uint16_t)0xFFFE) +#define HFA384x_RID_FWID ((uint16_t)0xFFFF) /*---------------------------------------------------------------------- Information RID Lengths: NIC Information - This is the length of JUST the DATA part of the RID (does not + This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ -#define HFA384x_RID_MAXLOADTIME_LEN ((UINT16)0) -#define HFA384x_RID_DOWNLOADBUFFER_LEN ((UINT16)sizeof(hfa384x_downloadbuffer_t)) -#define HFA384x_RID_PRIIDENTITY_LEN ((UINT16)8) -#define HFA384x_RID_PRISUPRANGE_LEN ((UINT16)10) -#define HFA384x_RID_CFIACTRANGES_LEN ((UINT16)10) -#define HFA384x_RID_NICSERIALNUMBER_LEN ((UINT16)12) -#define HFA384x_RID_NICIDENTITY_LEN ((UINT16)8) -#define HFA384x_RID_MFISUPRANGE_LEN ((UINT16)10) -#define HFA384x_RID_CFISUPRANGE_LEN ((UINT16)10) -#define HFA384x_RID_CHANNELLIST_LEN ((UINT16)0) -#define HFA384x_RID_REGULATORYDOMAINS_LEN ((UINT16)12) -#define HFA384x_RID_TEMPTYPE_LEN ((UINT16)0) -#define HFA384x_RID_CIS_LEN ((UINT16)480) -#define HFA384x_RID_STAIDENTITY_LEN ((UINT16)8) -#define HFA384x_RID_STASUPRANGE_LEN ((UINT16)10) -#define HFA384x_RID_MFIACTRANGES_LEN ((UINT16)10) -#define HFA384x_RID_CFIACTRANGES2_LEN ((UINT16)10) -#define HFA384x_RID_BUILDSEQ_LEN ((UINT16)sizeof(hfa384x_BuildSeq_t)) -#define HFA384x_RID_FWID_LEN ((UINT16)sizeof(hfa384x_FWID_t)) +#define HFA384x_RID_MAXLOADTIME_LEN ((uint16_t)0) +#define HFA384x_RID_DOWNLOADBUFFER_LEN ((uint16_t)sizeof(hfa384x_downloadbuffer_t)) +#define HFA384x_RID_PRIIDENTITY_LEN ((uint16_t)8) +#define HFA384x_RID_PRISUPRANGE_LEN ((uint16_t)10) +#define HFA384x_RID_CFIACTRANGES_LEN ((uint16_t)10) +#define HFA384x_RID_NICSERIALNUMBER_LEN ((uint16_t)12) +#define HFA384x_RID_NICIDENTITY_LEN ((uint16_t)8) +#define HFA384x_RID_MFISUPRANGE_LEN ((uint16_t)10) +#define HFA384x_RID_CFISUPRANGE_LEN ((uint16_t)10) +#define HFA384x_RID_CHANNELLIST_LEN ((uint16_t)0) +#define HFA384x_RID_REGULATORYDOMAINS_LEN ((uint16_t)12) +#define HFA384x_RID_TEMPTYPE_LEN ((uint16_t)0) +#define HFA384x_RID_CIS_LEN ((uint16_t)480) +#define HFA384x_RID_STAIDENTITY_LEN ((uint16_t)8) +#define HFA384x_RID_STASUPRANGE_LEN ((uint16_t)10) +#define HFA384x_RID_MFIACTRANGES_LEN ((uint16_t)10) +#define HFA384x_RID_CFIACTRANGES2_LEN ((uint16_t)10) +#define HFA384x_RID_BUILDSEQ_LEN ((uint16_t)sizeof(hfa384x_BuildSeq_t)) +#define HFA384x_RID_FWID_LEN ((uint16_t)sizeof(hfa384x_FWID_t)) /*-------------------------------------------------------------------- Information RIDs: MAC Information --------------------------------------------------------------------*/ -#define HFA384x_RID_PORTSTATUS ((UINT16)0xFD40) -#define HFA384x_RID_CURRENTSSID ((UINT16)0xFD41) -#define HFA384x_RID_CURRENTBSSID ((UINT16)0xFD42) -#define HFA384x_RID_COMMSQUALITY ((UINT16)0xFD43) -#define HFA384x_RID_CURRENTTXRATE ((UINT16)0xFD44) -#define HFA384x_RID_CURRENTBCNINT ((UINT16)0xFD45) -#define HFA384x_RID_CURRENTSCALETHRESH ((UINT16)0xFD46) -#define HFA384x_RID_PROTOCOLRSPTIME ((UINT16)0xFD47) -#define HFA384x_RID_SHORTRETRYLIMIT ((UINT16)0xFD48) -#define HFA384x_RID_LONGRETRYLIMIT ((UINT16)0xFD49) -#define HFA384x_RID_MAXTXLIFETIME ((UINT16)0xFD4A) -#define HFA384x_RID_MAXRXLIFETIME ((UINT16)0xFD4B) -#define HFA384x_RID_CFPOLLABLE ((UINT16)0xFD4C) -#define HFA384x_RID_AUTHALGORITHMS ((UINT16)0xFD4D) -#define HFA384x_RID_PRIVACYOPTIMP ((UINT16)0xFD4F) -#define HFA384x_RID_DBMCOMMSQUALITY ((UINT16)0xFD51) -#define HFA384x_RID_CURRENTTXRATE1 ((UINT16)0xFD80) -#define HFA384x_RID_CURRENTTXRATE2 ((UINT16)0xFD81) -#define HFA384x_RID_CURRENTTXRATE3 ((UINT16)0xFD82) -#define HFA384x_RID_CURRENTTXRATE4 ((UINT16)0xFD83) -#define HFA384x_RID_CURRENTTXRATE5 ((UINT16)0xFD84) -#define HFA384x_RID_CURRENTTXRATE6 ((UINT16)0xFD85) -#define HFA384x_RID_OWNMACADDRESS ((UINT16)0xFD86) -// #define HFA384x_RID_PCFINFO ((UINT16)0xFD87) -#define HFA384x_RID_SCANRESULTS ((UINT16)0xFD88) // NEW -#define HFA384x_RID_HOSTSCANRESULTS ((UINT16)0xFD89) // NEW -#define HFA384x_RID_AUTHENTICATIONUSED ((UINT16)0xFD8A) // NEW -#define HFA384x_RID_ASSOCIATEFAILURE ((UINT16)0xFD8D) // 1.8.0 +#define HFA384x_RID_PORTSTATUS ((uint16_t)0xFD40) +#define HFA384x_RID_CURRENTSSID ((uint16_t)0xFD41) +#define HFA384x_RID_CURRENTBSSID ((uint16_t)0xFD42) +#define HFA384x_RID_COMMSQUALITY ((uint16_t)0xFD43) +#define HFA384x_RID_CURRENTTXRATE ((uint16_t)0xFD44) +#define HFA384x_RID_CURRENTBCNint ((uint16_t)0xFD45) +#define HFA384x_RID_CURRENTSCALETHRESH ((uint16_t)0xFD46) +#define HFA384x_RID_PROTOCOLRSPTIME ((uint16_t)0xFD47) +#define HFA384x_RID_SHORTRETRYLIMIT ((uint16_t)0xFD48) +#define HFA384x_RID_LONGRETRYLIMIT ((uint16_t)0xFD49) +#define HFA384x_RID_MAXTXLIFETIME ((uint16_t)0xFD4A) +#define HFA384x_RID_MAXRXLIFETIME ((uint16_t)0xFD4B) +#define HFA384x_RID_CFPOLLABLE ((uint16_t)0xFD4C) +#define HFA384x_RID_AUTHALGORITHMS ((uint16_t)0xFD4D) +#define HFA384x_RID_PRIVACYOPTIMP ((uint16_t)0xFD4F) +#define HFA384x_RID_DBMCOMMSQUALITY ((uint16_t)0xFD51) +#define HFA384x_RID_CURRENTTXRATE1 ((uint16_t)0xFD80) +#define HFA384x_RID_CURRENTTXRATE2 ((uint16_t)0xFD81) +#define HFA384x_RID_CURRENTTXRATE3 ((uint16_t)0xFD82) +#define HFA384x_RID_CURRENTTXRATE4 ((uint16_t)0xFD83) +#define HFA384x_RID_CURRENTTXRATE5 ((uint16_t)0xFD84) +#define HFA384x_RID_CURRENTTXRATE6 ((uint16_t)0xFD85) +#define HFA384x_RID_OWNMACADDRESS ((uint16_t)0xFD86) +// #define HFA384x_RID_PCFINFO ((uint16_t)0xFD87) +#define HFA384x_RID_SCANRESULTS ((uint16_t)0xFD88) // NEW +#define HFA384x_RID_HOSTSCANRESULTS ((uint16_t)0xFD89) // NEW +#define HFA384x_RID_AUTHENTICATIONUSED ((uint16_t)0xFD8A) // NEW +#define HFA384x_RID_ASSOCIATEFAILURE ((uint16_t)0xFD8D) // 1.8.0 /*-------------------------------------------------------------------- Information RID Lengths: MAC Information - This is the length of JUST the DATA part of the RID (does not + This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ -#define HFA384x_RID_PORTSTATUS_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTSSID_LEN ((UINT16)34) -#define HFA384x_RID_CURRENTBSSID_LEN ((UINT16)WLAN_BSSID_LEN) -#define HFA384x_RID_COMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_commsquality_t)) -#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((UINT16)sizeof(hfa384x_dbmcommsquality_t)) -#define HFA384x_RID_CURRENTTXRATE_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTBCNINT_LEN ((UINT16)0) -#define HFA384x_RID_STACURSCALETHRESH_LEN ((UINT16)12) -#define HFA384x_RID_APCURSCALETHRESH_LEN ((UINT16)6) -#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((UINT16)0) -#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((UINT16)0) -#define HFA384x_RID_LONGRETRYLIMIT_LEN ((UINT16)0) -#define HFA384x_RID_MAXTXLIFETIME_LEN ((UINT16)0) -#define HFA384x_RID_MAXRXLIFETIME_LEN ((UINT16)0) -#define HFA384x_RID_CFPOLLABLE_LEN ((UINT16)0) -#define HFA384x_RID_AUTHALGORITHMS_LEN ((UINT16)4) -#define HFA384x_RID_PRIVACYOPTIMP_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTTXRATE1_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTTXRATE2_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTTXRATE3_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTTXRATE4_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTTXRATE5_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTTXRATE6_LEN ((UINT16)0) -#define HFA384x_RID_OWNMACADDRESS_LEN ((UINT16)6) -#define HFA384x_RID_PCFINFO_LEN ((UINT16)6) -#define HFA384x_RID_CNFAPPCFINFO_LEN ((UINT16)sizeof(hfa384x_PCFInfo_data_t)) -#define HFA384x_RID_SCANREQUEST_LEN ((UINT16)sizeof(hfa384x_ScanRequest_data_t)) -#define HFA384x_RID_JOINREQUEST_LEN ((UINT16)sizeof(hfa384x_JoinRequest_data_t)) -#define HFA384x_RID_AUTHENTICATESTA_LEN ((UINT16)sizeof(hfa384x_authenticateStation_data_t)) -#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((UINT16)sizeof(hfa384x_ChannelInfoRequest_data_t)) +#define HFA384x_RID_PORTSTATUS_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTSSID_LEN ((uint16_t)34) +#define HFA384x_RID_CURRENTBSSID_LEN ((uint16_t)WLAN_BSSID_LEN) +#define HFA384x_RID_COMMSQUALITY_LEN ((uint16_t)sizeof(hfa384x_commsquality_t)) +#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((uint16_t)sizeof(hfa384x_dbmcommsquality_t)) +#define HFA384x_RID_CURRENTTXRATE_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTBCNINT_LEN ((uint16_t)0) +#define HFA384x_RID_STACURSCALETHRESH_LEN ((uint16_t)12) +#define HFA384x_RID_APCURSCALETHRESH_LEN ((uint16_t)6) +#define HFA384x_RID_PROTOCOLRSPTIME_LEN ((uint16_t)0) +#define HFA384x_RID_SHORTRETRYLIMIT_LEN ((uint16_t)0) +#define HFA384x_RID_LONGRETRYLIMIT_LEN ((uint16_t)0) +#define HFA384x_RID_MAXTXLIFETIME_LEN ((uint16_t)0) +#define HFA384x_RID_MAXRXLIFETIME_LEN ((uint16_t)0) +#define HFA384x_RID_CFPOLLABLE_LEN ((uint16_t)0) +#define HFA384x_RID_AUTHALGORITHMS_LEN ((uint16_t)4) +#define HFA384x_RID_PRIVACYOPTIMP_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTTXRATE1_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTTXRATE2_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTTXRATE3_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTTXRATE4_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTTXRATE5_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTTXRATE6_LEN ((uint16_t)0) +#define HFA384x_RID_OWNMACADDRESS_LEN ((uint16_t)6) +#define HFA384x_RID_PCFINFO_LEN ((uint16_t)6) +#define HFA384x_RID_CNFAPPCFINFO_LEN ((uint16_t)sizeof(hfa384x_PCFInfo_data_t)) +#define HFA384x_RID_SCANREQUEST_LEN ((uint16_t)sizeof(hfa384x_ScanRequest_data_t)) +#define HFA384x_RID_JOINREQUEST_LEN ((uint16_t)sizeof(hfa384x_JoinRequest_data_t)) +#define HFA384x_RID_AUTHENTICATESTA_LEN ((uint16_t)sizeof(hfa384x_authenticateStation_data_t)) +#define HFA384x_RID_CHANNELINFOREQUEST_LEN ((uint16_t)sizeof(hfa384x_ChannelInfoRequest_data_t)) /*-------------------------------------------------------------------- Information RIDs: Modem Information --------------------------------------------------------------------*/ -#define HFA384x_RID_PHYTYPE ((UINT16)0xFDC0) -#define HFA384x_RID_CURRENTCHANNEL ((UINT16)0xFDC1) -#define HFA384x_RID_CURRENTPOWERSTATE ((UINT16)0xFDC2) -#define HFA384x_RID_CCAMODE ((UINT16)0xFDC3) -#define HFA384x_RID_SUPPORTEDDATARATES ((UINT16)0xFDC6) -#define HFA384x_RID_LFOSTATUS ((UINT16)0xFDC7) // 1.7.1 +#define HFA384x_RID_PHYTYPE ((uint16_t)0xFDC0) +#define HFA384x_RID_CURRENTCHANNEL ((uint16_t)0xFDC1) +#define HFA384x_RID_CURRENTPOWERSTATE ((uint16_t)0xFDC2) +#define HFA384x_RID_CCAMODE ((uint16_t)0xFDC3) +#define HFA384x_RID_SUPPORTEDDATARATES ((uint16_t)0xFDC6) +#define HFA384x_RID_LFOSTATUS ((uint16_t)0xFDC7) // 1.7.1 /*-------------------------------------------------------------------- -Information RID Lengths: Modem Information - This is the length of JUST the DATA part of the RID (does not +Information RID Lengths: Modem Information + This is the length of JUST the DATA part of the RID (does not include the len or code fields) --------------------------------------------------------------------*/ -#define HFA384x_RID_PHYTYPE_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTCHANNEL_LEN ((UINT16)0) -#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((UINT16)0) -#define HFA384x_RID_CCAMODE_LEN ((UINT16)0) -#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((UINT16)10) +#define HFA384x_RID_PHYTYPE_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTCHANNEL_LEN ((uint16_t)0) +#define HFA384x_RID_CURRENTPOWERSTATE_LEN ((uint16_t)0) +#define HFA384x_RID_CCAMODE_LEN ((uint16_t)0) +#define HFA384x_RID_SUPPORTEDDATARATES_LEN ((uint16_t)10) /*-------------------------------------------------------------------- API ENHANCEMENTS (NOT ALREADY IMPLEMENTED) --------------------------------------------------------------------*/ -#define HFA384x_RID_CNFWEPDEFAULTKEYID ((UINT16)0xFC23) -#define HFA384x_RID_CNFWEPDEFAULTKEY0 ((UINT16)0xFC24) -#define HFA384x_RID_CNFWEPDEFAULTKEY1 ((UINT16)0xFC25) -#define HFA384x_RID_CNFWEPDEFAULTKEY2 ((UINT16)0xFC26) -#define HFA384x_RID_CNFWEPDEFAULTKEY3 ((UINT16)0xFC27) -#define HFA384x_RID_CNFWEPFLAGS ((UINT16)0xFC28) -#define HFA384x_RID_CNFWEPKEYMAPTABLE ((UINT16)0xFC29) -#define HFA384x_RID_CNFAUTHENTICATION ((UINT16)0xFC2A) -#define HFA384x_RID_CNFMAXASSOCSTATIONS ((UINT16)0xFC2B) -#define HFA384x_RID_CNFTXCONTROL ((UINT16)0xFC2C) -#define HFA384x_RID_CNFROAMINGMODE ((UINT16)0xFC2D) -#define HFA384x_RID_CNFHOSTAUTHASSOC ((UINT16)0xFC2E) -#define HFA384x_RID_CNFRCVCRCERROR ((UINT16)0xFC30) -// #define HFA384x_RID_CNFMMLIFE ((UINT16)0xFC31) -#define HFA384x_RID_CNFALTRETRYCNT ((UINT16)0xFC32) -#define HFA384x_RID_CNFAPBCNINT ((UINT16)0xFC33) -#define HFA384x_RID_CNFAPPCFINFO ((UINT16)0xFC34) -#define HFA384x_RID_CNFSTAPCFINFO ((UINT16)0xFC35) -#define HFA384x_RID_CNFPRIORITYQUSAGE ((UINT16)0xFC37) -#define HFA384x_RID_CNFTIMCTRL ((UINT16)0xFC40) -#define HFA384x_RID_CNFTHIRTY2TALLY ((UINT16)0xFC42) -#define HFA384x_RID_CNFENHSECURITY ((UINT16)0xFC43) -#define HFA384x_RID_CNFDBMADJUST ((UINT16)0xFC46) // NEW -#define HFA384x_RID_CNFWPADATA ((UINT16)0xFC48) // 1.7.0 -#define HFA384x_RID_CNFPROPOGATIONDELAY ((UINT16)0xFC49) // 1.7.6 -#define HFA384x_RID_CNFSHORTPREAMBLE ((UINT16)0xFCB0) -#define HFA384x_RID_CNFEXCLONGPREAMBLE ((UINT16)0xFCB1) -#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((UINT16)0xFCB2) -#define HFA384x_RID_CNFBASICRATES ((UINT16)0xFCB3) -#define HFA384x_RID_CNFSUPPRATES ((UINT16)0xFCB4) -#define HFA384x_RID_CNFFALLBACKCTRL ((UINT16)0xFCB5) // NEW -#define HFA384x_RID_WEPKEYSTATUS ((UINT16)0xFCB6) // NEW -#define HFA384x_RID_WEPKEYMAPINDEX ((UINT16)0xFCB7) // NEW -#define HFA384x_RID_BROADCASTKEYID ((UINT16)0xFCB8) // NEW -#define HFA384x_RID_ENTSECFLAGEYID ((UINT16)0xFCB9) // NEW -#define HFA384x_RID_CNFPASSIVESCANCTRL ((UINT16)0xFCBA) // NEW STA -#define HFA384x_RID_CNFWPAHANDLING ((UINT16)0xFCBB) // 1.7.0 -#define HFA384x_RID_MDCCONTROL ((UINT16)0xFCBC) // 1.7.0/1.4.0 -#define HFA384x_RID_MDCCOUNTRY ((UINT16)0xFCBD) // 1.7.0/1.4.0 -#define HFA384x_RID_TXPOWERMAX ((UINT16)0xFCBE) // 1.7.0/1.4.0 -#define HFA384x_RID_CNFLFOENBLED ((UINT16)0xFCBF) // 1.6.3 -#define HFA384x_RID_CAPINFO ((UINT16)0xFCC0) // 1.7.0/1.3.7 -#define HFA384x_RID_LISTENINTERVAL ((UINT16)0xFCC1) // 1.7.0/1.3.7 -#define HFA384x_RID_DIVERSITYENABLED ((UINT16)0xFCC2) // 1.7.0/1.3.7 -#define HFA384x_RID_LED_CONTROL ((UINT16)0xFCC4) // 1.7.6 -#define HFA384x_RID_HFO_DELAY ((UINT16)0xFCC5) // 1.7.6 -#define HFA384x_RID_DISSALOWEDBSSID ((UINT16)0xFCC6) // 1.8.0 -#define HFA384x_RID_SCANREQUEST ((UINT16)0xFCE1) -#define HFA384x_RID_JOINREQUEST ((UINT16)0xFCE2) -#define HFA384x_RID_AUTHENTICATESTA ((UINT16)0xFCE3) -#define HFA384x_RID_CHANNELINFOREQUEST ((UINT16)0xFCE4) -#define HFA384x_RID_HOSTSCAN ((UINT16)0xFCE5) // NEW STA -#define HFA384x_RID_ASSOCIATESTA ((UINT16)0xFCE6) +#define HFA384x_RID_CNFWEPDEFAULTKEYID ((uint16_t)0xFC23) +#define HFA384x_RID_CNFWEPDEFAULTKEY0 ((uint16_t)0xFC24) +#define HFA384x_RID_CNFWEPDEFAULTKEY1 ((uint16_t)0xFC25) +#define HFA384x_RID_CNFWEPDEFAULTKEY2 ((uint16_t)0xFC26) +#define HFA384x_RID_CNFWEPDEFAULTKEY3 ((uint16_t)0xFC27) +#define HFA384x_RID_CNFWEPFLAGS ((uint16_t)0xFC28) +#define HFA384x_RID_CNFWEPKEYMAPTABLE ((uint16_t)0xFC29) +#define HFA384x_RID_CNFAUTHENTICATION ((uint16_t)0xFC2A) +#define HFA384x_RID_CNFMAXASSOCSTATIONS ((uint16_t)0xFC2B) +#define HFA384x_RID_CNFTXCONTROL ((uint16_t)0xFC2C) +#define HFA384x_RID_CNFROAMINGMODE ((uint16_t)0xFC2D) +#define HFA384x_RID_CNFHOSTAUTHASSOC ((uint16_t)0xFC2E) +#define HFA384x_RID_CNFRCVCRCERROR ((uint16_t)0xFC30) +// #define HFA384x_RID_CNFMMLIFE ((uint16_t)0xFC31) +#define HFA384x_RID_CNFALTRETRYCNT ((uint16_t)0xFC32) +#define HFA384x_RID_CNFAPBCNint ((uint16_t)0xFC33) +#define HFA384x_RID_CNFAPPCFINFO ((uint16_t)0xFC34) +#define HFA384x_RID_CNFSTAPCFINFO ((uint16_t)0xFC35) +#define HFA384x_RID_CNFPRIORITYQUSAGE ((uint16_t)0xFC37) +#define HFA384x_RID_CNFTIMCTRL ((uint16_t)0xFC40) +#define HFA384x_RID_CNFTHIRTY2TALLY ((uint16_t)0xFC42) +#define HFA384x_RID_CNFENHSECURITY ((uint16_t)0xFC43) +#define HFA384x_RID_CNFDBMADJUST ((uint16_t)0xFC46) // NEW +#define HFA384x_RID_CNFWPADATA ((uint16_t)0xFC48) // 1.7.0 +#define HFA384x_RID_CNFPROPOGATIONDELAY ((uint16_t)0xFC49) // 1.7.6 +#define HFA384x_RID_CNFSHORTPREAMBLE ((uint16_t)0xFCB0) +#define HFA384x_RID_CNFEXCLONGPREAMBLE ((uint16_t)0xFCB1) +#define HFA384x_RID_CNFAUTHRSPTIMEOUT ((uint16_t)0xFCB2) +#define HFA384x_RID_CNFBASICRATES ((uint16_t)0xFCB3) +#define HFA384x_RID_CNFSUPPRATES ((uint16_t)0xFCB4) +#define HFA384x_RID_CNFFALLBACKCTRL ((uint16_t)0xFCB5) // NEW +#define HFA384x_RID_WEPKEYSTATUS ((uint16_t)0xFCB6) // NEW +#define HFA384x_RID_WEPKEYMAPINDEX ((uint16_t)0xFCB7) // NEW +#define HFA384x_RID_BROADCASTKEYID ((uint16_t)0xFCB8) // NEW +#define HFA384x_RID_ENTSECFLAGEYID ((uint16_t)0xFCB9) // NEW +#define HFA384x_RID_CNFPASSIVESCANCTRL ((uint16_t)0xFCBA) // NEW STA +#define HFA384x_RID_CNFWPAHANDLING ((uint16_t)0xFCBB) // 1.7.0 +#define HFA384x_RID_MDCCONTROL ((uint16_t)0xFCBC) // 1.7.0/1.4.0 +#define HFA384x_RID_MDCCOUNTRY ((uint16_t)0xFCBD) // 1.7.0/1.4.0 +#define HFA384x_RID_TXPOWERMAX ((uint16_t)0xFCBE) // 1.7.0/1.4.0 +#define HFA384x_RID_CNFLFOENBLED ((uint16_t)0xFCBF) // 1.6.3 +#define HFA384x_RID_CAPINFO ((uint16_t)0xFCC0) // 1.7.0/1.3.7 +#define HFA384x_RID_LISTENINTERVAL ((uint16_t)0xFCC1) // 1.7.0/1.3.7 +#define HFA384x_RID_DIVERSITYENABLED ((uint16_t)0xFCC2) // 1.7.0/1.3.7 +#define HFA384x_RID_LED_CONTROL ((uint16_t)0xFCC4) // 1.7.6 +#define HFA384x_RID_HFO_DELAY ((uint16_t)0xFCC5) // 1.7.6 +#define HFA384x_RID_DISSALOWEDBSSID ((uint16_t)0xFCC6) // 1.8.0 +#define HFA384x_RID_SCANREQUEST ((uint16_t)0xFCE1) +#define HFA384x_RID_JOINREQUEST ((uint16_t)0xFCE2) +#define HFA384x_RID_AUTHENTICATESTA ((uint16_t)0xFCE3) +#define HFA384x_RID_CHANNELINFOREQUEST ((uint16_t)0xFCE4) +#define HFA384x_RID_HOSTSCAN ((uint16_t)0xFCE5) // NEW STA +#define HFA384x_RID_ASSOCIATESTA ((uint16_t)0xFCE6) -#define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((UINT16)6) -#define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((UINT16)14) -#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((UINT16)4) +#define HFA384x_RID_CNFWEPDEFAULTKEY_LEN ((uint16_t)6) +#define HFA384x_RID_CNFWEP128DEFAULTKEY_LEN ((uint16_t)14) +#define HFA384x_RID_CNFPRIOQUSAGE_LEN ((uint16_t)4) /*-------------------------------------------------------------------- PD Record codes --------------------------------------------------------------------*/ -#define HFA384x_PDR_PCB_PARTNUM ((UINT16)0x0001) -#define HFA384x_PDR_PDAVER ((UINT16)0x0002) -#define HFA384x_PDR_NIC_SERIAL ((UINT16)0x0003) -#define HFA384x_PDR_MKK_MEASUREMENTS ((UINT16)0x0004) -#define HFA384x_PDR_NIC_RAMSIZE ((UINT16)0x0005) -#define HFA384x_PDR_MFISUPRANGE ((UINT16)0x0006) -#define HFA384x_PDR_CFISUPRANGE ((UINT16)0x0007) -#define HFA384x_PDR_NICID ((UINT16)0x0008) -//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((UINT16)0x0010) -//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((UINT16)0x0020) -//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((UINT16)0x0030) -//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((UINT16)0x0040) -//#define HFA384x_PDR_COREGA_HACK ((UINT16)0x00ff) -#define HFA384x_PDR_MAC_ADDRESS ((UINT16)0x0101) -//#define HFA384x_PDR_MKK_CALLNAME ((UINT16)0x0102) -#define HFA384x_PDR_REGDOMAIN ((UINT16)0x0103) -#define HFA384x_PDR_ALLOWED_CHANNEL ((UINT16)0x0104) -#define HFA384x_PDR_DEFAULT_CHANNEL ((UINT16)0x0105) -//#define HFA384x_PDR_PRIVACY_OPTION ((UINT16)0x0106) -#define HFA384x_PDR_TEMPTYPE ((UINT16)0x0107) -//#define HFA384x_PDR_REFDAC_SETUP ((UINT16)0x0110) -//#define HFA384x_PDR_VGDAC_SETUP ((UINT16)0x0120) -//#define HFA384x_PDR_LEVEL_COMP_SETUP ((UINT16)0x0130) -//#define HFA384x_PDR_TRIMDAC_SETUP ((UINT16)0x0140) -#define HFA384x_PDR_IFR_SETTING ((UINT16)0x0200) -#define HFA384x_PDR_RFR_SETTING ((UINT16)0x0201) -#define HFA384x_PDR_HFA3861_BASELINE ((UINT16)0x0202) -#define HFA384x_PDR_HFA3861_SHADOW ((UINT16)0x0203) -#define HFA384x_PDR_HFA3861_IFRF ((UINT16)0x0204) -#define HFA384x_PDR_HFA3861_CHCALSP ((UINT16)0x0300) -#define HFA384x_PDR_HFA3861_CHCALI ((UINT16)0x0301) -#define HFA384x_PDR_MAX_TX_POWER ((UINT16)0x0302) -#define HFA384x_PDR_MASTER_CHAN_LIST ((UINT16)0x0303) -#define HFA384x_PDR_3842_NIC_CONFIG ((UINT16)0x0400) -#define HFA384x_PDR_USB_ID ((UINT16)0x0401) -#define HFA384x_PDR_PCI_ID ((UINT16)0x0402) -#define HFA384x_PDR_PCI_IFCONF ((UINT16)0x0403) -#define HFA384x_PDR_PCI_PMCONF ((UINT16)0x0404) -#define HFA384x_PDR_RFENRGY ((UINT16)0x0406) -#define HFA384x_PDR_USB_POWER_TYPE ((UINT16)0x0407) -//#define HFA384x_PDR_UNKNOWN408 ((UINT16)0x0408) -#define HFA384x_PDR_USB_MAX_POWER ((UINT16)0x0409) -#define HFA384x_PDR_USB_MANUFACTURER ((UINT16)0x0410) -#define HFA384x_PDR_USB_PRODUCT ((UINT16)0x0411) -#define HFA384x_PDR_ANT_DIVERSITY ((UINT16)0x0412) -#define HFA384x_PDR_HFO_DELAY ((UINT16)0x0413) -#define HFA384x_PDR_SCALE_THRESH ((UINT16)0x0414) +#define HFA384x_PDR_PCB_PARTNUM ((uint16_t)0x0001) +#define HFA384x_PDR_PDAVER ((uint16_t)0x0002) +#define HFA384x_PDR_NIC_SERIAL ((uint16_t)0x0003) +#define HFA384x_PDR_MKK_MEASUREMENTS ((uint16_t)0x0004) +#define HFA384x_PDR_NIC_RAMSIZE ((uint16_t)0x0005) +#define HFA384x_PDR_MFISUPRANGE ((uint16_t)0x0006) +#define HFA384x_PDR_CFISUPRANGE ((uint16_t)0x0007) +#define HFA384x_PDR_NICID ((uint16_t)0x0008) +//#define HFA384x_PDR_REFDAC_MEASUREMENTS ((uint16_t)0x0010) +//#define HFA384x_PDR_VGDAC_MEASUREMENTS ((uint16_t)0x0020) +//#define HFA384x_PDR_LEVEL_COMP_MEASUREMENTS ((uint16_t)0x0030) +//#define HFA384x_PDR_MODEM_TRIMDAC_MEASUREMENTS ((uint16_t)0x0040) +//#define HFA384x_PDR_COREGA_HACK ((uint16_t)0x00ff) +#define HFA384x_PDR_MAC_ADDRESS ((uint16_t)0x0101) +//#define HFA384x_PDR_MKK_CALLNAME ((uint16_t)0x0102) +#define HFA384x_PDR_REGDOMAIN ((uint16_t)0x0103) +#define HFA384x_PDR_ALLOWED_CHANNEL ((uint16_t)0x0104) +#define HFA384x_PDR_DEFAULT_CHANNEL ((uint16_t)0x0105) +//#define HFA384x_PDR_PRIVACY_OPTION ((uint16_t)0x0106) +#define HFA384x_PDR_TEMPTYPE ((uint16_t)0x0107) +//#define HFA384x_PDR_REFDAC_SETUP ((uint16_t)0x0110) +//#define HFA384x_PDR_VGDAC_SETUP ((uint16_t)0x0120) +//#define HFA384x_PDR_LEVEL_COMP_SETUP ((uint16_t)0x0130) +//#define HFA384x_PDR_TRIMDAC_SETUP ((uint16_t)0x0140) +#define HFA384x_PDR_IFR_SETTING ((uint16_t)0x0200) +#define HFA384x_PDR_RFR_SETTING ((uint16_t)0x0201) +#define HFA384x_PDR_HFA3861_BASELINE ((uint16_t)0x0202) +#define HFA384x_PDR_HFA3861_SHADOW ((uint16_t)0x0203) +#define HFA384x_PDR_HFA3861_IFRF ((uint16_t)0x0204) +#define HFA384x_PDR_HFA3861_CHCALSP ((uint16_t)0x0300) +#define HFA384x_PDR_HFA3861_CHCALI ((uint16_t)0x0301) +#define HFA384x_PDR_MAX_TX_POWER ((uint16_t)0x0302) +#define HFA384x_PDR_MASTER_CHAN_LIST ((uint16_t)0x0303) +#define HFA384x_PDR_3842_NIC_CONFIG ((uint16_t)0x0400) +#define HFA384x_PDR_USB_ID ((uint16_t)0x0401) +#define HFA384x_PDR_PCI_ID ((uint16_t)0x0402) +#define HFA384x_PDR_PCI_IFCONF ((uint16_t)0x0403) +#define HFA384x_PDR_PCI_PMCONF ((uint16_t)0x0404) +#define HFA384x_PDR_RFENRGY ((uint16_t)0x0406) +#define HFA384x_PDR_USB_POWER_TYPE ((uint16_t)0x0407) +//#define HFA384x_PDR_UNKNOWN408 ((uint16_t)0x0408) +#define HFA384x_PDR_USB_MAX_POWER ((uint16_t)0x0409) +#define HFA384x_PDR_USB_MANUFACTURER ((uint16_t)0x0410) +#define HFA384x_PDR_USB_PRODUCT ((uint16_t)0x0411) +#define HFA384x_PDR_ANT_DIVERSITY ((uint16_t)0x0412) +#define HFA384x_PDR_HFO_DELAY ((uint16_t)0x0413) +#define HFA384x_PDR_SCALE_THRESH ((uint16_t)0x0414) -#define HFA384x_PDR_HFA3861_MANF_TESTSP ((UINT16)0x0900) -#define HFA384x_PDR_HFA3861_MANF_TESTI ((UINT16)0x0901) -#define HFA384x_PDR_END_OF_PDA ((UINT16)0x0000) +#define HFA384x_PDR_HFA3861_MANF_TESTSP ((uint16_t)0x0900) +#define HFA384x_PDR_HFA3861_MANF_TESTI ((uint16_t)0x0901) +#define HFA384x_PDR_END_OF_PDA ((uint16_t)0x0000) /*=============================================================*/ @@ -819,96 +819,96 @@ PD Record codes /*--- Register Test/Get/Set Field macros ------------------------*/ -#define HFA384x_CMD_ISBUSY(value) ((UINT16)(((UINT16)value) & HFA384x_CMD_BUSY)) -#define HFA384x_CMD_AINFO_GET(value) ((UINT16)(((UINT16)(value) & HFA384x_CMD_AINFO) >> 8)) -#define HFA384x_CMD_AINFO_SET(value) ((UINT16)((UINT16)(value) << 8)) -#define HFA384x_CMD_MACPORT_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_MACPORT))) -#define HFA384x_CMD_MACPORT_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value)) -#define HFA384x_CMD_ISRECL(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_RECL))) -#define HFA384x_CMD_RECL_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET(value)) -#define HFA384x_CMD_QOS_GET(value) ((UINT16((((UINT16)(value))&((UINT16)0x3000)) >> 12)) -#define HFA384x_CMD_QOS_SET(value) ((UINT16)((((UINT16)(value)) << 12) & 0x3000)) -#define HFA384x_CMD_ISWRITE(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_WRITE))) -#define HFA384x_CMD_WRITE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value)) -#define HFA384x_CMD_PROGMODE_GET(value) ((UINT16)(HFA384x_CMD_AINFO_GET((UINT16)(value) & HFA384x_CMD_PROGMODE))) -#define HFA384x_CMD_PROGMODE_SET(value) ((UINT16)HFA384x_CMD_AINFO_SET((UINT16)value)) -#define HFA384x_CMD_CMDCODE_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_CMD_CMDCODE)) -#define HFA384x_CMD_CMDCODE_SET(value) ((UINT16)(value)) +#define HFA384x_CMD_ISBUSY(value) ((uint16_t)(((uint16_t)value) & HFA384x_CMD_BUSY)) +#define HFA384x_CMD_AINFO_GET(value) ((uint16_t)(((uint16_t)(value) & HFA384x_CMD_AINFO) >> 8)) +#define HFA384x_CMD_AINFO_SET(value) ((uint16_t)((uint16_t)(value) << 8)) +#define HFA384x_CMD_MACPORT_GET(value) ((uint16_t)(HFA384x_CMD_AINFO_GET((uint16_t)(value) & HFA384x_CMD_MACPORT))) +#define HFA384x_CMD_MACPORT_SET(value) ((uint16_t)HFA384x_CMD_AINFO_SET(value)) +#define HFA384x_CMD_ISRECL(value) ((uint16_t)(HFA384x_CMD_AINFO_GET((uint16_t)(value) & HFA384x_CMD_RECL))) +#define HFA384x_CMD_RECL_SET(value) ((uint16_t)HFA384x_CMD_AINFO_SET(value)) +#define HFA384x_CMD_QOS_GET(value) ((uint16_t((((uint16_t)(value))&((uint16_t)0x3000)) >> 12)) +#define HFA384x_CMD_QOS_SET(value) ((uint16_t)((((uint16_t)(value)) << 12) & 0x3000)) +#define HFA384x_CMD_ISWRITE(value) ((uint16_t)(HFA384x_CMD_AINFO_GET((uint16_t)(value) & HFA384x_CMD_WRITE))) +#define HFA384x_CMD_WRITE_SET(value) ((uint16_t)HFA384x_CMD_AINFO_SET((uint16_t)value)) +#define HFA384x_CMD_PROGMODE_GET(value) ((uint16_t)(HFA384x_CMD_AINFO_GET((uint16_t)(value) & HFA384x_CMD_PROGMODE))) +#define HFA384x_CMD_PROGMODE_SET(value) ((uint16_t)HFA384x_CMD_AINFO_SET((uint16_t)value)) +#define HFA384x_CMD_CMDCODE_GET(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_CMD_CMDCODE)) +#define HFA384x_CMD_CMDCODE_SET(value) ((uint16_t)(value)) -#define HFA384x_STATUS_RESULT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_STATUS_RESULT) >> 8)) -#define HFA384x_STATUS_RESULT_SET(value) (((UINT16)(value)) << 8) -#define HFA384x_STATUS_CMDCODE_GET(value) (((UINT16)(value)) & HFA384x_STATUS_CMDCODE) -#define HFA384x_STATUS_CMDCODE_SET(value) ((UINT16)(value)) +#define HFA384x_STATUS_RESULT_GET(value) ((uint16_t)((((uint16_t)(value)) & HFA384x_STATUS_RESULT) >> 8)) +#define HFA384x_STATUS_RESULT_SET(value) (((uint16_t)(value)) << 8) +#define HFA384x_STATUS_CMDCODE_GET(value) (((uint16_t)(value)) & HFA384x_STATUS_CMDCODE) +#define HFA384x_STATUS_CMDCODE_SET(value) ((uint16_t)(value)) -#define HFA384x_OFFSET_ISBUSY(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_BUSY)) -#define HFA384x_OFFSET_ISERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_ERR)) -#define HFA384x_OFFSET_DATAOFF_GET(value) ((UINT16)(((UINT16)(value)) & HFA384x_OFFSET_DATAOFF)) -#define HFA384x_OFFSET_DATAOFF_SET(value) ((UINT16)(value)) +#define HFA384x_OFFSET_ISBUSY(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_OFFSET_BUSY)) +#define HFA384x_OFFSET_ISERR(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_OFFSET_ERR)) +#define HFA384x_OFFSET_DATAOFF_GET(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_OFFSET_DATAOFF)) +#define HFA384x_OFFSET_DATAOFF_SET(value) ((uint16_t)(value)) -#define HFA384x_EVSTAT_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TICK)) -#define HFA384x_EVSTAT_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_WTERR)) -#define HFA384x_EVSTAT_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFDROP)) -#define HFA384x_EVSTAT_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_INFO)) -#define HFA384x_EVSTAT_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_DTIM)) -#define HFA384x_EVSTAT_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_CMD)) -#define HFA384x_EVSTAT_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_ALLOC)) -#define HFA384x_EVSTAT_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TXEXC)) -#define HFA384x_EVSTAT_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_TX)) -#define HFA384x_EVSTAT_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVSTAT_RX)) +#define HFA384x_EVSTAT_ISTICK(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_TICK)) +#define HFA384x_EVSTAT_ISWTERR(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_WTERR)) +#define HFA384x_EVSTAT_ISINFDROP(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_INFDROP)) +#define HFA384x_EVSTAT_ISINFO(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_INFO)) +#define HFA384x_EVSTAT_ISDTIM(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_DTIM)) +#define HFA384x_EVSTAT_ISCMD(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_CMD)) +#define HFA384x_EVSTAT_ISALLOC(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_ALLOC)) +#define HFA384x_EVSTAT_ISTXEXC(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_TXEXC)) +#define HFA384x_EVSTAT_ISTX(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_TX)) +#define HFA384x_EVSTAT_ISRX(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVSTAT_RX)) -#define HFA384x_EVSTAT_ISBAP_OP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INT_BAP_OP)) +#define HFA384x_EVSTAT_ISBAP_OP(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INT_BAP_OP)) -#define HFA384x_INTEN_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TICK)) -#define HFA384x_INTEN_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15)) -#define HFA384x_INTEN_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_WTERR)) -#define HFA384x_INTEN_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14)) -#define HFA384x_INTEN_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFDROP)) -#define HFA384x_INTEN_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13)) -#define HFA384x_INTEN_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_INFO)) -#define HFA384x_INTEN_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7)) -#define HFA384x_INTEN_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_DTIM)) -#define HFA384x_INTEN_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5)) -#define HFA384x_INTEN_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_CMD)) -#define HFA384x_INTEN_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4)) -#define HFA384x_INTEN_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_ALLOC)) -#define HFA384x_INTEN_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3)) -#define HFA384x_INTEN_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TXEXC)) -#define HFA384x_INTEN_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2)) -#define HFA384x_INTEN_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_TX)) -#define HFA384x_INTEN_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1)) -#define HFA384x_INTEN_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_INTEN_RX)) -#define HFA384x_INTEN_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0)) +#define HFA384x_INTEN_ISTICK(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_TICK)) +#define HFA384x_INTEN_TICK_SET(value) ((uint16_t)(((uint16_t)(value)) << 15)) +#define HFA384x_INTEN_ISWTERR(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_WTERR)) +#define HFA384x_INTEN_WTERR_SET(value) ((uint16_t)(((uint16_t)(value)) << 14)) +#define HFA384x_INTEN_ISINFDROP(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_INFDROP)) +#define HFA384x_INTEN_INFDROP_SET(value) ((uint16_t)(((uint16_t)(value)) << 13)) +#define HFA384x_INTEN_ISINFO(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_INFO)) +#define HFA384x_INTEN_INFO_SET(value) ((uint16_t)(((uint16_t)(value)) << 7)) +#define HFA384x_INTEN_ISDTIM(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_DTIM)) +#define HFA384x_INTEN_DTIM_SET(value) ((uint16_t)(((uint16_t)(value)) << 5)) +#define HFA384x_INTEN_ISCMD(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_CMD)) +#define HFA384x_INTEN_CMD_SET(value) ((uint16_t)(((uint16_t)(value)) << 4)) +#define HFA384x_INTEN_ISALLOC(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_ALLOC)) +#define HFA384x_INTEN_ALLOC_SET(value) ((uint16_t)(((uint16_t)(value)) << 3)) +#define HFA384x_INTEN_ISTXEXC(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_TXEXC)) +#define HFA384x_INTEN_TXEXC_SET(value) ((uint16_t)(((uint16_t)(value)) << 2)) +#define HFA384x_INTEN_ISTX(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_TX)) +#define HFA384x_INTEN_TX_SET(value) ((uint16_t)(((uint16_t)(value)) << 1)) +#define HFA384x_INTEN_ISRX(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_INTEN_RX)) +#define HFA384x_INTEN_RX_SET(value) ((uint16_t)(((uint16_t)(value)) << 0)) -#define HFA384x_EVACK_ISTICK(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TICK)) -#define HFA384x_EVACK_TICK_SET(value) ((UINT16)(((UINT16)(value)) << 15)) -#define HFA384x_EVACK_ISWTERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_WTERR)) -#define HFA384x_EVACK_WTERR_SET(value) ((UINT16)(((UINT16)(value)) << 14)) -#define HFA384x_EVACK_ISINFDROP(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFDROP)) -#define HFA384x_EVACK_INFDROP_SET(value) ((UINT16)(((UINT16)(value)) << 13)) -#define HFA384x_EVACK_ISINFO(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_INFO)) -#define HFA384x_EVACK_INFO_SET(value) ((UINT16)(((UINT16)(value)) << 7)) -#define HFA384x_EVACK_ISDTIM(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_DTIM)) -#define HFA384x_EVACK_DTIM_SET(value) ((UINT16)(((UINT16)(value)) << 5)) -#define HFA384x_EVACK_ISCMD(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_CMD)) -#define HFA384x_EVACK_CMD_SET(value) ((UINT16)(((UINT16)(value)) << 4)) -#define HFA384x_EVACK_ISALLOC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_ALLOC)) -#define HFA384x_EVACK_ALLOC_SET(value) ((UINT16)(((UINT16)(value)) << 3)) -#define HFA384x_EVACK_ISTXEXC(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TXEXC)) -#define HFA384x_EVACK_TXEXC_SET(value) ((UINT16)(((UINT16)(value)) << 2)) -#define HFA384x_EVACK_ISTX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_TX)) -#define HFA384x_EVACK_TX_SET(value) ((UINT16)(((UINT16)(value)) << 1)) -#define HFA384x_EVACK_ISRX(value) ((UINT16)(((UINT16)(value)) & HFA384x_EVACK_RX)) -#define HFA384x_EVACK_RX_SET(value) ((UINT16)(((UINT16)(value)) << 0)) +#define HFA384x_EVACK_ISTICK(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_TICK)) +#define HFA384x_EVACK_TICK_SET(value) ((uint16_t)(((uint16_t)(value)) << 15)) +#define HFA384x_EVACK_ISWTERR(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_WTERR)) +#define HFA384x_EVACK_WTERR_SET(value) ((uint16_t)(((uint16_t)(value)) << 14)) +#define HFA384x_EVACK_ISINFDROP(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_INFDROP)) +#define HFA384x_EVACK_INFDROP_SET(value) ((uint16_t)(((uint16_t)(value)) << 13)) +#define HFA384x_EVACK_ISINFO(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_INFO)) +#define HFA384x_EVACK_INFO_SET(value) ((uint16_t)(((uint16_t)(value)) << 7)) +#define HFA384x_EVACK_ISDTIM(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_DTIM)) +#define HFA384x_EVACK_DTIM_SET(value) ((uint16_t)(((uint16_t)(value)) << 5)) +#define HFA384x_EVACK_ISCMD(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_CMD)) +#define HFA384x_EVACK_CMD_SET(value) ((uint16_t)(((uint16_t)(value)) << 4)) +#define HFA384x_EVACK_ISALLOC(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_ALLOC)) +#define HFA384x_EVACK_ALLOC_SET(value) ((uint16_t)(((uint16_t)(value)) << 3)) +#define HFA384x_EVACK_ISTXEXC(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_TXEXC)) +#define HFA384x_EVACK_TXEXC_SET(value) ((uint16_t)(((uint16_t)(value)) << 2)) +#define HFA384x_EVACK_ISTX(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_TX)) +#define HFA384x_EVACK_TX_SET(value) ((uint16_t)(((uint16_t)(value)) << 1)) +#define HFA384x_EVACK_ISRX(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_EVACK_RX)) +#define HFA384x_EVACK_RX_SET(value) ((uint16_t)(((uint16_t)(value)) << 0)) -#define HFA384x_CONTROL_AUXEN_SET(value) ((UINT16)(((UINT16)(value)) << 14)) -#define HFA384x_CONTROL_AUXEN_GET(value) ((UINT16)(((UINT16)(value)) >> 14)) +#define HFA384x_CONTROL_AUXEN_SET(value) ((uint16_t)(((uint16_t)(value)) << 14)) +#define HFA384x_CONTROL_AUXEN_GET(value) ((uint16_t)(((uint16_t)(value)) >> 14)) /* Byte Order */ #ifdef __KERNEL__ -#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n))) -#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n))) -#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n))) -#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n))) +#define hfa384x2host_16(n) (__le16_to_cpu((uint16_t)(n))) +#define hfa384x2host_32(n) (__le32_to_cpu((uint32_t)(n))) +#define host2hfa384x_16(n) (__cpu_to_le16((uint16_t)(n))) +#define host2hfa384x_32(n) (__cpu_to_le32((uint32_t)(n))) #endif /* Host Maintained State Info */ @@ -929,14 +929,14 @@ PD Record codes /* Commonly used basic types */ typedef struct hfa384x_bytestr { - UINT16 len; - UINT8 data[0]; + uint16_t len; + uint8_t data[0]; } __WLAN_ATTRIB_PACK__ hfa384x_bytestr_t; typedef struct hfa384x_bytestr32 { - UINT16 len; - UINT8 data[32]; + uint16_t len; + uint8_t data[32]; } __WLAN_ATTRIB_PACK__ hfa384x_bytestr32_t; /*-------------------------------------------------------------------- @@ -946,114 +946,114 @@ Configuration Record Structures: /* Prototype structure: all configuration record structures start with these members */ -typedef struct hfa384x_record +typedef struct hfa384x_record { - UINT16 reclen; - UINT16 rid; + uint16_t reclen; + uint16_t rid; } __WLAN_ATTRIB_PACK__ hfa384x_rec_t; typedef struct hfa384x_record16 { - UINT16 reclen; - UINT16 rid; - UINT16 val; + uint16_t reclen; + uint16_t rid; + uint16_t val; } __WLAN_ATTRIB_PACK__ hfa384x_rec16_t; typedef struct hfa384x_record32 { - UINT16 reclen; - UINT16 rid; - UINT32 val; + uint16_t reclen; + uint16_t rid; + uint32_t val; } __WLAN_ATTRIB_PACK__ hfa384x_rec32; /*-- Hardware/Firmware Component Information ----------*/ typedef struct hfa384x_compident { - UINT16 id; - UINT16 variant; - UINT16 major; - UINT16 minor; + uint16_t id; + uint16_t variant; + uint16_t major; + uint16_t minor; } __WLAN_ATTRIB_PACK__ hfa384x_compident_t; typedef struct hfa384x_caplevel { - UINT16 role; - UINT16 id; - UINT16 variant; - UINT16 bottom; - UINT16 top; + uint16_t role; + uint16_t id; + uint16_t variant; + uint16_t bottom; + uint16_t top; } __WLAN_ATTRIB_PACK__ hfa384x_caplevel_t; /*-- Configuration Record: cnfPortType --*/ typedef struct hfa384x_cnfPortType { - UINT16 cnfPortType; + uint16_t cnfPortType; } __WLAN_ATTRIB_PACK__ hfa384x_cnfPortType_t; /*-- Configuration Record: cnfOwnMACAddress --*/ typedef struct hfa384x_cnfOwnMACAddress { - UINT8 cnfOwnMACAddress[6]; + uint8_t cnfOwnMACAddress[6]; } __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnMACAddress_t; /*-- Configuration Record: cnfDesiredSSID --*/ typedef struct hfa384x_cnfDesiredSSID { - UINT8 cnfDesiredSSID[34]; + uint8_t cnfDesiredSSID[34]; } __WLAN_ATTRIB_PACK__ hfa384x_cnfDesiredSSID_t; /*-- Configuration Record: cnfOwnChannel --*/ typedef struct hfa384x_cnfOwnChannel { - UINT16 cnfOwnChannel; + uint16_t cnfOwnChannel; } __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnChannel_t; /*-- Configuration Record: cnfOwnSSID --*/ typedef struct hfa384x_cnfOwnSSID { - UINT8 cnfOwnSSID[34]; + uint8_t cnfOwnSSID[34]; } __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnSSID_t; /*-- Configuration Record: cnfOwnATIMWindow --*/ typedef struct hfa384x_cnfOwnATIMWindow { - UINT16 cnfOwnATIMWindow; + uint16_t cnfOwnATIMWindow; } __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnATIMWindow_t; /*-- Configuration Record: cnfSystemScale --*/ typedef struct hfa384x_cnfSystemScale { - UINT16 cnfSystemScale; + uint16_t cnfSystemScale; } __WLAN_ATTRIB_PACK__ hfa384x_cnfSystemScale_t; /*-- Configuration Record: cnfMaxDataLength --*/ typedef struct hfa384x_cnfMaxDataLength { - UINT16 cnfMaxDataLength; + uint16_t cnfMaxDataLength; } __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxDataLength_t; /*-- Configuration Record: cnfWDSAddress --*/ typedef struct hfa384x_cnfWDSAddress { - UINT8 cnfWDSAddress[6]; + uint8_t cnfWDSAddress[6]; } __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddress_t; /*-- Configuration Record: cnfPMEnabled --*/ typedef struct hfa384x_cnfPMEnabled { - UINT16 cnfPMEnabled; + uint16_t cnfPMEnabled; } __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEnabled_t; /*-- Configuration Record: cnfPMEPS --*/ typedef struct hfa384x_cnfPMEPS { - UINT16 cnfPMEPS; + uint16_t cnfPMEPS; } __WLAN_ATTRIB_PACK__ hfa384x_cnfPMEPS_t; /*-- Configuration Record: cnfMulticastReceive --*/ typedef struct hfa384x_cnfMulticastReceive { - UINT16 cnfMulticastReceive; + uint16_t cnfMulticastReceive; } __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastReceive_t; /*-- Configuration Record: cnfAuthentication --*/ @@ -1064,37 +1064,37 @@ typedef struct hfa384x_cnfMulticastReceive /*-- Configuration Record: cnfMaxSleepDuration --*/ typedef struct hfa384x_cnfMaxSleepDuration { - UINT16 cnfMaxSleepDuration; + uint16_t cnfMaxSleepDuration; } __WLAN_ATTRIB_PACK__ hfa384x_cnfMaxSleepDuration_t; /*-- Configuration Record: cnfPMHoldoverDuration --*/ typedef struct hfa384x_cnfPMHoldoverDuration { - UINT16 cnfPMHoldoverDuration; + uint16_t cnfPMHoldoverDuration; } __WLAN_ATTRIB_PACK__ hfa384x_cnfPMHoldoverDuration_t; /*-- Configuration Record: cnfOwnName --*/ typedef struct hfa384x_cnfOwnName { - UINT8 cnfOwnName[34]; + uint8_t cnfOwnName[34]; } __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnName_t; /*-- Configuration Record: cnfOwnDTIMPeriod --*/ typedef struct hfa384x_cnfOwnDTIMPeriod { - UINT16 cnfOwnDTIMPeriod; + uint16_t cnfOwnDTIMPeriod; } __WLAN_ATTRIB_PACK__ hfa384x_cnfOwnDTIMPeriod_t; /*-- Configuration Record: cnfWDSAddress --*/ typedef struct hfa384x_cnfWDSAddressN { - UINT8 cnfWDSAddress[6]; + uint8_t cnfWDSAddress[6]; } __WLAN_ATTRIB_PACK__ hfa384x_cnfWDSAddressN_t; /*-- Configuration Record: cnfMulticastPMBuffering --*/ typedef struct hfa384x_cnfMulticastPMBuffering { - UINT16 cnfMulticastPMBuffering; + uint16_t cnfMulticastPMBuffering; } __WLAN_ATTRIB_PACK__ hfa384x_cnfMulticastPMBuffering_t; /*-------------------------------------------------------------------- @@ -1105,13 +1105,13 @@ Configuration Record Structures: /*-- Configuration Record: GroupAddresses --*/ typedef struct hfa384x_GroupAddresses { - UINT8 MACAddress[16][6]; + uint8_t MACAddress[16][6]; } __WLAN_ATTRIB_PACK__ hfa384x_GroupAddresses_t; /*-- Configuration Record: CreateIBSS --*/ typedef struct hfa384x_CreateIBSS { - UINT16 CreateIBSS; + uint16_t CreateIBSS; } __WLAN_ATTRIB_PACK__ hfa384x_CreateIBSS_t; #define HFA384x_CREATEIBSS_JOINCREATEIBSS 0 @@ -1122,87 +1122,87 @@ typedef struct hfa384x_CreateIBSS /*-- Configuration Record: FragmentationThreshold --*/ typedef struct hfa384x_FragmentationThreshold { - UINT16 FragmentationThreshold; + uint16_t FragmentationThreshold; } __WLAN_ATTRIB_PACK__ hfa384x_FragmentationThreshold_t; /*-- Configuration Record: RTSThreshold --*/ typedef struct hfa384x_RTSThreshold { - UINT16 RTSThreshold; + uint16_t RTSThreshold; } __WLAN_ATTRIB_PACK__ hfa384x_RTSThreshold_t; /*-- Configuration Record: TxRateControl --*/ typedef struct hfa384x_TxRateControl { - UINT16 TxRateControl; + uint16_t TxRateControl; } __WLAN_ATTRIB_PACK__ hfa384x_TxRateControl_t; /*-- Configuration Record: PromiscuousMode --*/ typedef struct hfa384x_PromiscuousMode { - UINT16 PromiscuousMode; + uint16_t PromiscuousMode; } __WLAN_ATTRIB_PACK__ hfa384x_PromiscuousMode_t; /*-- Configuration Record: ScanRequest (data portion only) --*/ typedef struct hfa384x_ScanRequest_data { - UINT16 channelList; - UINT16 txRate; + uint16_t channelList; + uint16_t txRate; } __WLAN_ATTRIB_PACK__ hfa384x_ScanRequest_data_t; /*-- Configuration Record: HostScanRequest (data portion only) --*/ typedef struct hfa384x_HostScanRequest_data { - UINT16 channelList; - UINT16 txRate; + uint16_t channelList; + uint16_t txRate; hfa384x_bytestr32_t ssid; } __WLAN_ATTRIB_PACK__ hfa384x_HostScanRequest_data_t; /*-- Configuration Record: JoinRequest (data portion only) --*/ typedef struct hfa384x_JoinRequest_data { - UINT8 bssid[WLAN_BSSID_LEN]; - UINT16 channel; + uint8_t bssid[WLAN_BSSID_LEN]; + uint16_t channel; } __WLAN_ATTRIB_PACK__ hfa384x_JoinRequest_data_t; /*-- Configuration Record: authenticateStation (data portion only) --*/ typedef struct hfa384x_authenticateStation_data { - UINT8 address[WLAN_ADDR_LEN]; - UINT16 status; - UINT16 algorithm; + uint8_t address[WLAN_ADDR_LEN]; + uint16_t status; + uint16_t algorithm; } __WLAN_ATTRIB_PACK__ hfa384x_authenticateStation_data_t; /*-- Configuration Record: associateStation (data portion only) --*/ typedef struct hfa384x_associateStation_data { - UINT8 address[WLAN_ADDR_LEN]; - UINT16 status; - UINT16 type; + uint8_t address[WLAN_ADDR_LEN]; + uint16_t status; + uint16_t type; } __WLAN_ATTRIB_PACK__ hfa384x_associateStation_data_t; /*-- Configuration Record: ChannelInfoRequest (data portion only) --*/ typedef struct hfa384x_ChannelInfoRequest_data { - UINT16 channelList; - UINT16 channelDwellTime; + uint16_t channelList; + uint16_t channelDwellTime; } __WLAN_ATTRIB_PACK__ hfa384x_ChannelInfoRequest_data_t; /*-- Configuration Record: WEPKeyMapping (data portion only) --*/ typedef struct hfa384x_WEPKeyMapping { - UINT8 address[WLAN_ADDR_LEN]; - UINT16 key_index; - UINT8 key[16]; - UINT8 mic_transmit_key[4]; - UINT8 mic_receive_key[4]; + uint8_t address[WLAN_ADDR_LEN]; + uint16_t key_index; + uint8_t key[16]; + uint8_t mic_transmit_key[4]; + uint8_t mic_receive_key[4]; } __WLAN_ATTRIB_PACK__ hfa384x_WEPKeyMapping_t; /*-- Configuration Record: WPAData (data portion only) --*/ typedef struct hfa384x_WPAData { - UINT16 datalen; - UINT8 data[0]; // max 80 + uint16_t datalen; + uint8_t data[0]; // max 80 } __WLAN_ATTRIB_PACK__ hfa384x_WPAData_t; /*-------------------------------------------------------------------- @@ -1212,7 +1212,7 @@ Configuration Record Structures: Behavior Parameters /*-- Configuration Record: TickTime --*/ typedef struct hfa384x_TickTime { - UINT16 TickTime; + uint16_t TickTime; } __WLAN_ATTRIB_PACK__ hfa384x_TickTime_t; /*-------------------------------------------------------------------- @@ -1222,146 +1222,146 @@ Information Record Structures: NIC Information /*-- Information Record: MaxLoadTime --*/ typedef struct hfa384x_MaxLoadTime { - UINT16 MaxLoadTime; + uint16_t MaxLoadTime; } __WLAN_ATTRIB_PACK__ hfa384x_MaxLoadTime_t; /*-- Information Record: DownLoadBuffer --*/ /* NOTE: The page and offset are in AUX format */ typedef struct hfa384x_downloadbuffer { - UINT16 page; - UINT16 offset; - UINT16 len; + uint16_t page; + uint16_t offset; + uint16_t len; } __WLAN_ATTRIB_PACK__ hfa384x_downloadbuffer_t; /*-- Information Record: PRIIdentity --*/ typedef struct hfa384x_PRIIdentity { - UINT16 PRICompID; - UINT16 PRIVariant; - UINT16 PRIMajorVersion; - UINT16 PRIMinorVersion; + uint16_t PRICompID; + uint16_t PRIVariant; + uint16_t PRIMajorVersion; + uint16_t PRIMinorVersion; } __WLAN_ATTRIB_PACK__ hfa384x_PRIIdentity_t; /*-- Information Record: PRISupRange --*/ typedef struct hfa384x_PRISupRange { - UINT16 PRIRole; - UINT16 PRIID; - UINT16 PRIVariant; - UINT16 PRIBottom; - UINT16 PRITop; + uint16_t PRIRole; + uint16_t PRIID; + uint16_t PRIVariant; + uint16_t PRIBottom; + uint16_t PRITop; } __WLAN_ATTRIB_PACK__ hfa384x_PRISupRange_t; /*-- Information Record: CFIActRanges --*/ typedef struct hfa384x_CFIActRanges { - UINT16 CFIRole; - UINT16 CFIID; - UINT16 CFIVariant; - UINT16 CFIBottom; - UINT16 CFITop; + uint16_t CFIRole; + uint16_t CFIID; + uint16_t CFIVariant; + uint16_t CFIBottom; + uint16_t CFITop; } __WLAN_ATTRIB_PACK__ hfa384x_CFIActRanges_t; /*-- Information Record: NICSerialNumber --*/ typedef struct hfa384x_NICSerialNumber { - UINT8 NICSerialNumber[12]; + uint8_t NICSerialNumber[12]; } __WLAN_ATTRIB_PACK__ hfa384x_NICSerialNumber_t; /*-- Information Record: NICIdentity --*/ typedef struct hfa384x_NICIdentity { - UINT16 NICCompID; - UINT16 NICVariant; - UINT16 NICMajorVersion; - UINT16 NICMinorVersion; + uint16_t NICCompID; + uint16_t NICVariant; + uint16_t NICMajorVersion; + uint16_t NICMinorVersion; } __WLAN_ATTRIB_PACK__ hfa384x_NICIdentity_t; /*-- Information Record: MFISupRange --*/ typedef struct hfa384x_MFISupRange { - UINT16 MFIRole; - UINT16 MFIID; - UINT16 MFIVariant; - UINT16 MFIBottom; - UINT16 MFITop; + uint16_t MFIRole; + uint16_t MFIID; + uint16_t MFIVariant; + uint16_t MFIBottom; + uint16_t MFITop; } __WLAN_ATTRIB_PACK__ hfa384x_MFISupRange_t; /*-- Information Record: CFISupRange --*/ typedef struct hfa384x_CFISupRange { - UINT16 CFIRole; - UINT16 CFIID; - UINT16 CFIVariant; - UINT16 CFIBottom; - UINT16 CFITop; + uint16_t CFIRole; + uint16_t CFIID; + uint16_t CFIVariant; + uint16_t CFIBottom; + uint16_t CFITop; } __WLAN_ATTRIB_PACK__ hfa384x_CFISupRange_t; /*-- Information Record: BUILDSEQ:BuildSeq --*/ typedef struct hfa384x_BuildSeq { - UINT16 primary; - UINT16 secondary; + uint16_t primary; + uint16_t secondary; } __WLAN_ATTRIB_PACK__ hfa384x_BuildSeq_t; /*-- Information Record: FWID --*/ #define HFA384x_FWID_LEN 14 typedef struct hfa384x_FWID { - UINT8 primary[HFA384x_FWID_LEN]; - UINT8 secondary[HFA384x_FWID_LEN]; + uint8_t primary[HFA384x_FWID_LEN]; + uint8_t secondary[HFA384x_FWID_LEN]; } __WLAN_ATTRIB_PACK__ hfa384x_FWID_t; /*-- Information Record: ChannelList --*/ typedef struct hfa384x_ChannelList { - UINT16 ChannelList; + uint16_t ChannelList; } __WLAN_ATTRIB_PACK__ hfa384x_ChannelList_t; /*-- Information Record: RegulatoryDomains --*/ typedef struct hfa384x_RegulatoryDomains { - UINT8 RegulatoryDomains[12]; + uint8_t RegulatoryDomains[12]; } __WLAN_ATTRIB_PACK__ hfa384x_RegulatoryDomains_t; /*-- Information Record: TempType --*/ typedef struct hfa384x_TempType { - UINT16 TempType; + uint16_t TempType; } __WLAN_ATTRIB_PACK__ hfa384x_TempType_t; /*-- Information Record: CIS --*/ typedef struct hfa384x_CIS { - UINT8 CIS[480]; + uint8_t CIS[480]; } __WLAN_ATTRIB_PACK__ hfa384x_CIS_t; /*-- Information Record: STAIdentity --*/ typedef struct hfa384x_STAIdentity { - UINT16 STACompID; - UINT16 STAVariant; - UINT16 STAMajorVersion; - UINT16 STAMinorVersion; + uint16_t STACompID; + uint16_t STAVariant; + uint16_t STAMajorVersion; + uint16_t STAMinorVersion; } __WLAN_ATTRIB_PACK__ hfa384x_STAIdentity_t; /*-- Information Record: STASupRange --*/ typedef struct hfa384x_STASupRange { - UINT16 STARole; - UINT16 STAID; - UINT16 STAVariant; - UINT16 STABottom; - UINT16 STATop; + uint16_t STARole; + uint16_t STAID; + uint16_t STAVariant; + uint16_t STABottom; + uint16_t STATop; } __WLAN_ATTRIB_PACK__ hfa384x_STASupRange_t; /*-- Information Record: MFIActRanges --*/ typedef struct hfa384x_MFIActRanges { - UINT16 MFIRole; - UINT16 MFIID; - UINT16 MFIVariant; - UINT16 MFIBottom; - UINT16 MFITop; + uint16_t MFIRole; + uint16_t MFIID; + uint16_t MFIVariant; + uint16_t MFIBottom; + uint16_t MFITop; } __WLAN_ATTRIB_PACK__ hfa384x_MFIActRanges_t; /*-------------------------------------------------------------------- @@ -1371,187 +1371,187 @@ Information Record Structures: NIC Information /*-- Information Record: PortStatus --*/ typedef struct hfa384x_PortStatus { - UINT16 PortStatus; + uint16_t PortStatus; } __WLAN_ATTRIB_PACK__ hfa384x_PortStatus_t; -#define HFA384x_PSTATUS_DISABLED ((UINT16)1) -#define HFA384x_PSTATUS_SEARCHING ((UINT16)2) -#define HFA384x_PSTATUS_CONN_IBSS ((UINT16)3) -#define HFA384x_PSTATUS_CONN_ESS ((UINT16)4) -#define HFA384x_PSTATUS_OUTOFRANGE ((UINT16)5) -#define HFA384x_PSTATUS_CONN_WDS ((UINT16)6) +#define HFA384x_PSTATUS_DISABLED ((uint16_t)1) +#define HFA384x_PSTATUS_SEARCHING ((uint16_t)2) +#define HFA384x_PSTATUS_CONN_IBSS ((uint16_t)3) +#define HFA384x_PSTATUS_CONN_ESS ((uint16_t)4) +#define HFA384x_PSTATUS_OUTOFRANGE ((uint16_t)5) +#define HFA384x_PSTATUS_CONN_WDS ((uint16_t)6) /*-- Information Record: CurrentSSID --*/ typedef struct hfa384x_CurrentSSID { - UINT8 CurrentSSID[34]; + uint8_t CurrentSSID[34]; } __WLAN_ATTRIB_PACK__ hfa384x_CurrentSSID_t; /*-- Information Record: CurrentBSSID --*/ typedef struct hfa384x_CurrentBSSID { - UINT8 CurrentBSSID[6]; + uint8_t CurrentBSSID[6]; } __WLAN_ATTRIB_PACK__ hfa384x_CurrentBSSID_t; /*-- Information Record: commsquality --*/ typedef struct hfa384x_commsquality { - UINT16 CQ_currBSS; - UINT16 ASL_currBSS; - UINT16 ANL_currFC; + uint16_t CQ_currBSS; + uint16_t ASL_currBSS; + uint16_t ANL_currFC; } __WLAN_ATTRIB_PACK__ hfa384x_commsquality_t; /*-- Information Record: dmbcommsquality --*/ typedef struct hfa384x_dbmcommsquality { - UINT16 CQdbm_currBSS; - UINT16 ASLdbm_currBSS; - UINT16 ANLdbm_currFC; + uint16_t CQdbm_currBSS; + uint16_t ASLdbm_currBSS; + uint16_t ANLdbm_currFC; } __WLAN_ATTRIB_PACK__ hfa384x_dbmcommsquality_t; /*-- Information Record: CurrentTxRate --*/ typedef struct hfa384x_CurrentTxRate { - UINT16 CurrentTxRate; + uint16_t CurrentTxRate; } __WLAN_ATTRIB_PACK__ hfa384x_CurrentTxRate_t; /*-- Information Record: CurrentBeaconInterval --*/ typedef struct hfa384x_CurrentBeaconInterval { - UINT16 CurrentBeaconInterval; + uint16_t CurrentBeaconInterval; } __WLAN_ATTRIB_PACK__ hfa384x_CurrentBeaconInterval_t; /*-- Information Record: CurrentScaleThresholds --*/ typedef struct hfa384x_CurrentScaleThresholds { - UINT16 EnergyDetectThreshold; - UINT16 CarrierDetectThreshold; - UINT16 DeferDetectThreshold; - UINT16 CellSearchThreshold; /* Stations only */ - UINT16 DeadSpotThreshold; /* Stations only */ + uint16_t EnergyDetectThreshold; + uint16_t CarrierDetectThreshold; + uint16_t DeferDetectThreshold; + uint16_t CellSearchThreshold; /* Stations only */ + uint16_t DeadSpotThreshold; /* Stations only */ } __WLAN_ATTRIB_PACK__ hfa384x_CurrentScaleThresholds_t; /*-- Information Record: ProtocolRspTime --*/ typedef struct hfa384x_ProtocolRspTime { - UINT16 ProtocolRspTime; + uint16_t ProtocolRspTime; } __WLAN_ATTRIB_PACK__ hfa384x_ProtocolRspTime_t; /*-- Information Record: ShortRetryLimit --*/ typedef struct hfa384x_ShortRetryLimit { - UINT16 ShortRetryLimit; + uint16_t ShortRetryLimit; } __WLAN_ATTRIB_PACK__ hfa384x_ShortRetryLimit_t; /*-- Information Record: LongRetryLimit --*/ typedef struct hfa384x_LongRetryLimit { - UINT16 LongRetryLimit; + uint16_t LongRetryLimit; } __WLAN_ATTRIB_PACK__ hfa384x_LongRetryLimit_t; /*-- Information Record: MaxTransmitLifetime --*/ typedef struct hfa384x_MaxTransmitLifetime { - UINT16 MaxTransmitLifetime; + uint16_t MaxTransmitLifetime; } __WLAN_ATTRIB_PACK__ hfa384x_MaxTransmitLifetime_t; /*-- Information Record: MaxReceiveLifetime --*/ typedef struct hfa384x_MaxReceiveLifetime { - UINT16 MaxReceiveLifetime; + uint16_t MaxReceiveLifetime; } __WLAN_ATTRIB_PACK__ hfa384x_MaxReceiveLifetime_t; /*-- Information Record: CFPollable --*/ typedef struct hfa384x_CFPollable { - UINT16 CFPollable; + uint16_t CFPollable; } __WLAN_ATTRIB_PACK__ hfa384x_CFPollable_t; /*-- Information Record: AuthenticationAlgorithms --*/ typedef struct hfa384x_AuthenticationAlgorithms { - UINT16 AuthenticationType; - UINT16 TypeEnabled; + uint16_t AuthenticationType; + uint16_t TypeEnabled; } __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_t; /*-- Information Record: AuthenticationAlgorithms (data only --*/ typedef struct hfa384x_AuthenticationAlgorithms_data { - UINT16 AuthenticationType; - UINT16 TypeEnabled; + uint16_t AuthenticationType; + uint16_t TypeEnabled; } __WLAN_ATTRIB_PACK__ hfa384x_AuthenticationAlgorithms_data_t; /*-- Information Record: PrivacyOptionImplemented --*/ typedef struct hfa384x_PrivacyOptionImplemented { - UINT16 PrivacyOptionImplemented; + uint16_t PrivacyOptionImplemented; } __WLAN_ATTRIB_PACK__ hfa384x_PrivacyOptionImplemented_t; /*-- Information Record: OwnMACAddress --*/ typedef struct hfa384x_OwnMACAddress { - UINT8 OwnMACAddress[6]; + uint8_t OwnMACAddress[6]; } __WLAN_ATTRIB_PACK__ hfa384x_OwnMACAddress_t; /*-- Information Record: PCFInfo --*/ typedef struct hfa384x_PCFInfo { - UINT16 MediumOccupancyLimit; - UINT16 CFPPeriod; - UINT16 CFPMaxDuration; - UINT16 CFPFlags; + uint16_t MediumOccupancyLimit; + uint16_t CFPPeriod; + uint16_t CFPMaxDuration; + uint16_t CFPFlags; } __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_t; /*-- Information Record: PCFInfo (data portion only) --*/ typedef struct hfa384x_PCFInfo_data { - UINT16 MediumOccupancyLimit; - UINT16 CFPPeriod; - UINT16 CFPMaxDuration; - UINT16 CFPFlags; + uint16_t MediumOccupancyLimit; + uint16_t CFPPeriod; + uint16_t CFPMaxDuration; + uint16_t CFPFlags; } __WLAN_ATTRIB_PACK__ hfa384x_PCFInfo_data_t; /*-------------------------------------------------------------------- -Information Record Structures: Modem Information Records +Information Record Structures: Modem Information Records --------------------------------------------------------------------*/ /*-- Information Record: PHYType --*/ typedef struct hfa384x_PHYType { - UINT16 PHYType; + uint16_t PHYType; } __WLAN_ATTRIB_PACK__ hfa384x_PHYType_t; /*-- Information Record: CurrentChannel --*/ typedef struct hfa384x_CurrentChannel { - UINT16 CurrentChannel; + uint16_t CurrentChannel; } __WLAN_ATTRIB_PACK__ hfa384x_CurrentChannel_t; /*-- Information Record: CurrentPowerState --*/ typedef struct hfa384x_CurrentPowerState { - UINT16 CurrentPowerState; + uint16_t CurrentPowerState; } __WLAN_ATTRIB_PACK__ hfa384x_CurrentPowerState_t; /*-- Information Record: CCAMode --*/ typedef struct hfa384x_CCAMode { - UINT16 CCAMode; + uint16_t CCAMode; } __WLAN_ATTRIB_PACK__ hfa384x_CCAMode_t; /*-- Information Record: SupportedDataRates --*/ typedef struct hfa384x_SupportedDataRates { - UINT8 SupportedDataRates[10]; + uint8_t SupportedDataRates[10]; } __WLAN_ATTRIB_PACK__ hfa384x_SupportedDataRates_t; /*-- Information Record: LFOStatus --*/ -typedef struct hfa384x_LFOStatus +typedef struct hfa384x_LFOStatus { - UINT16 TestResults; - UINT16 LFOResult; - UINT16 VRHFOResult; + uint16_t TestResults; + uint16_t LFOResult; + uint16_t VRHFOResult; } __WLAN_ATTRIB_PACK__ hfa384x_LFOStatus_t; #define HFA384x_TESTRESULT_ALLPASSED BIT0 @@ -1563,11 +1563,11 @@ typedef struct hfa384x_LFOStatus /*-- Information Record: LEDControl --*/ typedef struct hfa384x_LEDControl { - UINT16 searching_on; - UINT16 searching_off; - UINT16 assoc_on; - UINT16 assoc_off; - UINT16 activity; + uint16_t searching_on; + uint16_t searching_off; + uint16_t assoc_on; + uint16_t assoc_off; + uint16_t activity; } __WLAN_ATTRIB_PACK__ hfa384x_LEDControl_t; /*-------------------------------------------------------------------- @@ -1578,32 +1578,32 @@ FRAME DESCRIPTORS: Offsets ---------------------------------------------------------------------- Control Info (offset 44-51) --------------------------------------------------------------------*/ -#define HFA384x_FD_STATUS_OFF ((UINT16)0x44) -#define HFA384x_FD_TIME_OFF ((UINT16)0x46) -#define HFA384x_FD_SWSUPPORT_OFF ((UINT16)0x4A) -#define HFA384x_FD_SILENCE_OFF ((UINT16)0x4A) -#define HFA384x_FD_SIGNAL_OFF ((UINT16)0x4B) -#define HFA384x_FD_RATE_OFF ((UINT16)0x4C) -#define HFA384x_FD_RXFLOW_OFF ((UINT16)0x4D) -#define HFA384x_FD_RESERVED_OFF ((UINT16)0x4E) -#define HFA384x_FD_TXCONTROL_OFF ((UINT16)0x50) +#define HFA384x_FD_STATUS_OFF ((uint16_t)0x44) +#define HFA384x_FD_TIME_OFF ((uint16_t)0x46) +#define HFA384x_FD_SWSUPPORT_OFF ((uint16_t)0x4A) +#define HFA384x_FD_SILENCE_OFF ((uint16_t)0x4A) +#define HFA384x_FD_SIGNAL_OFF ((uint16_t)0x4B) +#define HFA384x_FD_RATE_OFF ((uint16_t)0x4C) +#define HFA384x_FD_RXFLOW_OFF ((uint16_t)0x4D) +#define HFA384x_FD_RESERVED_OFF ((uint16_t)0x4E) +#define HFA384x_FD_TXCONTROL_OFF ((uint16_t)0x50) /*-------------------------------------------------------------------- 802.11 Header (offset 52-6B) --------------------------------------------------------------------*/ -#define HFA384x_FD_FRAMECONTROL_OFF ((UINT16)0x52) -#define HFA384x_FD_DURATIONID_OFF ((UINT16)0x54) -#define HFA384x_FD_ADDRESS1_OFF ((UINT16)0x56) -#define HFA384x_FD_ADDRESS2_OFF ((UINT16)0x5C) -#define HFA384x_FD_ADDRESS3_OFF ((UINT16)0x62) -#define HFA384x_FD_SEQCONTROL_OFF ((UINT16)0x68) -#define HFA384x_FD_ADDRESS4_OFF ((UINT16)0x6A) -#define HFA384x_FD_DATALEN_OFF ((UINT16)0x70) +#define HFA384x_FD_FRAMECONTROL_OFF ((uint16_t)0x52) +#define HFA384x_FD_DURATIONID_OFF ((uint16_t)0x54) +#define HFA384x_FD_ADDRESS1_OFF ((uint16_t)0x56) +#define HFA384x_FD_ADDRESS2_OFF ((uint16_t)0x5C) +#define HFA384x_FD_ADDRESS3_OFF ((uint16_t)0x62) +#define HFA384x_FD_SEQCONTROL_OFF ((uint16_t)0x68) +#define HFA384x_FD_ADDRESS4_OFF ((uint16_t)0x6A) +#define HFA384x_FD_DATALEN_OFF ((uint16_t)0x70) /*-------------------------------------------------------------------- 802.3 Header (offset 72-7F) --------------------------------------------------------------------*/ -#define HFA384x_FD_DESTADDRESS_OFF ((UINT16)0x72) -#define HFA384x_FD_SRCADDRESS_OFF ((UINT16)0x78) -#define HFA384x_FD_DATALENGTH_OFF ((UINT16)0x7E) +#define HFA384x_FD_DESTADDRESS_OFF ((uint16_t)0x72) +#define HFA384x_FD_SRCADDRESS_OFF ((uint16_t)0x78) +#define HFA384x_FD_DATALENGTH_OFF ((uint16_t)0x7E) /*-------------------------------------------------------------------- FRAME STRUCTURES: Communication Frames @@ -1613,67 +1613,67 @@ Communication Frames: Transmit Frames /*-- Communication Frame: Transmit Frame Structure --*/ typedef struct hfa384x_tx_frame { - UINT16 status; - UINT16 reserved1; - UINT16 reserved2; - UINT32 sw_support; - UINT8 tx_retrycount; - UINT8 tx_rate; - UINT16 tx_control; + uint16_t status; + uint16_t reserved1; + uint16_t reserved2; + uint32_t sw_support; + uint8_t tx_retrycount; + uint8_t tx_rate; + uint16_t tx_control; /*-- 802.11 Header Information --*/ - UINT16 frame_control; - UINT16 duration_id; - UINT8 address1[6]; - UINT8 address2[6]; - UINT8 address3[6]; - UINT16 sequence_control; - UINT8 address4[6]; - UINT16 data_len; /* little endian format */ + uint16_t frame_control; + uint16_t duration_id; + uint8_t address1[6]; + uint8_t address2[6]; + uint8_t address3[6]; + uint16_t sequence_control; + uint8_t address4[6]; + uint16_t data_len; /* little endian format */ /*-- 802.3 Header Information --*/ - UINT8 dest_addr[6]; - UINT8 src_addr[6]; - UINT16 data_length; /* big endian format */ + uint8_t dest_addr[6]; + uint8_t src_addr[6]; + uint16_t data_length; /* big endian format */ } __WLAN_ATTRIB_PACK__ hfa384x_tx_frame_t; /*-------------------------------------------------------------------- Communication Frames: Field Masks for Transmit Frames --------------------------------------------------------------------*/ /*-- Status Field --*/ -#define HFA384x_TXSTATUS_ACKERR ((UINT16)BIT5) -#define HFA384x_TXSTATUS_FORMERR ((UINT16)BIT3) -#define HFA384x_TXSTATUS_DISCON ((UINT16)BIT2) -#define HFA384x_TXSTATUS_AGEDERR ((UINT16)BIT1) -#define HFA384x_TXSTATUS_RETRYERR ((UINT16)BIT0) +#define HFA384x_TXSTATUS_ACKERR ((uint16_t)BIT5) +#define HFA384x_TXSTATUS_FORMERR ((uint16_t)BIT3) +#define HFA384x_TXSTATUS_DISCON ((uint16_t)BIT2) +#define HFA384x_TXSTATUS_AGEDERR ((uint16_t)BIT1) +#define HFA384x_TXSTATUS_RETRYERR ((uint16_t)BIT0) /*-- Transmit Control Field --*/ -#define HFA384x_TX_CFPOLL ((UINT16)BIT12) -#define HFA384x_TX_PRST ((UINT16)BIT11) -#define HFA384x_TX_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) -#define HFA384x_TX_NOENCRYPT ((UINT16)BIT7) -#define HFA384x_TX_RETRYSTRAT ((UINT16)(BIT6 | BIT5)) -#define HFA384x_TX_STRUCTYPE ((UINT16)(BIT4 | BIT3)) -#define HFA384x_TX_TXEX ((UINT16)BIT2) -#define HFA384x_TX_TXOK ((UINT16)BIT1) +#define HFA384x_TX_CFPOLL ((uint16_t)BIT12) +#define HFA384x_TX_PRST ((uint16_t)BIT11) +#define HFA384x_TX_MACPORT ((uint16_t)(BIT10 | BIT9 | BIT8)) +#define HFA384x_TX_NOENCRYPT ((uint16_t)BIT7) +#define HFA384x_TX_RETRYSTRAT ((uint16_t)(BIT6 | BIT5)) +#define HFA384x_TX_STRUCTYPE ((uint16_t)(BIT4 | BIT3)) +#define HFA384x_TX_TXEX ((uint16_t)BIT2) +#define HFA384x_TX_TXOK ((uint16_t)BIT1) /*-------------------------------------------------------------------- Communication Frames: Test/Get/Set Field Values for Transmit Frames --------------------------------------------------------------------*/ /*-- Status Field --*/ #define HFA384x_TXSTATUS_ISERROR(v) \ - (((UINT16)(v))&\ + (((uint16_t)(v))&\ (HFA384x_TXSTATUS_ACKERR|HFA384x_TXSTATUS_FORMERR|\ HFA384x_TXSTATUS_DISCON|HFA384x_TXSTATUS_AGEDERR|\ HFA384x_TXSTATUS_RETRYERR)) -#define HFA384x_TXSTATUS_ISACKERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_ACKERR)) -#define HFA384x_TXSTATUS_ISFORMERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_FORMERR)) -#define HFA384x_TXSTATUS_ISDISCON(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_DISCON)) -#define HFA384x_TXSTATUS_ISAGEDERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_AGEDERR)) -#define HFA384x_TXSTATUS_ISRETRYERR(v) ((UINT16)(((UINT16)(v)) & HFA384x_TXSTATUS_RETRYERR)) +#define HFA384x_TXSTATUS_ISACKERR(v) ((uint16_t)(((uint16_t)(v)) & HFA384x_TXSTATUS_ACKERR)) +#define HFA384x_TXSTATUS_ISFORMERR(v) ((uint16_t)(((uint16_t)(v)) & HFA384x_TXSTATUS_FORMERR)) +#define HFA384x_TXSTATUS_ISDISCON(v) ((uint16_t)(((uint16_t)(v)) & HFA384x_TXSTATUS_DISCON)) +#define HFA384x_TXSTATUS_ISAGEDERR(v) ((uint16_t)(((uint16_t)(v)) & HFA384x_TXSTATUS_AGEDERR)) +#define HFA384x_TXSTATUS_ISRETRYERR(v) ((uint16_t)(((uint16_t)(v)) & HFA384x_TXSTATUS_RETRYERR)) -#define HFA384x_TX_GET(v,m,s) ((((UINT16)(v))&((UINT16)(m)))>>((UINT16)(s))) -#define HFA384x_TX_SET(v,m,s) ((((UINT16)(v))<<((UINT16)(s)))&((UINT16)(m))) +#define HFA384x_TX_GET(v,m,s) ((((uint16_t)(v))&((uint16_t)(m)))>>((uint16_t)(s))) +#define HFA384x_TX_SET(v,m,s) ((((uint16_t)(v))<<((uint16_t)(s)))&((uint16_t)(m))) #define HFA384x_TX_CFPOLL_GET(v) HFA384x_TX_GET(v, HFA384x_TX_CFPOLL,12) #define HFA384x_TX_CFPOLL_SET(v) HFA384x_TX_SET(v, HFA384x_TX_CFPOLL,12) @@ -1698,70 +1698,70 @@ Communication Frames: Receive Frames typedef struct hfa384x_rx_frame { /*-- MAC rx descriptor (hfa384x byte order) --*/ - UINT16 status; - UINT32 time; - UINT8 silence; - UINT8 signal; - UINT8 rate; - UINT8 rx_flow; - UINT16 reserved1; - UINT16 reserved2; + uint16_t status; + uint32_t time; + uint8_t silence; + uint8_t signal; + uint8_t rate; + uint8_t rx_flow; + uint16_t reserved1; + uint16_t reserved2; /*-- 802.11 Header Information (802.11 byte order) --*/ - UINT16 frame_control; - UINT16 duration_id; - UINT8 address1[6]; - UINT8 address2[6]; - UINT8 address3[6]; - UINT16 sequence_control; - UINT8 address4[6]; - UINT16 data_len; /* hfa384x (little endian) format */ + uint16_t frame_control; + uint16_t duration_id; + uint8_t address1[6]; + uint8_t address2[6]; + uint8_t address3[6]; + uint16_t sequence_control; + uint8_t address4[6]; + uint16_t data_len; /* hfa384x (little endian) format */ /*-- 802.3 Header Information --*/ - UINT8 dest_addr[6]; - UINT8 src_addr[6]; - UINT16 data_length; /* IEEE? (big endian) format */ + uint8_t dest_addr[6]; + uint8_t src_addr[6]; + uint16_t data_length; /* IEEE? (big endian) format */ } __WLAN_ATTRIB_PACK__ hfa384x_rx_frame_t; /*-------------------------------------------------------------------- Communication Frames: Field Masks for Receive Frames --------------------------------------------------------------------*/ /*-- Offsets --------*/ -#define HFA384x_RX_DATA_LEN_OFF ((UINT16)44) -#define HFA384x_RX_80211HDR_OFF ((UINT16)14) -#define HFA384x_RX_DATA_OFF ((UINT16)60) +#define HFA384x_RX_DATA_LEN_OFF ((uint16_t)44) +#define HFA384x_RX_80211HDR_OFF ((uint16_t)14) +#define HFA384x_RX_DATA_OFF ((uint16_t)60) /*-- Status Fields --*/ -#define HFA384x_RXSTATUS_MSGTYPE ((UINT16)(BIT15 | BIT14 | BIT13)) -#define HFA384x_RXSTATUS_MACPORT ((UINT16)(BIT10 | BIT9 | BIT8)) -#define HFA384x_RXSTATUS_UNDECR ((UINT16)BIT1) -#define HFA384x_RXSTATUS_FCSERR ((UINT16)BIT0) +#define HFA384x_RXSTATUS_MSGTYPE ((uint16_t)(BIT15 | BIT14 | BIT13)) +#define HFA384x_RXSTATUS_MACPORT ((uint16_t)(BIT10 | BIT9 | BIT8)) +#define HFA384x_RXSTATUS_UNDECR ((uint16_t)BIT1) +#define HFA384x_RXSTATUS_FCSERR ((uint16_t)BIT0) /*-------------------------------------------------------------------- Communication Frames: Test/Get/Set Field Values for Receive Frames --------------------------------------------------------------------*/ -#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13)) -#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((UINT16)(((UINT16)(value)) << 13)) -#define HFA384x_RXSTATUS_MACPORT_GET(value) ((UINT16)((((UINT16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8)) -#define HFA384x_RXSTATUS_MACPORT_SET(value) ((UINT16)(((UINT16)(value)) << 8)) -#define HFA384x_RXSTATUS_ISUNDECR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_UNDECR)) -#define HFA384x_RXSTATUS_ISFCSERR(value) ((UINT16)(((UINT16)(value)) & HFA384x_RXSTATUS_FCSERR)) +#define HFA384x_RXSTATUS_MSGTYPE_GET(value) ((uint16_t)((((uint16_t)(value)) & HFA384x_RXSTATUS_MSGTYPE) >> 13)) +#define HFA384x_RXSTATUS_MSGTYPE_SET(value) ((uint16_t)(((uint16_t)(value)) << 13)) +#define HFA384x_RXSTATUS_MACPORT_GET(value) ((uint16_t)((((uint16_t)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8)) +#define HFA384x_RXSTATUS_MACPORT_SET(value) ((uint16_t)(((uint16_t)(value)) << 8)) +#define HFA384x_RXSTATUS_ISUNDECR(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_RXSTATUS_UNDECR)) +#define HFA384x_RXSTATUS_ISFCSERR(value) ((uint16_t)(((uint16_t)(value)) & HFA384x_RXSTATUS_FCSERR)) /*-------------------------------------------------------------------- FRAME STRUCTURES: Information Types and Information Frame Structures ---------------------------------------------------------------------- Information Types --------------------------------------------------------------------*/ -#define HFA384x_IT_HANDOVERADDR ((UINT16)0xF000UL) -#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((UINT16)0xF001UL)//AP 1.3.7 -#define HFA384x_IT_COMMTALLIES ((UINT16)0xF100UL) -#define HFA384x_IT_SCANRESULTS ((UINT16)0xF101UL) -#define HFA384x_IT_CHINFORESULTS ((UINT16)0xF102UL) -#define HFA384x_IT_HOSTSCANRESULTS ((UINT16)0xF103UL) -#define HFA384x_IT_LINKSTATUS ((UINT16)0xF200UL) -#define HFA384x_IT_ASSOCSTATUS ((UINT16)0xF201UL) -#define HFA384x_IT_AUTHREQ ((UINT16)0xF202UL) -#define HFA384x_IT_PSUSERCNT ((UINT16)0xF203UL) -#define HFA384x_IT_KEYIDCHANGED ((UINT16)0xF204UL) -#define HFA384x_IT_ASSOCREQ ((UINT16)0xF205UL) -#define HFA384x_IT_MICFAILURE ((UINT16)0xF206UL) +#define HFA384x_IT_HANDOVERADDR ((uint16_t)0xF000UL) +#define HFA384x_IT_HANDOVERDEAUTHADDRESS ((uint16_t)0xF001UL)//AP 1.3.7 +#define HFA384x_IT_COMMTALLIES ((uint16_t)0xF100UL) +#define HFA384x_IT_SCANRESULTS ((uint16_t)0xF101UL) +#define HFA384x_IT_CHINFORESULTS ((uint16_t)0xF102UL) +#define HFA384x_IT_HOSTSCANRESULTS ((uint16_t)0xF103UL) +#define HFA384x_IT_LINKSTATUS ((uint16_t)0xF200UL) +#define HFA384x_IT_ASSOCSTATUS ((uint16_t)0xF201UL) +#define HFA384x_IT_AUTHREQ ((uint16_t)0xF202UL) +#define HFA384x_IT_PSUSERCNT ((uint16_t)0xF203UL) +#define HFA384x_IT_KEYIDCHANGED ((uint16_t)0xF204UL) +#define HFA384x_IT_ASSOCREQ ((uint16_t)0xF205UL) +#define HFA384x_IT_MICFAILURE ((uint16_t)0xF206UL) /*-------------------------------------------------------------------- Information Frames Structures @@ -1771,80 +1771,80 @@ Information Frames: Notification Frame Structures /*-- Notification Frame,MAC Mgmt: Handover Address --*/ typedef struct hfa384x_HandoverAddr { - UINT16 framelen; - UINT16 infotype; - UINT8 handover_addr[WLAN_BSSID_LEN]; + uint16_t framelen; + uint16_t infotype; + uint8_t handover_addr[WLAN_BSSID_LEN]; } __WLAN_ATTRIB_PACK__ hfa384x_HandoverAddr_t; /*-- Inquiry Frame, Diagnose: Communication Tallies --*/ typedef struct hfa384x_CommTallies16 { - UINT16 txunicastframes; - UINT16 txmulticastframes; - UINT16 txfragments; - UINT16 txunicastoctets; - UINT16 txmulticastoctets; - UINT16 txdeferredtrans; - UINT16 txsingleretryframes; - UINT16 txmultipleretryframes; - UINT16 txretrylimitexceeded; - UINT16 txdiscards; - UINT16 rxunicastframes; - UINT16 rxmulticastframes; - UINT16 rxfragments; - UINT16 rxunicastoctets; - UINT16 rxmulticastoctets; - UINT16 rxfcserrors; - UINT16 rxdiscardsnobuffer; - UINT16 txdiscardswrongsa; - UINT16 rxdiscardswepundecr; - UINT16 rxmsginmsgfrag; - UINT16 rxmsginbadmsgfrag; + uint16_t txunicastframes; + uint16_t txmulticastframes; + uint16_t txfragments; + uint16_t txunicastoctets; + uint16_t txmulticastoctets; + uint16_t txdeferredtrans; + uint16_t txsingleretryframes; + uint16_t txmultipleretryframes; + uint16_t txretrylimitexceeded; + uint16_t txdiscards; + uint16_t rxunicastframes; + uint16_t rxmulticastframes; + uint16_t rxfragments; + uint16_t rxunicastoctets; + uint16_t rxmulticastoctets; + uint16_t rxfcserrors; + uint16_t rxdiscardsnobuffer; + uint16_t txdiscardswrongsa; + uint16_t rxdiscardswepundecr; + uint16_t rxmsginmsgfrag; + uint16_t rxmsginbadmsgfrag; } __WLAN_ATTRIB_PACK__ hfa384x_CommTallies16_t; typedef struct hfa384x_CommTallies32 { - UINT32 txunicastframes; - UINT32 txmulticastframes; - UINT32 txfragments; - UINT32 txunicastoctets; - UINT32 txmulticastoctets; - UINT32 txdeferredtrans; - UINT32 txsingleretryframes; - UINT32 txmultipleretryframes; - UINT32 txretrylimitexceeded; - UINT32 txdiscards; - UINT32 rxunicastframes; - UINT32 rxmulticastframes; - UINT32 rxfragments; - UINT32 rxunicastoctets; - UINT32 rxmulticastoctets; - UINT32 rxfcserrors; - UINT32 rxdiscardsnobuffer; - UINT32 txdiscardswrongsa; - UINT32 rxdiscardswepundecr; - UINT32 rxmsginmsgfrag; - UINT32 rxmsginbadmsgfrag; + uint32_t txunicastframes; + uint32_t txmulticastframes; + uint32_t txfragments; + uint32_t txunicastoctets; + uint32_t txmulticastoctets; + uint32_t txdeferredtrans; + uint32_t txsingleretryframes; + uint32_t txmultipleretryframes; + uint32_t txretrylimitexceeded; + uint32_t txdiscards; + uint32_t rxunicastframes; + uint32_t rxmulticastframes; + uint32_t rxfragments; + uint32_t rxunicastoctets; + uint32_t rxmulticastoctets; + uint32_t rxfcserrors; + uint32_t rxdiscardsnobuffer; + uint32_t txdiscardswrongsa; + uint32_t rxdiscardswepundecr; + uint32_t rxmsginmsgfrag; + uint32_t rxmsginbadmsgfrag; } __WLAN_ATTRIB_PACK__ hfa384x_CommTallies32_t; /*-- Inquiry Frame, Diagnose: Scan Results & Subfields--*/ typedef struct hfa384x_ScanResultSub { - UINT16 chid; - UINT16 anl; - UINT16 sl; - UINT8 bssid[WLAN_BSSID_LEN]; - UINT16 bcnint; - UINT16 capinfo; + uint16_t chid; + uint16_t anl; + uint16_t sl; + uint8_t bssid[WLAN_BSSID_LEN]; + uint16_t bcnint; + uint16_t capinfo; hfa384x_bytestr32_t ssid; - UINT8 supprates[10]; /* 802.11 info element */ - UINT16 proberesp_rate; + uint8_t supprates[10]; /* 802.11 info element */ + uint16_t proberesp_rate; } __WLAN_ATTRIB_PACK__ hfa384x_ScanResultSub_t; typedef struct hfa384x_ScanResult { - UINT16 rsvd; - UINT16 scanreason; + uint16_t rsvd; + uint16_t scanreason; hfa384x_ScanResultSub_t result[HFA384x_SCANRESULT_MAX]; } __WLAN_ATTRIB_PACK__ hfa384x_ScanResult_t; @@ -1852,10 +1852,10 @@ typedef struct hfa384x_ScanResult /*-- Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/ typedef struct hfa384x_ChInfoResultSub { - UINT16 chid; - UINT16 anl; - UINT16 pnl; - UINT16 active; + uint16_t chid; + uint16_t anl; + uint16_t pnl; + uint16_t active; } __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResultSub_t; #define HFA384x_CHINFORESULT_BSSACTIVE BIT0 @@ -1863,83 +1863,83 @@ typedef struct hfa384x_ChInfoResultSub typedef struct hfa384x_ChInfoResult { - UINT16 scanchannels; - hfa384x_ChInfoResultSub_t + uint16_t scanchannels; + hfa384x_ChInfoResultSub_t result[HFA384x_CHINFORESULT_MAX]; } __WLAN_ATTRIB_PACK__ hfa384x_ChInfoResult_t; /*-- Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/ typedef struct hfa384x_HScanResultSub { - UINT16 chid; - UINT16 anl; - UINT16 sl; - UINT8 bssid[WLAN_BSSID_LEN]; - UINT16 bcnint; - UINT16 capinfo; + uint16_t chid; + uint16_t anl; + uint16_t sl; + uint8_t bssid[WLAN_BSSID_LEN]; + uint16_t bcnint; + uint16_t capinfo; hfa384x_bytestr32_t ssid; - UINT8 supprates[10]; /* 802.11 info element */ - UINT16 proberesp_rate; - UINT16 atim; + uint8_t supprates[10]; /* 802.11 info element */ + uint16_t proberesp_rate; + uint16_t atim; } __WLAN_ATTRIB_PACK__ hfa384x_HScanResultSub_t; typedef struct hfa384x_HScanResult { - UINT16 nresult; - UINT16 rsvd; + uint16_t nresult; + uint16_t rsvd; hfa384x_HScanResultSub_t result[HFA384x_HSCANRESULT_MAX]; } __WLAN_ATTRIB_PACK__ hfa384x_HScanResult_t; /*-- Unsolicited Frame, MAC Mgmt: LinkStatus --*/ -#define HFA384x_LINK_NOTCONNECTED ((UINT16)0) -#define HFA384x_LINK_CONNECTED ((UINT16)1) -#define HFA384x_LINK_DISCONNECTED ((UINT16)2) -#define HFA384x_LINK_AP_CHANGE ((UINT16)3) -#define HFA384x_LINK_AP_OUTOFRANGE ((UINT16)4) -#define HFA384x_LINK_AP_INRANGE ((UINT16)5) -#define HFA384x_LINK_ASSOCFAIL ((UINT16)6) +#define HFA384x_LINK_NOTCONNECTED ((uint16_t)0) +#define HFA384x_LINK_CONNECTED ((uint16_t)1) +#define HFA384x_LINK_DISCONNECTED ((uint16_t)2) +#define HFA384x_LINK_AP_CHANGE ((uint16_t)3) +#define HFA384x_LINK_AP_OUTOFRANGE ((uint16_t)4) +#define HFA384x_LINK_AP_INRANGE ((uint16_t)5) +#define HFA384x_LINK_ASSOCFAIL ((uint16_t)6) typedef struct hfa384x_LinkStatus { - UINT16 linkstatus; + uint16_t linkstatus; } __WLAN_ATTRIB_PACK__ hfa384x_LinkStatus_t; /*-- Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/ -#define HFA384x_ASSOCSTATUS_STAASSOC ((UINT16)1) -#define HFA384x_ASSOCSTATUS_REASSOC ((UINT16)2) -#define HFA384x_ASSOCSTATUS_DISASSOC ((UINT16)3) -#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((UINT16)4) -#define HFA384x_ASSOCSTATUS_AUTHFAIL ((UINT16)5) +#define HFA384x_ASSOCSTATUS_STAASSOC ((uint16_t)1) +#define HFA384x_ASSOCSTATUS_REASSOC ((uint16_t)2) +#define HFA384x_ASSOCSTATUS_DISASSOC ((uint16_t)3) +#define HFA384x_ASSOCSTATUS_ASSOCFAIL ((uint16_t)4) +#define HFA384x_ASSOCSTATUS_AUTHFAIL ((uint16_t)5) typedef struct hfa384x_AssocStatus { - UINT16 assocstatus; - UINT8 sta_addr[WLAN_ADDR_LEN]; + uint16_t assocstatus; + uint8_t sta_addr[WLAN_ADDR_LEN]; /* old_ap_addr is only valid if assocstatus == 2 */ - UINT8 old_ap_addr[WLAN_ADDR_LEN]; - UINT16 reason; - UINT16 reserved; + uint8_t old_ap_addr[WLAN_ADDR_LEN]; + uint16_t reason; + uint16_t reserved; } __WLAN_ATTRIB_PACK__ hfa384x_AssocStatus_t; /*-- Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/ typedef struct hfa384x_AuthRequest { - UINT8 sta_addr[WLAN_ADDR_LEN]; - UINT16 algorithm; + uint8_t sta_addr[WLAN_ADDR_LEN]; + uint16_t algorithm; } __WLAN_ATTRIB_PACK__ hfa384x_AuthReq_t; /*-- Unsolicited Frame, MAC Mgmt: AssocRequest (AP Only) --*/ typedef struct hfa384x_AssocRequest { - UINT8 sta_addr[WLAN_ADDR_LEN]; - UINT16 type; - UINT8 wpa_data[80]; + uint8_t sta_addr[WLAN_ADDR_LEN]; + uint16_t type; + uint8_t wpa_data[80]; } __WLAN_ATTRIB_PACK__ hfa384x_AssocReq_t; @@ -1948,23 +1948,23 @@ typedef struct hfa384x_AssocRequest /*-- Unsolicited Frame, MAC Mgmt: MIC Failure (AP Only) --*/ -typedef struct hfa384x_MicFailure +typedef struct hfa384x_MicFailure { - UINT8 sender[WLAN_ADDR_LEN]; - UINT8 dest[WLAN_ADDR_LEN]; + uint8_t sender[WLAN_ADDR_LEN]; + uint8_t dest[WLAN_ADDR_LEN]; } __WLAN_ATTRIB_PACK__ hfa384x_MicFailure_t; /*-- Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/ typedef struct hfa384x_PSUserCount { - UINT16 usercnt; + uint16_t usercnt; } __WLAN_ATTRIB_PACK__ hfa384x_PSUserCount_t; typedef struct hfa384x_KeyIDChanged { - UINT8 sta_addr[WLAN_ADDR_LEN]; - UINT16 keyid; + uint8_t sta_addr[WLAN_ADDR_LEN]; + uint16_t keyid; } __WLAN_ATTRIB_PACK__ hfa384x_KeyIDChanged_t; /*-- Collection of all Inf frames ---------------*/ @@ -1983,8 +1983,8 @@ typedef union hfa384x_infodata { typedef struct hfa384x_InfFrame { - UINT16 framelen; - UINT16 infotype; + uint16_t framelen; + uint16_t infotype; hfa384x_infodata_t info; } __WLAN_ATTRIB_PACK__ hfa384x_InfFrame_t; @@ -2022,46 +2022,46 @@ USB Packet structures and constants. typedef struct hfa384x_usb_txfrm { hfa384x_tx_frame_t desc; - UINT8 data[WLAN_DATA_MAXLEN]; + uint8_t data[WLAN_DATA_MAXLEN]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_txfrm_t; typedef struct hfa384x_usb_cmdreq { - UINT16 type; - UINT16 cmd; - UINT16 parm0; - UINT16 parm1; - UINT16 parm2; - UINT8 pad[54]; + uint16_t type; + uint16_t cmd; + uint16_t parm0; + uint16_t parm1; + uint16_t parm2; + uint8_t pad[54]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdreq_t; typedef struct hfa384x_usb_wridreq { - UINT16 type; - UINT16 frmlen; - UINT16 rid; - UINT8 data[HFA384x_RIDDATA_MAXLEN]; + uint16_t type; + uint16_t frmlen; + uint16_t rid; + uint8_t data[HFA384x_RIDDATA_MAXLEN]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_wridreq_t; typedef struct hfa384x_usb_rridreq { - UINT16 type; - UINT16 frmlen; - UINT16 rid; - UINT8 pad[58]; + uint16_t type; + uint16_t frmlen; + uint16_t rid; + uint8_t pad[58]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_rridreq_t; typedef struct hfa384x_usb_wmemreq { - UINT16 type; - UINT16 frmlen; - UINT16 offset; - UINT16 page; - UINT8 data[HFA384x_USB_RWMEM_MAXLEN]; + uint16_t type; + uint16_t frmlen; + uint16_t offset; + uint16_t page; + uint8_t data[HFA384x_USB_RWMEM_MAXLEN]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_wmemreq_t; typedef struct hfa384x_usb_rmemreq { - UINT16 type; - UINT16 frmlen; - UINT16 offset; - UINT16 page; - UINT8 pad[56]; + uint16_t type; + uint16_t frmlen; + uint16_t offset; + uint16_t page; + uint8_t pad[56]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemreq_t; /*------------------------------------*/ @@ -2069,54 +2069,54 @@ typedef struct hfa384x_usb_rmemreq { typedef struct hfa384x_usb_rxfrm { hfa384x_rx_frame_t desc; - UINT8 data[WLAN_DATA_MAXLEN]; + uint8_t data[WLAN_DATA_MAXLEN]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_rxfrm_t; typedef struct hfa384x_usb_infofrm { - UINT16 type; + uint16_t type; hfa384x_InfFrame_t info; } __WLAN_ATTRIB_PACK__ hfa384x_usb_infofrm_t; typedef struct hfa384x_usb_statusresp { - UINT16 type; - UINT16 status; - UINT16 resp0; - UINT16 resp1; - UINT16 resp2; + uint16_t type; + uint16_t status; + uint16_t resp0; + uint16_t resp1; + uint16_t resp2; } __WLAN_ATTRIB_PACK__ hfa384x_usb_cmdresp_t; typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t; typedef struct hfa384x_usb_rridresp { - UINT16 type; - UINT16 frmlen; - UINT16 rid; - UINT8 data[HFA384x_RIDDATA_MAXLEN]; + uint16_t type; + uint16_t frmlen; + uint16_t rid; + uint8_t data[HFA384x_RIDDATA_MAXLEN]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_rridresp_t; typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t; typedef struct hfa384x_usb_rmemresp { - UINT16 type; - UINT16 frmlen; - UINT8 data[HFA384x_USB_RWMEM_MAXLEN]; + uint16_t type; + uint16_t frmlen; + uint8_t data[HFA384x_USB_RWMEM_MAXLEN]; } __WLAN_ATTRIB_PACK__ hfa384x_usb_rmemresp_t; typedef struct hfa384x_usb_bufavail { - UINT16 type; - UINT16 frmlen; + uint16_t type; + uint16_t frmlen; } __WLAN_ATTRIB_PACK__ hfa384x_usb_bufavail_t; typedef struct hfa384x_usb_error { - UINT16 type; - UINT16 errortype; + uint16_t type; + uint16_t errortype; } __WLAN_ATTRIB_PACK__ hfa384x_usb_error_t; /*----------------------------------------------------------*/ /* Unions for packaging all the known packet types together */ typedef union hfa384x_usbout { - UINT16 type; + uint16_t type; hfa384x_usb_txfrm_t txfrm; hfa384x_usb_cmdreq_t cmdreq; hfa384x_usb_wridreq_t wridreq; @@ -2126,7 +2126,7 @@ typedef union hfa384x_usbout { } __WLAN_ATTRIB_PACK__ hfa384x_usbout_t; typedef union hfa384x_usbin { - UINT16 type; + uint16_t type; hfa384x_usb_rxfrm_t rxfrm; hfa384x_usb_txfrm_t txfrm; hfa384x_usb_infofrm_t infofrm; @@ -2137,7 +2137,7 @@ typedef union hfa384x_usbin { hfa384x_usb_rmemresp_t rmemresp; hfa384x_usb_bufavail_t bufavail; hfa384x_usb_error_t usberror; - UINT8 boguspad[3000]; + uint8_t boguspad[3000]; } __WLAN_ATTRIB_PACK__ hfa384x_usbin_t; #endif /* WLAN_USB */ @@ -2148,17 +2148,17 @@ PD record structures. typedef struct hfa384x_pdr_pcb_partnum { - UINT8 num[8]; + uint8_t num[8]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_partnum_t; typedef struct hfa384x_pdr_pcb_tracenum { - UINT8 num[8]; + uint8_t num[8]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_pcb_tracenum_t; typedef struct hfa384x_pdr_nic_serial { - UINT8 num[12]; + uint8_t num[12]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_serial_t; typedef struct hfa384x_pdr_mkk_measurements @@ -2182,170 +2182,170 @@ typedef struct hfa384x_pdr_mkk_measurements typedef struct hfa384x_pdr_nic_ramsize { - UINT8 size[12]; /* units of KB */ + uint8_t size[12]; /* units of KB */ } __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_ramsize_t; typedef struct hfa384x_pdr_mfisuprange { - UINT16 id; - UINT16 variant; - UINT16 bottom; - UINT16 top; + uint16_t id; + uint16_t variant; + uint16_t bottom; + uint16_t top; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_mfisuprange_t; typedef struct hfa384x_pdr_cfisuprange { - UINT16 id; - UINT16 variant; - UINT16 bottom; - UINT16 top; + uint16_t id; + uint16_t variant; + uint16_t bottom; + uint16_t top; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_cfisuprange_t; typedef struct hfa384x_pdr_nicid { - UINT16 id; - UINT16 variant; - UINT16 major; - UINT16 minor; + uint16_t id; + uint16_t variant; + uint16_t major; + uint16_t minor; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_nicid_t; typedef struct hfa384x_pdr_refdac_measurements { - UINT16 value[0]; + uint16_t value[0]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_measurements_t; typedef struct hfa384x_pdr_vgdac_measurements { - UINT16 value[0]; + uint16_t value[0]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_measurements_t; typedef struct hfa384x_pdr_level_comp_measurements { - UINT16 value[0]; + uint16_t value[0]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_compc_measurements_t; typedef struct hfa384x_pdr_mac_address { - UINT8 addr[6]; + uint8_t addr[6]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_mac_address_t; typedef struct hfa384x_pdr_mkk_callname { - UINT8 callname[8]; + uint8_t callname[8]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_mkk_callname_t; typedef struct hfa384x_pdr_regdomain { - UINT16 numdomains; - UINT16 domain[5]; + uint16_t numdomains; + uint16_t domain[5]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_regdomain_t; typedef struct hfa384x_pdr_allowed_channel { - UINT16 ch_bitmap; + uint16_t ch_bitmap; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_allowed_channel_t; typedef struct hfa384x_pdr_default_channel { - UINT16 channel; + uint16_t channel; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_default_channel_t; typedef struct hfa384x_pdr_privacy_option { - UINT16 available; + uint16_t available; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_privacy_option_t; typedef struct hfa384x_pdr_temptype { - UINT16 type; + uint16_t type; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_temptype_t; typedef struct hfa384x_pdr_refdac_setup { - UINT16 ch_value[14]; + uint16_t ch_value[14]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_refdac_setup_t; typedef struct hfa384x_pdr_vgdac_setup { - UINT16 ch_value[14]; + uint16_t ch_value[14]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_vgdac_setup_t; typedef struct hfa384x_pdr_level_comp_setup { - UINT16 ch_value[14]; + uint16_t ch_value[14]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_level_comp_setup_t; typedef struct hfa384x_pdr_trimdac_setup { - UINT16 trimidac; - UINT16 trimqdac; + uint16_t trimidac; + uint16_t trimqdac; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_trimdac_setup_t; typedef struct hfa384x_pdr_ifr_setting { - UINT16 value[3]; + uint16_t value[3]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_ifr_setting_t; typedef struct hfa384x_pdr_rfr_setting { - UINT16 value[3]; + uint16_t value[3]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_rfr_setting_t; typedef struct hfa384x_pdr_hfa3861_baseline { - UINT16 value[50]; + uint16_t value[50]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_baseline_t; typedef struct hfa384x_pdr_hfa3861_shadow { - UINT32 value[32]; + uint32_t value[32]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_shadow_t; typedef struct hfa384x_pdr_hfa3861_ifrf { - UINT32 value[20]; + uint32_t value[20]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_ifrf_t; typedef struct hfa384x_pdr_hfa3861_chcalsp { - UINT16 value[14]; + uint16_t value[14]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcalsp_t; typedef struct hfa384x_pdr_hfa3861_chcali { - UINT16 value[17]; + uint16_t value[17]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_chcali_t; typedef struct hfa384x_pdr_hfa3861_nic_config { - UINT16 config_bitmap; + uint16_t config_bitmap; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_nic_config_t; typedef struct hfa384x_pdr_hfo_delay { - UINT8 hfo_delay; + uint8_t hfo_delay; } __WLAN_ATTRIB_PACK__ hfa384x_hfo_delay_t; typedef struct hfa384x_pdr_hfa3861_manf_testsp { - UINT16 value[30]; + uint16_t value[30]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testsp_t; typedef struct hfa384x_pdr_hfa3861_manf_testi { - UINT16 value[30]; + uint16_t value[30]; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_hfa3861_manf_testi_t; typedef struct hfa384x_end_of_pda { - UINT16 crc; + uint16_t crc; } __WLAN_ATTRIB_PACK__ hfa384x_pdr_end_of_pda_t; typedef struct hfa384x_pdrec { - UINT16 len; /* in words */ - UINT16 code; + uint16_t len; /* in words */ + uint16_t code; union pdr { hfa384x_pdr_pcb_partnum_t pcb_partnum; hfa384x_pdr_pcb_tracenum_t pcb_tracenum; @@ -2393,19 +2393,19 @@ typedef struct hfa384x_pdrec --------------------------------------------------------------------*/ typedef struct hfa384x_statusresult { - UINT16 status; - UINT16 resp0; - UINT16 resp1; - UINT16 resp2; + uint16_t status; + uint16_t resp0; + uint16_t resp1; + uint16_t resp2; } hfa384x_cmdresult_t; #if (WLAN_HOSTIF == WLAN_USB) /* USB Control Exchange (CTLX): - * A queue of the structure below is maintained for all of the + * A queue of the structure below is maintained for all of the * Request/Response type USB packets supported by Prism2. */ -/* The following hfa384x_* structures are arguments to +/* The following hfa384x_* structures are arguments to * the usercb() for the different CTLX types. */ typedef hfa384x_cmdresult_t hfa384x_wridresult_t; @@ -2413,9 +2413,9 @@ typedef hfa384x_cmdresult_t hfa384x_wmemresult_t; typedef struct hfa384x_rridresult { - UINT16 rid; + uint16_t rid; const void *riddata; - UINT riddata_len; + unsigned int riddata_len; } hfa384x_rridresult_t; enum ctlx_state { @@ -2437,7 +2437,7 @@ struct hfa384x; typedef void (*ctlx_cmdcb_t)( struct hfa384x*, const struct hfa384x_usbctlx* ); typedef void (*ctlx_usercb_t)( - struct hfa384x *hw, + struct hfa384x *hw, void *ctlxresult, void *usercb_data); @@ -2473,14 +2473,14 @@ typedef struct hfa384x_usbctlxq typedef struct hfa484x_metacmd { - UINT16 cmd; + uint16_t cmd; - UINT16 parm0; - UINT16 parm1; - UINT16 parm2; + uint16_t parm0; + uint16_t parm1; + uint16_t parm2; #if 0 //XXX cmd irq stuff - UINT16 bulkid; /* what RID/FID to copy down. */ + uint16_t bulkid; /* what RID/FID to copy down. */ int bulklen; /* how much to copy from BAP */ char *bulkdata; /* And to where? */ #endif @@ -2509,27 +2509,27 @@ typedef struct hfa484x_metacmd /* XXX These are going away ASAP */ typedef struct prism2sta_authlist { - UINT cnt; - UINT8 addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN]; - UINT8 assoc[WLAN_AUTH_MAX]; + unsigned int cnt; + uint8_t addr[WLAN_AUTH_MAX][WLAN_ADDR_LEN]; + uint8_t assoc[WLAN_AUTH_MAX]; } prism2sta_authlist_t; typedef struct prism2sta_accesslist { - UINT modify; - UINT cnt; - UINT8 addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; - UINT cnt1; - UINT8 addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; + unsigned int modify; + unsigned int cnt; + uint8_t addr[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; + unsigned int cnt1; + uint8_t addr1[WLAN_ACCESS_MAX][WLAN_ADDR_LEN]; } prism2sta_accesslist_t; typedef struct hfa384x { #if (WLAN_HOSTIF != WLAN_USB) /* Resource config */ - UINT32 iobase; + uint32_t iobase; char __iomem *membase; - UINT32 irq; + uint32_t irq; #else /* USB support data */ struct usb_device *usb; @@ -2574,25 +2574,25 @@ typedef struct hfa384x #endif int sniff_fcs; - int sniff_channel; - int sniff_truncate; + int sniff_channel; + int sniff_truncate; int sniffhdr; wait_queue_head_t cmdq; /* wait queue itself */ /* Controller state */ - UINT32 state; - UINT32 isap; - UINT8 port_enabled[HFA384x_NUMPORTS_MAX]; + uint32_t state; + uint32_t isap; + uint8_t port_enabled[HFA384x_NUMPORTS_MAX]; #if (WLAN_HOSTIF != WLAN_USB) - UINT auxen; - UINT isram16; + unsigned int auxen; + unsigned int isram16; #endif /* !USB */ /* Download support */ - UINT dlstate; + unsigned int dlstate; hfa384x_downloadbuffer_t bufinfo; - UINT16 dltimeout; + uint16_t dltimeout; #if (WLAN_HOSTIF != WLAN_USB) spinlock_t cmdlock; @@ -2600,15 +2600,15 @@ typedef struct hfa384x hfa384x_metacmd_t *cmddata; /* for our async callback */ /* BAP support */ - spinlock_t baplock; + spinlock_t baplock; struct tasklet_struct bap_tasklet; /* MAC buffer ids */ - UINT16 txfid_head; - UINT16 txfid_tail; - UINT txfid_N; - UINT16 txfid_queue[HFA384x_DRVR_FIDSTACKLEN_MAX]; - UINT16 infofid; + uint16_t txfid_head; + uint16_t txfid_tail; + unsigned int txfid_N; + uint16_t txfid_queue[HFA384x_DRVR_FIDSTACKLEN_MAX]; + uint16_t infofid; struct semaphore infofid_sem; #endif /* !USB */ @@ -2625,31 +2625,31 @@ typedef struct hfa384x hfa384x_commsquality_t qual; struct timer_list commsqual_timer; - UINT16 link_status; - UINT16 link_status_new; + uint16_t link_status; + uint16_t link_status_new; struct sk_buff_head authq; /* And here we have stuff that used to be in priv */ /* State variables */ - UINT presniff_port_type; - UINT16 presniff_wepflags; - UINT32 dot11_desired_bss_type; + unsigned int presniff_port_type; + uint16_t presniff_wepflags; + uint32_t dot11_desired_bss_type; int ap; /* AP flag: 0 - Station, 1 - Access Point. */ int dbmadjust; /* Group Addresses - right now, there are up to a total of MAX_GRP_ADDR group addresses */ - UINT8 dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN]; - UINT dot11_grpcnt; + uint8_t dot11_grp_addr[MAX_GRP_ADDR][WLAN_ADDR_LEN]; + unsigned int dot11_grpcnt; /* Component Identities */ hfa384x_compident_t ident_nic; hfa384x_compident_t ident_pri_fw; hfa384x_compident_t ident_sta_fw; hfa384x_compident_t ident_ap_fw; - UINT16 mm_mods; + uint16_t mm_mods; /* Supplier compatibility ranges */ hfa384x_caplevel_t cap_sup_mfi; @@ -2665,14 +2665,14 @@ typedef struct hfa384x hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */ hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */ - UINT32 psusercount; /* Power save user count. */ + uint32_t psusercount; /* Power save user count. */ hfa384x_CommTallies32_t tallies; /* Communication tallies. */ - UINT8 comment[WLAN_COMMENT_MAX+1]; /* User comment */ + uint8_t comment[WLAN_COMMENT_MAX+1]; /* User comment */ /* Channel Info request results (AP only) */ struct { atomic_t done; - UINT8 count; + uint8_t count; hfa384x_ChInfoResult_t results; } channel_info; @@ -2680,7 +2680,7 @@ typedef struct hfa384x prism2sta_authlist_t authlist; /* Authenticated station list. */ - UINT accessmode; /* Access mode. */ + unsigned int accessmode; /* Access mode. */ prism2sta_accesslist_t allow; /* Allowed station list. */ prism2sta_accesslist_t deny; /* Denied station list. */ @@ -2690,23 +2690,23 @@ typedef struct hfa384x /*--- Function Declarations -----------------------------------*/ /*=============================================================*/ #if (WLAN_HOSTIF == WLAN_USB) -void -hfa384x_create( - hfa384x_t *hw, +void +hfa384x_create( + hfa384x_t *hw, struct usb_device *usb); #else -void -hfa384x_create( - hfa384x_t *hw, - UINT irq, - UINT32 iobase, - UINT8 __iomem *membase); +void +hfa384x_create( + hfa384x_t *hw, + unsigned int irq, + uint32_t iobase, + uint8_t __iomem *membase); #endif void hfa384x_destroy(hfa384x_t *hw); irqreturn_t -hfa384x_interrupt(int irq, void *dev_id PT_REGS); +hfa384x_INTerrupt(int irq, void *dev_id PT_REGS); int hfa384x_corereset( hfa384x_t *hw, int holdtime, int settletime, int genesis); int @@ -2714,97 +2714,97 @@ hfa384x_drvr_chinforesults( hfa384x_t *hw); int hfa384x_drvr_commtallies( hfa384x_t *hw); int -hfa384x_drvr_disable(hfa384x_t *hw, UINT16 macport); +hfa384x_drvr_disable(hfa384x_t *hw, uint16_t macport); int -hfa384x_drvr_enable(hfa384x_t *hw, UINT16 macport); +hfa384x_drvr_enable(hfa384x_t *hw, uint16_t macport); int hfa384x_drvr_flashdl_enable(hfa384x_t *hw); int hfa384x_drvr_flashdl_disable(hfa384x_t *hw); int -hfa384x_drvr_flashdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len); +hfa384x_drvr_flashdl_write(hfa384x_t *hw, uint32_t daddr, void* buf, uint32_t len); int -hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len); +hfa384x_drvr_getconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len); int -hfa384x_drvr_handover( hfa384x_t *hw, UINT8 *addr); +hfa384x_drvr_handover( hfa384x_t *hw, uint8_t *addr); int hfa384x_drvr_hostscanresults( hfa384x_t *hw); int hfa384x_drvr_low_level(hfa384x_t *hw, hfa384x_metacmd_t *cmd); int -hfa384x_drvr_mmi_read(hfa384x_t *hw, UINT32 address, UINT32 *result); +hfa384x_drvr_mmi_read(hfa384x_t *hw, uint32_t address, uint32_t *result); int -hfa384x_drvr_mmi_write(hfa384x_t *hw, UINT32 address, UINT32 data); +hfa384x_drvr_mmi_write(hfa384x_t *hw, uint32_t address, uint32_t data); int -hfa384x_drvr_ramdl_enable(hfa384x_t *hw, UINT32 exeaddr); +hfa384x_drvr_ramdl_enable(hfa384x_t *hw, uint32_t exeaddr); int hfa384x_drvr_ramdl_disable(hfa384x_t *hw); int -hfa384x_drvr_ramdl_write(hfa384x_t *hw, UINT32 daddr, void* buf, UINT32 len); +hfa384x_drvr_ramdl_write(hfa384x_t *hw, uint32_t daddr, void* buf, uint32_t len); int -hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, UINT len); +hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len); int hfa384x_drvr_scanresults( hfa384x_t *hw); int -hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len); +hfa384x_drvr_setconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len); -static inline int -hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val) +static inline int +hfa384x_drvr_getconfig16(hfa384x_t *hw, uint16_t rid, void *val) { int result = 0; - result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16)); + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint16_t)); if ( result == 0 ) { - *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val)); + *((uint16_t*)val) = hfa384x2host_16(*((uint16_t*)val)); } return result; } -static inline int -hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val) +static inline int +hfa384x_drvr_getconfig32(hfa384x_t *hw, uint16_t rid, void *val) { int result = 0; - result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32)); + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint32_t)); if ( result == 0 ) { - *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val)); + *((uint32_t*)val) = hfa384x2host_32(*((uint32_t*)val)); } return result; } static inline int -hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 val) +hfa384x_drvr_setconfig16(hfa384x_t *hw, uint16_t rid, uint16_t val) { - UINT16 value = host2hfa384x_16(val); + uint16_t value = host2hfa384x_16(val); return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); } static inline int -hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 val) +hfa384x_drvr_setconfig32(hfa384x_t *hw, uint16_t rid, uint32_t val) { - UINT32 value = host2hfa384x_32(val); + uint32_t value = host2hfa384x_32(val); return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value)); } -#if (WLAN_HOSTIF == WLAN_USB) -int -hfa384x_drvr_getconfig_async(hfa384x_t *hw, - UINT16 rid, - ctlx_usercb_t usercb, - void *usercb_data); - -int -hfa384x_drvr_setconfig_async(hfa384x_t *hw, - UINT16 rid, - void *buf, - UINT16 len, - ctlx_usercb_t usercb, - void *usercb_data); +#if (WLAN_HOSTIF == WLAN_USB) +int +hfa384x_drvr_getconfig_async(hfa384x_t *hw, + uint16_t rid, + ctlx_usercb_t usercb, + void *usercb_data); + +int +hfa384x_drvr_setconfig_async(hfa384x_t *hw, + uint16_t rid, + void *buf, + uint16_t len, + ctlx_usercb_t usercb, + void *usercb_data); #else static inline int -hfa384x_drvr_setconfig_async(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len, - void *ptr1, void *ptr2) +hfa384x_drvr_setconfig_async(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len, + void *ptr1, void *ptr2) { (void)ptr1; (void)ptr2; @@ -2813,19 +2813,19 @@ hfa384x_drvr_setconfig_async(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len, #endif static inline int -hfa384x_drvr_setconfig16_async(hfa384x_t *hw, UINT16 rid, UINT16 val) -{ - UINT16 value = host2hfa384x_16(val); - return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), - NULL , NULL); +hfa384x_drvr_setconfig16_async(hfa384x_t *hw, uint16_t rid, uint16_t val) +{ + uint16_t value = host2hfa384x_16(val); + return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), + NULL , NULL); } static inline int -hfa384x_drvr_setconfig32_async(hfa384x_t *hw, UINT16 rid, UINT32 val) -{ - UINT32 value = host2hfa384x_32(val); - return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), - NULL , NULL); +hfa384x_drvr_setconfig32_async(hfa384x_t *hw, uint16_t rid, uint32_t val) +{ + uint32_t value = host2hfa384x_32(val); + return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value), + NULL , NULL); } @@ -2841,87 +2841,87 @@ hfa384x_tx_timeout(wlandevice_t *wlandev); int hfa384x_cmd_initialize(hfa384x_t *hw); int -hfa384x_cmd_enable(hfa384x_t *hw, UINT16 macport); +hfa384x_cmd_enable(hfa384x_t *hw, uint16_t macport); int -hfa384x_cmd_disable(hfa384x_t *hw, UINT16 macport); +hfa384x_cmd_disable(hfa384x_t *hw, uint16_t macport); int hfa384x_cmd_diagnose(hfa384x_t *hw); int -hfa384x_cmd_allocate(hfa384x_t *hw, UINT16 len); +hfa384x_cmd_allocate(hfa384x_t *hw, uint16_t len); int -hfa384x_cmd_transmit(hfa384x_t *hw, UINT16 reclaim, UINT16 qos, UINT16 fid); +hfa384x_cmd_transmit(hfa384x_t *hw, uint16_t reclaim, uint16_t qos, uint16_t fid); int -hfa384x_cmd_clearpersist(hfa384x_t *hw, UINT16 fid); +hfa384x_cmd_clearpersist(hfa384x_t *hw, uint16_t fid); int -hfa384x_cmd_notify(hfa384x_t *hw, UINT16 reclaim, UINT16 fid, void *buf, UINT16 len); +hfa384x_cmd_notify(hfa384x_t *hw, uint16_t reclaim, uint16_t fid, void *buf, uint16_t len); int -hfa384x_cmd_inquire(hfa384x_t *hw, UINT16 fid); +hfa384x_cmd_inquire(hfa384x_t *hw, uint16_t fid); int -hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid, void *buf, UINT16 len); +hfa384x_cmd_access(hfa384x_t *hw, uint16_t write, uint16_t rid, void *buf, uint16_t len); int -hfa384x_cmd_monitor(hfa384x_t *hw, UINT16 enable); +hfa384x_cmd_monitor(hfa384x_t *hw, uint16_t enable); int hfa384x_cmd_download( - hfa384x_t *hw, - UINT16 mode, - UINT16 lowaddr, - UINT16 highaddr, - UINT16 codelen); + hfa384x_t *hw, + uint16_t mode, + uint16_t lowaddr, + uint16_t highaddr, + uint16_t codelen); int hfa384x_cmd_aux_enable(hfa384x_t *hw, int force); int hfa384x_cmd_aux_disable(hfa384x_t *hw); int hfa384x_copy_from_bap( - hfa384x_t *hw, - UINT16 bap, - UINT16 id, - UINT16 offset, + hfa384x_t *hw, + uint16_t bap, + uint16_t id, + uint16_t offset, void *buf, - UINT len); + unsigned int len); int hfa384x_copy_to_bap( - hfa384x_t *hw, - UINT16 bap, - UINT16 id, - UINT16 offset, - void *buf, - UINT len); -void + hfa384x_t *hw, + uint16_t bap, + uint16_t id, + uint16_t offset, + void *buf, + unsigned int len); +void hfa384x_copy_from_aux( - hfa384x_t *hw, - UINT32 cardaddr, - UINT32 auxctl, - void *buf, - UINT len); -void + hfa384x_t *hw, + uint32_t cardaddr, + uint32_t auxctl, + void *buf, + unsigned int len); +void hfa384x_copy_to_aux( - hfa384x_t *hw, - UINT32 cardaddr, - UINT32 auxctl, - void *buf, - UINT len); + hfa384x_t *hw, + uint32_t cardaddr, + uint32_t auxctl, + void *buf, + unsigned int len); #if (WLAN_HOSTIF != WLAN_USB) -/* +/* HFA384x is a LITTLE ENDIAN part. the get/setreg functions implicitly byte-swap the data to LE. the _noswap variants do not perform a byte-swap on the data. */ -static inline UINT16 -__hfa384x_getreg(hfa384x_t *hw, UINT reg); - -static inline void -__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg); - -static inline UINT16 -__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg); +static inline uint16_t +__hfa384x_getreg(hfa384x_t *hw, unsigned int reg); static inline void -__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg); +__hfa384x_setreg(hfa384x_t *hw, uint16_t val, unsigned int reg); + +static inline uint16_t +__hfa384x_getreg_noswap(hfa384x_t *hw, unsigned int reg); + +static inline void +__hfa384x_setreg_noswap(hfa384x_t *hw, uint16_t val, unsigned int reg); #ifdef REVERSE_ENDIAN #define hfa384x_getreg __hfa384x_getreg_noswap @@ -2949,8 +2949,8 @@ __hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg); * Returns: * Value from the register in HOST ORDER!!!! ----------------------------------------------------------------*/ -static inline UINT16 -__hfa384x_getreg(hfa384x_t *hw, UINT reg) +static inline uint16_t +__hfa384x_getreg(hfa384x_t *hw, unsigned int reg) { /* printk(KERN_DEBUG "Reading from 0x%0x\n", hw->membase + reg); */ #if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) @@ -2976,7 +2976,7 @@ __hfa384x_getreg(hfa384x_t *hw, UINT reg) * Nothing ----------------------------------------------------------------*/ static inline void -__hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg) +__hfa384x_setreg(hfa384x_t *hw, uint16_t val, unsigned int reg) { #if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) wlan_outw_cpu_to_le16( val, hw->iobase + reg); @@ -3001,8 +3001,8 @@ __hfa384x_setreg(hfa384x_t *hw, UINT16 val, UINT reg) * Returns: * Value from the register. ----------------------------------------------------------------*/ -static inline UINT16 -__hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg) +static inline uint16_t +__hfa384x_getreg_noswap(hfa384x_t *hw, unsigned int reg) { #if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) return wlan_inw(hw->iobase+reg); @@ -3026,8 +3026,8 @@ __hfa384x_getreg_noswap(hfa384x_t *hw, UINT reg) * Returns: * Nothing ----------------------------------------------------------------*/ -static inline void -__hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg) +static inline void +__hfa384x_setreg_noswap(hfa384x_t *hw, uint16_t val, unsigned int reg) { #if ((WLAN_HOSTIF == WLAN_PCMCIA) || (WLAN_HOSTIF == WLAN_PLX)) wlan_outw( val, hw->iobase + reg); @@ -3041,25 +3041,25 @@ __hfa384x_setreg_noswap(hfa384x_t *hw, UINT16 val, UINT reg) static inline void hfa384x_events_all(hfa384x_t *hw) { - hfa384x_setreg(hw, + hfa384x_setreg(hw, HFA384x_INT_NORMAL #ifdef CMD_IRQ | HFA384x_INTEN_CMD_SET(1) #endif , - HFA384x_INTEN); + HFA384x_INTEN); } static inline void hfa384x_events_nobap(hfa384x_t *hw) { - hfa384x_setreg(hw, + hfa384x_setreg(hw, (HFA384x_INT_NORMAL & ~HFA384x_INT_BAP_OP) #ifdef CMD_IRQ | HFA384x_INTEN_CMD_SET(1) #endif , - HFA384x_INTEN); + HFA384x_INTEN); } diff --git a/src/drivers/net/p80211hdr.h b/src/drivers/net/p80211hdr.h index 110905c5..6e427293 100644 --- a/src/drivers/net/p80211hdr.h +++ b/src/drivers/net/p80211hdr.h @@ -39,7 +39,7 @@ * * -------------------------------------------------------------------- * -* Portions of the development of this software were funded by +* Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development. * * -------------------------------------------------------------------- @@ -47,7 +47,7 @@ * This file declares the constants and types used in the interface * between a wlan driver and the user mode utilities. * -* Note: +* Note: * - Constant values are always in HOST byte order. To assign * values to multi-byte fields they _must_ be converted to * ieee byte order. To retrieve multi-byte values from incoming @@ -117,7 +117,7 @@ FILE_LICENCE ( GPL2_ONLY ); #define WLAN_FSTYPE_ASSOCRESP 0x01 #define WLAN_FSTYPE_REASSOCREQ 0x02 #define WLAN_FSTYPE_REASSOCRESP 0x03 -#define WLAN_FSTYPE_PROBEREQ 0x04 +#define WLAN_FSTYPE_PROBEREQ 0x04 #define WLAN_FSTYPE_PROBERESP 0x05 #define WLAN_FSTYPE_BEACON 0x08 #define WLAN_FSTYPE_ATIM 0x09 @@ -168,29 +168,29 @@ FILE_LICENCE ( GPL2_ONLY ); /* SET_FC_FSTYPE(WLAN_FSTYPE_RTS) ); */ /*------------------------------------------------------------*/ -#define WLAN_GET_FC_PVER(n) (((UINT16)(n)) & (BIT0 | BIT1)) -#define WLAN_GET_FC_FTYPE(n) ((((UINT16)(n)) & (BIT2 | BIT3)) >> 2) -#define WLAN_GET_FC_FSTYPE(n) ((((UINT16)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4) -#define WLAN_GET_FC_TODS(n) ((((UINT16)(n)) & (BIT8)) >> 8) -#define WLAN_GET_FC_FROMDS(n) ((((UINT16)(n)) & (BIT9)) >> 9) -#define WLAN_GET_FC_MOREFRAG(n) ((((UINT16)(n)) & (BIT10)) >> 10) -#define WLAN_GET_FC_RETRY(n) ((((UINT16)(n)) & (BIT11)) >> 11) -#define WLAN_GET_FC_PWRMGT(n) ((((UINT16)(n)) & (BIT12)) >> 12) -#define WLAN_GET_FC_MOREDATA(n) ((((UINT16)(n)) & (BIT13)) >> 13) -#define WLAN_GET_FC_ISWEP(n) ((((UINT16)(n)) & (BIT14)) >> 14) -#define WLAN_GET_FC_ORDER(n) ((((UINT16)(n)) & (BIT15)) >> 15) +#define WLAN_GET_FC_PVER(n) (((uint16_t)(n)) & (BIT0 | BIT1)) +#define WLAN_GET_FC_FTYPE(n) ((((uint16_t)(n)) & (BIT2 | BIT3)) >> 2) +#define WLAN_GET_FC_FSTYPE(n) ((((uint16_t)(n)) & (BIT4|BIT5|BIT6|BIT7)) >> 4) +#define WLAN_GET_FC_TODS(n) ((((uint16_t)(n)) & (BIT8)) >> 8) +#define WLAN_GET_FC_FROMDS(n) ((((uint16_t)(n)) & (BIT9)) >> 9) +#define WLAN_GET_FC_MOREFRAG(n) ((((uint16_t)(n)) & (BIT10)) >> 10) +#define WLAN_GET_FC_RETRY(n) ((((uint16_t)(n)) & (BIT11)) >> 11) +#define WLAN_GET_FC_PWRMGT(n) ((((uint16_t)(n)) & (BIT12)) >> 12) +#define WLAN_GET_FC_MOREDATA(n) ((((uint16_t)(n)) & (BIT13)) >> 13) +#define WLAN_GET_FC_ISWEP(n) ((((uint16_t)(n)) & (BIT14)) >> 14) +#define WLAN_GET_FC_ORDER(n) ((((uint16_t)(n)) & (BIT15)) >> 15) -#define WLAN_SET_FC_PVER(n) ((UINT16)(n)) -#define WLAN_SET_FC_FTYPE(n) (((UINT16)(n)) << 2) -#define WLAN_SET_FC_FSTYPE(n) (((UINT16)(n)) << 4) -#define WLAN_SET_FC_TODS(n) (((UINT16)(n)) << 8) -#define WLAN_SET_FC_FROMDS(n) (((UINT16)(n)) << 9) -#define WLAN_SET_FC_MOREFRAG(n) (((UINT16)(n)) << 10) -#define WLAN_SET_FC_RETRY(n) (((UINT16)(n)) << 11) -#define WLAN_SET_FC_PWRMGT(n) (((UINT16)(n)) << 12) -#define WLAN_SET_FC_MOREDATA(n) (((UINT16)(n)) << 13) -#define WLAN_SET_FC_ISWEP(n) (((UINT16)(n)) << 14) -#define WLAN_SET_FC_ORDER(n) (((UINT16)(n)) << 15) +#define WLAN_SET_FC_PVER(n) ((uint16_t)(n)) +#define WLAN_SET_FC_FTYPE(n) (((uint16_t)(n)) << 2) +#define WLAN_SET_FC_FSTYPE(n) (((uint16_t)(n)) << 4) +#define WLAN_SET_FC_TODS(n) (((uint16_t)(n)) << 8) +#define WLAN_SET_FC_FROMDS(n) (((uint16_t)(n)) << 9) +#define WLAN_SET_FC_MOREFRAG(n) (((uint16_t)(n)) << 10) +#define WLAN_SET_FC_RETRY(n) (((uint16_t)(n)) << 11) +#define WLAN_SET_FC_PWRMGT(n) (((uint16_t)(n)) << 12) +#define WLAN_SET_FC_MOREDATA(n) (((uint16_t)(n)) << 13) +#define WLAN_SET_FC_ISWEP(n) (((uint16_t)(n)) << 14) +#define WLAN_SET_FC_ORDER(n) (((uint16_t)(n)) << 15) /*--- Duration Macros ----------------------------------------*/ /* Macros to get/set the bitfields of the Duration Field */ @@ -203,45 +203,45 @@ FILE_LICENCE ( GPL2_ONLY ); /* Macros to get/set the bitfields of the Sequence Control */ /* Field. */ /*------------------------------------------------------------*/ -#define WLAN_GET_SEQ_FRGNUM(n) (((UINT16)(n)) & (BIT0|BIT1|BIT2|BIT3)) -#define WLAN_GET_SEQ_SEQNUM(n) ((((UINT16)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) +#define WLAN_GET_SEQ_FRGNUM(n) (((uint16_t)(n)) & (BIT0|BIT1|BIT2|BIT3)) +#define WLAN_GET_SEQ_SEQNUM(n) ((((uint16_t)(n)) & (~(BIT0|BIT1|BIT2|BIT3))) >> 4) /*--- Data ptr macro -----------------------------------------*/ -/* Creates a UINT8* to the data portion of a frame */ +/* Creates a uint8_t* to the data portion of a frame */ /* Assumes you're passing in a ptr to the beginning of the hdr*/ /*------------------------------------------------------------*/ -#define WLAN_HDR_A3_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A3_LEN) -#define WLAN_HDR_A4_DATAP(p) (((UINT8*)(p)) + WLAN_HDR_A4_LEN) +#define WLAN_HDR_A3_DATAP(p) (((uint8_t*)(p)) + WLAN_HDR_A3_LEN) +#define WLAN_HDR_A4_DATAP(p) (((uint8_t*)(p)) + WLAN_HDR_A4_LEN) -#define DOT11_RATE5_ISBASIC_GET(r) (((UINT8)(r)) & BIT7) +#define DOT11_RATE5_ISBASIC_GET(r) (((uint8_t)(r)) & BIT7) /*================================================================*/ /* Types */ /* BSS Timestamp */ -typedef UINT8 wlan_bss_ts_t[WLAN_BSS_TS_LEN]; +typedef uint8_t wlan_bss_ts_t[WLAN_BSS_TS_LEN]; /* Generic 802.11 Header types */ typedef struct p80211_hdr_a3 { - UINT16 fc; - UINT16 dur; - UINT8 a1[WLAN_ADDR_LEN]; - UINT8 a2[WLAN_ADDR_LEN]; - UINT8 a3[WLAN_ADDR_LEN]; - UINT16 seq; + uint16_t fc; + uint16_t dur; + uint8_t a1[WLAN_ADDR_LEN]; + uint8_t a2[WLAN_ADDR_LEN]; + uint8_t a3[WLAN_ADDR_LEN]; + uint16_t seq; } __WLAN_ATTRIB_PACK__ p80211_hdr_a3_t; typedef struct p80211_hdr_a4 { - UINT16 fc; - UINT16 dur; - UINT8 a1[WLAN_ADDR_LEN]; - UINT8 a2[WLAN_ADDR_LEN]; - UINT8 a3[WLAN_ADDR_LEN]; - UINT16 seq; - UINT8 a4[WLAN_ADDR_LEN]; + uint16_t fc; + uint16_t dur; + uint8_t a1[WLAN_ADDR_LEN]; + uint8_t a2[WLAN_ADDR_LEN]; + uint8_t a3[WLAN_ADDR_LEN]; + uint16_t seq; + uint8_t a4[WLAN_ADDR_LEN]; } __WLAN_ATTRIB_PACK__ p80211_hdr_a4_t; typedef union p80211_hdr @@ -273,9 +273,9 @@ typedef union p80211_hdr #define WLAN_FCS_LEN 4 /* ftcl in HOST order */ -inline static UINT16 p80211_headerlen(UINT16 fctl) +inline static uint16_t p80211_headerlen(uint16_t fctl) { - UINT16 hdrlen = 0; + uint16_t hdrlen = 0; switch ( WLAN_GET_FC_FTYPE(fctl) ) { case WLAN_FTYPE_MGMT: @@ -288,13 +288,13 @@ inline static UINT16 p80211_headerlen(UINT16 fctl) } break; case WLAN_FTYPE_CTL: - hdrlen = WLAN_CTL_FRAMELEN(WLAN_GET_FC_FSTYPE(fctl)) - - WLAN_FCS_LEN; + hdrlen = WLAN_CTL_FRAMELEN(WLAN_GET_FC_FSTYPE(fctl)) - + WLAN_FCS_LEN; break; default: hdrlen = WLAN_HDR_A3_LEN; } - + return hdrlen; } diff --git a/src/drivers/net/prism2.c b/src/drivers/net/prism2.c index d2160148..ad388074 100644 --- a/src/drivers/net/prism2.c +++ b/src/drivers/net/prism2.c @@ -69,10 +69,10 @@ static const char hardcoded_ssid[] = ""; #define __cpu_to_le16(x) (x) #define __cpu_to_le32(x) (x) -#define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n))) -#define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n))) -#define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n))) -#define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n))) +#define hfa384x2host_16(n) (__le16_to_cpu((uint16_t)(n))) +#define hfa384x2host_32(n) (__le32_to_cpu((uint32_t)(n))) +#define host2hfa384x_16(n) (__cpu_to_le16((uint16_t)(n))) +#define host2hfa384x_32(n) (__cpu_to_le32((uint32_t)(n))) /* * PLX9052 PCI register offsets @@ -119,14 +119,14 @@ static const char hardcoded_ssid[] = ""; typedef struct hfa384x { - UINT32 iobase; + uint32_t iobase; void *membase; - UINT16 lastcmd; - UINT16 status; /* in host order */ - UINT16 resp0; /* in host order */ - UINT16 resp1; /* in host order */ - UINT16 resp2; /* in host order */ - UINT8 bssid[WLAN_BSSID_LEN]; + uint16_t lastcmd; + uint16_t status; /* in host order */ + uint16_t resp0; /* in host order */ + uint16_t resp1; /* in host order */ + uint16_t resp2; /* in host order */ + uint8_t bssid[WLAN_BSSID_LEN]; } hfa384x_t; /* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */ @@ -141,9 +141,9 @@ static hfa384x_t hw_global = { typedef struct wlan_llc { - UINT8 dsap; - UINT8 ssap; - UINT8 ctl; + uint8_t dsap; + uint8_t ssap; + uint8_t ctl; } wlan_llc_t; static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */ @@ -151,8 +151,8 @@ static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indi #define WLAN_IEEE_OUI_LEN 3 typedef struct wlan_snap { - UINT8 oui[WLAN_IEEE_OUI_LEN]; - UINT16 type; + uint8_t oui[WLAN_IEEE_OUI_LEN]; + uint16_t type; } wlan_snap_t; typedef struct wlan_80211hdr @@ -168,11 +168,11 @@ typedef struct wlan_80211hdr /* * Hardware-level hfa384x functions * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined). - * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions. + * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions. */ /* Retrieve the value of one of the MAC registers. */ -static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg ) +static inline uint16_t hfa384x_getreg( hfa384x_t *hw, unsigned int reg ) { #if (WLAN_HOSTIF == WLAN_PLX) return inw ( hw->iobase + reg ); @@ -182,7 +182,7 @@ static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg ) } /* Set the value of one of the MAC registers. */ -static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg ) +static inline void hfa384x_setreg( hfa384x_t *hw, uint16_t val, unsigned int reg ) { #if (WLAN_HOSTIF == WLAN_PLX) outw ( val, hw->iobase + reg ); @@ -192,15 +192,15 @@ static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg ) return; } -/* +/* * Noswap versions * Etherboot is i386 only, so swap and noswap are the same... */ -static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg ) +static inline uint16_t hfa384x_getreg_noswap( hfa384x_t *hw, unsigned int reg ) { return hfa384x_getreg ( hw, reg ); } -static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg ) +static inline void hfa384x_setreg_noswap( hfa384x_t *hw, uint16_t val, unsigned int reg ) { hfa384x_setreg ( hw, val, reg ); } @@ -227,12 +227,12 @@ static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg ) * >0 command indicated error, Status and Resp0-2 are * in hw structure. */ -static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2) +static int hfa384x_docmd_wait( hfa384x_t *hw, uint16_t cmd, uint16_t parm0, uint16_t parm1, uint16_t parm2) { - UINT16 reg = 0; - UINT16 counter = 0; - - /* wait for the busy bit to clear */ + uint16_t reg = 0; + uint16_t counter = 0; + + /* wait for the busy bit to clear */ counter = 0; reg = hfa384x_getreg(hw, HFA384x_CMD); while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) { @@ -251,7 +251,7 @@ static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 p hfa384x_setreg(hw, parm2, HFA384x_PARAM2); hw->lastcmd = cmd; hfa384x_setreg(hw, cmd, HFA384x_CMD); - + /* Now wait for completion */ counter = 0; reg = hfa384x_getreg(hw, HFA384x_EVSTAT); @@ -286,14 +286,14 @@ static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 p * hw device structure * id FID or RID, destined for the select register (host order) * offset An _even_ offset into the buffer for the given FID/RID. - * Returns: + * Returns: * 0 success */ -static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset) +static int hfa384x_prepare_bap(hfa384x_t *hw, uint16_t id, uint16_t offset) { int result = 0; - UINT16 reg; - UINT16 i; + uint16_t reg; + uint16_t i; /* Validate offset, buf, and len */ if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) { @@ -304,7 +304,7 @@ static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset) udelay(10); hfa384x_setreg(hw, offset, HFA384x_OFFSET0); /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */ - i = 0; + i = 0; do { reg = hfa384x_getreg(hw, HFA384x_OFFSET0); if ( i > 0 ) udelay(2); @@ -330,28 +330,28 @@ static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset) * offset An _even_ offset into the buffer for the given FID/RID. * buf ptr to array of bytes * len length of data to transfer in bytes - * Returns: + * Returns: * 0 success */ -static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset, - void *buf, UINT len) +static int hfa384x_copy_from_bap(hfa384x_t *hw, uint16_t id, uint16_t offset, + void *buf, unsigned int len) { int result = 0; - UINT8 *d = (UINT8*)buf; - UINT16 i; - UINT16 reg = 0; - + uint8_t *d = (uint8_t*)buf; + uint16_t i; + uint16_t reg = 0; + /* Prepare BAP */ result = hfa384x_prepare_bap ( hw, id, offset ); if ( result == 0 ) { /* Read even(len) buf contents from data reg */ for ( i = 0; i < (len & 0xfffe); i+=2 ) { - *(UINT16*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0); + *(uint16_t*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0); } /* If len odd, handle last byte */ if ( len % 2 ){ reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0); - d[len-1] = ((UINT8*)(®))[0]; + d[len-1] = ((uint8_t*)(®))[0]; } } if (result) { @@ -369,30 +369,30 @@ static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset, * offset An _even_ offset into the buffer for the given FID/RID. * buf ptr to array of bytes * len length of data to transfer in bytes - * Returns: + * Returns: * 0 success */ -static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset, - void *buf, UINT len) +static int hfa384x_copy_to_bap(hfa384x_t *hw, uint16_t id, uint16_t offset, + void *buf, unsigned int len) { int result = 0; - UINT8 *d = (UINT8*)buf; - UINT16 i; - UINT16 savereg; + uint8_t *d = (uint8_t*)buf; + uint16_t i; + uint16_t savereg; /* Prepare BAP */ result = hfa384x_prepare_bap ( hw, id, offset ); if ( result == 0 ) { /* Write even(len) buf contents to data reg */ for ( i = 0; i < (len & 0xfffe); i+=2 ) { - hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), HFA384x_DATA0); + hfa384x_setreg_noswap(hw, *(uint16_t*)(&(d[i])), HFA384x_DATA0); } /* If len odd, handle last byte */ if ( len % 2 ){ savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0); result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) ); if ( result == 0 ) { - ((UINT8*)(&savereg))[0] = d[len-1]; + ((uint8_t*)(&savereg))[0] = d[len-1]; hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0); } } @@ -412,10 +412,10 @@ static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset, * configuration record. (host order) * rid RID of the record to read/write. (host order) * - * Returns: + * Returns: * 0 success */ -static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid) +static inline int hfa384x_cmd_access(hfa384x_t *hw, uint16_t write, uint16_t rid) { return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0); } @@ -427,14 +427,14 @@ static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid) * hw device structure * rid config/info record id (host order) * buf host side record buffer. Upon return it will - * contain the body portion of the record (minus the + * contain the body portion of the record (minus the * RID and len). * len buffer length (in bytes, should match record length) * - * Returns: + * Returns: * 0 success */ -static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +static int hfa384x_drvr_getconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len) { int result = 0; hfa384x_rec_t rec; @@ -469,27 +469,27 @@ static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 l * rid config/info record id (in host order) * val ptr to 16/32 bit buffer to receive value (in host order) * - * Returns: + * Returns: * 0 success */ #if 0 /* Not actually used anywhere */ -static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val) +static int hfa384x_drvr_getconfig16(hfa384x_t *hw, uint16_t rid, void *val) { int result = 0; - result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16)); + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint16_t)); if ( result == 0 ) { - *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val)); + *((uint16_t*)val) = hfa384x2host_16(*((uint16_t*)val)); } return result; } #endif #if 0 /* Not actually used anywhere */ -static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val) +static int hfa384x_drvr_getconfig32(hfa384x_t *hw, uint16_t rid, void *val) { int result = 0; - result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32)); + result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint32_t)); if ( result == 0 ) { - *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val)); + *((uint32_t*)val) = hfa384x2host_32(*((uint32_t*)val)); } return result; } @@ -504,10 +504,10 @@ static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val) * buf host side record buffer * len buffer length (in bytes) * - * Returns: + * Returns: * 0 success */ -static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len) +static int hfa384x_drvr_setconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len) { int result = 0; hfa384x_rec_t rec; @@ -541,21 +541,21 @@ static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 l * rid config/info record id (in host order) * val 16/32 bit value to store (in host order) * - * Returns: + * Returns: * 0 success */ -static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val) +static int hfa384x_drvr_setconfig16(hfa384x_t *hw, uint16_t rid, uint16_t *val) { - UINT16 value; + uint16_t value; value = host2hfa384x_16(*val); - return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16)); + return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint16_t)); } #if 0 /* Not actually used anywhere */ -static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val) +static int hfa384x_drvr_setconfig32(hfa384x_t *hw, uint16_t rid, uint32_t *val) { - UINT32 value; + uint32_t value; value = host2hfa384x_32(*val); - return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32)); + return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint32_t)); } #endif @@ -573,14 +573,14 @@ static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val) * descr Descriptive text string of what is being waited for * (will be printed out if a timeout happens) * - * Returns: - * value of EVSTAT register, or 0 on failure + * Returns: + * value of EVSTAT register, or 0 on failure */ -static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr) +static int hfa384x_wait_for_event(hfa384x_t *hw, uint16_t event_mask, uint16_t event_ack, int wait, int timeout, const char *descr) { - UINT16 reg; + uint16_t reg; int count = 0; - + do { reg = hfa384x_getreg(hw, HFA384x_EVSTAT); if ( count > 0 ) udelay(wait); @@ -600,12 +600,12 @@ POLL - Wait for a frame ***************************************************************************/ static int prism2_poll(struct nic *nic, int retrieve) { - UINT16 reg; - UINT16 rxfid; - UINT16 result; + uint16_t reg; + uint16_t rxfid; + uint16_t result; hfa384x_rx_frame_t rxdesc; hfa384x_t *hw = &hw_global; - + /* Check for received packet */ reg = hfa384x_getreg(hw, HFA384x_EVSTAT); if ( ! HFA384x_EVSTAT_ISRX(reg) ) { @@ -617,7 +617,7 @@ static int prism2_poll(struct nic *nic, int retrieve) /* Acknowledge RX event */ hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK); - /* Get RX FID */ + /* Get RX FID */ rxfid = hfa384x_getreg(hw, HFA384x_RXFID); /* Get the descriptor (including headers) */ result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc)); @@ -660,8 +660,8 @@ static void prism2_transmit( hfa384x_t *hw = &hw_global; hfa384x_tx_frame_t txdesc; wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} }; - UINT16 fid; - UINT16 status; + uint16_t fid; + uint16_t status; int result; // Request FID allocation @@ -675,7 +675,7 @@ static void prism2_transmit( /* Build Tx frame structure */ memset(&txdesc, 0, sizeof(txdesc)); - txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | + txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) ); txdesc.frame_control = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) | WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) | @@ -687,13 +687,13 @@ static void prism2_transmit( /* Set up SNAP header */ /* Let OUI default to RFC1042 (0x000000) */ p80211hdr.snap.type = htons(t); - + /* Copy txdesc, p80211hdr and payload parts to FID */ result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc)); if ( result ) return; /* fail */ result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) ); if ( result ) return; /* fail */ - result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (UINT8*)p, s ); + result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (uint8_t*)p, s ); if ( result ) return; /* fail */ /* Issue Tx command */ @@ -702,7 +702,7 @@ static void prism2_transmit( printf("hfa384x: Transmit failed with result %#hx.\n", result); return; } - + /* Wait for transmit completion (or exception) */ result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO, 200, 500, "Tx to complete\n" ); @@ -760,8 +760,8 @@ You should omit the last argument struct pci_device * for a non-PCI NIC ***************************************************************************/ static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) { int result; - UINT16 tmp16 = 0; - UINT16 infofid; + uint16_t tmp16 = 0; + uint16_t infofid; hfa384x_InfFrame_t inf; char ssid[HFA384x_RID_CNFDESIREDSSID_LEN]; int info_count = 0; @@ -820,17 +820,17 @@ static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) { } else { printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count ); } - + if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0; printf("done\n"); infofid = hfa384x_getreg(hw, HFA384x_INFOFID); /* Retrieve the length */ - result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(UINT16)); + result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(uint16_t)); if ( result ) return 0; /* fail */ inf.framelen = hfa384x2host_16(inf.framelen); /* Retrieve the rest */ - result = hfa384x_copy_from_bap( hw, infofid, sizeof(UINT16), - &(inf.infotype), inf.framelen * sizeof(UINT16)); + result = hfa384x_copy_from_bap( hw, infofid, sizeof(uint16_t), + &(inf.infotype), inf.framelen * sizeof(uint16_t)); if ( result ) return 0; /* fail */ if ( inf.infotype != HFA384x_IT_LINKSTATUS ) { /* Not a Link Status info frame: die */ @@ -843,13 +843,13 @@ static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) { printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus ); } } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ); - + /* Retrieve BSSID and print Connected message */ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN); DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) ); DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) ); - + /* point to NIC specific routines */ nic->nic_op = &prism2_operations; return 1; diff --git a/src/drivers/net/wlan_compat.h b/src/drivers/net/wlan_compat.h index 9b7693bb..5b7b2f3c 100644 --- a/src/drivers/net/wlan_compat.h +++ b/src/drivers/net/wlan_compat.h @@ -39,7 +39,7 @@ * * -------------------------------------------------------------------- * -* Portions of the development of this software were funded by +* Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development. * * -------------------------------------------------------------------- @@ -109,7 +109,7 @@ FILE_LICENCE ( GPL2_ONLY ); /* Lets try to figure out what we've got. Kernel mode or User mode? */ #if defined(__KERNEL__) #define WLAN_OS WLAN_LINUX_KERNEL -#else +#else #define WLAN_OS WLAN_LINUX_USER #endif @@ -179,8 +179,8 @@ FILE_LICENCE ( GPL2_ONLY ); Linux/PPC on PowerMacs (PCI) Arm/Intel Xscale (PCI) - This may also affect PLX boards and other BE &| PPC platforms; - as new ones are discovered, add them below. + This may also affect PLX boards and other BE &| PPC platforms; + as new ones are discovered, add them below. */ #if (WLAN_HOSTIF == WLAN_PCI) @@ -226,28 +226,6 @@ FILE_LICENCE ( GPL2_ONLY ); #define BIT30 0x40000000 #define BIT31 0x80000000 -typedef unsigned char UINT8; -typedef unsigned short UINT16; -typedef unsigned long UINT32; - -typedef signed char INT8; -typedef signed short INT16; -typedef signed long INT32; - -typedef unsigned int UINT; -typedef signed int INT; - -typedef unsigned long long UINT64; -typedef signed long long INT64; - -#define UINT8_MAX (0xffUL) -#define UINT16_MAX (0xffffUL) -#define UINT32_MAX (0xffffffffUL) - -#define INT8_MAX (0x7fL) -#define INT16_MAX (0x7fffL) -#define INT32_MAX (0x7fffffffL) - /*=============================================================*/ /*------ Compiler Portability Macros --------------------------*/ /*=============================================================*/ @@ -298,7 +276,7 @@ typedef signed long long INT64; int __i__; \ printk(KERN_DEBUG x ":"); \ for( __i__=0; __i__ < (n); __i__++) \ - printk( " %02x", ((UINT8*)(p))[__i__]); \ + printk( " %02x", ((uint8_t*)(p))[__i__]); \ printk("\n"); } #define DBFENTER { if ( WLAN_DBVAR >= 4 ){ WLAN_LOG_DEBUG0(3,"Enter\n"); } } @@ -312,11 +290,11 @@ typedef signed long long INT64; #define WLAN_LOG_DEBUG5(l,x,n1,n2,n3,n4,n5) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n1), (n2), (n3), (n4), (n5)); #define WLAN_LOG_DEBUG6(l,x,n1,n2,n3,n4,n5,n6) if ( WLAN_DBVAR >= (l)) printk(KERN_DEBUG "%s: " x , __FUNCTION__ , (n1), (n2), (n3), (n4), (n5), (n6)); #else - #define WLAN_ASSERT(c) + #define WLAN_ASSERT(c) #define WLAN_HEX_DUMP( l, s, p, n) - #define DBFENTER - #define DBFEXIT + #define DBFENTER + #define DBFEXIT #define WLAN_LOG_DEBUG0(l, s) #define WLAN_LOG_DEBUG1(l, s,n) @@ -344,11 +322,11 @@ typedef signed long long INT64; #define WLAN_LOG_NOTICE3(s,n1,n2,n3) #define WLAN_LOG_NOTICE4(s,n1,n2,n3,n4) - #define WLAN_ASSERT(c) + #define WLAN_ASSERT(c) #define WLAN_HEX_DUMP( l, s, p, n) - #define DBFENTER - #define DBFEXIT + #define DBFENTER + #define DBFEXIT #define WLAN_LOG_INFO0(s) #define WLAN_LOG_INFO1(s,n) @@ -378,7 +356,7 @@ typedef signed long long INT64; #ifdef CONFIG_SMP #define __SMP__ 1 -#endif +#endif #ifndef KERNEL_VERSION #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) From 6979b7a2d35bdc5fa5d691a20a3620992c824985 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 27 Mar 2013 21:23:21 +0000 Subject: [PATCH 249/250] [efi] Fetch device path for loaded image during initialisation Signed-off-by: Michael Brown --- src/include/ipxe/efi/efi.h | 1 + src/interface/efi/efi_init.c | 50 ++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index 46b66690..3aaac60e 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -127,6 +127,7 @@ struct efi_config_table { extern EFI_HANDLE efi_image_handle; extern EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; +extern EFI_DEVICE_PATH_PROTOCOL *efi_loaded_image_path; extern EFI_SYSTEM_TABLE *efi_systab; extern const char * efi_strerror ( EFI_STATUS efirc ); diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index 48cac538..e40de4dd 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include #include #include @@ -31,6 +32,9 @@ EFI_HANDLE efi_image_handle; /** Loaded image protocol for this image */ EFI_LOADED_IMAGE_PROTOCOL *efi_loaded_image; +/** Loaded image protocol device path for this image */ +EFI_DEVICE_PATH_PROTOCOL *efi_loaded_image_path; + /** System table passed to entry point */ EFI_SYSTEM_TABLE *efi_systab; @@ -38,6 +42,10 @@ EFI_SYSTEM_TABLE *efi_systab; static EFI_GUID efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; +/** EFI loaded image device path protocol GUID */ +static EFI_GUID efi_loaded_image_device_path_protocol_guid + = EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID; + /** Event used to signal shutdown */ static EFI_EVENT efi_shutdown_event; @@ -83,8 +91,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, EFI_BOOT_SERVICES *bs; struct efi_protocol *prot; struct efi_config_table *tab; - EFI_STATUS efirc; void *loaded_image; + void *loaded_image_path; + EFI_STATUS efirc; /* Store image handle and system table pointer for future use */ efi_image_handle = image_handle; @@ -105,19 +114,7 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, return EFI_NOT_AVAILABLE_YET; } DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab ); - bs = systab->BootServices; - efirc = bs->OpenProtocol ( image_handle, - &efi_loaded_image_protocol_guid, - &loaded_image, image_handle, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL ); - if ( efirc ) { - DBGC ( systab, "Could not get loaded image protocol" ); - return efirc; - } - - efi_loaded_image = loaded_image; - DBG ( "Image base address = %p\n", efi_loaded_image->ImageBase ); /* Look up used protocols */ for_each_table_entry ( prot, EFI_PROTOCOLS ) { @@ -147,6 +144,33 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, } } + /* Get loaded image protocol */ + if ( ( efirc = bs->OpenProtocol ( image_handle, + &efi_loaded_image_protocol_guid, + &loaded_image, image_handle, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { + DBGC ( systab, "EFI could not get loaded image protocol: %s", + efi_strerror ( efirc ) ); + return efirc; + } + efi_loaded_image = loaded_image; + DBGC ( systab, "EFI image base address %p\n", + efi_loaded_image->ImageBase ); + + /* Get loaded image device path protocol */ + if ( ( efirc = bs->OpenProtocol ( image_handle, + &efi_loaded_image_device_path_protocol_guid, + &loaded_image_path, image_handle, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL ) ) != 0 ) { + DBGC ( systab, "EFI could not get loaded image device path " + "protocol: %s", efi_strerror ( efirc ) ); + return efirc; + } + efi_loaded_image_path = loaded_image_path; + DBGC ( systab, "EFI image device path " ); + DBGC_EFI_DEVPATH ( systab, efi_loaded_image_path ); + DBGC ( systab, "\n" ); + /* EFI is perfectly capable of gracefully shutting down any * loaded devices if it decides to fall back to a legacy boot. * For no particularly comprehensible reason, it doesn't From 0e2ba15a5831fb6d5ddecfb56cb5e927a94bcf95 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sat, 6 Apr 2013 11:27:27 +0100 Subject: [PATCH 250/250] [settings] Expose build architecture and platform via settings Expose the build architecture (e.g. "i386" or "x86_64") via ${buildarch} and the firmware platform (e.g. "pcbios" or "efi") via ${platform}. These settings directly expose the ARCH and PLATFORM variables from the Makefile. Note that the build architecture reflects the architecture for which iPXE was compiled, not the architecture on which iPXE is currently running. The "cpuid" command can be used to detect a 64-bit system at runtime. Requested-by: James A. Peltier Signed-off-by: Michael Brown --- src/core/settings.c | 100 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 15 deletions(-) diff --git a/src/core/settings.c b/src/core/settings.c index 656ae19f..43715fbd 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -1985,6 +1985,19 @@ struct setting priority_setting __setting ( SETTING_MISC ) = { ****************************************************************************** */ +/** A built-in setting operation */ +struct builtin_setting_operation { + /** Setting */ + struct setting *setting; + /** Fetch setting value + * + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ + int ( * fetch ) ( void *data, size_t len ); +}; + /** Built-in setting tag magic */ #define BUILTIN_SETTING_TAG_MAGIC 0xb1 @@ -2010,15 +2023,11 @@ struct setting errno_setting __setting ( SETTING_MISC ) = { /** * Fetch error number setting * - * @v settings Settings block - * @v setting Setting to fetch - * @v data Setting data, or NULL to clear setting - * @v len Length of setting data - * @ret rc Return status code + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error */ -static int errno_fetch ( struct settings *settings __unused, - struct setting *setting __unused, - void *data, size_t len ) { +static int errno_fetch ( void *data, size_t len ) { uint32_t content; /* Return current error */ @@ -2029,24 +2038,85 @@ static int errno_fetch ( struct settings *settings __unused, return sizeof ( content ); } +/** "buildarch" setting tag */ +#define BUILTIN_SETTING_TAG_BUILDARCH BUILTIN_SETTING_TAG ( 0x02 ) + +/** Build architecture setting */ +struct setting buildarch_setting __setting ( SETTING_MISC ) = { + .name = "buildarch", + .description = "Build architecture", + .tag = BUILTIN_SETTING_TAG_BUILDARCH, + .type = &setting_type_string, +}; + +/** + * Fetch build architecture setting + * + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int buildarch_fetch ( void *data, size_t len ) { + static const char buildarch[] = _S2 ( ARCH ); + + strncpy ( data, buildarch, len ); + return ( sizeof ( buildarch ) - 1 /* NUL */ ); +} + +/** "platform" setting tag */ +#define BUILTIN_SETTING_TAG_PLATFORM BUILTIN_SETTING_TAG ( 0x03 ) + +/** Platform setting */ +struct setting platform_setting __setting ( SETTING_MISC ) = { + .name = "platform", + .description = "Platform", + .tag = BUILTIN_SETTING_TAG_PLATFORM, + .type = &setting_type_string, +}; + +/** + * Fetch platform setting + * + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error + */ +static int platform_fetch ( void *data, size_t len ) { + static const char platform[] = _S2 ( PLATFORM ); + + strncpy ( data, platform, len ); + return ( sizeof ( platform ) - 1 /* NUL */ ); +} + +/** List of built-in setting operations */ +static struct builtin_setting_operation builtin_setting_operations[] = { + { &errno_setting, errno_fetch }, + { &buildarch_setting, buildarch_fetch }, + { &platform_setting, platform_fetch }, +}; + /** * Fetch built-in setting * * @v settings Settings block * @v setting Setting to fetch - * @v data Setting data, or NULL to clear setting - * @v len Length of setting data - * @ret rc Return status code + * @v data Buffer to fill with setting data + * @v len Length of buffer + * @ret len Length of setting data, or negative error */ static int builtin_fetch ( struct settings *settings __unused, struct setting *setting, void *data, size_t len ) { + struct builtin_setting_operation *builtin; + unsigned int i; - if ( setting_cmp ( setting, &errno_setting ) == 0 ) { - return errno_fetch ( settings, setting, data, len ); - } else { - return -ENOENT; + for ( i = 0 ; i < ( sizeof ( builtin_setting_operations ) / + sizeof ( builtin_setting_operations[0] ) ) ; i++ ) { + builtin = &builtin_setting_operations[i]; + if ( setting_cmp ( setting, builtin->setting ) == 0 ) + return builtin->fetch ( data, len ); } + return -ENOENT; } /**