⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nvram_64.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	new_part->index = free_part->index;	new_part->header.signature = NVRAM_SIG_OS;	new_part->header.length = size;	strcpy(new_part->header.name, "ppc64,linux");	new_part->header.checksum = nvram_checksum(&new_part->header);	rc = nvram_write_header(new_part);	if (rc <= 0) {		printk(KERN_ERR "nvram_create_os_partition: nvram_write_header \				failed (%d)\n", rc);		return rc;	}	/* make sure and initialize to zero the sequence number and the error	   type logged */	tmp_index = new_part->index + NVRAM_HEADER_LEN;	rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "nvram_create_os_partition: nvram_write "				"failed (%d)\n", rc);		return rc;	}		nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN;	nvram_error_log_size = ((part->header.length - 1) *				NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);		list_add_tail(&new_part->partition, &free_part->partition);	if (free_part->header.length <= size) {		list_del(&free_part->partition);		kfree(free_part);		return 0;	} 	/* Adjust the partition we stole the space from */	free_part->index += size * NVRAM_BLOCK_LEN;	free_part->header.length -= size;	free_part->header.checksum = nvram_checksum(&free_part->header);		rc = nvram_write_header(free_part);	if (rc <= 0) {		printk(KERN_ERR "nvram_create_os_partition: nvram_write_header "		       "failed (%d)\n", rc);		return rc;	}	return 0;}/* nvram_setup_partition * * This will setup the partition we need for buffering the * error logs and cleanup partitions if needed. * * The general strategy is the following: * 1.) If there is ppc64,linux partition large enough then use it. * 2.) If there is not a ppc64,linux partition large enough, search * for a free partition that is large enough. * 3.) If there is not a free partition large enough remove  * _all_ OS partitions and consolidate the space. * 4.) Will first try getting a chunk that will satisfy the maximum * error log size (NVRAM_MAX_REQ). * 5.) If the max chunk cannot be allocated then try finding a chunk * that will satisfy the minum needed (NVRAM_MIN_REQ). */static int nvram_setup_partition(void){	struct list_head * p;	struct nvram_partition * part;	int rc;	/* For now, we don't do any of this on pmac, until I	 * have figured out if it's worth killing some unused stuffs	 * in our nvram, as Apple defined partitions use pretty much	 * all of the space	 */	if (_machine == PLATFORM_POWERMAC)		return -ENOSPC;	/* see if we have an OS partition that meets our needs.	   will try getting the max we need.  If not we'll delete	   partitions and try again. */	list_for_each(p, &nvram_part->partition) {		part = list_entry(p, struct nvram_partition, partition);		if (part->header.signature != NVRAM_SIG_OS)			continue;		if (strcmp(part->header.name, "ppc64,linux"))			continue;		if (part->header.length >= NVRAM_MIN_REQ) {			/* found our partition */			nvram_error_log_index = part->index + NVRAM_HEADER_LEN;			nvram_error_log_size = ((part->header.length - 1) *						NVRAM_BLOCK_LEN) - sizeof(struct err_log_info);			return 0;		}	}		/* try creating a partition with the free space we have */	rc = nvram_create_os_partition();	if (!rc) {		return 0;	}			/* need to free up some space */	rc = nvram_remove_os_partition();	if (rc) {		return rc;	}		/* create a partition in this new space */	rc = nvram_create_os_partition();	if (rc) {		printk(KERN_ERR "nvram_create_os_partition: Could not find a "		       "NVRAM partition large enough\n");		return rc;	}		return 0;}static int nvram_scan_partitions(void){	loff_t cur_index = 0;	struct nvram_header phead;	struct nvram_partition * tmp_part;	unsigned char c_sum;	char * header;	int total_size;	int err;	if (ppc_md.nvram_size == NULL)		return -ENODEV;	total_size = ppc_md.nvram_size();		header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL);	if (!header) {		printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n");		return -ENOMEM;	}	while (cur_index < total_size) {		err = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index);		if (err != NVRAM_HEADER_LEN) {			printk(KERN_ERR "nvram_scan_partitions: Error parsing "			       "nvram partitions\n");			goto out;		}		cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */		memcpy(&phead, header, NVRAM_HEADER_LEN);		err = 0;		c_sum = nvram_checksum(&phead);		if (c_sum != phead.checksum) {			printk(KERN_WARNING "WARNING: nvram partition checksum"			       " was %02x, should be %02x!\n",			       phead.checksum, c_sum);			printk(KERN_WARNING "Terminating nvram partition scan\n");			goto out;		}		if (!phead.length) {			printk(KERN_WARNING "WARNING: nvram corruption "			       "detected: 0-length partition\n");			goto out;		}		tmp_part = (struct nvram_partition *)			kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);		err = -ENOMEM;		if (!tmp_part) {			printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n");			goto out;		}				memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN);		tmp_part->index = cur_index;		list_add_tail(&tmp_part->partition, &nvram_part->partition);				cur_index += phead.length * NVRAM_BLOCK_LEN;	}	err = 0; out:	kfree(header);	return err;}static int __init nvram_init(void){	int error;	int rc;		if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)		return  -ENODEV;  	rc = misc_register(&nvram_dev);	if (rc != 0) {		printk(KERN_ERR "nvram_init: failed to register device\n");		return rc;	}  	  	/* initialize our anchor for the nvram partition list */  	nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);  	if (!nvram_part) {  		printk(KERN_ERR "nvram_init: Failed kmalloc\n");  		return -ENOMEM;  	}  	INIT_LIST_HEAD(&nvram_part->partition);    	/* Get all the NVRAM partitions */  	error = nvram_scan_partitions();  	if (error) {  		printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n");  		return error;  	}  		  	if(nvram_setup_partition())   		printk(KERN_WARNING "nvram_init: Could not find nvram partition"  		       " for nvram buffered error logging.\n");  #ifdef DEBUG_NVRAM	nvram_print_partitions("NVRAM Partitions");#endif  	return rc;}void __exit nvram_cleanup(void){        misc_deregister( &nvram_dev );}#ifdef CONFIG_PPC_PSERIES/* nvram_write_error_log * * We need to buffer the error logs into nvram to ensure that we have * the failure information to decode.  If we have a severe error there * is no way to guarantee that the OS or the machine is in a state to * get back to user land and write the error to disk.  For example if * the SCSI device driver causes a Machine Check by writing to a bad * IO address, there is no way of guaranteeing that the device driver * is in any state that is would also be able to write the error data * captured to disk, thus we buffer it in NVRAM for analysis on the * next boot. * * In NVRAM the partition containing the error log buffer will looks like: * Header (in bytes): * +-----------+----------+--------+------------+------------------+ * | signature | checksum | length | name       | data             | * |0          |1         |2      3|4         15|16        length-1| * +-----------+----------+--------+------------+------------------+ * * The 'data' section would look like (in bytes): * +--------------+------------+-----------------------------------+ * | event_logged | sequence # | error log                         | * |0            3|4          7|8            nvram_error_log_size-1| * +--------------+------------+-----------------------------------+ * * event_logged: 0 if event has not been logged to syslog, 1 if it has * sequence #: The unique sequence # for each event. (until it wraps) * error log: The error log from event_scan */int nvram_write_error_log(char * buff, int length, unsigned int err_type){	int rc;	loff_t tmp_index;	struct err_log_info info;		if (no_logging) {		return -EPERM;	}	if (nvram_error_log_index == -1) {		return -ESPIPE;	}	if (length > nvram_error_log_size) {		length = nvram_error_log_size;	}	info.error_type = err_type;	info.seq_num = error_log_cnt;	tmp_index = nvram_error_log_index;	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);		return rc;	}	rc = ppc_md.nvram_write(buff, length, &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);		return rc;	}		return 0;}/* nvram_read_error_log * * Reads nvram for error log for at most 'length' */int nvram_read_error_log(char * buff, int length, unsigned int * err_type){	int rc;	loff_t tmp_index;	struct err_log_info info;		if (nvram_error_log_index == -1)		return -1;	if (length > nvram_error_log_size)		length = nvram_error_log_size;	tmp_index = nvram_error_log_index;	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);		return rc;	}	rc = ppc_md.nvram_read(buff, length, &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc);		return rc;	}	error_log_cnt = info.seq_num;	*err_type = info.error_type;	return 0;}/* This doesn't actually zero anything, but it sets the event_logged * word to tell that this event is safely in syslog. */int nvram_clear_error_log(void){	loff_t tmp_index;	int clear_word = ERR_FLAG_ALREADY_LOGGED;	int rc;	tmp_index = nvram_error_log_index;		rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);		return rc;	}	return 0;}#endif /* CONFIG_PPC_PSERIES */module_init(nvram_init);module_exit(nvram_cleanup);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -