|
@@ -313,9 +313,15 @@ static int __init nvram_remove_os_partition(void)
|
|
* @sig: signature of the partition to create
|
|
* @sig: signature of the partition to create
|
|
* @req_size: size of data to allocate in bytes
|
|
* @req_size: size of data to allocate in bytes
|
|
* @min_size: minimum acceptable size (0 means req_size)
|
|
* @min_size: minimum acceptable size (0 means req_size)
|
|
|
|
+ *
|
|
|
|
+ * Returns a negative error code or a positive nvram index
|
|
|
|
+ * of the beginning of the data area of the newly created
|
|
|
|
+ * partition. If you provided a min_size smaller than req_size
|
|
|
|
+ * you need to query for the actual size yourself after the
|
|
|
|
+ * call using nvram_partition_get_size().
|
|
*/
|
|
*/
|
|
-static int __init nvram_create_partition(const char *name, int sig,
|
|
|
|
- int req_size, int min_size)
|
|
|
|
|
|
+static loff_t __init nvram_create_partition(const char *name, int sig,
|
|
|
|
+ int req_size, int min_size)
|
|
{
|
|
{
|
|
struct nvram_partition *part;
|
|
struct nvram_partition *part;
|
|
struct nvram_partition *new_part;
|
|
struct nvram_partition *new_part;
|
|
@@ -334,6 +340,8 @@ static int __init nvram_create_partition(const char *name, int sig,
|
|
*/
|
|
*/
|
|
if (min_size == 0)
|
|
if (min_size == 0)
|
|
min_size = req_size;
|
|
min_size = req_size;
|
|
|
|
+ if (min_size > req_size)
|
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
/* Now add one block to each for the header */
|
|
/* Now add one block to each for the header */
|
|
req_size += 1;
|
|
req_size += 1;
|
|
@@ -362,7 +370,7 @@ static int __init nvram_create_partition(const char *name, int sig,
|
|
/* Create our OS partition */
|
|
/* Create our OS partition */
|
|
new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
|
|
new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
|
|
if (!new_part) {
|
|
if (!new_part) {
|
|
- printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n");
|
|
|
|
|
|
+ pr_err("nvram_create_os_partition: kmalloc failed\n");
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -374,12 +382,29 @@ static int __init nvram_create_partition(const char *name, int sig,
|
|
|
|
|
|
rc = nvram_write_header(new_part);
|
|
rc = nvram_write_header(new_part);
|
|
if (rc <= 0) {
|
|
if (rc <= 0) {
|
|
- printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "
|
|
|
|
- "failed (%d)\n", rc);
|
|
|
|
|
|
+ pr_err("nvram_create_os_partition: nvram_write_header "
|
|
|
|
+ "failed (%d)\n", rc);
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
+ list_add_tail(&new_part->partition, &free_part->partition);
|
|
|
|
+
|
|
|
|
+ /* Adjust or remove the partition we stole the space from */
|
|
|
|
+ if (free_part->header.length > size) {
|
|
|
|
+ free_part->index += size * NVRAM_BLOCK_LEN;
|
|
|
|
+ free_part->header.length -= size;
|
|
|
|
+ free_part->header.checksum = nvram_checksum(&free_part->header);
|
|
|
|
+ rc = nvram_write_header(free_part);
|
|
|
|
+ if (rc <= 0) {
|
|
|
|
+ pr_err("nvram_create_os_partition: nvram_write_header "
|
|
|
|
+ "failed (%d)\n", rc);
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ list_del(&free_part->partition);
|
|
|
|
+ kfree(free_part);
|
|
|
|
+ }
|
|
|
|
|
|
- /* Clear the partition */
|
|
|
|
|
|
+ /* Clear the new partition */
|
|
for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
|
|
for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
|
|
tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
|
|
tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
|
|
tmp_index += NVRAM_BLOCK_LEN) {
|
|
tmp_index += NVRAM_BLOCK_LEN) {
|
|
@@ -390,31 +415,24 @@ static int __init nvram_create_partition(const char *name, int sig,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;
|
|
|
|
- nvram_error_log_size = ((part->header.length - 1) *
|
|
|
|
- NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
|
|
|
|
-
|
|
|
|
- list_add_tail(&new_part->partition, &free_part->partition);
|
|
|
|
-
|
|
|
|
- if (free_part->header.length <= size) {
|
|
|
|
- list_del(&free_part->partition);
|
|
|
|
- kfree(free_part);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ return new_part->index + NVRAM_HEADER_LEN;
|
|
|
|
+}
|
|
|
|
|
|
- /* Adjust the partition we stole the space from */
|
|
|
|
- free_part->index += size * NVRAM_BLOCK_LEN;
|
|
|
|
- free_part->header.length -= size;
|
|
|
|
- free_part->header.checksum = nvram_checksum(&free_part->header);
|
|
|
|
|
|
+/**
|
|
|
|
+ * nvram_get_partition_size - Get the data size of an nvram partition
|
|
|
|
+ * @data_index: This is the offset of the start of the data of
|
|
|
|
+ * the partition. The same value that is returned by
|
|
|
|
+ * nvram_create_partition().
|
|
|
|
+ */
|
|
|
|
+static int nvram_get_partition_size(loff_t data_index)
|
|
|
|
+{
|
|
|
|
+ struct nvram_partition *part;
|
|
|
|
|
|
- rc = nvram_write_header(free_part);
|
|
|
|
- if (rc <= 0) {
|
|
|
|
- printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "
|
|
|
|
- "failed (%d)\n", rc);
|
|
|
|
- return rc;
|
|
|
|
|
|
+ list_for_each_entry(part, &nvram_part->partition, partition) {
|
|
|
|
+ if (part->index + NVRAM_HEADER_LEN == data_index)
|
|
|
|
+ return (part->header.length - 1) * NVRAM_BLOCK_LEN;
|
|
}
|
|
}
|
|
-
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -469,30 +487,28 @@ static int __init nvram_setup_partition(void)
|
|
}
|
|
}
|
|
|
|
|
|
/* try creating a partition with the free space we have */
|
|
/* try creating a partition with the free space we have */
|
|
- rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
|
|
|
|
|
|
+ rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
|
|
NVRAM_MAX_REQ, NVRAM_MIN_REQ);
|
|
NVRAM_MAX_REQ, NVRAM_MIN_REQ);
|
|
- if (!rc)
|
|
|
|
- return 0;
|
|
|
|
-
|
|
|
|
- /* need to free up some space */
|
|
|
|
- rc = nvram_remove_os_partition();
|
|
|
|
- if (rc) {
|
|
|
|
- return rc;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* create a partition in this new space */
|
|
|
|
- rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
|
|
|
|
- NVRAM_MAX_REQ, NVRAM_MIN_REQ);
|
|
|
|
- if (rc) {
|
|
|
|
- printk(KERN_ERR "nvram_create_partition: Could not find a "
|
|
|
|
- "NVRAM partition large enough\n");
|
|
|
|
- return rc;
|
|
|
|
|
|
+ if (rc < 0) {
|
|
|
|
+ /* need to free up some space */
|
|
|
|
+ rc = nvram_remove_os_partition();
|
|
|
|
+ if (rc)
|
|
|
|
+ return rc;
|
|
|
|
+ /* create a partition in this new space */
|
|
|
|
+ rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
|
|
|
|
+ NVRAM_MAX_REQ, NVRAM_MIN_REQ);
|
|
|
|
+ if (rc < 0) {
|
|
|
|
+ pr_err("nvram_create_partition: Could not find"
|
|
|
|
+ " enough space in NVRAM for partition\n");
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ nvram_error_log_index = rc;
|
|
|
|
+ nvram_error_log_size = nvram_get_partition_size(rc) - sizeof(struct err_log_info);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
static int __init nvram_scan_partitions(void)
|
|
static int __init nvram_scan_partitions(void)
|
|
{
|
|
{
|
|
loff_t cur_index = 0;
|
|
loff_t cur_index = 0;
|