mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	x86/boot: Introduce setup_indirect
The setup_data is a bit awkward to use for extremely large data objects, both because the setup_data header has to be adjacent to the data object and because it has a 32-bit length field. However, it is important that intermediate stages of the boot process have a way to identify which chunks of memory are occupied by kernel data. Thus introduce an uniform way to specify such indirect data as setup_indirect struct and SETUP_INDIRECT type. And finally bump setup_header version in arch/x86/boot/header.S. Suggested-by: H. Peter Anvin (Intel) <hpa@zytor.com> Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com> Signed-off-by: Borislav Petkov <bp@suse.de> Reviewed-by: Ross Philipson <ross.philipson@oracle.com> Reviewed-by: H. Peter Anvin (Intel) <hpa@zytor.com> Acked-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: ard.biesheuvel@linaro.org Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: dave.hansen@linux.intel.com Cc: eric.snowberg@oracle.com Cc: Ingo Molnar <mingo@redhat.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Juergen Gross <jgross@suse.com> Cc: kanth.ghatraju@oracle.com Cc: linux-doc@vger.kernel.org Cc: linux-efi <linux-efi@vger.kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: rdunlap@infradead.org Cc: ross.philipson@oracle.com Cc: Thomas Gleixner <tglx@linutronix.de> Cc: x86-ml <x86@kernel.org> Cc: xen-devel@lists.xenproject.org Link: https://lkml.kernel.org/r/20191112134640.16035-4-daniel.kiper@oracle.com
This commit is contained in:
		
							parent
							
								
									00cd1c154d
								
							
						
					
					
						commit
						b3c72fc9a7
					
				
					 10 changed files with 138 additions and 17 deletions
				
			
		| 
						 | 
					@ -827,6 +827,47 @@ Protocol:	2.09+
 | 
				
			||||||
  sure to consider the case where the linked list already contains
 | 
					  sure to consider the case where the linked list already contains
 | 
				
			||||||
  entries.
 | 
					  entries.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The setup_data is a bit awkward to use for extremely large data objects,
 | 
				
			||||||
 | 
					  both because the setup_data header has to be adjacent to the data object
 | 
				
			||||||
 | 
					  and because it has a 32-bit length field. However, it is important that
 | 
				
			||||||
 | 
					  intermediate stages of the boot process have a way to identify which
 | 
				
			||||||
 | 
					  chunks of memory are occupied by kernel data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Thus setup_indirect struct and SETUP_INDIRECT type were introduced in
 | 
				
			||||||
 | 
					  protocol 2.15.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  struct setup_indirect {
 | 
				
			||||||
 | 
					    __u32 type;
 | 
				
			||||||
 | 
					    __u32 reserved;  /* Reserved, must be set to zero. */
 | 
				
			||||||
 | 
					    __u64 len;
 | 
				
			||||||
 | 
					    __u64 addr;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The type member is a SETUP_INDIRECT | SETUP_* type. However, it cannot be
 | 
				
			||||||
 | 
					  SETUP_INDIRECT itself since making the setup_indirect a tree structure
 | 
				
			||||||
 | 
					  could require a lot of stack space in something that needs to parse it
 | 
				
			||||||
 | 
					  and stack space can be limited in boot contexts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Let's give an example how to point to SETUP_E820_EXT data using setup_indirect.
 | 
				
			||||||
 | 
					  In this case setup_data and setup_indirect will look like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  struct setup_data {
 | 
				
			||||||
 | 
					    __u64 next = 0 or <addr_of_next_setup_data_struct>;
 | 
				
			||||||
 | 
					    __u32 type = SETUP_INDIRECT;
 | 
				
			||||||
 | 
					    __u32 len = sizeof(setup_data);
 | 
				
			||||||
 | 
					    __u8 data[sizeof(setup_indirect)] = struct setup_indirect {
 | 
				
			||||||
 | 
					      __u32 type = SETUP_INDIRECT | SETUP_E820_EXT;
 | 
				
			||||||
 | 
					      __u32 reserved = 0;
 | 
				
			||||||
 | 
					      __u64 len = <len_of_SETUP_E820_EXT_data>;
 | 
				
			||||||
 | 
					      __u64 addr = <addr_of_SETUP_E820_EXT_data>;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note::
 | 
				
			||||||
 | 
					     SETUP_INDIRECT | SETUP_NONE objects cannot be properly distinguished
 | 
				
			||||||
 | 
					     from SETUP_INDIRECT itself. So, this kind of objects cannot be provided
 | 
				
			||||||
 | 
					     by the bootloaders.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
============	============
 | 
					============	============
 | 
				
			||||||
Field name:	pref_address
 | 
					Field name:	pref_address
 | 
				
			||||||
Type:		read (reloc)
 | 
					Type:		read (reloc)
 | 
				
			||||||
| 
						 | 
					@ -986,7 +1027,7 @@ Field name:	setup_type_max
 | 
				
			||||||
Offset/size:	0x000c/4
 | 
					Offset/size:	0x000c/4
 | 
				
			||||||
============	==============
 | 
					============	==============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  This field contains maximal allowed type for setup_data.
 | 
					  This field contains maximal allowed type for setup_data and setup_indirect structs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The Image Checksum
 | 
					The Image Checksum
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -459,6 +459,18 @@ static bool mem_avoid_overlap(struct mem_vector *img,
 | 
				
			||||||
			is_overlapping = true;
 | 
								is_overlapping = true;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ptr->type == SETUP_INDIRECT &&
 | 
				
			||||||
 | 
							    ((struct setup_indirect *)ptr->data)->type != SETUP_INDIRECT) {
 | 
				
			||||||
 | 
								avoid.start = ((struct setup_indirect *)ptr->data)->addr;
 | 
				
			||||||
 | 
								avoid.size = ((struct setup_indirect *)ptr->data)->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (mem_overlaps(img, &avoid) && (avoid.start < earliest)) {
 | 
				
			||||||
 | 
									*overlap = avoid;
 | 
				
			||||||
 | 
									earliest = overlap->start;
 | 
				
			||||||
 | 
									is_overlapping = true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ptr = (struct setup_data *)(unsigned long)ptr->next;
 | 
							ptr = (struct setup_data *)(unsigned long)ptr->next;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,7 @@ kernel_info:
 | 
				
			||||||
	/* Size total. */
 | 
						/* Size total. */
 | 
				
			||||||
	.long	kernel_info_end - kernel_info
 | 
						.long	kernel_info_end - kernel_info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Maximal allowed type for setup_data. */
 | 
						/* Maximal allowed type for setup_data and setup_indirect structs. */
 | 
				
			||||||
	.long	SETUP_TYPE_MAX
 | 
						.long	SETUP_TYPE_MAX
 | 
				
			||||||
 | 
					
 | 
				
			||||||
kernel_info_var_len_data:
 | 
					kernel_info_var_len_data:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -300,7 +300,7 @@ _start:
 | 
				
			||||||
	# Part 2 of the header, from the old setup.S
 | 
						# Part 2 of the header, from the old setup.S
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		.ascii	"HdrS"		# header signature
 | 
							.ascii	"HdrS"		# header signature
 | 
				
			||||||
		.word	0x020d		# header version number (>= 0x0105)
 | 
							.word	0x020f		# header version number (>= 0x0105)
 | 
				
			||||||
					# or else old loadlin-1.5 will fail)
 | 
										# or else old loadlin-1.5 will fail)
 | 
				
			||||||
		.globl realmode_swtch
 | 
							.globl realmode_swtch
 | 
				
			||||||
realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
 | 
					realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
#ifndef _ASM_X86_BOOTPARAM_H
 | 
					#ifndef _ASM_X86_BOOTPARAM_H
 | 
				
			||||||
#define _ASM_X86_BOOTPARAM_H
 | 
					#define _ASM_X86_BOOTPARAM_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* setup_data types */
 | 
					/* setup_data/setup_indirect types */
 | 
				
			||||||
#define SETUP_NONE			0
 | 
					#define SETUP_NONE			0
 | 
				
			||||||
#define SETUP_E820_EXT			1
 | 
					#define SETUP_E820_EXT			1
 | 
				
			||||||
#define SETUP_DTB			2
 | 
					#define SETUP_DTB			2
 | 
				
			||||||
| 
						 | 
					@ -11,8 +11,10 @@
 | 
				
			||||||
#define SETUP_APPLE_PROPERTIES		5
 | 
					#define SETUP_APPLE_PROPERTIES		5
 | 
				
			||||||
#define SETUP_JAILHOUSE			6
 | 
					#define SETUP_JAILHOUSE			6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* max(SETUP_*) */
 | 
					#define SETUP_INDIRECT			(1<<31)
 | 
				
			||||||
#define SETUP_TYPE_MAX			SETUP_JAILHOUSE
 | 
					
 | 
				
			||||||
 | 
					/* SETUP_INDIRECT | max(SETUP_*) */
 | 
				
			||||||
 | 
					#define SETUP_TYPE_MAX			(SETUP_INDIRECT | SETUP_JAILHOUSE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ram_size flags */
 | 
					/* ram_size flags */
 | 
				
			||||||
#define RAMDISK_IMAGE_START_MASK	0x07FF
 | 
					#define RAMDISK_IMAGE_START_MASK	0x07FF
 | 
				
			||||||
| 
						 | 
					@ -52,6 +54,14 @@ struct setup_data {
 | 
				
			||||||
	__u8 data[0];
 | 
						__u8 data[0];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* extensible setup indirect data node */
 | 
				
			||||||
 | 
					struct setup_indirect {
 | 
				
			||||||
 | 
						__u32 type;
 | 
				
			||||||
 | 
						__u32 reserved;  /* Reserved, must be set to zero. */
 | 
				
			||||||
 | 
						__u64 len;
 | 
				
			||||||
 | 
						__u64 addr;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct setup_header {
 | 
					struct setup_header {
 | 
				
			||||||
	__u8	setup_sects;
 | 
						__u8	setup_sects;
 | 
				
			||||||
	__u16	root_flags;
 | 
						__u16	root_flags;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -999,6 +999,17 @@ void __init e820__reserve_setup_data(void)
 | 
				
			||||||
		data = early_memremap(pa_data, sizeof(*data));
 | 
							data = early_memremap(pa_data, sizeof(*data));
 | 
				
			||||||
		e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
 | 
							e820__range_update(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
 | 
				
			||||||
		e820__range_update_kexec(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
 | 
							e820__range_update_kexec(pa_data, sizeof(*data)+data->len, E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (data->type == SETUP_INDIRECT &&
 | 
				
			||||||
 | 
							    ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
 | 
				
			||||||
 | 
								e820__range_update(((struct setup_indirect *)data->data)->addr,
 | 
				
			||||||
 | 
										   ((struct setup_indirect *)data->data)->len,
 | 
				
			||||||
 | 
										   E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
 | 
				
			||||||
 | 
								e820__range_update_kexec(((struct setup_indirect *)data->data)->addr,
 | 
				
			||||||
 | 
											 ((struct setup_indirect *)data->data)->len,
 | 
				
			||||||
 | 
											 E820_TYPE_RAM, E820_TYPE_RESERVED_KERN);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pa_data = data->next;
 | 
							pa_data = data->next;
 | 
				
			||||||
		early_memunmap(data, sizeof(*data));
 | 
							early_memunmap(data, sizeof(*data));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,12 @@ static ssize_t setup_data_read(struct file *file, char __user *user_buf,
 | 
				
			||||||
	if (count > node->len - pos)
 | 
						if (count > node->len - pos)
 | 
				
			||||||
		count = node->len - pos;
 | 
							count = node->len - pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pa = node->paddr + sizeof(struct setup_data) + pos;
 | 
						pa = node->paddr + pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Is it direct data or invalid indirect one? */
 | 
				
			||||||
 | 
						if (!(node->type & SETUP_INDIRECT) || node->type == SETUP_INDIRECT)
 | 
				
			||||||
 | 
							pa += sizeof(struct setup_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p = memremap(pa, count, MEMREMAP_WB);
 | 
						p = memremap(pa, count, MEMREMAP_WB);
 | 
				
			||||||
	if (!p)
 | 
						if (!p)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -108,9 +113,17 @@ static int __init create_setup_data_nodes(struct dentry *parent)
 | 
				
			||||||
			goto err_dir;
 | 
								goto err_dir;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		node->paddr = pa_data;
 | 
							if (data->type == SETUP_INDIRECT &&
 | 
				
			||||||
		node->type = data->type;
 | 
							    ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
 | 
				
			||||||
		node->len = data->len;
 | 
								node->paddr = ((struct setup_indirect *)data->data)->addr;
 | 
				
			||||||
 | 
								node->type  = ((struct setup_indirect *)data->data)->type;
 | 
				
			||||||
 | 
								node->len   = ((struct setup_indirect *)data->data)->len;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								node->paddr = pa_data;
 | 
				
			||||||
 | 
								node->type  = data->type;
 | 
				
			||||||
 | 
								node->len   = data->len;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		create_setup_data_node(d, no, node);
 | 
							create_setup_data_node(d, no, node);
 | 
				
			||||||
		pa_data = data->next;
 | 
							pa_data = data->next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,12 @@ static int __init get_setup_data_size(int nr, size_t *size)
 | 
				
			||||||
		if (!data)
 | 
							if (!data)
 | 
				
			||||||
			return -ENOMEM;
 | 
								return -ENOMEM;
 | 
				
			||||||
		if (nr == i) {
 | 
							if (nr == i) {
 | 
				
			||||||
			*size = data->len;
 | 
								if (data->type == SETUP_INDIRECT &&
 | 
				
			||||||
 | 
								    ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT)
 | 
				
			||||||
 | 
									*size = ((struct setup_indirect *)data->data)->len;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									*size = data->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			memunmap(data);
 | 
								memunmap(data);
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -130,7 +135,10 @@ static ssize_t type_show(struct kobject *kobj,
 | 
				
			||||||
	if (!data)
 | 
						if (!data)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = sprintf(buf, "0x%x\n", data->type);
 | 
						if (data->type == SETUP_INDIRECT)
 | 
				
			||||||
 | 
							ret = sprintf(buf, "0x%x\n", ((struct setup_indirect *)data->data)->type);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							ret = sprintf(buf, "0x%x\n", data->type);
 | 
				
			||||||
	memunmap(data);
 | 
						memunmap(data);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -142,7 +150,7 @@ static ssize_t setup_data_data_read(struct file *fp,
 | 
				
			||||||
				    loff_t off, size_t count)
 | 
									    loff_t off, size_t count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int nr, ret = 0;
 | 
						int nr, ret = 0;
 | 
				
			||||||
	u64 paddr;
 | 
						u64 paddr, len;
 | 
				
			||||||
	struct setup_data *data;
 | 
						struct setup_data *data;
 | 
				
			||||||
	void *p;
 | 
						void *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -157,19 +165,28 @@ static ssize_t setup_data_data_read(struct file *fp,
 | 
				
			||||||
	if (!data)
 | 
						if (!data)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (off > data->len) {
 | 
						if (data->type == SETUP_INDIRECT &&
 | 
				
			||||||
 | 
						    ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
 | 
				
			||||||
 | 
							paddr = ((struct setup_indirect *)data->data)->addr;
 | 
				
			||||||
 | 
							len = ((struct setup_indirect *)data->data)->len;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							paddr += sizeof(*data);
 | 
				
			||||||
 | 
							len = data->len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (off > len) {
 | 
				
			||||||
		ret = -EINVAL;
 | 
							ret = -EINVAL;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (count > data->len - off)
 | 
						if (count > len - off)
 | 
				
			||||||
		count = data->len - off;
 | 
							count = len - off;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!count)
 | 
						if (!count)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = count;
 | 
						ret = count;
 | 
				
			||||||
	p = memremap(paddr + sizeof(*data), data->len, MEMREMAP_WB);
 | 
						p = memremap(paddr, len, MEMREMAP_WB);
 | 
				
			||||||
	if (!p) {
 | 
						if (!p) {
 | 
				
			||||||
		ret = -ENOMEM;
 | 
							ret = -ENOMEM;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -438,6 +438,12 @@ static void __init memblock_x86_reserve_range_setup_data(void)
 | 
				
			||||||
	while (pa_data) {
 | 
						while (pa_data) {
 | 
				
			||||||
		data = early_memremap(pa_data, sizeof(*data));
 | 
							data = early_memremap(pa_data, sizeof(*data));
 | 
				
			||||||
		memblock_reserve(pa_data, sizeof(*data) + data->len);
 | 
							memblock_reserve(pa_data, sizeof(*data) + data->len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (data->type == SETUP_INDIRECT &&
 | 
				
			||||||
 | 
							    ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT)
 | 
				
			||||||
 | 
								memblock_reserve(((struct setup_indirect *)data->data)->addr,
 | 
				
			||||||
 | 
										 ((struct setup_indirect *)data->data)->len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pa_data = data->next;
 | 
							pa_data = data->next;
 | 
				
			||||||
		early_memunmap(data, sizeof(*data));
 | 
							early_memunmap(data, sizeof(*data));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -626,6 +626,17 @@ static bool memremap_is_setup_data(resource_size_t phys_addr,
 | 
				
			||||||
		paddr_next = data->next;
 | 
							paddr_next = data->next;
 | 
				
			||||||
		len = data->len;
 | 
							len = data->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ((phys_addr > paddr) && (phys_addr < (paddr + len))) {
 | 
				
			||||||
 | 
								memunmap(data);
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (data->type == SETUP_INDIRECT &&
 | 
				
			||||||
 | 
							    ((struct setup_indirect *)data->data)->type != SETUP_INDIRECT) {
 | 
				
			||||||
 | 
								paddr = ((struct setup_indirect *)data->data)->addr;
 | 
				
			||||||
 | 
								len = ((struct setup_indirect *)data->data)->len;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		memunmap(data);
 | 
							memunmap(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((phys_addr > paddr) && (phys_addr < (paddr + len)))
 | 
							if ((phys_addr > paddr) && (phys_addr < (paddr + len)))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue