1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * c 2001 PPC 64 Team, IBM Corp
5 * /dev/nvram driver for PPC64
8 #include <linux/types.h>
9 #include <linux/errno.h>
11 #include <linux/miscdevice.h>
12 #include <linux/fcntl.h>
13 #include <linux/nvram.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
16 #include <linux/spinlock.h>
17 #include <linux/kmsg_dump.h>
18 #include <linux/pagemap.h>
19 #include <linux/pstore.h>
20 #include <linux/zlib.h>
21 #include <linux/uaccess.h>
22 #include <asm/nvram.h>
25 #include <asm/machdep.h>
29 #define NVRAM_HEADER_LEN sizeof(struct nvram_header)
30 #define NVRAM_BLOCK_LEN NVRAM_HEADER_LEN
32 /* If change this size, then change the size of NVNAME_LEN */
34 unsigned char signature
;
35 unsigned char checksum
;
36 unsigned short length
;
37 /* Terminating null required only for names < 12 chars. */
41 struct nvram_partition
{
42 struct list_head partition
;
43 struct nvram_header header
;
47 static LIST_HEAD(nvram_partitions
);
49 #ifdef CONFIG_PPC_PSERIES
50 struct nvram_os_partition rtas_log_partition
= {
51 .name
= "ibm,rtas-log",
59 struct nvram_os_partition oops_log_partition
= {
60 .name
= "lnx,oops-log",
67 static const char *nvram_os_partitions
[] = {
68 #ifdef CONFIG_PPC_PSERIES
75 static void oops_to_nvram(struct kmsg_dumper
*dumper
,
76 enum kmsg_dump_reason reason
);
78 static struct kmsg_dumper nvram_kmsg_dumper
= {
83 * For capturing and compressing an oops or panic report...
85 * big_oops_buf[] holds the uncompressed text we're capturing.
87 * oops_buf[] holds the compressed text, preceded by a oops header.
88 * oops header has u16 holding the version of oops header (to differentiate
89 * between old and new format header) followed by u16 holding the length of
90 * the compressed* text (*Or uncompressed, if compression fails.) and u64
91 * holding the timestamp. oops_buf[] gets written to NVRAM.
93 * oops_log_info points to the header. oops_data points to the compressed text.
98 * +-----------+-----------+-----------+------------------------+
99 * | version | length | timestamp | text |
100 * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) |
101 * +-----------+-----------+-----------+------------------------+
105 * We preallocate these buffers during init to avoid kmalloc during oops/panic.
107 static size_t big_oops_buf_sz
;
108 static char *big_oops_buf
, *oops_buf
;
109 static char *oops_data
;
110 static size_t oops_data_sz
;
112 /* Compression parameters */
113 #define COMPR_LEVEL 6
114 #define WINDOW_BITS 12
116 static struct z_stream_s stream
;
119 #ifdef CONFIG_PPC_POWERNV
120 static struct nvram_os_partition skiboot_partition
= {
121 .name
= "ibm,skiboot",
123 .os_partition
= false
127 #ifdef CONFIG_PPC_PSERIES
128 static struct nvram_os_partition of_config_partition
= {
131 .os_partition
= false
135 static struct nvram_os_partition common_partition
= {
138 .os_partition
= false
141 static enum pstore_type_id nvram_type_ids
[] = {
143 PSTORE_TYPE_PPC_COMMON
,
148 static int read_type
;
151 /* nvram_write_os_partition
153 * We need to buffer the error logs into nvram to ensure that we have
154 * the failure information to decode. If we have a severe error there
155 * is no way to guarantee that the OS or the machine is in a state to
156 * get back to user land and write the error to disk. For example if
157 * the SCSI device driver causes a Machine Check by writing to a bad
158 * IO address, there is no way of guaranteeing that the device driver
159 * is in any state that is would also be able to write the error data
160 * captured to disk, thus we buffer it in NVRAM for analysis on the
163 * In NVRAM the partition containing the error log buffer will looks like:
165 * +-----------+----------+--------+------------+------------------+
166 * | signature | checksum | length | name | data |
167 * |0 |1 |2 3|4 15|16 length-1|
168 * +-----------+----------+--------+------------+------------------+
170 * The 'data' section would look like (in bytes):
171 * +--------------+------------+-----------------------------------+
172 * | event_logged | sequence # | error log |
173 * |0 3|4 7|8 error_log_size-1|
174 * +--------------+------------+-----------------------------------+
176 * event_logged: 0 if event has not been logged to syslog, 1 if it has
177 * sequence #: The unique sequence # for each event. (until it wraps)
178 * error log: The error log from event_scan
180 int nvram_write_os_partition(struct nvram_os_partition
*part
,
181 char *buff
, int length
,
182 unsigned int err_type
,
183 unsigned int error_log_cnt
)
187 struct err_log_info info
;
189 if (part
->index
== -1)
192 if (length
> part
->size
)
195 info
.error_type
= cpu_to_be32(err_type
);
196 info
.seq_num
= cpu_to_be32(error_log_cnt
);
198 tmp_index
= part
->index
;
200 rc
= ppc_md
.nvram_write((char *)&info
, sizeof(info
), &tmp_index
);
202 pr_err("%s: Failed nvram_write (%d)\n", __func__
, rc
);
206 rc
= ppc_md
.nvram_write(buff
, length
, &tmp_index
);
208 pr_err("%s: Failed nvram_write (%d)\n", __func__
, rc
);
215 /* nvram_read_partition
217 * Reads nvram partition for at most 'length'
219 int nvram_read_partition(struct nvram_os_partition
*part
, char *buff
,
220 int length
, unsigned int *err_type
,
221 unsigned int *error_log_cnt
)
225 struct err_log_info info
;
227 if (part
->index
== -1)
230 if (length
> part
->size
)
233 tmp_index
= part
->index
;
235 if (part
->os_partition
) {
236 rc
= ppc_md
.nvram_read((char *)&info
, sizeof(info
), &tmp_index
);
238 pr_err("%s: Failed nvram_read (%d)\n", __func__
, rc
);
243 rc
= ppc_md
.nvram_read(buff
, length
, &tmp_index
);
245 pr_err("%s: Failed nvram_read (%d)\n", __func__
, rc
);
249 if (part
->os_partition
) {
250 *error_log_cnt
= be32_to_cpu(info
.seq_num
);
251 *err_type
= be32_to_cpu(info
.error_type
);
257 /* nvram_init_os_partition
259 * This sets up a partition with an "OS" signature.
261 * The general strategy is the following:
262 * 1.) If a partition with the indicated name already exists...
263 * - If it's large enough, use it.
264 * - Otherwise, recycle it and keep going.
265 * 2.) Search for a free partition that is large enough.
266 * 3.) If there's not a free partition large enough, recycle any obsolete
267 * OS partitions and try again.
268 * 4.) Will first try getting a chunk that will satisfy the requested size.
269 * 5.) If a chunk of the requested size cannot be allocated, then try finding
270 * a chunk that will satisfy the minum needed.
272 * Returns 0 on success, else -1.
274 int __init
nvram_init_os_partition(struct nvram_os_partition
*part
)
280 p
= nvram_find_partition(part
->name
, NVRAM_SIG_OS
, &size
);
282 /* Found one but too small, remove it */
283 if (p
&& size
< part
->min_size
) {
284 pr_info("nvram: Found too small %s partition,"
285 " removing it...\n", part
->name
);
286 nvram_remove_partition(part
->name
, NVRAM_SIG_OS
, NULL
);
290 /* Create one if we didn't find */
292 p
= nvram_create_partition(part
->name
, NVRAM_SIG_OS
,
293 part
->req_size
, part
->min_size
);
295 pr_info("nvram: No room to create %s partition, "
296 "deleting any obsolete OS partitions...\n",
298 nvram_remove_partition(NULL
, NVRAM_SIG_OS
,
299 nvram_os_partitions
);
300 p
= nvram_create_partition(part
->name
, NVRAM_SIG_OS
,
301 part
->req_size
, part
->min_size
);
306 pr_err("nvram: Failed to find or create %s"
307 " partition, err %d\n", part
->name
, (int)p
);
312 part
->size
= nvram_get_partition_size(p
) - sizeof(struct err_log_info
);
317 /* Derived from logfs_compress() */
318 static int nvram_compress(const void *in
, void *out
, size_t inlen
,
324 err
= zlib_deflateInit2(&stream
, COMPR_LEVEL
, Z_DEFLATED
, WINDOW_BITS
,
325 MEM_LEVEL
, Z_DEFAULT_STRATEGY
);
330 stream
.avail_in
= inlen
;
332 stream
.next_out
= out
;
333 stream
.avail_out
= outlen
;
334 stream
.total_out
= 0;
336 err
= zlib_deflate(&stream
, Z_FINISH
);
337 if (err
!= Z_STREAM_END
)
340 err
= zlib_deflateEnd(&stream
);
344 if (stream
.total_out
>= stream
.total_in
)
347 ret
= stream
.total_out
;
352 /* Compress the text from big_oops_buf into oops_buf. */
353 static int zip_oops(size_t text_len
)
355 struct oops_log_info
*oops_hdr
= (struct oops_log_info
*)oops_buf
;
356 int zipped_len
= nvram_compress(big_oops_buf
, oops_data
, text_len
,
358 if (zipped_len
< 0) {
359 pr_err("nvram: compression failed; returned %d\n", zipped_len
);
360 pr_err("nvram: logging uncompressed oops/panic report\n");
363 oops_hdr
->version
= cpu_to_be16(OOPS_HDR_VERSION
);
364 oops_hdr
->report_length
= cpu_to_be16(zipped_len
);
365 oops_hdr
->timestamp
= cpu_to_be64(ktime_get_real_seconds());
370 static int nvram_pstore_open(struct pstore_info
*psi
)
372 /* Reset the iterator to start reading partitions again */
378 * nvram_pstore_write - pstore write callback for nvram
379 * @record: pstore record to write, with @id to be set
381 * Called by pstore_dump() when an oops or panic report is logged in the
383 * Returns 0 on successful write.
385 static int nvram_pstore_write(struct pstore_record
*record
)
388 unsigned int err_type
= ERR_TYPE_KERNEL_PANIC
;
389 struct oops_log_info
*oops_hdr
= (struct oops_log_info
*) oops_buf
;
391 /* part 1 has the recent messages from printk buffer */
392 if (record
->part
> 1 || (record
->type
!= PSTORE_TYPE_DMESG
))
395 if (clobbering_unread_rtas_event())
398 oops_hdr
->version
= cpu_to_be16(OOPS_HDR_VERSION
);
399 oops_hdr
->report_length
= cpu_to_be16(record
->size
);
400 oops_hdr
->timestamp
= cpu_to_be64(ktime_get_real_seconds());
402 if (record
->compressed
)
403 err_type
= ERR_TYPE_KERNEL_PANIC_GZ
;
405 rc
= nvram_write_os_partition(&oops_log_partition
, oops_buf
,
406 (int) (sizeof(*oops_hdr
) + record
->size
), err_type
,
412 record
->id
= record
->part
;
417 * Reads the oops/panic report, rtas, of-config and common partition.
418 * Returns the length of the data we read from each partition.
419 * Returns 0 if we've been called before.
421 static ssize_t
nvram_pstore_read(struct pstore_record
*record
)
423 struct oops_log_info
*oops_hdr
;
424 unsigned int err_type
, id_no
, size
= 0;
425 struct nvram_os_partition
*part
= NULL
;
432 switch (nvram_type_ids
[read_type
]) {
433 case PSTORE_TYPE_DMESG
:
434 part
= &oops_log_partition
;
435 record
->type
= PSTORE_TYPE_DMESG
;
437 case PSTORE_TYPE_PPC_COMMON
:
439 part
= &common_partition
;
440 record
->type
= PSTORE_TYPE_PPC_COMMON
;
441 record
->id
= PSTORE_TYPE_PPC_COMMON
;
442 record
->time
.tv_sec
= 0;
443 record
->time
.tv_nsec
= 0;
445 #ifdef CONFIG_PPC_PSERIES
446 case PSTORE_TYPE_PPC_RTAS
:
447 part
= &rtas_log_partition
;
448 record
->type
= PSTORE_TYPE_PPC_RTAS
;
449 record
->time
.tv_sec
= last_rtas_event
;
450 record
->time
.tv_nsec
= 0;
452 case PSTORE_TYPE_PPC_OF
:
454 part
= &of_config_partition
;
455 record
->type
= PSTORE_TYPE_PPC_OF
;
456 record
->id
= PSTORE_TYPE_PPC_OF
;
457 record
->time
.tv_sec
= 0;
458 record
->time
.tv_nsec
= 0;
461 #ifdef CONFIG_PPC_POWERNV
462 case PSTORE_TYPE_PPC_OPAL
:
464 part
= &skiboot_partition
;
465 record
->type
= PSTORE_TYPE_PPC_OPAL
;
466 record
->id
= PSTORE_TYPE_PPC_OPAL
;
467 record
->time
.tv_sec
= 0;
468 record
->time
.tv_nsec
= 0;
475 if (!part
->os_partition
) {
476 p
= nvram_find_partition(part
->name
, sig
, &size
);
478 pr_err("nvram: Failed to find partition %s, "
479 "err %d\n", part
->name
, (int)p
);
486 buff
= kmalloc(part
->size
, GFP_KERNEL
);
491 if (nvram_read_partition(part
, buff
, part
->size
, &err_type
, &id_no
)) {
498 if (part
->os_partition
)
501 if (nvram_type_ids
[read_type
] == PSTORE_TYPE_DMESG
) {
502 size_t length
, hdr_size
;
504 oops_hdr
= (struct oops_log_info
*)buff
;
505 if (be16_to_cpu(oops_hdr
->version
) < OOPS_HDR_VERSION
) {
506 /* Old format oops header had 2-byte record size */
507 hdr_size
= sizeof(u16
);
508 length
= be16_to_cpu(oops_hdr
->version
);
509 record
->time
.tv_sec
= 0;
510 record
->time
.tv_nsec
= 0;
512 hdr_size
= sizeof(*oops_hdr
);
513 length
= be16_to_cpu(oops_hdr
->report_length
);
514 record
->time
.tv_sec
= be64_to_cpu(oops_hdr
->timestamp
);
515 record
->time
.tv_nsec
= 0;
517 record
->buf
= kmemdup(buff
+ hdr_size
, length
, GFP_KERNEL
);
519 if (record
->buf
== NULL
)
522 record
->ecc_notice_size
= 0;
523 if (err_type
== ERR_TYPE_KERNEL_PANIC_GZ
)
524 record
->compressed
= true;
526 record
->compressed
= false;
534 static struct pstore_info nvram_pstore_info
= {
535 .owner
= THIS_MODULE
,
537 .flags
= PSTORE_FLAGS_DMESG
,
538 .open
= nvram_pstore_open
,
539 .read
= nvram_pstore_read
,
540 .write
= nvram_pstore_write
,
543 static int nvram_pstore_init(void)
547 if (machine_is(pseries
)) {
548 nvram_type_ids
[2] = PSTORE_TYPE_PPC_RTAS
;
549 nvram_type_ids
[3] = PSTORE_TYPE_PPC_OF
;
551 nvram_type_ids
[2] = PSTORE_TYPE_PPC_OPAL
;
553 nvram_pstore_info
.buf
= oops_data
;
554 nvram_pstore_info
.bufsize
= oops_data_sz
;
556 rc
= pstore_register(&nvram_pstore_info
);
557 if (rc
&& (rc
!= -EPERM
))
558 /* Print error only when pstore.backend == nvram */
559 pr_err("nvram: pstore_register() failed, returned %d. "
560 "Defaults to kmsg_dump\n", rc
);
565 static int nvram_pstore_init(void)
571 void __init
nvram_init_oops_partition(int rtas_partition_exists
)
575 rc
= nvram_init_os_partition(&oops_log_partition
);
577 #ifdef CONFIG_PPC_PSERIES
578 if (!rtas_partition_exists
) {
579 pr_err("nvram: Failed to initialize oops partition!");
582 pr_notice("nvram: Using %s partition to log both"
583 " RTAS errors and oops/panic reports\n",
584 rtas_log_partition
.name
);
585 memcpy(&oops_log_partition
, &rtas_log_partition
,
586 sizeof(rtas_log_partition
));
588 pr_err("nvram: Failed to initialize oops partition!");
592 oops_buf
= kmalloc(oops_log_partition
.size
, GFP_KERNEL
);
594 pr_err("nvram: No memory for %s partition\n",
595 oops_log_partition
.name
);
598 oops_data
= oops_buf
+ sizeof(struct oops_log_info
);
599 oops_data_sz
= oops_log_partition
.size
- sizeof(struct oops_log_info
);
601 rc
= nvram_pstore_init();
607 * Figure compression (preceded by elimination of each line's <n>
608 * severity prefix) will reduce the oops/panic report to at most
609 * 45% of its original size.
611 big_oops_buf_sz
= (oops_data_sz
* 100) / 45;
612 big_oops_buf
= kmalloc(big_oops_buf_sz
, GFP_KERNEL
);
614 stream
.workspace
= kmalloc(zlib_deflate_workspacesize(
615 WINDOW_BITS
, MEM_LEVEL
), GFP_KERNEL
);
616 if (!stream
.workspace
) {
617 pr_err("nvram: No memory for compression workspace; "
618 "skipping compression of %s partition data\n",
619 oops_log_partition
.name
);
624 pr_err("No memory for uncompressed %s data; "
625 "skipping compression\n", oops_log_partition
.name
);
626 stream
.workspace
= NULL
;
629 rc
= kmsg_dump_register(&nvram_kmsg_dumper
);
631 pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc
);
634 kfree(stream
.workspace
);
639 * This is our kmsg_dump callback, called after an oops or panic report
640 * has been written to the printk buffer. We want to capture as much
641 * of the printk buffer as possible. First, capture as much as we can
642 * that we think will compress sufficiently to fit in the lnx,oops-log
643 * partition. If that's too much, go back and capture uncompressed text.
645 static void oops_to_nvram(struct kmsg_dumper
*dumper
,
646 enum kmsg_dump_reason reason
)
648 struct oops_log_info
*oops_hdr
= (struct oops_log_info
*)oops_buf
;
649 static unsigned int oops_count
= 0;
650 static bool panicking
= false;
651 static DEFINE_SPINLOCK(lock
);
654 unsigned int err_type
= ERR_TYPE_KERNEL_PANIC_GZ
;
658 case KMSG_DUMP_RESTART
:
660 case KMSG_DUMP_POWEROFF
:
661 /* These are almost always orderly shutdowns. */
665 case KMSG_DUMP_PANIC
:
668 case KMSG_DUMP_EMERG
:
670 /* Panic report already captured. */
674 pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
675 __func__
, (int) reason
);
679 if (clobbering_unread_rtas_event())
682 if (!spin_trylock_irqsave(&lock
, flags
))
686 kmsg_dump_get_buffer(dumper
, false,
687 big_oops_buf
, big_oops_buf_sz
, &text_len
);
688 rc
= zip_oops(text_len
);
691 kmsg_dump_rewind(dumper
);
692 kmsg_dump_get_buffer(dumper
, false,
693 oops_data
, oops_data_sz
, &text_len
);
694 err_type
= ERR_TYPE_KERNEL_PANIC
;
695 oops_hdr
->version
= cpu_to_be16(OOPS_HDR_VERSION
);
696 oops_hdr
->report_length
= cpu_to_be16(text_len
);
697 oops_hdr
->timestamp
= cpu_to_be64(ktime_get_real_seconds());
700 (void) nvram_write_os_partition(&oops_log_partition
, oops_buf
,
701 (int) (sizeof(*oops_hdr
) + text_len
), err_type
,
704 spin_unlock_irqrestore(&lock
, flags
);
708 static void __init
nvram_print_partitions(char * label
)
710 struct nvram_partition
* tmp_part
;
712 printk(KERN_WARNING
"--------%s---------\n", label
);
713 printk(KERN_WARNING
"indx\t\tsig\tchks\tlen\tname\n");
714 list_for_each_entry(tmp_part
, &nvram_partitions
, partition
) {
715 printk(KERN_WARNING
"%4d \t%02x\t%02x\t%d\t%12.12s\n",
716 tmp_part
->index
, tmp_part
->header
.signature
,
717 tmp_part
->header
.checksum
, tmp_part
->header
.length
,
718 tmp_part
->header
.name
);
724 static int __init
nvram_write_header(struct nvram_partition
* part
)
728 struct nvram_header phead
;
730 memcpy(&phead
, &part
->header
, NVRAM_HEADER_LEN
);
731 phead
.length
= cpu_to_be16(phead
.length
);
733 tmp_index
= part
->index
;
734 rc
= ppc_md
.nvram_write((char *)&phead
, NVRAM_HEADER_LEN
, &tmp_index
);
740 static unsigned char __init
nvram_checksum(struct nvram_header
*p
)
742 unsigned int c_sum
, c_sum2
;
743 unsigned short *sp
= (unsigned short *)p
->name
; /* assume 6 shorts */
744 c_sum
= p
->signature
+ p
->length
+ sp
[0] + sp
[1] + sp
[2] + sp
[3] + sp
[4] + sp
[5];
746 /* The sum may have spilled into the 3rd byte. Fold it back. */
747 c_sum
= ((c_sum
& 0xffff) + (c_sum
>> 16)) & 0xffff;
748 /* The sum cannot exceed 2 bytes. Fold it into a checksum */
749 c_sum2
= (c_sum
>> 8) + (c_sum
<< 8);
750 c_sum
= ((c_sum
+ c_sum2
) >> 8) & 0xff;
755 * Per the criteria passed via nvram_remove_partition(), should this
756 * partition be removed? 1=remove, 0=keep
758 static int nvram_can_remove_partition(struct nvram_partition
*part
,
759 const char *name
, int sig
, const char *exceptions
[])
761 if (part
->header
.signature
!= sig
)
764 if (strncmp(name
, part
->header
.name
, 12))
766 } else if (exceptions
) {
768 for (except
= exceptions
; *except
; except
++) {
769 if (!strncmp(*except
, part
->header
.name
, 12))
777 * nvram_remove_partition - Remove one or more partitions in nvram
778 * @name: name of the partition to remove, or NULL for a
779 * signature only match
780 * @sig: signature of the partition(s) to remove
781 * @exceptions: When removing all partitions with a matching signature,
785 int __init
nvram_remove_partition(const char *name
, int sig
,
786 const char *exceptions
[])
788 struct nvram_partition
*part
, *prev
, *tmp
;
791 list_for_each_entry(part
, &nvram_partitions
, partition
) {
792 if (!nvram_can_remove_partition(part
, name
, sig
, exceptions
))
795 /* Make partition a free partition */
796 part
->header
.signature
= NVRAM_SIG_FREE
;
797 memset(part
->header
.name
, 'w', 12);
798 part
->header
.checksum
= nvram_checksum(&part
->header
);
799 rc
= nvram_write_header(part
);
801 printk(KERN_ERR
"nvram_remove_partition: nvram_write failed (%d)\n", rc
);
806 /* Merge contiguous ones */
808 list_for_each_entry_safe(part
, tmp
, &nvram_partitions
, partition
) {
809 if (part
->header
.signature
!= NVRAM_SIG_FREE
) {
814 prev
->header
.length
+= part
->header
.length
;
815 prev
->header
.checksum
= nvram_checksum(&prev
->header
);
816 rc
= nvram_write_header(prev
);
818 printk(KERN_ERR
"nvram_remove_partition: nvram_write failed (%d)\n", rc
);
821 list_del(&part
->partition
);
831 * nvram_create_partition - Create a partition in nvram
832 * @name: name of the partition to create
833 * @sig: signature of the partition to create
834 * @req_size: size of data to allocate in bytes
835 * @min_size: minimum acceptable size (0 means req_size)
837 * Returns a negative error code or a positive nvram index
838 * of the beginning of the data area of the newly created
839 * partition. If you provided a min_size smaller than req_size
840 * you need to query for the actual size yourself after the
841 * call using nvram_partition_get_size().
843 loff_t __init
nvram_create_partition(const char *name
, int sig
,
844 int req_size
, int min_size
)
846 struct nvram_partition
*part
;
847 struct nvram_partition
*new_part
;
848 struct nvram_partition
*free_part
= NULL
;
849 static char nv_init_vals
[16];
854 BUILD_BUG_ON(NVRAM_BLOCK_LEN
!= 16);
856 /* Convert sizes from bytes to blocks */
857 req_size
= _ALIGN_UP(req_size
, NVRAM_BLOCK_LEN
) / NVRAM_BLOCK_LEN
;
858 min_size
= _ALIGN_UP(min_size
, NVRAM_BLOCK_LEN
) / NVRAM_BLOCK_LEN
;
860 /* If no minimum size specified, make it the same as the
865 if (min_size
> req_size
)
868 /* Now add one block to each for the header */
872 /* Find a free partition that will give us the maximum needed size
873 If can't find one that will give us the minimum size needed */
874 list_for_each_entry(part
, &nvram_partitions
, partition
) {
875 if (part
->header
.signature
!= NVRAM_SIG_FREE
)
878 if (part
->header
.length
>= req_size
) {
883 if (part
->header
.length
> size
&&
884 part
->header
.length
>= min_size
) {
885 size
= part
->header
.length
;
892 /* Create our OS partition */
893 new_part
= kzalloc(sizeof(*new_part
), GFP_KERNEL
);
895 pr_err("%s: kmalloc failed\n", __func__
);
899 new_part
->index
= free_part
->index
;
900 new_part
->header
.signature
= sig
;
901 new_part
->header
.length
= size
;
902 memcpy(new_part
->header
.name
, name
, strnlen(name
, sizeof(new_part
->header
.name
)));
903 new_part
->header
.checksum
= nvram_checksum(&new_part
->header
);
905 rc
= nvram_write_header(new_part
);
907 pr_err("%s: nvram_write_header failed (%d)\n", __func__
, rc
);
911 list_add_tail(&new_part
->partition
, &free_part
->partition
);
913 /* Adjust or remove the partition we stole the space from */
914 if (free_part
->header
.length
> size
) {
915 free_part
->index
+= size
* NVRAM_BLOCK_LEN
;
916 free_part
->header
.length
-= size
;
917 free_part
->header
.checksum
= nvram_checksum(&free_part
->header
);
918 rc
= nvram_write_header(free_part
);
920 pr_err("%s: nvram_write_header failed (%d)\n",
925 list_del(&free_part
->partition
);
929 /* Clear the new partition */
930 for (tmp_index
= new_part
->index
+ NVRAM_HEADER_LEN
;
931 tmp_index
< ((size
- 1) * NVRAM_BLOCK_LEN
);
932 tmp_index
+= NVRAM_BLOCK_LEN
) {
933 rc
= ppc_md
.nvram_write(nv_init_vals
, NVRAM_BLOCK_LEN
, &tmp_index
);
935 pr_err("%s: nvram_write failed (%d)\n",
941 return new_part
->index
+ NVRAM_HEADER_LEN
;
945 * nvram_get_partition_size - Get the data size of an nvram partition
946 * @data_index: This is the offset of the start of the data of
947 * the partition. The same value that is returned by
948 * nvram_create_partition().
950 int nvram_get_partition_size(loff_t data_index
)
952 struct nvram_partition
*part
;
954 list_for_each_entry(part
, &nvram_partitions
, partition
) {
955 if (part
->index
+ NVRAM_HEADER_LEN
== data_index
)
956 return (part
->header
.length
- 1) * NVRAM_BLOCK_LEN
;
963 * nvram_find_partition - Find an nvram partition by signature and name
964 * @name: Name of the partition or NULL for any name
965 * @sig: Signature to test against
966 * @out_size: if non-NULL, returns the size of the data part of the partition
968 loff_t
nvram_find_partition(const char *name
, int sig
, int *out_size
)
970 struct nvram_partition
*p
;
972 list_for_each_entry(p
, &nvram_partitions
, partition
) {
973 if (p
->header
.signature
== sig
&&
974 (!name
|| !strncmp(p
->header
.name
, name
, 12))) {
976 *out_size
= (p
->header
.length
- 1) *
978 return p
->index
+ NVRAM_HEADER_LEN
;
984 int __init
nvram_scan_partitions(void)
986 loff_t cur_index
= 0;
987 struct nvram_header phead
;
988 struct nvram_partition
* tmp_part
;
994 if (ppc_md
.nvram_size
== NULL
|| ppc_md
.nvram_size() <= 0)
996 total_size
= ppc_md
.nvram_size();
998 header
= kmalloc(NVRAM_HEADER_LEN
, GFP_KERNEL
);
1000 printk(KERN_ERR
"nvram_scan_partitions: Failed kmalloc\n");
1004 while (cur_index
< total_size
) {
1006 err
= ppc_md
.nvram_read(header
, NVRAM_HEADER_LEN
, &cur_index
);
1007 if (err
!= NVRAM_HEADER_LEN
) {
1008 printk(KERN_ERR
"nvram_scan_partitions: Error parsing "
1009 "nvram partitions\n");
1013 cur_index
-= NVRAM_HEADER_LEN
; /* nvram_read will advance us */
1015 memcpy(&phead
, header
, NVRAM_HEADER_LEN
);
1017 phead
.length
= be16_to_cpu(phead
.length
);
1020 c_sum
= nvram_checksum(&phead
);
1021 if (c_sum
!= phead
.checksum
) {
1022 printk(KERN_WARNING
"WARNING: nvram partition checksum"
1023 " was %02x, should be %02x!\n",
1024 phead
.checksum
, c_sum
);
1025 printk(KERN_WARNING
"Terminating nvram partition scan\n");
1028 if (!phead
.length
) {
1029 printk(KERN_WARNING
"WARNING: nvram corruption "
1030 "detected: 0-length partition\n");
1033 tmp_part
= kmalloc(sizeof(*tmp_part
), GFP_KERNEL
);
1036 printk(KERN_ERR
"nvram_scan_partitions: kmalloc failed\n");
1040 memcpy(&tmp_part
->header
, &phead
, NVRAM_HEADER_LEN
);
1041 tmp_part
->index
= cur_index
;
1042 list_add_tail(&tmp_part
->partition
, &nvram_partitions
);
1044 cur_index
+= phead
.length
* NVRAM_BLOCK_LEN
;
1049 nvram_print_partitions("NVRAM Partitions");