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

📄 nvram.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	return 0;}/* setup_nvram_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 setup_nvram_partition(void){	struct list_head * p;	struct nvram_partition * part;	int rc;	/* 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 */			error_log_nvram_index = part->index + NVRAM_HEADER_LEN;			error_log_nvram_size = (part->header.length * NVRAM_BLOCK_LEN) -						NVRAM_HEADER_LEN - sizeof(struct err_log_info);			return 0;		}	}	/* try creating a partition with the free space we have */	rc = create_os_nvram_partition();	if (!rc) {		return 0;	}	/* need to free up some space */	rc = remove_os_nvram_partition();	if (rc) {		return rc;	}	/* create a partition in this new space */	rc = create_os_nvram_partition();	if (rc) {		printk(KERN_ERR "create_os_nvram_partition: Could not find a "		       "NVRAM partition large enough (%d)\n", rc);		return rc;	}	return 0;}static int remove_os_nvram_partition(void){	struct list_head *i;	struct list_head *j;	struct nvram_partition * part;	struct nvram_partition * cur_part;	int rc;	list_for_each(i, &nvram_part->partition) {		part = list_entry(i, struct nvram_partition, partition);		if (part->header.signature != NVRAM_SIG_OS)			continue;		/* Make os partition a free partition */		part->header.signature = NVRAM_SIG_FREE;		sprintf(part->header.name, "wwwwwwwwwwww");		part->header.checksum = nvram_checksum(&part->header);		/* Merge contiguous free partitions backwards */		list_for_each_prev(j, &part->partition) {			cur_part = list_entry(j, struct nvram_partition, partition);			if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {				break;			}			part->header.length += cur_part->header.length;			part->header.checksum = nvram_checksum(&part->header);			part->index = cur_part->index;			list_del(&cur_part->partition);			kfree(cur_part);			j = &part->partition; /* fixup our loop */		}		/* Merge contiguous free partitions forwards */		list_for_each(j, &part->partition) {			cur_part = list_entry(j, struct nvram_partition, partition);			if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) {				break;			}			part->header.length += cur_part->header.length;			part->header.checksum = nvram_checksum(&part->header);			list_del(&cur_part->partition);			kfree(cur_part);			j = &part->partition; /* fixup our loop */		}		rc = write_nvram_header(part);		if (rc <= 0) {			printk(KERN_ERR "remove_os_nvram_partition: write_nvram failed (%d)\n", rc);			return rc;		}	}	return 0;}/* create_os_nvram_partition * * Create a OS linux partition to buffer error logs. * Will create a partition starting at the first free * space found if space has enough room. */static int create_os_nvram_partition(void){	struct list_head * p;	struct nvram_partition * part;	struct nvram_partition * new_part = NULL;	struct nvram_partition * free_part;	struct err_log_info seq_init = { 0, 0 };	loff_t tmp_index;	long size = 0;	int rc;	/* Find a free partition that will give us the maximum needed size	   If can't find one that will give us the minimum size needed */	list_for_each(p, &nvram_part->partition) {		part = list_entry(p, struct nvram_partition, partition);		if (part->header.signature != NVRAM_SIG_FREE)			continue;		if (part->header.length >= NVRAM_MAX_REQ) {			size = NVRAM_MAX_REQ;			free_part = part;			break;		}		if (!size && part->header.length >= NVRAM_MIN_REQ) {			size = NVRAM_MIN_REQ;			free_part = part;		}	}	if (!size) {		return -ENOSPC;	}	/* Create our OS partition */	new_part = kmalloc(sizeof(struct nvram_partition), GFP_KERNEL);	if (!new_part) {		printk(KERN_ERR "create_os_nvram_partition: kmalloc failed\n");		return -ENOMEM;	}	new_part->index = free_part->index;	new_part->header.signature = NVRAM_SIG_OS;	new_part->header.length = size;	sprintf(new_part->header.name, "ppc64,linux");	new_part->header.checksum = nvram_checksum(&new_part->header);	rc = write_nvram_header(new_part);	if (rc <= 0) {		printk(KERN_ERR "create_os_nvram_partition: write_nvram_header \				failed (%d)\n", rc);		kfree(new_part);		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 = write_nvram((char *)&seq_init, sizeof(seq_init), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "create_os_nvram_partition: write_nvram failed (%d)\n", rc);		kfree(new_part);		return rc;	}	error_log_nvram_index = new_part->index + NVRAM_HEADER_LEN;	error_log_nvram_size = (new_part->header.length * NVRAM_BLOCK_LEN) -		NVRAM_HEADER_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 = write_nvram_header(free_part);	if (rc <= 0) {		printk(KERN_ERR "create_os_nvram_partition: write_nvram_header "		       "failed (%d)\n", rc);		error_log_nvram_index = -1;		error_log_nvram_size = 0;		return rc;	}	return 0;}void print_nvram_partitions(char * label){	struct list_head * p;	struct nvram_partition * tmp_part;	printk(KERN_WARNING "--------%s---------\n", label);	printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");	list_for_each(p, &nvram_part->partition) {		tmp_part = list_entry(p, struct nvram_partition, partition);		printk(KERN_WARNING "%d    \t%02x\t%02x\t%d\t%s\n",		       tmp_part->index, tmp_part->header.signature,		       tmp_part->header.checksum, tmp_part->header.length,		       tmp_part->header.name);	}}/* write_error_log_nvram * 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| * +-----------+----------+--------+------------+------------------+ * NOTE: length is in NVRAM_BLOCK_LEN * * The 'data' section would look like (in bytes): * +--------------+------------+-----------------------------------+ * | event_logged | sequence # | error log                         | * |0            3|4          7|8            error_log_nvram_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 write_error_log_nvram(char * buff, int num_bytes, unsigned int err_type){	int rc;	loff_t tmp_index;	struct err_log_info info;	if (no_more_logging) {		return -EPERM;	}	if (error_log_nvram_index == -1) {		return -ESPIPE;	}	if (num_bytes > error_log_nvram_size) {		num_bytes = error_log_nvram_size;	}	info.error_type = err_type;	info.seq_num = error_log_cnt;	tmp_index = error_log_nvram_index;	rc = write_nvram((char *)&info, sizeof(struct err_log_info), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "write_error_log_nvram: Failed write_nvram (%d)\n", rc);		return rc;	}	rc = write_nvram(buff, num_bytes, &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "write_error_log_nvram: Failed write_nvram (%d)\n", rc);		return rc;	}	return 0;}/* read_error_log_nvram * * Reads nvram for error log for at most 'num_bytes' */int read_error_log_nvram(char * buff, int num_bytes, unsigned int * err_type){	int rc;	loff_t tmp_index;	struct err_log_info info;	if (error_log_nvram_index == -1)		return -1;	if (num_bytes > error_log_nvram_size)		num_bytes = error_log_nvram_size;	tmp_index = error_log_nvram_index;	rc = read_nvram((char *)&info, sizeof(struct err_log_info), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "read_error_log_nvram: Failed read_nvram (%d)\n", rc);		return rc;	}	rc = read_nvram(buff, num_bytes, &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "read_error_log_nvram: Failed read_nvram (%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 clear_error_log_nvram(){	loff_t tmp_index;	int clear_word = ERR_FLAG_ALREADY_LOGGED;	int rc;	if (error_log_nvram_index == -1) {		return -ESPIPE;	}	tmp_index = error_log_nvram_index;	rc = write_nvram((char *)&clear_word, sizeof(int), &tmp_index);	if (rc <= 0) {		printk(KERN_ERR "clear_error_log_nvram: Failed write_nvram (%d)\n", rc);		return rc;	}	return 0;}static int write_nvram_header(struct nvram_partition * part){	loff_t tmp_index;	int rc;	tmp_index = part->index;	rc = write_nvram((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index);	return rc;}static unsigned char nvram_checksum(struct nvram_header *p){	unsigned int c_sum, c_sum2;	unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */	c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5];	/* The sum may have spilled into the 3rd byte.  Fold it back. */	c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff;	/* The sum cannot exceed 2 bytes.  Fold it into a checksum */	c_sum2 = (c_sum >> 8) + (c_sum << 8);	c_sum = ((c_sum + c_sum2) >> 8) & 0xff;	return c_sum;}module_init(nvram_init);module_exit(nvram_cleanup);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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