aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/nvram_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/nvram_64.c')
-rw-r--r--arch/powerpc/kernel/nvram_64.c66
1 files changed, 51 insertions, 15 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index bb12b3248f1..28b898e6818 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -84,22 +84,30 @@ static ssize_t dev_nvram_read(struct file *file, char __user *buf,
char *tmp = NULL;
ssize_t size;
- ret = -ENODEV;
- if (!ppc_md.nvram_size)
+ if (!ppc_md.nvram_size) {
+ ret = -ENODEV;
goto out;
+ }
- ret = 0;
size = ppc_md.nvram_size();
- if (*ppos >= size || size < 0)
+ if (size < 0) {
+ ret = size;
goto out;
+ }
+
+ if (*ppos >= size) {
+ ret = 0;
+ goto out;
+ }
count = min_t(size_t, count, size - *ppos);
count = min(count, PAGE_SIZE);
- ret = -ENOMEM;
tmp = kmalloc(count, GFP_KERNEL);
- if (!tmp)
+ if (!tmp) {
+ ret = -ENOMEM;
goto out;
+ }
ret = ppc_md.nvram_read(tmp, count, ppos);
if (ret <= 0)
@@ -202,7 +210,7 @@ static void __init nvram_print_partitions(char * label)
printk(KERN_WARNING "--------%s---------\n", label);
printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
list_for_each_entry(tmp_part, &nvram_partitions, partition) {
- printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12s\n",
+ printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%12.12s\n",
tmp_part->index, tmp_part->header.signature,
tmp_part->header.checksum, tmp_part->header.length,
tmp_part->header.name);
@@ -215,9 +223,13 @@ static int __init nvram_write_header(struct nvram_partition * part)
{
loff_t tmp_index;
int rc;
-
+ struct nvram_header phead;
+
+ memcpy(&phead, &part->header, NVRAM_HEADER_LEN);
+ phead.length = cpu_to_be16(phead.length);
+
tmp_index = part->index;
- rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index);
+ rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index);
return rc;
}
@@ -237,22 +249,45 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
return c_sum;
}
+/*
+ * Per the criteria passed via nvram_remove_partition(), should this
+ * partition be removed? 1=remove, 0=keep
+ */
+static int nvram_can_remove_partition(struct nvram_partition *part,
+ const char *name, int sig, const char *exceptions[])
+{
+ if (part->header.signature != sig)
+ return 0;
+ if (name) {
+ if (strncmp(name, part->header.name, 12))
+ return 0;
+ } else if (exceptions) {
+ const char **except;
+ for (except = exceptions; *except; except++) {
+ if (!strncmp(*except, part->header.name, 12))
+ return 0;
+ }
+ }
+ return 1;
+}
+
/**
* nvram_remove_partition - Remove one or more partitions in nvram
* @name: name of the partition to remove, or NULL for a
* signature only match
* @sig: signature of the partition(s) to remove
+ * @exceptions: When removing all partitions with a matching signature,
+ * leave these alone.
*/
-int __init nvram_remove_partition(const char *name, int sig)
+int __init nvram_remove_partition(const char *name, int sig,
+ const char *exceptions[])
{
struct nvram_partition *part, *prev, *tmp;
int rc;
list_for_each_entry(part, &nvram_partitions, partition) {
- if (part->header.signature != sig)
- continue;
- if (name && strncmp(name, part->header.name, 12))
+ if (!nvram_can_remove_partition(part, name, sig, exceptions))
continue;
/* Make partition a free partition */
@@ -474,6 +509,8 @@ int __init nvram_scan_partitions(void)
memcpy(&phead, header, NVRAM_HEADER_LEN);
+ phead.length = be16_to_cpu(phead.length);
+
err = 0;
c_sum = nvram_checksum(&phead);
if (c_sum != phead.checksum) {
@@ -488,8 +525,7 @@ int __init nvram_scan_partitions(void)
"detected: 0-length partition\n");
goto out;
}
- tmp_part = (struct nvram_partition *)
- kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
+ tmp_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);
err = -ENOMEM;
if (!tmp_part) {
printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");