Home | History | Annotate | Download | only in core
      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  */
     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  */
     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  */
     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 
     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 
    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  */
    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