blob: d9f307f32f830fc05cbb7e8f96490b197af7a2b5 [file] [log] [blame]
Michael Karcher6701ee82010-01-20 14:14:11 +00001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009,2010 Michael Karcher
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <string.h>
22#include <stdio.h>
23#include <stdlib.h>
24
25#include "flash.h"
26
Michael Karcherfd416702010-03-14 17:57:52 +000027const char *dmidecode_names[] = {
Michael Karcherf6498d72010-02-24 22:43:44 +000028 "system-manufacturer",
29 "system-product-name",
30 "system-version",
31 "baseboard-manufacturer",
32 "baseboard-product-name",
Uwe Hermann43959702010-03-13 17:28:29 +000033 "baseboard-version",
Michael Karcher6701ee82010-01-20 14:14:11 +000034};
35
36#define DMI_COMMAND_LEN_MAX 260
37const char *dmidecode_command = "dmidecode";
38
39int has_dmi_support = 0;
Michael Karcherfd416702010-03-14 17:57:52 +000040char *dmistrings[ARRAY_SIZE(dmidecode_names)];
Michael Karcher6701ee82010-01-20 14:14:11 +000041
Uwe Hermann43959702010-03-13 17:28:29 +000042/* Strings longer than 4096 in DMI are just insane. */
Michael Karcher6701ee82010-01-20 14:14:11 +000043#define DMI_MAX_ANSWER_LEN 4096
44
Michael Karcher0d7fb7c2010-02-26 09:51:16 +000045static char *get_dmi_string(const char *string_name)
Michael Karcher6701ee82010-01-20 14:14:11 +000046{
47 FILE *dmidecode_pipe;
Michael Karcher0d7fb7c2010-02-26 09:51:16 +000048 char *result;
49 char answerbuf[DMI_MAX_ANSWER_LEN];
Uwe Hermann43959702010-03-13 17:28:29 +000050 char commandline[DMI_COMMAND_LEN_MAX + 40];
51
Michael Karcher0d7fb7c2010-02-26 09:51:16 +000052 snprintf(commandline, sizeof(commandline),
53 "%s -s %s", dmidecode_command, string_name);
54 dmidecode_pipe = popen(commandline, "r");
55 if (!dmidecode_pipe) {
56 printf_debug("DMI pipe open error\n");
57 return NULL;
Michael Karcher6701ee82010-01-20 14:14:11 +000058 }
Michael Karcher45f79cb2010-03-24 17:55:04 +000059 if (!fgets(answerbuf, DMI_MAX_ANSWER_LEN, dmidecode_pipe)) {
60 if(ferror(dmidecode_pipe)) {
61 printf_debug("DMI pipe read error\n");
62 pclose(dmidecode_pipe);
63 return NULL;
64 } else {
65 answerbuf[0] = 0; /* Hit EOF */
66 }
Michael Karcher0d7fb7c2010-02-26 09:51:16 +000067 }
68 /* Toss all output above DMI_MAX_ANSWER_LEN away to prevent
69 deadlock on pclose. */
70 while (!feof(dmidecode_pipe))
71 getc(dmidecode_pipe);
72 if (pclose(dmidecode_pipe) != 0) {
73 printf_debug("DMI pipe close error\n");
74 return NULL;
75 }
Michael Karcher6701ee82010-01-20 14:14:11 +000076
Uwe Hermann43959702010-03-13 17:28:29 +000077 /* Chomp trailing newline. */
Michael Karcher0d7fb7c2010-02-26 09:51:16 +000078 if (answerbuf[0] != 0 &&
79 answerbuf[strlen(answerbuf) - 1] == '\n')
80 answerbuf[strlen(answerbuf) - 1] = 0;
81 printf_debug("DMI string %s: \"%s\"\n", string_name, answerbuf);
82
83 result = strdup(answerbuf);
84 if (!result)
85 puts("WARNING: Out of memory - DMI support fails");
86
87 return result;
88}
89
90void dmi_init(void)
91{
92 int i;
Michael Karcher8c1df282010-02-26 09:51:20 +000093 char *chassis_type;
Uwe Hermann43959702010-03-13 17:28:29 +000094
Michael Karcher6701ee82010-01-20 14:14:11 +000095 has_dmi_support = 1;
Michael Karcherfd416702010-03-14 17:57:52 +000096 for (i = 0; i < ARRAY_SIZE(dmidecode_names); i++) {
Michael Karcher0d7fb7c2010-02-26 09:51:16 +000097 dmistrings[i] = get_dmi_string(dmidecode_names[i]);
98 if (!dmistrings[i]) {
99 has_dmi_support = 0;
Michael Karcherfd416702010-03-14 17:57:52 +0000100 return;
Michael Karcher0d7fb7c2010-02-26 09:51:16 +0000101 }
102 }
Michael Karcher8c1df282010-02-26 09:51:20 +0000103
104 chassis_type = get_dmi_string("chassis-type");
105 if (chassis_type && !strcmp(chassis_type, "Notebook")) {
Michael Karcherfd416702010-03-14 17:57:52 +0000106 printf_debug("Laptop detected via DMI\n");
Michael Karcher8c1df282010-02-26 09:51:20 +0000107 is_laptop = 1;
108 }
109 free(chassis_type);
Michael Karcher6701ee82010-01-20 14:14:11 +0000110}
111
112/**
113 * Does an substring/prefix/postfix/whole-string match.
114 *
115 * The pattern is matched as-is. The only metacharacters supported are '^'
116 * at the beginning and '$' at the end. So you can look for "^prefix",
117 * "suffix$", "substring" or "^complete string$".
118 *
119 * @param value The string to check.
120 * @param pattern The pattern.
121 * @return Nonzero if pattern matches.
122 */
123static int dmi_compare(const char *value, const char *pattern)
124{
125 int anchored = 0;
126 int patternlen;
Uwe Hermann43959702010-03-13 17:28:29 +0000127
Michael Karcher6701ee82010-01-20 14:14:11 +0000128 printf_debug("matching %s against %s\n", value, pattern);
Uwe Hermann43959702010-03-13 17:28:29 +0000129 /* The empty string is part of all strings! */
Michael Karcher6701ee82010-01-20 14:14:11 +0000130 if (pattern[0] == 0)
131 return 1;
132
133 if (pattern[0] == '^') {
134 anchored = 1;
135 pattern++;
136 }
137
138 patternlen = strlen(pattern);
139 if (pattern[patternlen - 1] == '$') {
140 int valuelen = strlen(value);
141 patternlen--;
Uwe Hermann43959702010-03-13 17:28:29 +0000142 if (patternlen > valuelen)
Michael Karcher6701ee82010-01-20 14:14:11 +0000143 return 0;
144
145 /* full string match: require same length */
Uwe Hermann43959702010-03-13 17:28:29 +0000146 if (anchored && (valuelen != patternlen))
Michael Karcher6701ee82010-01-20 14:14:11 +0000147 return 0;
148
149 /* start character to make ends match */
150 value += valuelen - patternlen;
151 anchored = 1;
152 }
153
154 if (anchored)
155 return strncmp(value, pattern, patternlen) == 0;
156 else
157 return strstr(value, pattern) != NULL;
158}
159
160int dmi_match(const char *pattern)
161{
162 int i;
Uwe Hermann43959702010-03-13 17:28:29 +0000163
Michael Karcher6701ee82010-01-20 14:14:11 +0000164 if (!has_dmi_support)
165 return 0;
166
Michael Karcherfd416702010-03-14 17:57:52 +0000167 for (i = 0; i < ARRAY_SIZE(dmidecode_names); i++)
Uwe Hermann43959702010-03-13 17:28:29 +0000168 if (dmi_compare(dmistrings[i], pattern))
Michael Karcher4dfa0932010-02-12 05:44:18 +0000169 return 1;
Michael Karcher6701ee82010-01-20 14:14:11 +0000170
171 return 0;
172}