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

📄 rtas_flash.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				size_t count, loff_t *off){	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);	struct rtas_manage_flash_t *args_buf;	const char reject_str[] = "0";	const char commit_str[] = "1";	char stkbuf[10];	int op;	args_buf = (struct rtas_manage_flash_t *) dp->data;	if ((args_buf->status == MANAGE_AUTH) || (count == 0))		return count;			op = -1;	if (buf) {		if (count > 9) count = 9;		if (copy_from_user (stkbuf, buf, count)) {			return -EFAULT;		}		if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0) 			op = RTAS_REJECT_TMP_IMG;		else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0) 			op = RTAS_COMMIT_TMP_IMG;	}		if (op == -1)   /* buf is empty, or contains invalid string */		return -EINVAL;	args_buf->op = op;	manage_flash(args_buf);	return count;}static void validate_flash(struct rtas_validate_flash_t *args_buf){	int token = rtas_token("ibm,validate-flash-image");	int update_results;	s32 rc;		rc = 0;	do {		spin_lock(&rtas_data_buf_lock);		memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE);		rc = rtas_call(token, 2, 2, &update_results, 			       (u32) __pa(rtas_data_buf), args_buf->buf_size);		memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE);		spin_unlock(&rtas_data_buf_lock);	} while (rtas_busy_delay(rc));	args_buf->status = rc;	args_buf->update_results = update_results;}static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, 		                   char *msg){	int n;	if (args_buf->status >= VALIDATE_TMP_UPDATE) { 		n = sprintf(msg, "%d\n", args_buf->update_results);		if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) ||		    (args_buf->update_results == VALIDATE_TMP_UPDATE))			n += sprintf(msg + n, "%s\n", args_buf->buf);	} else {		n = sprintf(msg, "%d\n", args_buf->status);	}	return n;}static ssize_t validate_flash_read(struct file *file, char __user *buf,			       size_t count, loff_t *ppos){	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);	struct rtas_validate_flash_t *args_buf;	char msg[RTAS_MSG_MAXLEN];	int msglen;	args_buf = (struct rtas_validate_flash_t *) dp->data;	if (ppos && *ppos != 0)		return 0;	/* be cheap */		msglen = get_validate_flash_msg(args_buf, msg);	if (msglen > count)		msglen = count;	if (!access_ok(VERIFY_WRITE, buf, msglen))		return -EINVAL;	if (copy_to_user(buf, msg, msglen))		return -EFAULT;	if (ppos)		*ppos = msglen;	return msglen;}static ssize_t validate_flash_write(struct file *file, const char __user *buf,				    size_t count, loff_t *off){	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);	struct rtas_validate_flash_t *args_buf;	int rc;	args_buf = (struct rtas_validate_flash_t *) dp->data;	if (dp->data == NULL) {		dp->data = kmalloc(sizeof(struct rtas_validate_flash_t), 				GFP_KERNEL);		if (dp->data == NULL) 			return -ENOMEM;	}	/* We are only interested in the first 4K of the	 * candidate image */	if ((*off >= VALIDATE_BUF_SIZE) || 		(args_buf->status == VALIDATE_AUTH)) {		*off += count;		return count;	}	if (*off + count >= VALIDATE_BUF_SIZE)  {		count = VALIDATE_BUF_SIZE - *off;		args_buf->status = VALIDATE_READY;		} else {		args_buf->status = VALIDATE_INCOMPLETE;	}	if (!access_ok(VERIFY_READ, buf, count)) {		rc = -EFAULT;		goto done;	}	if (copy_from_user(args_buf->buf + *off, buf, count)) {		rc = -EFAULT;		goto done;	}	*off += count;	rc = count;done:	if (rc < 0) {		kfree(dp->data);		dp->data = NULL;	}	return rc;}static int validate_flash_release(struct inode *inode, struct file *file){	struct proc_dir_entry *dp = PDE(file->f_path.dentry->d_inode);	struct rtas_validate_flash_t *args_buf;	args_buf = (struct rtas_validate_flash_t *) dp->data;	if (args_buf->status == VALIDATE_READY) {		args_buf->buf_size = VALIDATE_BUF_SIZE;		validate_flash(args_buf);	}	/* The matching atomic_inc was in rtas_excl_open() */	atomic_dec(&dp->count);	return 0;}static void rtas_flash_firmware(int reboot_type){	unsigned long image_size;	struct flash_block_list *f, *next, *flist;	unsigned long rtas_block_list;	int i, status, update_token;	if (rtas_firmware_flash_list.next == NULL)		return;		/* nothing to do */	if (reboot_type != SYS_RESTART) {		printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");		printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");		return;	}	update_token = rtas_token("ibm,update-flash-64-and-reboot");	if (update_token == RTAS_UNKNOWN_SERVICE) {		printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot "		       "is not available -- not a service partition?\n");		printk(KERN_ALERT "FLASH: firmware will not be flashed\n");		return;	}	/* NOTE: the "first" block list is a global var with no data	 * blocks in the kernel data segment.  We do this because	 * we want to ensure this block_list addr is under 4GB.	 */	rtas_firmware_flash_list.num_blocks = 0;	flist = (struct flash_block_list *)&rtas_firmware_flash_list;	rtas_block_list = virt_to_abs(flist);	if (rtas_block_list >= 4UL*1024*1024*1024) {		printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");		return;	}	printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");	/* Update the block_list in place. */	image_size = 0;	for (f = flist; f; f = next) {		/* Translate data addrs to absolute */		for (i = 0; i < f->num_blocks; i++) {			f->blocks[i].data = (char *)virt_to_abs(f->blocks[i].data);			image_size += f->blocks[i].length;		}		next = f->next;		/* Don't translate NULL pointer for last entry */		if (f->next)			f->next = (struct flash_block_list *)virt_to_abs(f->next);		else			f->next = NULL;		/* make num_blocks into the version/length field */		f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);	}	printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);	printk(KERN_ALERT "FLASH: performing flash and reboot\n");	rtas_progress("Flashing        \n", 0x0);	rtas_progress("Please Wait...  ", 0x0);	printk(KERN_ALERT "FLASH: this will take several minutes.  Do not power off!\n");	status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);	switch (status) {	/* should only get "bad" status */	    case 0:		printk(KERN_ALERT "FLASH: success\n");		break;	    case -1:		printk(KERN_ALERT "FLASH: hardware error.  Firmware may not be not flashed\n");		break;	    case -3:		printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform.  Firmware not flashed\n");		break;	    case -4:		printk(KERN_ALERT "FLASH: flash failed when partially complete.  System may not reboot\n");		break;	    default:		printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);		break;	}}static void remove_flash_pde(struct proc_dir_entry *dp){	if (dp) {		kfree(dp->data);		dp->owner = NULL;		remove_proc_entry(dp->name, dp->parent);	}}static int initialize_flash_pde_data(const char *rtas_call_name,				     size_t buf_size,				     struct proc_dir_entry *dp){	int *status;	int token;	dp->data = kzalloc(buf_size, GFP_KERNEL);	if (dp->data == NULL) {		remove_flash_pde(dp);		return -ENOMEM;	}	/*	 * This code assumes that the status int is the first member of the	 * struct 	 */	status = (int *) dp->data;	token = rtas_token(rtas_call_name);	if (token == RTAS_UNKNOWN_SERVICE)		*status = FLASH_AUTH;	else		*status = FLASH_NO_OP;	return 0;}static struct proc_dir_entry *create_flash_pde(const char *filename,					       const struct file_operations *fops){	struct proc_dir_entry *ent = NULL;	ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL);	if (ent != NULL) {		ent->proc_fops = fops;		ent->owner = THIS_MODULE;	}	return ent;}static const struct file_operations rtas_flash_operations = {	.read		= rtas_flash_read,	.write		= rtas_flash_write,	.open		= rtas_excl_open,	.release	= rtas_flash_release,};static const struct file_operations manage_flash_operations = {	.read		= manage_flash_read,	.write		= manage_flash_write,	.open		= rtas_excl_open,	.release	= rtas_excl_release,};static const struct file_operations validate_flash_operations = {	.read		= validate_flash_read,	.write		= validate_flash_write,	.open		= rtas_excl_open,	.release	= validate_flash_release,};int __init rtas_flash_init(void){	int rc;	if (rtas_token("ibm,update-flash-64-and-reboot") ==		       RTAS_UNKNOWN_SERVICE) {		printk(KERN_ERR "rtas_flash: no firmware flash support\n");		return 1;	}	firmware_flash_pde = create_flash_pde("ppc64/rtas/"					      FIRMWARE_FLASH_NAME,					      &rtas_flash_operations);	if (firmware_flash_pde == NULL) {		rc = -ENOMEM;		goto cleanup;	}	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",			 	       sizeof(struct rtas_update_flash_t), 				       firmware_flash_pde);	if (rc != 0)		goto cleanup;	firmware_update_pde = create_flash_pde("ppc64/rtas/"					       FIRMWARE_UPDATE_NAME,					       &rtas_flash_operations);	if (firmware_update_pde == NULL) {		rc = -ENOMEM;		goto cleanup;	}	rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot",			 	       sizeof(struct rtas_update_flash_t), 				       firmware_update_pde);	if (rc != 0)		goto cleanup;	validate_pde = create_flash_pde("ppc64/rtas/" VALIDATE_FLASH_NAME,			      		&validate_flash_operations);	if (validate_pde == NULL) {		rc = -ENOMEM;		goto cleanup;	}	rc = initialize_flash_pde_data("ibm,validate-flash-image",		                       sizeof(struct rtas_validate_flash_t), 				       validate_pde);	if (rc != 0)		goto cleanup;	manage_pde = create_flash_pde("ppc64/rtas/" MANAGE_FLASH_NAME,				      &manage_flash_operations);	if (manage_pde == NULL) {		rc = -ENOMEM;		goto cleanup;	}	rc = initialize_flash_pde_data("ibm,manage-flash-image",			               sizeof(struct rtas_manage_flash_t),				       manage_pde);	if (rc != 0)		goto cleanup;	rtas_flash_term_hook = rtas_flash_firmware;	flash_block_cache = kmem_cache_create("rtas_flash_cache",				RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,				rtas_block_ctor);	if (!flash_block_cache) {		printk(KERN_ERR "%s: failed to create block cache\n",				__FUNCTION__);		rc = -ENOMEM;		goto cleanup;	}	return 0;cleanup:	remove_flash_pde(firmware_flash_pde);	remove_flash_pde(firmware_update_pde);	remove_flash_pde(validate_pde);	remove_flash_pde(manage_pde);	return rc;}void __exit rtas_flash_cleanup(void){	rtas_flash_term_hook = NULL;	if (flash_block_cache)		kmem_cache_destroy(flash_block_cache);	remove_flash_pde(firmware_flash_pde);	remove_flash_pde(firmware_update_pde);	remove_flash_pde(validate_pde);	remove_flash_pde(manage_pde);}module_init(rtas_flash_init);module_exit(rtas_flash_cleanup);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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