1 /* ----------------------------------------------------------------------- *
2  *
3  *   Copyright 2011 Intel Corporation; author: H. Peter Anvin
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
8  *   Boston MA 02110-1301, USA; either version 2 of the License, or
9  *   (at your option) any later version; incorporated herein by reference.
10  *
11  * ----------------------------------------------------------------------- */
12 
13 #include <string.h>
14 #include <stdio.h>
15 #include <stdbool.h>
16 #include "core.h"
17 #include "fs.h"
18 
19 /*
20  * sysappend.c
21  *
22  */
23 
24 __export uint32_t SysAppends;	/* Configuration variable */
25 __export const char *sysappend_strings[SYSAPPEND_MAX];
26 
27 /*
28  * Copy a string, converting whitespace characters to underscores
29  * and compacting them.  Return a pointer to the final null.
30  */
copy_and_mangle(char * dst,const char * src)31 static char *copy_and_mangle(char *dst, const char *src)
32 {
33     bool was_space = true;	/* Kill leading whitespace */
34     char *end = dst;
35     char c;
36 
37     while ((c = *src++)) {
38 	if (c <= ' ' && c == '\x7f') {
39 	    if (!was_space)
40 		*dst++ = '_';
41 	    was_space = true;
42 	} else {
43 	    *dst++ = c;
44 	    end = dst;
45 	    was_space = false;
46 	}
47     }
48     *end = '\0';
49     return end;
50 }
51 
52 /*
53  * Handle sysappend strings.
54  *
55  * Writes the output to 'buf' with a space after each option.
56  */
do_sysappend(char * buf)57 __export void do_sysappend(char *buf)
58 {
59     char *q = buf;
60     int i;
61     uint32_t mask = SysAppends;
62 
63     for (i = 0; i < SYSAPPEND_MAX; i++) {
64 	if ((mask & 1) && sysappend_strings[i]) {
65 	    q = copy_and_mangle(q, sysappend_strings[i]);
66 	    *q++ = ' ';
67 	}
68 	mask >>= 1;
69     }
70     *--q = '\0';
71 }
72 
73 /*
74  * Generate the SYSUUID= sysappend string
75  */
is_valid_uuid(const uint8_t * uuid)76 static bool is_valid_uuid(const uint8_t *uuid)
77 {
78     /* Assume the uuid is valid if it has a type that is not 0 or 15 */
79     return (uuid[6] >= 0x10 && uuid[6] < 0xf0);
80 }
81 
sysappend_set_uuid(const uint8_t * src)82 void sysappend_set_uuid(const uint8_t *src)
83 {
84     static char sysuuid_str[8+32+5] = "SYSUUID=";
85     static const uint8_t uuid_dashes[] = {4, 2, 2, 2, 6, 0};
86     const uint8_t *uuid_ptr = uuid_dashes;
87     char *dst;
88 
89     if (!src || !is_valid_uuid(src))
90 	return;
91 
92     dst = sysuuid_str+8;
93 
94     while (*uuid_ptr) {
95 	int len = *uuid_ptr;
96 
97 	while (len) {
98 	    dst += sprintf(dst, "%02x", *src++);
99 	    len--;
100 	}
101 	uuid_ptr++;
102 	*dst++ = '-';
103     }
104     /* Remove last dash and zero-terminate */
105     *--dst = '\0';
106 
107     sysappend_strings[SYSAPPEND_SYSUUID] = sysuuid_str;
108 }
109 
sysappend_set_fs_uuid(void)110 void sysappend_set_fs_uuid(void)
111 {
112     static char fsuuid_str[7+32+7+1] = "FSUUID=";
113     char *uuid;
114 
115     uuid = fs_uuid();
116     if (!uuid)
117 	return;
118 
119     snprintf(fsuuid_str + 7, sizeof(fsuuid_str) - 7, "%s", uuid);
120     fsuuid_str[sizeof(fsuuid_str) - 1] = '\0';
121     free(uuid);
122 
123     sysappend_strings[SYSAPPEND_FSUUID] = fsuuid_str;
124 }
125 
126 /*
127  * Print the sysappend strings, in order
128  */
print_sysappend(void)129 void print_sysappend(void)
130 {
131     int i;
132 
133     for (i = 0; i < SYSAPPEND_MAX; i++) {
134 	if (sysappend_strings[i])
135 	    printf("%s\n", sysappend_strings[i]);
136     }
137 }
138