aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/nvram_64.c108
1 files changed, 62 insertions, 46 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index 02737e687559..eabee7c61183 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -313,9 +313,15 @@ static int __init nvram_remove_os_partition(void)
313 * @sig: signature of the partition to create 313 * @sig: signature of the partition to create
314 * @req_size: size of data to allocate in bytes 314 * @req_size: size of data to allocate in bytes
315 * @min_size: minimum acceptable size (0 means req_size) 315 * @min_size: minimum acceptable size (0 means req_size)
316 *
317 * Returns a negative error code or a positive nvram index
318 * of the beginning of the data area of the newly created
319 * partition. If you provided a min_size smaller than req_size
320 * you need to query for the actual size yourself after the
321 * call using nvram_partition_get_size().
316 */ 322 */
317static int __init nvram_create_partition(const char *name, int sig, 323static loff_t __init nvram_create_partition(const char *name, int sig,
318 int req_size, int min_size) 324 int req_size, int min_size)
319{ 325{
320 struct nvram_partition *part; 326 struct nvram_partition *part;
321 struct nvram_partition *new_part; 327 struct nvram_partition *new_part;
@@ -334,6 +340,8 @@ static int __init nvram_create_partition(const char *name, int sig,
334 */ 340 */
335 if (min_size == 0) 341 if (min_size == 0)
336 min_size = req_size; 342 min_size = req_size;
343 if (min_size > req_size)
344 return -EINVAL;
337 345
338 /* Now add one block to each for the header */ 346 /* Now add one block to each for the header */
339 req_size += 1; 347 req_size += 1;
@@ -362,7 +370,7 @@ static int __init nvram_create_partition(const char *name, int sig,
362 /* Create our OS partition */ 370 /* Create our OS partition */
363 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); 371 new_part = kmalloc(sizeof(*new_part), GFP_KERNEL);
364 if (!new_part) { 372 if (!new_part) {
365 printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); 373 pr_err("nvram_create_os_partition: kmalloc failed\n");
366 return -ENOMEM; 374 return -ENOMEM;
367 } 375 }
368 376
@@ -374,12 +382,29 @@ static int __init nvram_create_partition(const char *name, int sig,
374 382
375 rc = nvram_write_header(new_part); 383 rc = nvram_write_header(new_part);
376 if (rc <= 0) { 384 if (rc <= 0) {
377 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " 385 pr_err("nvram_create_os_partition: nvram_write_header "
378 "failed (%d)\n", rc); 386 "failed (%d)\n", rc);
379 return rc; 387 return rc;
380 } 388 }
389 list_add_tail(&new_part->partition, &free_part->partition);
390
391 /* Adjust or remove the partition we stole the space from */
392 if (free_part->header.length > size) {
393 free_part->index += size * NVRAM_BLOCK_LEN;
394 free_part->header.length -= size;
395 free_part->header.checksum = nvram_checksum(&free_part->header);
396 rc = nvram_write_header(free_part);
397 if (rc <= 0) {
398 pr_err("nvram_create_os_partition: nvram_write_header "
399 "failed (%d)\n", rc);
400 return rc;
401 }
402 } else {
403 list_del(&free_part->partition);
404 kfree(free_part);
405 }
381 406
382 /* Clear the partition */ 407 /* Clear the new partition */
383 for (tmp_index = new_part->index + NVRAM_HEADER_LEN; 408 for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
384 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN); 409 tmp_index < ((size - 1) * NVRAM_BLOCK_LEN);
385 tmp_index += NVRAM_BLOCK_LEN) { 410 tmp_index += NVRAM_BLOCK_LEN) {
@@ -390,31 +415,24 @@ static int __init nvram_create_partition(const char *name, int sig,
390 } 415 }
391 } 416 }
392 417
393 nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN; 418 return new_part->index + NVRAM_HEADER_LEN;
394 nvram_error_log_size = ((part->header.length - 1) * 419}
395 NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);
396
397 list_add_tail(&new_part->partition, &free_part->partition);
398
399 if (free_part->header.length <= size) {
400 list_del(&free_part->partition);
401 kfree(free_part);
402 return 0;
403 }
404 420
405 /* Adjust the partition we stole the space from */ 421/**
406 free_part->index += size * NVRAM_BLOCK_LEN; 422 * nvram_get_partition_size - Get the data size of an nvram partition
407 free_part->header.length -= size; 423 * @data_index: This is the offset of the start of the data of
408 free_part->header.checksum = nvram_checksum(&free_part->header); 424 * the partition. The same value that is returned by
425 * nvram_create_partition().
426 */
427static int nvram_get_partition_size(loff_t data_index)
428{
429 struct nvram_partition *part;
409 430
410 rc = nvram_write_header(free_part); 431 list_for_each_entry(part, &nvram_part->partition, partition) {
411 if (rc <= 0) { 432 if (part->index + NVRAM_HEADER_LEN == data_index)
412 printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " 433 return (part->header.length - 1) * NVRAM_BLOCK_LEN;
413 "failed (%d)\n", rc);
414 return rc;
415 } 434 }
416 435 return -1;
417 return 0;
418} 436}
419 437
420 438
@@ -469,30 +487,28 @@ static int __init nvram_setup_partition(void)
469 } 487 }
470 488
471 /* try creating a partition with the free space we have */ 489 /* try creating a partition with the free space we have */
472 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS, 490 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
473 NVRAM_MAX_REQ, NVRAM_MIN_REQ); 491 NVRAM_MAX_REQ, NVRAM_MIN_REQ);
474 if (!rc) 492 if (rc < 0) {
475 return 0; 493 /* need to free up some space */
476 494 rc = nvram_remove_os_partition();
477 /* need to free up some space */ 495 if (rc)
478 rc = nvram_remove_os_partition(); 496 return rc;
479 if (rc) { 497 /* create a partition in this new space */
480 return rc; 498 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS,
481 } 499 NVRAM_MAX_REQ, NVRAM_MIN_REQ);
482 500 if (rc < 0) {
483 /* create a partition in this new space */ 501 pr_err("nvram_create_partition: Could not find"
484 rc = nvram_create_partition("ppc64,linux", NVRAM_SIG_OS, 502 " enough space in NVRAM for partition\n");
485 NVRAM_MAX_REQ, NVRAM_MIN_REQ); 503 return rc;
486 if (rc) { 504 }
487 printk(KERN_ERR "nvram_create_partition: Could not find a "
488 "NVRAM partition large enough\n");
489 return rc;
490 } 505 }
491 506
507 nvram_error_log_index = rc;
508 nvram_error_log_size = nvram_get_partition_size(rc) - sizeof(struct err_log_info);
492 return 0; 509 return 0;
493} 510}
494 511
495
496static int __init nvram_scan_partitions(void) 512static int __init nvram_scan_partitions(void)
497{ 513{
498 loff_t cur_index = 0; 514 loff_t cur_index = 0;