Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  *  c 2001 PPC 64 Team, IBM Corp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * /dev/nvram driver for PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/miscdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/nvram.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/kmsg_dump.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/pstore.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/zlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <asm/nvram.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <asm/rtas.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <asm/machdep.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #undef DEBUG_NVRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #define NVRAM_HEADER_LEN	sizeof(struct nvram_header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #define NVRAM_BLOCK_LEN		NVRAM_HEADER_LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) /* If change this size, then change the size of NVNAME_LEN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) struct nvram_header {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) 	unsigned char signature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 	unsigned char checksum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 	unsigned short length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 	/* Terminating null required only for names < 12 chars. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 	char name[12];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) struct nvram_partition {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 	struct list_head partition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	struct nvram_header header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	unsigned int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) static LIST_HEAD(nvram_partitions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) struct nvram_os_partition rtas_log_partition = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	.name = "ibm,rtas-log",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	.req_size = 2079,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	.min_size = 1055,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 	.index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	.os_partition = true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) struct nvram_os_partition oops_log_partition = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	.name = "lnx,oops-log",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 	.req_size = 4000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	.min_size = 2000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	.index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	.os_partition = true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) static const char *nvram_os_partitions[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	"ibm,rtas-log",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	"lnx,oops-log",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 	NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) static void oops_to_nvram(struct kmsg_dumper *dumper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 			  enum kmsg_dump_reason reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) static struct kmsg_dumper nvram_kmsg_dumper = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 	.dump = oops_to_nvram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83)  * For capturing and compressing an oops or panic report...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85)  * big_oops_buf[] holds the uncompressed text we're capturing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87)  * oops_buf[] holds the compressed text, preceded by a oops header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88)  * oops header has u16 holding the version of oops header (to differentiate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89)  * between old and new format header) followed by u16 holding the length of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  * the compressed* text (*Or uncompressed, if compression fails.) and u64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91)  * holding the timestamp. oops_buf[] gets written to NVRAM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93)  * oops_log_info points to the header. oops_data points to the compressed text.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)  * +- oops_buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96)  * |                                   +- oops_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97)  * v                                   v
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98)  * +-----------+-----------+-----------+------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99)  * | version   | length    | timestamp | text                   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100)  * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes)   |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101)  * +-----------+-----------+-----------+------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102)  * ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103)  * +- oops_log_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  * We preallocate these buffers during init to avoid kmalloc during oops/panic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static size_t big_oops_buf_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) static char *big_oops_buf, *oops_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) static char *oops_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) static size_t oops_data_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) /* Compression parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) #define COMPR_LEVEL 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) #define WINDOW_BITS 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) #define MEM_LEVEL 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) static struct z_stream_s stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) #ifdef CONFIG_PSTORE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) static struct nvram_os_partition skiboot_partition = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) 	.name = "ibm,skiboot",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 	.index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) 	.os_partition = false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) static struct nvram_os_partition of_config_partition = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	.name = "of-config",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	.index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 	.os_partition = false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) static struct nvram_os_partition common_partition = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	.name = "common",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	.index = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	.os_partition = false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) static enum pstore_type_id nvram_type_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	PSTORE_TYPE_DMESG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	PSTORE_TYPE_PPC_COMMON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	-1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 	-1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	-1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) static int read_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) /* nvram_write_os_partition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153)  * We need to buffer the error logs into nvram to ensure that we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154)  * the failure information to decode.  If we have a severe error there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155)  * is no way to guarantee that the OS or the machine is in a state to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156)  * get back to user land and write the error to disk.  For example if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157)  * the SCSI device driver causes a Machine Check by writing to a bad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158)  * IO address, there is no way of guaranteeing that the device driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159)  * is in any state that is would also be able to write the error data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160)  * captured to disk, thus we buffer it in NVRAM for analysis on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161)  * next boot.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163)  * In NVRAM the partition containing the error log buffer will looks like:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164)  * Header (in bytes):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165)  * +-----------+----------+--------+------------+------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166)  * | signature | checksum | length | name       | data             |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167)  * |0          |1         |2      3|4         15|16        length-1|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168)  * +-----------+----------+--------+------------+------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170)  * The 'data' section would look like (in bytes):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171)  * +--------------+------------+-----------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172)  * | event_logged | sequence # | error log                         |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173)  * |0            3|4          7|8                  error_log_size-1|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174)  * +--------------+------------+-----------------------------------+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176)  * event_logged: 0 if event has not been logged to syslog, 1 if it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)  * sequence #: The unique sequence # for each event. (until it wraps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)  * error log: The error log from event_scan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) int nvram_write_os_partition(struct nvram_os_partition *part,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 			     char *buff, int length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 			     unsigned int err_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 			     unsigned int error_log_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	loff_t tmp_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	struct err_log_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	if (part->index == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 		return -ESPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	if (length > part->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 		length = part->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	info.error_type = cpu_to_be32(err_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	info.seq_num = cpu_to_be32(error_log_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	tmp_index = part->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	rc = ppc_md.nvram_write((char *)&info, sizeof(info), &tmp_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 		pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	rc = ppc_md.nvram_write(buff, length, &tmp_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 		pr_err("%s: Failed nvram_write (%d)\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) /* nvram_read_partition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217)  * Reads nvram partition for at most 'length'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) int nvram_read_partition(struct nvram_os_partition *part, char *buff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 			 int length, unsigned int *err_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 			 unsigned int *error_log_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	loff_t tmp_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	struct err_log_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	if (part->index == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	if (length > part->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 		length = part->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	tmp_index = part->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	if (part->os_partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 		rc = ppc_md.nvram_read((char *)&info, sizeof(info), &tmp_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 		if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 			pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	rc = ppc_md.nvram_read(buff, length, &tmp_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 		pr_err("%s: Failed nvram_read (%d)\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 	if (part->os_partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 		*error_log_cnt = be32_to_cpu(info.seq_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 		*err_type = be32_to_cpu(info.error_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) /* nvram_init_os_partition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259)  * This sets up a partition with an "OS" signature.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261)  * The general strategy is the following:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262)  * 1.) If a partition with the indicated name already exists...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263)  *	- If it's large enough, use it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264)  *	- Otherwise, recycle it and keep going.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265)  * 2.) Search for a free partition that is large enough.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266)  * 3.) If there's not a free partition large enough, recycle any obsolete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267)  * OS partitions and try again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268)  * 4.) Will first try getting a chunk that will satisfy the requested size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269)  * 5.) If a chunk of the requested size cannot be allocated, then try finding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270)  * a chunk that will satisfy the minum needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272)  * Returns 0 on success, else -1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) int __init nvram_init_os_partition(struct nvram_os_partition *part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	loff_t p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	/* Look for ours */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	/* Found one but too small, remove it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	if (p && size < part->min_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		pr_info("nvram: Found too small %s partition,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 					" removing it...\n", part->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 		nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 		p = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	/* Create one if we didn't find */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 		p = nvram_create_partition(part->name, NVRAM_SIG_OS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 					part->req_size, part->min_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		if (p == -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 			pr_info("nvram: No room to create %s partition, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 				"deleting any obsolete OS partitions...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 				part->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 			nvram_remove_partition(NULL, NVRAM_SIG_OS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 					nvram_os_partitions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 			p = nvram_create_partition(part->name, NVRAM_SIG_OS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 					part->req_size, part->min_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	if (p <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 		pr_err("nvram: Failed to find or create %s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		       " partition, err %d\n", part->name, (int)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	part->index = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) /* Derived from logfs_compress() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) static int nvram_compress(const void *in, void *out, size_t inlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 							size_t outlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	int err, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 						MEM_LEVEL, Z_DEFAULT_STRATEGY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	if (err != Z_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	stream.next_in = in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	stream.avail_in = inlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	stream.total_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	stream.next_out = out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	stream.avail_out = outlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	stream.total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	err = zlib_deflate(&stream, Z_FINISH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	if (err != Z_STREAM_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	err = zlib_deflateEnd(&stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	if (err != Z_OK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 	if (stream.total_out >= stream.total_in)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	ret = stream.total_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) /* Compress the text from big_oops_buf into oops_buf. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) static int zip_oops(size_t text_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 								oops_data_sz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	if (zipped_len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 		pr_err("nvram: compression failed; returned %d\n", zipped_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 		pr_err("nvram: logging uncompressed oops/panic report\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	oops_hdr->report_length = cpu_to_be16(zipped_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) #ifdef CONFIG_PSTORE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) static int nvram_pstore_open(struct pstore_info *psi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	/* Reset the iterator to start reading partitions again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	read_type = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378)  * nvram_pstore_write - pstore write callback for nvram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379)  * @record:             pstore record to write, with @id to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381)  * Called by pstore_dump() when an oops or panic report is logged in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382)  * printk buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383)  * Returns 0 on successful write.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) static int nvram_pstore_write(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	/* part 1 has the recent messages from printk buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	if (record->part > 1 || (record->type != PSTORE_TYPE_DMESG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	if (clobbering_unread_rtas_event())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	oops_hdr->report_length = cpu_to_be16(record->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	if (record->compressed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		err_type = ERR_TYPE_KERNEL_PANIC_GZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 		(int) (sizeof(*oops_hdr) + record->size), err_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		record->count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	if (rc != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	record->id = record->part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417)  * Reads the oops/panic report, rtas, of-config and common partition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418)  * Returns the length of the data we read from each partition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419)  * Returns 0 if we've been called before.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) static ssize_t nvram_pstore_read(struct pstore_record *record)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 	struct oops_log_info *oops_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	unsigned int err_type, id_no, size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	struct nvram_os_partition *part = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 	char *buff = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 	int sig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	loff_t p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	read_type++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	switch (nvram_type_ids[read_type]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	case PSTORE_TYPE_DMESG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		part = &oops_log_partition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 		record->type = PSTORE_TYPE_DMESG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	case PSTORE_TYPE_PPC_COMMON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		sig = NVRAM_SIG_SYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		part = &common_partition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		record->type = PSTORE_TYPE_PPC_COMMON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 		record->id = PSTORE_TYPE_PPC_COMMON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 		record->time.tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 		record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	case PSTORE_TYPE_PPC_RTAS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		part = &rtas_log_partition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		record->type = PSTORE_TYPE_PPC_RTAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		record->time.tv_sec = last_rtas_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	case PSTORE_TYPE_PPC_OF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		sig = NVRAM_SIG_OF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 		part = &of_config_partition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		record->type = PSTORE_TYPE_PPC_OF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		record->id = PSTORE_TYPE_PPC_OF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		record->time.tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) #ifdef CONFIG_PPC_POWERNV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	case PSTORE_TYPE_PPC_OPAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		sig = NVRAM_SIG_FW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		part = &skiboot_partition;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		record->type = PSTORE_TYPE_PPC_OPAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		record->id = PSTORE_TYPE_PPC_OPAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		record->time.tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	if (!part->os_partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		p = nvram_find_partition(part->name, sig, &size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		if (p <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 			pr_err("nvram: Failed to find partition %s, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 				"err %d\n", part->name, (int)p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 		part->index = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 		part->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	buff = kmalloc(part->size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	if (!buff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		kfree(buff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	record->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	if (part->os_partition)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		record->id = id_no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 		size_t length, hdr_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		oops_hdr = (struct oops_log_info *)buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 		if (be16_to_cpu(oops_hdr->version) < OOPS_HDR_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 			/* Old format oops header had 2-byte record size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 			hdr_size = sizeof(u16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 			length = be16_to_cpu(oops_hdr->version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 			record->time.tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 			record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 			hdr_size = sizeof(*oops_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 			length = be16_to_cpu(oops_hdr->report_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 			record->time.tv_sec = be64_to_cpu(oops_hdr->timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 			record->time.tv_nsec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		record->buf = kmemdup(buff + hdr_size, length, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		kfree(buff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 		if (record->buf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 			return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		record->ecc_notice_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 			record->compressed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 			record->compressed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		return length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	record->buf = buff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	return part->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) static struct pstore_info nvram_pstore_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	.name = "nvram",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	.flags = PSTORE_FLAGS_DMESG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	.open = nvram_pstore_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	.read = nvram_pstore_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	.write = nvram_pstore_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) static int nvram_pstore_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	if (machine_is(pseries)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		nvram_type_ids[2] = PSTORE_TYPE_PPC_RTAS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 		nvram_type_ids[3] = PSTORE_TYPE_PPC_OF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 		nvram_type_ids[2] = PSTORE_TYPE_PPC_OPAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	nvram_pstore_info.buf = oops_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	nvram_pstore_info.bufsize = oops_data_sz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	rc = pstore_register(&nvram_pstore_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	if (rc && (rc != -EPERM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 		/* Print error only when pstore.backend == nvram */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 		pr_err("nvram: pstore_register() failed, returned %d. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 				"Defaults to kmsg_dump\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) static int nvram_pstore_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) void __init nvram_init_oops_partition(int rtas_partition_exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 	rc = nvram_init_os_partition(&oops_log_partition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) #ifdef CONFIG_PPC_PSERIES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		if (!rtas_partition_exists) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 			pr_err("nvram: Failed to initialize oops partition!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		pr_notice("nvram: Using %s partition to log both"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 			" RTAS errors and oops/panic reports\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 			rtas_log_partition.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		memcpy(&oops_log_partition, &rtas_log_partition,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 						sizeof(rtas_log_partition));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		pr_err("nvram: Failed to initialize oops partition!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 	if (!oops_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		pr_err("nvram: No memory for %s partition\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 						oops_log_partition.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	oops_data = oops_buf + sizeof(struct oops_log_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 	oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	rc = nvram_pstore_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	 * Figure compression (preceded by elimination of each line's <n>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	 * severity prefix) will reduce the oops/panic report to at most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	 * 45% of its original size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	big_oops_buf_sz = (oops_data_sz * 100) / 45;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 	big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	if (big_oops_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 		stream.workspace =  kmalloc(zlib_deflate_workspacesize(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 					WINDOW_BITS, MEM_LEVEL), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 		if (!stream.workspace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 			pr_err("nvram: No memory for compression workspace; "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 				"skipping compression of %s partition data\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 				oops_log_partition.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 			kfree(big_oops_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 			big_oops_buf = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 		pr_err("No memory for uncompressed %s data; "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 			"skipping compression\n", oops_log_partition.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		stream.workspace = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	rc = kmsg_dump_register(&nvram_kmsg_dumper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 		kfree(oops_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 		kfree(big_oops_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 		kfree(stream.workspace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639)  * This is our kmsg_dump callback, called after an oops or panic report
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640)  * has been written to the printk buffer.  We want to capture as much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641)  * of the printk buffer as possible.  First, capture as much as we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642)  * that we think will compress sufficiently to fit in the lnx,oops-log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643)  * partition.  If that's too much, go back and capture uncompressed text.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) static void oops_to_nvram(struct kmsg_dumper *dumper,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 			  enum kmsg_dump_reason reason)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	static unsigned int oops_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	static bool panicking = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	static DEFINE_SPINLOCK(lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	size_t text_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	unsigned int err_type = ERR_TYPE_KERNEL_PANIC_GZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	int rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	switch (reason) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	case KMSG_DUMP_SHUTDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 		/* These are almost always orderly shutdowns. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	case KMSG_DUMP_OOPS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	case KMSG_DUMP_PANIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		panicking = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	case KMSG_DUMP_EMERG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		if (panicking)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 			/* Panic report already captured. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 		       __func__, (int) reason);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	if (clobbering_unread_rtas_event())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 	if (!spin_trylock_irqsave(&lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	if (big_oops_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 		kmsg_dump_get_buffer(dumper, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 				     big_oops_buf, big_oops_buf_sz, &text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 		rc = zip_oops(text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		kmsg_dump_rewind(dumper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		kmsg_dump_get_buffer(dumper, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 				     oops_data, oops_data_sz, &text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		err_type = ERR_TYPE_KERNEL_PANIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		oops_hdr->report_length = cpu_to_be16(text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		(int) (sizeof(*oops_hdr) + text_len), err_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		++oops_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	spin_unlock_irqrestore(&lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) #ifdef DEBUG_NVRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) static void __init nvram_print_partitions(char * label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	struct nvram_partition * tmp_part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	printk(KERN_WARNING "--------%s---------\n", label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	list_for_each_entry(tmp_part, &nvram_partitions, partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		printk(KERN_WARNING "%4d    \t%02x\t%02x\t%d\t%12.12s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		       tmp_part->index, tmp_part->header.signature,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		       tmp_part->header.checksum, tmp_part->header.length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		       tmp_part->header.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) static int __init nvram_write_header(struct nvram_partition * part)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	loff_t tmp_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	struct nvram_header phead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	memcpy(&phead, &part->header, NVRAM_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	phead.length = cpu_to_be16(phead.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	tmp_index = part->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) static unsigned char __init nvram_checksum(struct nvram_header *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	unsigned int c_sum, c_sum2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	/* The sum may have spilled into the 3rd byte.  Fold it back. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	/* The sum cannot exceed 2 bytes.  Fold it into a checksum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	c_sum2 = (c_sum >> 8) + (c_sum << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	c_sum = ((c_sum + c_sum2) >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	return c_sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753)  * Per the criteria passed via nvram_remove_partition(), should this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754)  * partition be removed?  1=remove, 0=keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) static int nvram_can_remove_partition(struct nvram_partition *part,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 		const char *name, int sig, const char *exceptions[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	if (part->header.signature != sig)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	if (name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		if (strncmp(name, part->header.name, 12))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	} else if (exceptions) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 		const char **except;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 		for (except = exceptions; *except; except++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 			if (!strncmp(*except, part->header.name, 12))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775)  * nvram_remove_partition - Remove one or more partitions in nvram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776)  * @name: name of the partition to remove, or NULL for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777)  *        signature only match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778)  * @sig: signature of the partition(s) to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779)  * @exceptions: When removing all partitions with a matching signature,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780)  *        leave these alone.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) int __init nvram_remove_partition(const char *name, int sig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 						const char *exceptions[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	struct nvram_partition *part, *prev, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	list_for_each_entry(part, &nvram_partitions, partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 		if (!nvram_can_remove_partition(part, name, sig, exceptions))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 		/* Make partition a free partition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		part->header.signature = NVRAM_SIG_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		memset(part->header.name, 'w', 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 		part->header.checksum = nvram_checksum(&part->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		rc = nvram_write_header(part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 			printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	/* Merge contiguous ones */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	list_for_each_entry_safe(part, tmp, &nvram_partitions, partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		if (part->header.signature != NVRAM_SIG_FREE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 			prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 		if (prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 			prev->header.length += part->header.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 			prev->header.checksum = nvram_checksum(&prev->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 			rc = nvram_write_header(prev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 			if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 				printk(KERN_ERR "nvram_remove_partition: nvram_write failed (%d)\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 				return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 			list_del(&part->partition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 			kfree(part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 			prev = part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829)  * nvram_create_partition - Create a partition in nvram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830)  * @name: name of the partition to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831)  * @sig: signature of the partition to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832)  * @req_size: size of data to allocate in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833)  * @min_size: minimum acceptable size (0 means req_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835)  * Returns a negative error code or a positive nvram index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836)  * of the beginning of the data area of the newly created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837)  * partition. If you provided a min_size smaller than req_size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838)  * you need to query for the actual size yourself after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839)  * call using nvram_partition_get_size().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) loff_t __init nvram_create_partition(const char *name, int sig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 				     int req_size, int min_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	struct nvram_partition *part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	struct nvram_partition *new_part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	struct nvram_partition *free_part = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	static char nv_init_vals[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	loff_t tmp_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	long size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	/* Convert sizes from bytes to blocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	req_size = ALIGN(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	min_size = ALIGN(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	/* If no minimum size specified, make it the same as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	 * requested size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	if (min_size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		min_size = req_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 	if (min_size > req_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	/* Now add one block to each for the header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	req_size += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	min_size += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 	/* Find a free partition that will give us the maximum needed size 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 	   If can't find one that will give us the minimum size needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	list_for_each_entry(part, &nvram_partitions, partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		if (part->header.signature != NVRAM_SIG_FREE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 		if (part->header.length >= req_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 			size = req_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 			free_part = part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 		if (part->header.length > size &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 		    part->header.length >= min_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 			size = part->header.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 			free_part = part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	if (!size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 		return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	/* Create our OS partition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	new_part = kzalloc(sizeof(*new_part), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	if (!new_part) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 		pr_err("%s: kmalloc failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	new_part->index = free_part->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	new_part->header.signature = sig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	new_part->header.length = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	memcpy(new_part->header.name, name, strnlen(name, sizeof(new_part->header.name)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	new_part->header.checksum = nvram_checksum(&new_part->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	rc = nvram_write_header(new_part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		pr_err("%s: nvram_write_header failed (%d)\n", __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		kfree(new_part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	list_add_tail(&new_part->partition, &free_part->partition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	/* Adjust or remove the partition we stole the space from */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	if (free_part->header.length > size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 		free_part->index += size * NVRAM_BLOCK_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		free_part->header.length -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		free_part->header.checksum = nvram_checksum(&free_part->header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		rc = nvram_write_header(free_part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 			pr_err("%s: nvram_write_header failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 			       __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 		list_del(&free_part->partition);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		kfree(free_part);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	} 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	/* Clear the new partition */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	for (tmp_index = new_part->index + NVRAM_HEADER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	     tmp_index <  ((size - 1) * NVRAM_BLOCK_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	     tmp_index += NVRAM_BLOCK_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		rc = ppc_md.nvram_write(nv_init_vals, NVRAM_BLOCK_LEN, &tmp_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		if (rc <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 			pr_err("%s: nvram_write failed (%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 			       __func__, rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 			return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	return new_part->index + NVRAM_HEADER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943)  * nvram_get_partition_size - Get the data size of an nvram partition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944)  * @data_index: This is the offset of the start of the data of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945)  *              the partition. The same value that is returned by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946)  *              nvram_create_partition().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) int nvram_get_partition_size(loff_t data_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	struct nvram_partition *part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	list_for_each_entry(part, &nvram_partitions, partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 		if (part->index + NVRAM_HEADER_LEN == data_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 			return (part->header.length - 1) * NVRAM_BLOCK_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961)  * nvram_find_partition - Find an nvram partition by signature and name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962)  * @name: Name of the partition or NULL for any name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963)  * @sig: Signature to test against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964)  * @out_size: if non-NULL, returns the size of the data part of the partition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) loff_t nvram_find_partition(const char *name, int sig, int *out_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	struct nvram_partition *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	list_for_each_entry(p, &nvram_partitions, partition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		if (p->header.signature == sig &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		    (!name || !strncmp(p->header.name, name, 12))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 			if (out_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 				*out_size = (p->header.length - 1) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 					NVRAM_BLOCK_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			return p->index + NVRAM_HEADER_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) int __init nvram_scan_partitions(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	loff_t cur_index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	struct nvram_header phead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	struct nvram_partition * tmp_part;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	unsigned char c_sum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	char * header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	int total_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	total_size = ppc_md.nvram_size();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	header = kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	if (!header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	while (cur_index < total_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 		if (err != NVRAM_HEADER_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			printk(KERN_ERR "nvram_scan_partitions: Error parsing "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 			       "nvram partitions\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 		memcpy(&phead, header, NVRAM_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		phead.length = be16_to_cpu(phead.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 		c_sum = nvram_checksum(&phead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 		if (c_sum != phead.checksum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 			printk(KERN_WARNING "WARNING: nvram partition checksum"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 			       " was %02x, should be %02x!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 			       phead.checksum, c_sum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 			printk(KERN_WARNING "Terminating nvram partition scan\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 		if (!phead.length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 			printk(KERN_WARNING "WARNING: nvram corruption "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 			       "detected: 0-length partition\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 		tmp_part = kmalloc(sizeof(*tmp_part), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 		err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 		if (!tmp_part) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 			printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 		memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 		tmp_part->index = cur_index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 		list_add_tail(&tmp_part->partition, &nvram_partitions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 		
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 		cur_index += phead.length * NVRAM_BLOCK_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) #ifdef DEBUG_NVRAM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) 	nvram_print_partitions("NVRAM Partitions");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) 	kfree(header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }