Commit b3c72fc9 authored by Daniel Kiper's avatar Daniel Kiper Committed by Borislav Petkov
Browse files

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: default avatarH. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: default avatarDaniel Kiper <daniel.kiper@oracle.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarRoss Philipson <ross.philipson@oracle.com>
Reviewed-by: default avatarH. Peter Anvin (Intel) <hpa@zytor.com>
Acked-by: default avatarKonrad 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
parent 00cd1c15
Loading
Loading
Loading
Loading
+42 −1
Original line number Diff line number Diff line
@@ -827,6 +827,47 @@ Protocol: 2.09+
  sure to consider the case where the linked list already contains
  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
Type:		read (reloc)
@@ -986,7 +1027,7 @@ Field name: setup_type_max
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
+12 −0
Original line number Diff line number Diff line
@@ -459,6 +459,18 @@ static bool mem_avoid_overlap(struct mem_vector *img,
			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;
	}

+1 −1
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@ kernel_info:
	/* Size total. */
	.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

kernel_info_var_len_data:
+1 −1
Original line number Diff line number Diff line
@@ -300,7 +300,7 @@ _start:
	# Part 2 of the header, from the old setup.S

		.ascii	"HdrS"		# header signature
		.word	0x020d		# header version number (>= 0x0105)
		.word	0x020f		# header version number (>= 0x0105)
					# or else old loadlin-1.5 will fail)
		.globl realmode_swtch
realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
+13 −3
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
#ifndef _ASM_X86_BOOTPARAM_H
#define _ASM_X86_BOOTPARAM_H

/* setup_data types */
/* setup_data/setup_indirect types */
#define SETUP_NONE			0
#define SETUP_E820_EXT			1
#define SETUP_DTB			2
@@ -11,8 +11,10 @@
#define SETUP_APPLE_PROPERTIES		5
#define SETUP_JAILHOUSE			6

/* max(SETUP_*) */
#define SETUP_TYPE_MAX			SETUP_JAILHOUSE
#define SETUP_INDIRECT			(1<<31)

/* SETUP_INDIRECT | max(SETUP_*) */
#define SETUP_TYPE_MAX			(SETUP_INDIRECT | SETUP_JAILHOUSE)

/* ram_size flags */
#define RAMDISK_IMAGE_START_MASK	0x07FF
@@ -52,6 +54,14 @@ struct setup_data {
	__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 {
	__u8	setup_sects;
	__u16	root_flags;
Loading