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