[syslinux:lwip] Additional sysappend strings from DMI; pre-bake the http cookies
syslinux-bot for H. Peter Anvin
hpa at linux.intel.com
Tue Apr 26 14:45:20 PDT 2011
Commit-ID: b6401220c0bf7482ad5b204d08ba831a7cf9eabb
Gitweb: http://syslinux.zytor.com/commit/b6401220c0bf7482ad5b204d08ba831a7cf9eabb
Author: H. Peter Anvin <hpa at linux.intel.com>
AuthorDate: Tue, 26 Apr 2011 14:41:31 -0700
Committer: H. Peter Anvin <hpa at linux.intel.com>
CommitDate: Tue, 26 Apr 2011 14:41:31 -0700
Additional sysappend strings from DMI; pre-bake the http cookies
- Add additional sysappend strings from DMI; we may want to add even
more but let's think about it first.
- Pre-generate http cookies.
- Add a "sendcookies" command to mask out some of the information.
Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>
---
com32/include/syslinux/sysappend.h | 6 +-
com32/lib/Makefile | 2 +-
core/dmi.c | 256 ++++++++++++++++++++++++++++++++++++
core/extern.inc | 5 +-
core/fs/pxe/http.c | 61 +++++----
core/fs/pxe/pxe.c | 111 ++--------------
core/fs/pxe/pxe.h | 1 +
core/include/core.h | 1 +
core/init.inc | 6 +
core/keywords | 1 +
core/keywords.inc | 3 +
core/parseconfig.inc | 9 ++
core/sysappend.c | 67 +++++++++-
13 files changed, 401 insertions(+), 128 deletions(-)
diff --git a/com32/include/syslinux/sysappend.h b/com32/include/syslinux/sysappend.h
index dcc42dc..b767bf2 100644
--- a/com32/include/syslinux/sysappend.h
+++ b/com32/include/syslinux/sysappend.h
@@ -37,7 +37,11 @@
enum syslinux_sysappend {
SYSAPPEND_IP, /* PXELINUX: ip= address */
SYSAPPEND_BOOTIF, /* PXELINUX: BOOTIF= address */
- SYSAPPEND_UUID, /* System UUID from PXE or DMI */
+ SYSAPPEND_SYSUUID, /* System UUID from PXE or DMI */
+ SYSAPPEND_SYSVENDOR, /* System vendor from DMI */
+ SYSAPPEND_SYSPRODUCT, /* System product from DMI */
+ SYSAPPEND_SYSVERSION, /* System version from DMI */
+ SYSAPPEND_SYSSERIAL, /* System serial from DMI */
SYSAPPEND_MAX /* Total number of strings */
};
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 105c2bd..20002ac 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -134,7 +134,7 @@ LIBCOREOBJS = \
strlen.o stpcpy.o strcpy.o strcmp.o strlcpy.o strlcat.o \
strchr.o strncmp.o strncpy.o \
\
- snprintf.o sprintf.o vsnprintf.o \
+ asprintf.o snprintf.o sprintf.o vsnprintf.o \
\
dprintf.o vdprintf.o \
\
diff --git a/core/dmi.c b/core/dmi.c
new file mode 100644
index 0000000..674d27c
--- /dev/null
+++ b/core/dmi.c
@@ -0,0 +1,256 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2011 Intel Corporation; author: H. Peter Anvin
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Search DMI information for specific data or strings
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <syslinux/sysappend.h>
+#include "core.h"
+
+struct dmi_table {
+ uint8_t type;
+ uint8_t length;
+ uint16_t handle;
+};
+
+struct dmi_header {
+ char signature[5];
+ uint8_t csum;
+ uint16_t tbllen;
+ uint32_t tbladdr;
+ uint16_t nstruc;
+ uint8_t revision;
+ uint8_t reserved;
+};
+
+struct smbios_header {
+ char signature[4];
+ uint8_t csum;
+ uint8_t len;
+ uint8_t major;
+ uint8_t minor;
+ uint16_t maxsize;
+ uint8_t revision;
+ uint8_t fmt[5];
+
+ struct dmi_header dmi;
+};
+
+static const struct dmi_header *dmi;
+
+static uint8_t checksum(const void *buf, size_t len)
+{
+ const uint8_t *p = buf;
+ uint8_t csum = 0;
+
+ while (len--)
+ csum += *p++;
+
+ return csum;
+}
+
+static bool is_old_dmi(size_t dptr)
+{
+ const struct dmi_header *dmi = (void *)dptr;
+
+ return !memcmp(dmi->signature, "_DMI_", 5) &&
+ !checksum(dmi, 0x0f);
+ return false;
+}
+
+static bool is_smbios(size_t dptr)
+{
+ const struct smbios_header *smb = (void *)dptr;
+
+ return !memcmp(smb->signature, "_SM_", 4) &&
+ !checksum(smb, smb->len) &&
+ is_old_dmi(dptr+16);
+}
+
+/*
+ * Find the root structure
+ */
+static void dmi_find_header(void)
+{
+ size_t dptr;
+
+ /* Search for _SM_ or _DMI_ structure */
+ for (dptr = 0xf0000 ; dptr < 0x100000 ; dptr += 16) {
+ if (is_smbios(dptr)) {
+ dmi = (const struct dmi_header *)(dptr + 16);
+ break;
+ } else if (is_old_dmi(dptr)) {
+ dmi = (const struct dmi_header *)dptr;
+ break;
+ }
+ }
+}
+
+/*
+ * Return a specific data element in a specific table, and verify
+ * that it is within the bounds of the table.
+ */
+static const void *dmi_find_data(uint8_t type, uint8_t base, uint8_t length)
+{
+ const struct dmi_table *table;
+ size_t offset, end;
+ unsigned int tblcount;
+
+ if (!dmi)
+ return NULL;
+
+ if (base < 2)
+ return NULL;
+
+ end = base+length;
+
+ offset = 0;
+ tblcount = dmi->nstruc;
+
+ while (offset+2 < dmi->tbllen && tblcount) {
+ table = (const struct dmi_table *)(dmi->tbladdr + offset);
+
+ if (table->length < sizeof *table)
+ break; /* Invalid length */
+
+ offset += table->length;
+
+ if (table->type == type && end <= table->length)
+ return (const char *)table + base;
+
+ /* Search for a double NUL terminating the string table */
+ while (offset+2 < dmi->tbllen &&
+ *(const uint16_t *)(dmi->tbladdr + offset) != 0)
+ offset++;
+
+ offset += 2;
+ tblcount--;
+ }
+
+ return NULL;
+}
+
+/*
+ * Return a specific string in a specific table.
+ */
+static const char *dmi_find_string(uint8_t type, uint8_t base)
+{
+ const struct dmi_table *table;
+ size_t offset;
+ unsigned int tblcount;
+
+ if (!dmi)
+ return NULL;
+
+ if (base < 2)
+ return NULL;
+
+ offset = 0;
+ tblcount = dmi->nstruc;
+
+ while (offset+2 < dmi->tbllen && tblcount) {
+ table = (const struct dmi_table *)(dmi->tbladdr + offset);
+
+ if (table->length < sizeof *table)
+ break; /* Invalid length */
+
+ offset += table->length;
+
+ if (table->type == type && base < table->length) {
+ uint8_t index = ((const uint8_t *)table)[base];
+ const char *p = (const char *)table + table->length;
+ char c;
+
+ if (!index)
+ return NULL; /* String not present */
+
+ while (--index) {
+ if (!*p)
+ return NULL;
+
+ do {
+ c = *p;
+ if (++offset >= dmi->tbllen)
+ return NULL;
+ p++;
+ } while (c);
+ }
+
+ return p;
+ }
+
+ /* Search for a double NUL terminating the string table */
+ while (offset+2 < dmi->tbllen &&
+ *(const uint16_t *)(dmi->tbladdr + offset) != 0)
+ offset++;
+
+ offset += 2;
+ }
+
+ return NULL;
+}
+
+struct sysappend_dmi_strings {
+ const char *prefix;
+ enum syslinux_sysappend sa;
+ uint8_t index;
+ uint8_t offset;
+};
+
+static const struct sysappend_dmi_strings dmi_strings[] = {
+ { "SYSVENDOR=", SYSAPPEND_SYSVENDOR, 1, 0x04 },
+ { "SYSPRODUCT=", SYSAPPEND_SYSPRODUCT, 1, 0x05 },
+ { "SYSVERSION=", SYSAPPEND_SYSVERSION, 1, 0x06 },
+ { "SYSSERIAL=", SYSAPPEND_SYSSERIAL, 1, 0x07 },
+ { NULL, 0, 0, 0 }
+};
+
+void dmi_init(void)
+{
+ const struct sysappend_dmi_strings *ds;
+
+ dmi_find_header();
+ if (!dmi)
+ return;
+
+ sysappend_set_uuid(dmi_find_data(1, 0x08, 16));
+
+ for (ds = dmi_strings; ds->prefix; ds++) {
+ const char *str = dmi_find_string(ds->index, ds->offset);
+
+ if (sysappend_strings[ds->sa]) {
+ free((char *)sysappend_strings[ds->sa]);
+ sysappend_strings[ds->sa] = NULL;
+ }
+ if (str)
+ asprintf((char **)&sysappend_strings[ds->sa],
+ "%s%s", ds->prefix, str);
+ }
+}
diff --git a/core/extern.inc b/core/extern.inc
index 433d55e..3858f70 100644
--- a/core/extern.inc
+++ b/core/extern.inc
@@ -30,9 +30,12 @@
; sysappend.c
extern do_sysappend, print_sysappend
+ ; dmi.c
+ extern dmi_init
+
%if IS_PXELINUX
; pxe.c
- extern unload_pxe, reset_pxe
+ extern unload_pxe, reset_pxe, http_bake_cookies
%endif
%endif ; EXTERN_INC
diff --git a/core/fs/pxe/http.c b/core/fs/pxe/http.c
index ae5e010..d98cc4a 100644
--- a/core/fs/pxe/http.c
+++ b/core/fs/pxe/http.c
@@ -46,8 +46,10 @@ static bool append_ch(char *str, size_t size, size_t *pos, int ch)
return success;
}
-static size_t cookie_len;
-static char *cookie_buf;
+static size_t cookie_len, header_len;
+static char *cookie_buf, *header_buf;
+
+extern uint32_t SendCookies;
static size_t http_do_bake_cookies(char *q)
{
@@ -59,9 +61,10 @@ static size_t http_do_bake_cookies(char *q)
char c;
size_t qlen = q ? -1UL : 0;
bool first = true;
+ uint32_t mask = SendCookies;
for (i = 0; i < SYSAPPEND_MAX; i++) {
- if ((p = sysappend_strings[i])) {
+ if ((mask & 1) && (p = sysappend_strings[i])) {
len = snprintf(q, qlen, "%s_Syslinux_", first ? "Cookie: " : "");
if (q)
q += len;
@@ -96,6 +99,7 @@ static size_t http_do_bake_cookies(char *q)
*q++ = ';';
n++;
}
+ mask >>= 1;
}
if (!first) {
if (q) {
@@ -117,8 +121,20 @@ void http_bake_cookies(void)
cookie_len = http_do_bake_cookies(NULL);
cookie_buf = malloc(cookie_len+1);
- if (!cookie_buf)
+ if (!cookie_buf) {
+ cookie_len = 0;
return;
+ }
+
+ if (header_buf)
+ free(header_buf);
+
+ header_len = cookie_len + 6*FILENAME_MAX + 256;
+ header_buf = malloc(header_len);
+ if (!header_buf) {
+ header_len = 0;
+ return; /* Uh-oh... */
+ }
http_do_bake_cookies(cookie_buf);
}
@@ -126,8 +142,7 @@ void http_bake_cookies(void)
void http_open(struct url_info *url, struct inode *inode, const char **redir)
{
struct pxe_pvt_inode *socket = PVT(inode);
- char header_buf[4096];
- int header_len;
+ int header_bytes;
const char *next;
char field_name[20];
char field_value[1024];
@@ -151,9 +166,8 @@ void http_open(struct url_info *url, struct inode *inode, const char **redir)
int status;
int pos;
- /* XXX: make this an external call at the appropriate time instead */
- if (!cookie_buf)
- http_bake_cookies();
+ if (!header_buf)
+ return; /* http is broken... */
socket->fill_buffer = tcp_fill_buffer;
socket->close = tcp_close_file;
@@ -178,26 +192,25 @@ void http_open(struct url_info *url, struct inode *inode, const char **redir)
}
strcpy(header_buf, "GET /");
- header_len = 5;
- header_len += url_escape_unsafe(header_buf+5, url->path,
+ header_bytes = 5;
+ header_bytes += url_escape_unsafe(header_buf+5, url->path,
sizeof header_buf - 5);
- if (header_len > sizeof header_buf)
+ if (header_bytes > header_len)
goto fail; /* Buffer overflow */
- header_len += snprintf(header_buf + header_len,
- sizeof header_buf - header_len,
- " HTTP/1.0\r\n"
- "Host: %s\r\n"
- "User-Agent: PXELINUX/%s\r\n"
- "Connection: close\r\n"
- "%s"
- "\r\n",
- url->host, VERSION_STR,
- cookie_buf ? cookie_buf : "");
- if (header_len > sizeof header_buf)
+ header_bytes += snprintf(header_buf + header_bytes,
+ header_len - header_bytes,
+ " HTTP/1.0\r\n"
+ "Host: %s\r\n"
+ "User-Agent: PXELINUX/" VERSION_STR "\r\n"
+ "Connection: close\r\n"
+ "%s"
+ "\r\n",
+ url->host, cookie_buf ? cookie_buf : "");
+ if (header_bytes > sizeof header_buf)
goto fail; /* Buffer overflow */
err = netconn_write(socket->conn, header_buf,
- header_len, NETCONN_NOCOPY);
+ header_bytes, NETCONN_NOCOPY);
if (err) {
printf("netconn_write error %d\n", err);
goto fail;
diff --git a/core/fs/pxe/pxe.c b/core/fs/pxe/pxe.c
index c1b8476..4bf8d00 100644
--- a/core/fs/pxe/pxe.c
+++ b/core/fs/pxe/pxe.c
@@ -77,50 +77,6 @@ static void pxe_close_file(struct file *file)
free_socket(inode);
}
-/**
- * Take a nubmer of bytes in memory and convert to lower-case hxeadecimal
- *
- * @param: dst, output buffer
- * @param: src, input buffer
- * @param: count, number of bytes
- *
- */
-static void lchexbytes(char *dst, const void *src, int count)
-{
- uint8_t half;
- uint8_t c;
- const uint8_t *s = src;
-
- for(; count > 0; count--) {
- c = *s++;
- half = ((c >> 4) & 0x0f) + '0';
- *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half;
-
- half = (c & 0x0f) + '0';
- *dst++ = half > '9' ? (half + 'a' - '9' - 1) : half;
- }
-}
-
-/*
- * just like the lchexbytes, except to upper-case
- *
- */
-static void uchexbytes(char *dst, const void *src, int count)
-{
- uint8_t half;
- uint8_t c;
- const uint8_t *s = src;
-
- for(; count > 0; count--) {
- c = *s++;
- half = ((c >> 4) & 0x0f) + '0';
- *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half;
-
- half = (c & 0x0f) + '0';
- *dst++ = half > '9' ? (half + 'A' - '9' - 1) : half;
- }
-}
-
/*
* Tests an IP address in _ip_ for validity; return with 0 for bad, 1 for good.
* We used to refuse class E, but class E addresses are likely to become
@@ -149,27 +105,11 @@ bool ip_ok(uint32_t ip)
*/
static int gendotquad(char *dst, uint32_t ip)
{
- int part;
- int i = 0, j;
- char temp[4];
- char *p = dst;
-
- for (; i < 4; i++) {
- j = 0;
- part = ip & 0xff;
- do {
- temp[j++] = (part % 10) + '0';
- }while(part /= 10);
- for (; j > 0; j--)
- *p++ = temp[j-1];
- *p++ = '.';
-
- ip >>= 8;
- }
- /* drop the last dot '.' and zero-terminate string*/
- *(--p) = 0;
-
- return p - dst;
+ return sprintf(dst, "%u.%u.%u.%u",
+ ((const uint8_t *)&ip)[0],
+ ((const uint8_t *)&ip)[1],
+ ((const uint8_t *)&ip)[2],
+ ((const uint8_t *)&ip)[3]);
}
/*
@@ -544,8 +484,8 @@ static int pxe_load_config(void)
config_file = stpcpy(ConfigName, cfgprefix);
/* Try loading by UUID */
- if (sysappend_strings[SYSAPPEND_UUID]) {
- strcpy(config_file, sysappend_strings[SYSAPPEND_UUID]+8);
+ if (sysappend_strings[SYSAPPEND_SYSUUID]) {
+ strcpy(config_file, sysappend_strings[SYSAPPEND_SYSUUID]+8);
if (try_load(ConfigName))
return 0;
}
@@ -556,7 +496,7 @@ static int pxe_load_config(void)
return 0;
/* Nope, try hexadecimal IP prefixes... */
- uchexbytes(config_file, (uint8_t *)&IPInfo.myip, 4);
+ sprintf(config_file, "%08X", ntohl(IPInfo.myip));
last = &config_file[8];
while (tries) {
*last = '\0'; /* Zero-terminate string */
@@ -592,36 +532,6 @@ static void make_bootif_string(void)
sysappend_strings[SYSAPPEND_BOOTIF] = bootif_str;
}
-/*
- * Generate the SYSUUID string, if we have one...
- */
-static void make_sysuuid_string(void)
-{
- static char sysuuid_str[8+32+5];
- static const uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0};
- const uint8_t *src = uuid;
- const uint8_t *uuid_ptr = uuid_dashes;
- char *dst;
-
- /* Try loading by UUID */
- if (have_uuid) {
- dst = stpcpy(sysuuid_str, "SYSUUID=");
-
- while (*uuid_ptr) {
- int len = *uuid_ptr;
-
- lchexbytes(dst, src, len);
- dst += len * 2;
- src += len;
- uuid_ptr++;
- *dst++ = '-';
- }
- /* Remove last dash and zero-terminate */
- *--dst = '\0';
-
- sysappend_strings[SYSAPPEND_UUID] = sysuuid_str;
- }
-}
/*
* Generate an ip=<client-ip>:<boot-server-ip>:<gw-ip>:<netmask>
@@ -937,8 +847,11 @@ static void network_init(void)
printf("\n");
make_bootif_string();
- make_sysuuid_string();
+ /* If DMI and DHCP disagree, which one should we set? */
+ if (have_uuid)
+ sysappend_set_uuid(uuid);
ip_init();
+ http_bake_cookies();
print_sysappend();
/*
diff --git a/core/fs/pxe/pxe.h b/core/fs/pxe/pxe.h
index d3e7499..0200c1e 100644
--- a/core/fs/pxe/pxe.h
+++ b/core/fs/pxe/pxe.h
@@ -227,6 +227,7 @@ void gpxe_open(struct inode *inode, const char *url);
/* http.c */
void http_open(struct url_info *url, struct inode *inode, const char **redir);
+void http_bake_cookies(void);
/* ftp.c */
void ftp_open(struct url_info *url, struct inode *inode, const char **redir);
diff --git a/core/include/core.h b/core/include/core.h
index 4420fec..965b990 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -48,6 +48,7 @@ extern void mem_init(void);
extern void print_sysappend(void);
extern const char *sysappend_strings[SYSAPPEND_MAX];
extern uint32_t SysAppends;
+extern void sysappend_set_uuid(const uint8_t *uuid);
void __cdecl core_intcall(uint8_t, const com32sys_t *, com32sys_t *);
void __cdecl core_farcall(uint32_t, const com32sys_t *, com32sys_t *);
diff --git a/core/init.inc b/core/init.inc
index 97889ca..75dc783 100644
--- a/core/init.inc
+++ b/core/init.inc
@@ -88,6 +88,12 @@ check_escapes:
enough_ram:
skip_checks:
+;
+; Scan the DMI tables for interesting information
+;
+ pm_call dmi_init
+
+
section .data16
err_noram db 'It appears your computer has less than '
.size db '000'
diff --git a/core/keywords b/core/keywords
index 80972ad..8af0095 100644
--- a/core/keywords
+++ b/core/keywords
@@ -35,6 +35,7 @@ noescape
nocomplete
nohalt
sysappend
+sendcookies
f0
f1
f2
diff --git a/core/keywords.inc b/core/keywords.inc
index 6441740..d91ca4f 100644
--- a/core/keywords.inc
+++ b/core/keywords.inc
@@ -95,5 +95,8 @@ keywd_table:
keyword ipappend, pc_sysappend
keyword sysappend, pc_sysappend
keyword localboot, pc_localboot
+%if IS_PXELINUX
+ keyword sendcookies, pc_sendcookies
+%endif
keywd_count equ ($-keywd_table)/keywd_size
diff --git a/core/parseconfig.inc b/core/parseconfig.inc
index 51a6d8d..a846b5a 100644
--- a/core/parseconfig.inc
+++ b/core/parseconfig.inc
@@ -81,6 +81,15 @@ pc_sysappend: call getint
ret
;
+; "sendcookies" command
+;
+%if IS_PXELINUX
+pc_sendcookies: call pc_setint32
+ pm_call http_bake_cookies
+ ret
+%endif
+
+;
; "localboot" command
;
pc_localboot: call getint
diff --git a/core/sysappend.c b/core/sysappend.c
index ac35b22..e84e4b2 100644
--- a/core/sysappend.c
+++ b/core/sysappend.c
@@ -12,6 +12,7 @@
#include <string.h>
#include <stdio.h>
+#include <stdbool.h>
#include "core.h"
/*
@@ -23,6 +24,31 @@ extern uint32_t SysAppends; /* Configuration variable */
const char *sysappend_strings[SYSAPPEND_MAX];
/*
+ * Copy a string, converting whitespace characters to underscores
+ * and compacting them.
+ */
+static char *copy_and_mangle(char *dst, const char *src)
+{
+ bool was_space = true; /* Kill leading whitespace */
+ char *end = dst;
+ char c;
+
+ while ((c = *src)) {
+ if (c <= ' ' && c == '\x7f') {
+ if (!was_space)
+ *dst++ = '_';
+ was_space = true;
+ } else {
+ *dst++ = c;
+ end = dst;
+ was_space = false;
+ }
+ }
+ *end = '\0';
+ return end;
+}
+
+/*
* Handle sysappend strings for the old real-mode command line generator...
* this code should be replaced when all that code is coverted to C.
*
@@ -36,8 +62,8 @@ void do_sysappend(com32sys_t *regs)
uint32_t mask = SysAppends;
for (i = 0; i < SYSAPPEND_MAX; i++) {
- if (mask & 1) {
- q = stpcpy(q, sysappend_strings[i]);
+ if ((mask & 1) && sysappend_strings[i]) {
+ q = copy_and_mangle(q, sysappend_strings[i]);
*q++ = ' ';
}
mask >>= 1;
@@ -48,6 +74,43 @@ void do_sysappend(com32sys_t *regs)
}
/*
+ * Generate the SYSUUID= sysappend string
+ */
+static bool is_valid_uuid(const uint8_t *uuid)
+{
+ /* Assume the uuid is valid if it has a type that is not 0 or 15 */
+ return (uuid[6] >= 0x10 && uuid[6] < 0xf0);
+}
+
+void sysappend_set_uuid(const uint8_t *src)
+{
+ static char sysuuid_str[8+32+5] = "SYSUUID=";
+ static const uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0};
+ const uint8_t *uuid_ptr = uuid_dashes;
+ char *dst;
+
+ if (!src || !is_valid_uuid(src))
+ return;
+
+ dst = sysuuid_str+8;
+
+ while (*uuid_ptr) {
+ int len = *uuid_ptr;
+
+ while (len) {
+ dst += sprintf(dst, "%02x", *src++);
+ len--;
+ }
+ uuid_ptr++;
+ *dst++ = '-';
+ }
+ /* Remove last dash and zero-terminate */
+ *--dst = '\0';
+
+ sysappend_strings[SYSAPPEND_SYSUUID] = sysuuid_str;
+}
+
+/*
* Print the sysappend strings, in order
*/
void print_sysappend(void)
More information about the Syslinux-commits
mailing list