Merge "hnvram: allow adding variables in RO partition"
diff --git a/hnvram/hnvram_main.c b/hnvram/hnvram_main.c
index 4fbbf2f..a406caa 100644
--- a/hnvram/hnvram_main.c
+++ b/hnvram/hnvram_main.c
@@ -33,13 +33,14 @@
}
void usage(const char* progname) {
- printf("Usage: %s [-d | [-q|-b] [-r|-k] VARNAME] [ [-n] -w VARNAME=value]\n", progname);
+ printf("Usage: %s [-d | [-q|-b] [-r|-k] VARNAME] [ [-n [-p [RO|RW]]] -w VARNAME=value]\n", progname);
printf("\t-d : dump all NVRAM variables\n");
printf("\t-r VARNAME : read VARNAME from NVRAM\n");
printf("\t-q : quiet mode, suppress the variable name and equal sign\n");
printf("\t-b : read VARNAME from NVRAM in raw binary format, e.g. dumping a binary key\n");
printf("\t-w VARNAME=value : write value to VARNAME in NVRAM.\n");
printf("\t-n : toggles whether -w can create new variables. Default is off\n");
+ printf("\t-p [RW|RO] : toggles what partition new writes (-n) used. Default is RW\n");
printf("\t-k VARNAME : delete existing key/value pair from NVRAM.\n");
}
@@ -190,7 +191,14 @@
return (int)ret;
}
-char* read_nvram(const char* name, char* output, int outlen, int quiet) {
+// name - name of key to be read
+// output - buffer for value of key
+// outlen - length of buffer
+// quiet - whether buffer is KEY=VAL or VAL
+// part_used - in the case of dynamically added variables (is_field = false),
+// returns what partition we found the key in
+char* read_nvram(const char* name, char* output, int outlen, int quiet,
+ HMX_NVRAM_PARTITION_E* part_used) {
const hnvram_field_t* field = get_nvram_field(name);
int is_field = (field != NULL);
@@ -205,10 +213,18 @@
}
} else {
format_type = HNVRAM_STRING;
- DRV_Error e = HMX_NVRAM_Read(HMX_NVRAM_PARTITION_RW, (unsigned char*)name,
- 0, data, sizeof(data), &data_len);
+
+ // Try both partitions
+ *part_used = HMX_NVRAM_PARTITION_RW;
+ DRV_Error e = HMX_NVRAM_Read(*part_used, (unsigned char*)name, 0, data,
+ sizeof(data), &data_len);
if (e != DRV_OK) {
- return NULL;
+ *part_used = HMX_NVRAM_PARTITION_RO;
+ e = HMX_NVRAM_Read(*part_used, (unsigned char*)name, 0, data,
+ sizeof(data), &data_len);
+ if (e != DRV_OK) {
+ return NULL;
+ }
}
}
char formatbuf[NVRAM_MAX_DATA * 2];
@@ -354,25 +370,24 @@
}
DRV_Error clear_nvram(char* optarg) {
- DRV_Error e = HMX_NVRAM_Remove(HMX_NVRAM_PARTITION_RW,
- (unsigned char*)optarg);
- if (e == DRV_ERR) {
- // Avoid throwing error message if variable already cleared
+ DRV_Error err1 = HMX_NVRAM_Remove(HMX_NVRAM_PARTITION_RW,
+ (unsigned char*)optarg);
+ DRV_Error err2 = HMX_NVRAM_Remove(HMX_NVRAM_PARTITION_RO,
+ (unsigned char*)optarg);
+
+ // Avoid throwing error message if variable already cleared
+ if ((err1 == DRV_ERR || err1 == DRV_OK) &&
+ (err2 == DRV_ERR || err2 == DRV_OK)) {
return DRV_OK;
}
- return e;
+
+ fprintf(stderr, "Error while deleting key %s. RW: %d RO: %d.\n", optarg,
+ err1, err2);
+ return DRV_ERR;
}
-int write_nvram(char* optarg) {
- char* equal = strchr(optarg, '=');
- if (equal == NULL) {
- return -1;
- }
- char* name = optarg;
- *equal = '\0';
- char* value = ++equal;
-
+int write_nvram(char* name, char* value, HMX_NVRAM_PARTITION_E desired_part) {
const hnvram_field_t* field = get_nvram_field(name);
int is_field = (field != NULL);
@@ -397,22 +412,61 @@
if (!is_field) {
char tmp[NVRAM_MAX_DATA] = {0};
- int key_exists = (read_nvram(name, tmp, NVRAM_MAX_DATA, 1) != NULL);
- if (!can_add_flag && !key_exists) {
- fprintf(stderr, "Key not found in NVRAM. Add -n to allow creation %s\n",
- name);
- return -3;
+ HMX_NVRAM_PARTITION_E part_used;
+ if (read_nvram(name, tmp, NVRAM_MAX_DATA, 1, &part_used) == NULL) {
+ return -3; // Write failed: Variable not found
}
- DRV_Error er = HMX_NVRAM_Write(HMX_NVRAM_PARTITION_RW, (unsigned char*)name,
- 0, nvram_value, nvram_len);
- if (er != DRV_OK) {
+
+ if (desired_part != HMX_NVRAM_PARTITION_UNSPECIFIED &&
+ desired_part != part_used) {
+ fprintf(stderr, "Variable already exists in other partition: %s\n", name);
return -4;
}
- } else {
- if (HMX_NVRAM_SetField(field->nvram_type, 0,
- nvram_value, nvram_len) != DRV_OK) {
+
+ DRV_Error er = HMX_NVRAM_Write(part_used, (unsigned char*)name, 0,
+ nvram_value, nvram_len);
+ if (er != DRV_OK) {
return -5;
}
+ } else {
+ if (desired_part != HMX_NVRAM_PARTITION_UNSPECIFIED) {
+ fprintf(stderr, "Partition was specified (%d) on a field variable: %s\n",
+ desired_part, name);
+ return -6;
+ }
+ if (HMX_NVRAM_SetField(field->nvram_type, 0,
+ nvram_value, nvram_len) != DRV_OK) {
+ return -7;
+ }
+ }
+
+ return 0;
+}
+
+// Adds new variable to HNVRAM in desired_partition as STRING
+int write_nvram_new(char* name, char* value,
+ HMX_NVRAM_PARTITION_E desired_part) {
+ char tmp[NVRAM_MAX_DATA] = {0};
+ unsigned char nvram_value[NVRAM_MAX_DATA];
+ unsigned int nvram_len = sizeof(nvram_value);
+ if (parse_nvram(HNVRAM_STRING, value, nvram_value, &nvram_len) == NULL) {
+ return -1;
+ }
+
+ if (!can_add_flag) {
+ fprintf(stderr, "Key not found in NVRAM. Add -n to allow creation %s\n",
+ name);
+ return -2;
+ }
+
+ if (desired_part == HMX_NVRAM_PARTITION_UNSPECIFIED) {
+ desired_part = HMX_NVRAM_PARTITION_RW;
+ }
+
+ DRV_Error er = HMX_NVRAM_Write(desired_part, (unsigned char*)name, 0,
+ nvram_value, nvram_len);
+ if (er != DRV_OK) {
+ return -3;
}
return 0;
@@ -432,9 +486,11 @@
int op_cnt = 0; // operation
int q_flag = 0; // quiet: don't output name of variable.
int b_flag = 0; // binary: output the binary format
+ // Desired partition for new writes.
+ HMX_NVRAM_PARTITION_E desired_part = HMX_NVRAM_PARTITION_UNSPECIFIED;
char output[NVRAM_MAX_DATA];
int c;
- while ((c = getopt(argc, argv, "dbqrnw:k:")) != -1) {
+ while ((c = getopt(argc, argv, "dbqrnp:w:k:")) != -1) {
switch(c) {
case 'b':
b_flag = 1;
@@ -445,10 +501,35 @@
case 'n':
can_add_flag = 1;
break;
+ case 'p':
+ if (strcmp(optarg, "RO") == 0) {
+ desired_part = HMX_NVRAM_PARTITION_RO;
+ } else if (strcmp(optarg, "RW") == 0) {
+ desired_part = HMX_NVRAM_PARTITION_RW;
+ } else {
+ fprintf(stderr, "Invalid partition: %s. Use RW or RO\n", optarg);
+ exit(1);
+ }
+ break;
case 'w':
{
char* duparg = strdup(optarg);
- if (write_nvram(duparg) != 0) {
+ char* equal = strchr(duparg, '=');
+ if (equal == NULL) {
+ return -1;
+ }
+
+ char* name = duparg;
+ *equal = '\0';
+ char* value = equal + 1;
+
+ int ret = write_nvram(name, value, desired_part);
+ if (ret == -3 && can_add_flag) {
+ // key not found, and we are authorized to add a new one
+ ret = write_nvram_new(name, value, desired_part);
+ }
+
+ if (ret != 0) {
fprintf(stderr, "Unable to write %s\n", duparg);
free(duparg);
exit(1);
@@ -510,7 +591,8 @@
}
fwrite(output, 1, len, stdout);
} else {
- if (read_nvram(argv[optind], output, sizeof(output), q_flag) == NULL) {
+ HMX_NVRAM_PARTITION_E part_used;
+ if (read_nvram(argv[optind], output, sizeof(output), q_flag, &part_used) == NULL) {
fprintf(stderr, "Unable to read %s\n", argv[optind]);
exit(1);
}
diff --git a/hnvram/hnvram_test.cc b/hnvram/hnvram_test.cc
index 39f7e4a..643a436 100644
--- a/hnvram/hnvram_test.cc
+++ b/hnvram/hnvram_test.cc
@@ -8,16 +8,31 @@
int libupgrade_verbose = 1;
-char* HMX_NVRAM_Read_Data = NULL;
+char* HMX_NVRAM_Read_Data_RO = NULL;
+char* HMX_NVRAM_Read_Data_RW = NULL;
+
+char* get_Read_Data(HMX_NVRAM_PARTITION_E partition) {
+ if (partition == HMX_NVRAM_PARTITION_RO) {
+ return HMX_NVRAM_Read_Data_RO;
+ } else {
+ return HMX_NVRAM_Read_Data_RW;
+ }
+}
+
DRV_Error HMX_NVRAM_Read(HMX_NVRAM_PARTITION_E partition,
unsigned char* pName, unsigned int offset,
unsigned char* pValue, unsigned int ulSize,
unsigned int* pLen) {
- if (HMX_NVRAM_Read_Data == NULL) {
+ if (get_Read_Data(partition) == NULL) {
return DRV_ERR;
+ }
+ if (partition == HMX_NVRAM_PARTITION_RO) {
+ snprintf((char*)pValue, ulSize, "%s", HMX_NVRAM_Read_Data_RO);
+ *pLen = strlen(HMX_NVRAM_Read_Data_RO);
+ return DRV_OK;
} else {
- snprintf((char*)pValue, ulSize, "%s", HMX_NVRAM_Read_Data);
- *pLen = strlen(HMX_NVRAM_Read_Data);
+ snprintf((char*)pValue, ulSize, "%s", HMX_NVRAM_Read_Data_RW);
+ *pLen = strlen(HMX_NVRAM_Read_Data_RW);
return DRV_OK;
}
}
@@ -25,17 +40,26 @@
DRV_Error HMX_NVRAM_Write(HMX_NVRAM_PARTITION_E partition,
unsigned char* pName, unsigned int offset,
unsigned char* pValue, unsigned int ulSize) {
- HMX_NVRAM_Read_Data = (char*)malloc(ulSize);
- snprintf(HMX_NVRAM_Read_Data, sizeof(pValue), "%s", (char*)pValue);
+ if (partition == HMX_NVRAM_PARTITION_RO) {
+ HMX_NVRAM_Read_Data_RO = (char*)malloc(ulSize);
+ snprintf(HMX_NVRAM_Read_Data_RO, sizeof(pValue), "%s", (char*)pValue);
+ } else {
+ HMX_NVRAM_Read_Data_RW = (char*)malloc(ulSize);
+ snprintf(HMX_NVRAM_Read_Data_RW, sizeof(pValue), "%s", (char*)pValue);
+ }
return DRV_OK;
}
DRV_Error HMX_NVRAM_Remove(HMX_NVRAM_PARTITION_E partition,
unsigned char* pName) {
- if (HMX_NVRAM_Read_Data == NULL) {
+ if (get_Read_Data(partition) == NULL) {
return DRV_ERR;
}
- HMX_NVRAM_Read_Data = NULL;
+ if (partition == HMX_NVRAM_PARTITION_RO) {
+ HMX_NVRAM_Read_Data_RO = NULL;
+ } else {
+ HMX_NVRAM_Read_Data_RW = NULL;
+ }
return DRV_OK;
}
@@ -84,7 +108,8 @@
virtual ~HnvramTest() {}
virtual void SetUp() {
- HMX_NVRAM_Read_Data = NULL;
+ HMX_NVRAM_Read_Data_RO = NULL;
+ HMX_NVRAM_Read_Data_RW = NULL;
HMX_NVRAM_GetField_Data = NULL;
HMX_NVRAM_SetField_Data = NULL;
HMX_NVRAM_SetField_Len = -1;
@@ -184,104 +209,145 @@
TEST_F(HnvramTest, TestReadFieldNvram) {
char output[256];
+ HMX_NVRAM_PARTITION_E part;
HMX_NVRAM_GetField_Data = "TestSystemId";
EXPECT_STREQ("SYSTEM_ID=TestSystemId",
- read_nvram("SYSTEM_ID", output, sizeof(output), 0));
+ read_nvram("SYSTEM_ID", output, sizeof(output), 0, &part));
EXPECT_STREQ("TestSystemId",
- read_nvram("SYSTEM_ID", output, sizeof(output), 1));
+ read_nvram("SYSTEM_ID", output, sizeof(output), 1, &part));
HMX_NVRAM_GetField_Data = NULL;
- EXPECT_EQ(NULL, read_nvram("FAKE_SYSTEM_ID", output, sizeof(output), 1));
+ EXPECT_EQ(NULL, read_nvram("FAKE_SYSTEM_ID", output, sizeof(output), 1,
+ &part));
}
TEST_F(HnvramTest, TestReadVariableNvram) {
char output[256];
- HMX_NVRAM_Read_Data = strdup("ABC123");
+ HMX_NVRAM_PARTITION_E part;
+ HMX_NVRAM_Read_Data_RW = strdup("ABC123");
EXPECT_STREQ("TEST_VARIABLE=ABC123",
- read_nvram("TEST_VARIABLE", output, sizeof(output), 0));
+ read_nvram("TEST_VARIABLE", output, sizeof(output), 0, &part));
+ EXPECT_EQ((int)HMX_NVRAM_PARTITION_RW, part);
EXPECT_STREQ("ABC123",
- read_nvram("TEST_VARIABLE", output, sizeof(output), 1));
- HMX_NVRAM_Read_Data = NULL;
- EXPECT_STREQ(NULL, read_nvram("TEST_VARIABLE", output, sizeof(output), 1));
+ read_nvram("TEST_VARIABLE", output, sizeof(output), 1, &part));
+ EXPECT_EQ((int)HMX_NVRAM_PARTITION_RW, part);
+ HMX_NVRAM_Read_Data_RW = NULL;
+ EXPECT_STREQ(NULL, read_nvram("TEST_VARIABLE", output, sizeof(output), 1,
+ &part));
}
TEST_F(HnvramTest, TestWriteFieldNvram) {
// Type integer
- char* testdata = strdup("ACTIVATED_KERNEL_NUM=1");
- EXPECT_EQ(DRV_OK, write_nvram(testdata));
+ char* key = strdup("ACTIVATED_KERNEL_NUM");
+ char* val = strdup("1");
+ EXPECT_EQ(DRV_OK, write_nvram(key, val, HMX_NVRAM_PARTITION_UNSPECIFIED));
EXPECT_EQ(0x01, *HMX_NVRAM_SetField_Data);
EXPECT_EQ(1, HMX_NVRAM_SetField_Len);
// Type string
- testdata = strdup("ACTIVATED_KERNEL_NAME=kernel1");
- EXPECT_EQ(DRV_OK, write_nvram(testdata));
+ key = strdup("ACTIVATED_KERNEL_NAME");
+ val = strdup("kernel1");
+ EXPECT_EQ(DRV_OK, write_nvram(key, val, HMX_NVRAM_PARTITION_UNSPECIFIED));
EXPECT_STREQ("kernel1", (char*)HMX_NVRAM_SetField_Data);
EXPECT_EQ(7, HMX_NVRAM_SetField_Len);
// Make sure it called SetField and not HMX_NVRAM_Write
- EXPECT_EQ (NULL, HMX_NVRAM_Read_Data);
+ EXPECT_EQ (NULL, HMX_NVRAM_Read_Data_RW);
+ EXPECT_EQ (NULL, HMX_NVRAM_Read_Data_RO);
// Should fail trying to change value of non-exsting field
- testdata = strdup("FAKE_FIELD=abc123");
- EXPECT_NE(0, write_nvram(testdata));
- free(testdata);
+ key = strdup("FAKE_FIELD");
+ val = strdup("abc123");
+ EXPECT_NE(0, write_nvram(key, val, HMX_NVRAM_PARTITION_UNSPECIFIED));
+ free(key);
+ free(val);
}
-TEST_F(HnvramTest, TestWriteVariableNvram) {
+void testWriteVariableNvram(HMX_NVRAM_PARTITION_E partition, HMX_NVRAM_PARTITION_E other) {
char* key = strdup("TEST_FIELD");
char* val = strdup("abc123");
- char* keyval = strdup("TEST_FIELD=abc123");
// Fail to add new one without -n
- EXPECT_NE(0, write_nvram(strdup(keyval)));
+ EXPECT_NE(0, write_nvram(key, val, HMX_NVRAM_PARTITION_UNSPECIFIED));
+ EXPECT_NE(0, write_nvram(key, val, HMX_NVRAM_PARTITION_RW));
+ EXPECT_NE(0, write_nvram(key, val, HMX_NVRAM_PARTITION_RO));
- // Add new one successfully
can_add_flag = 1;
- EXPECT_EQ(0, write_nvram(keyval));
- EXPECT_STREQ(val,HMX_NVRAM_Read_Data);
+ EXPECT_EQ(-3, write_nvram(key, val, HMX_NVRAM_PARTITION_UNSPECIFIED));
+ EXPECT_EQ(-3, write_nvram(key, val, HMX_NVRAM_PARTITION_RO));
+ EXPECT_EQ(-3, write_nvram(key, val, HMX_NVRAM_PARTITION_RW));
+ // Add new one successfully
+ EXPECT_EQ(0, write_nvram_new(key, val, partition));
+ EXPECT_STREQ(val, get_Read_Data(partition));
// Should be able to read value
char output[256];
- EXPECT_STREQ(val, read_nvram(key, output, sizeof(output), 1));
+ HMX_NVRAM_PARTITION_E part_used;
+ EXPECT_STREQ(val, read_nvram(key, output, sizeof(output), 1, &part_used));
+
+ // Make sure read came from right partition
+ EXPECT_EQ(partition, part_used);
char* val2 = strdup("987def");
- char* keyval2 = strdup("TEST_FIELD=987def");
// Should be able to change value
- EXPECT_EQ(0, write_nvram(keyval2));
- EXPECT_STREQ(val2,HMX_NVRAM_Read_Data);
+ EXPECT_EQ(0, write_nvram(key, val2, HMX_NVRAM_PARTITION_UNSPECIFIED));
+ EXPECT_STREQ(val2, get_Read_Data(partition));
+
+ // And back again, this time with correct partition specified
+ EXPECT_EQ(0, write_nvram(key, val, partition));
+ EXPECT_STREQ(val, get_Read_Data(partition));
+
+ // Should fail when specifying wrong partition
+ EXPECT_EQ(-4, write_nvram(key, val2, other));
+ EXPECT_EQ(-4, write_nvram(key, val2, HMX_NVRAM_PARTITION_W_RAWFS));
free(key);
free(val);
- free(keyval);
free(val2);
- free(keyval2);
}
-TEST_F(HnvramTest, TestClearNvram) {
+TEST_F(HnvramTest, TestWriteVariableNvramRO) {
+ testWriteVariableNvram(HMX_NVRAM_PARTITION_RO, HMX_NVRAM_PARTITION_RW);
+}
+
+TEST_F(HnvramTest, TestWriteVariableNvramRW) {
+ testWriteVariableNvram(HMX_NVRAM_PARTITION_RW, HMX_NVRAM_PARTITION_RO);
+}
+
+void testClearNvram(HMX_NVRAM_PARTITION_E partition) {
char* key = strdup("TEST_FIELD2");
char* val = strdup("abc123");
- char* keyval = strdup("TEST_FIELD2=abc123");
// No error if variable already cleared
EXPECT_EQ(DRV_OK, clear_nvram(key));
- // Create new one
+ // Create new var
can_add_flag = 1;
- EXPECT_EQ(0, write_nvram(keyval));
- EXPECT_STREQ(val, HMX_NVRAM_Read_Data);
+ EXPECT_EQ(-3, write_nvram(key, val, HMX_NVRAM_PARTITION_UNSPECIFIED));
+ EXPECT_EQ(0, write_nvram_new(key, val, partition));
+ EXPECT_STREQ(val, get_Read_Data(partition));
// Should be able to read value
char output[256];
- EXPECT_STREQ(val, read_nvram(key, output, sizeof(output), 1));
+ HMX_NVRAM_PARTITION_E part_used;
+ EXPECT_STREQ(val, read_nvram(key, output, sizeof(output), 1, &part_used));
+ EXPECT_EQ((int)partition, part_used);
// Should be able to kill it
EXPECT_EQ(DRV_OK, clear_nvram(key));
// Should fail reading value
- EXPECT_STREQ(NULL, read_nvram(key, output, sizeof(output), 1));
+ EXPECT_STREQ(NULL, read_nvram(key, output, sizeof(output), 1, &part_used));
free(key);
free(val);
- free(keyval);
+}
+
+TEST_F(HnvramTest, TestClearNvramRO) {
+ testClearNvram(HMX_NVRAM_PARTITION_RO);
+}
+
+TEST_F(HnvramTest, TestClearNvramRW) {
+ testClearNvram(HMX_NVRAM_PARTITION_RW);
}
int main(int argc, char** argv) {