On Mon, 2012-10-22 at 10:45 +0100, Matt Fleming wrote:
> On Sun, 2012-10-21 at 15:44 -0700, Jordan Justen wrote:
> > This code is based on efilinux's bzimage support.
> > git://git.kernel.org/pub/scm/boot/efilinux/efilinux.git
> >
> > Signed-off-by: Jordan Justen <[email protected]>
> > Cc: Matt Fleming <[email protected]>
> > ---
> > OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S | 29 ++
> > OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm | 35 ++
> > OvmfPkg/Library/LoadLinuxLib/Linux.c | 487
> > ++++++++++++++++++++
> > OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c | 200 ++++++++
> > OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h | 56 +++
> > OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf | 50 ++
> > OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S | 30 ++
> > OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm | 34 ++
> > OvmfPkg/OvmfPkgIa32.dsc | 1 +
> > OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
> > OvmfPkg/OvmfPkgX64.dsc | 1 +
> > 11 files changed, 924 insertions(+)
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.S
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/Ia32/JumpToKernel.asm
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/Linux.c
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/LinuxGdt.c
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.h
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.S
> > create mode 100644 OvmfPkg/Library/LoadLinuxLib/X64/JumpToKernel.asm
>
> [...]
>
> > +VOID*
> > +EFIAPI
> > +LoadLinuxAllocateKernelSetupPages (
> > + IN UINTN Pages
> > + )
> > +{
> > + EFI_STATUS Status;
> > + EFI_PHYSICAL_ADDRESS Address;
> > +
> > + Address = 0xa0000;
> > + Status = gBS->AllocatePages (
> > + AllocateMaxAddress,
> > + EfiLoaderData,
> > + Pages,
> > + &Address
> > + );
> > + if (EFI_ERROR (Status)) {
> > + return NULL;
> > + }
> > +
> > + return (VOID*)(UINTN) Address;
> > +}
>
> It looks like you're using this function to allocate memory for the
> "struct boot_params" that you pass to the kernel image. This memory
> doesn't need to be allocated under 0xa0000, and in fact, it would
> probably be better if it wasn't since there's very little memory there
> anyway.
>
> But the memory you allocate for "struct boot_params" does need to be
> below the 1GB mark, which is what efilinux commit 8947b2 that you
> highlighted in the covering letter does - that commit doesn't affect the
> memory allocation for the initrd (see comments below for initrd
> allocation restrictions).
Whoops. Thanks for pointing this out.
> > +VOID*
> > +EFIAPI
> > +LoadLinuxAllocateInitrdPages (
> > + IN UINTN Pages
> > + )
> > +{
> > + EFI_STATUS Status;
> > + EFI_PHYSICAL_ADDRESS Address;
> > +
> > + Address = BASE_1GB;
> > + Status = gBS->AllocatePages (
> > + AllocateMaxAddress,
> > + EfiLoaderData,
> > + Pages,
> > + &Address
> > + );
> > + if (!EFI_ERROR (Status)) {
> > + return (VOID*)(UINTN) Address;
> > + } else {
> > + return NULL;
> > + }
> > +}
>
> What you should actually be using to restrict the allocation of the
> initrd is Bp->hdr.ramdisk_max, which may be much higher than 1GB. The
> initrd is accessed pretty late in the boot procedure, way after "proper"
> pagetables have been installed that lift the 1GB restriction.
>
> > +
> > +STATIC
> > +VOID
> > +SetupLinuxMemmap (
> > + IN OUT struct boot_params *Bp
> > + )
> > +{
> > + EFI_STATUS Status;
> > + UINT8 TmpMemoryMap[1];
> > + UINTN MapKey;
> > + UINTN DescriptorSize;
> > + UINT32 DescriptorVersion;
> > + UINTN MemoryMapSize;
> > + EFI_MEMORY_DESCRIPTOR *MemoryMap;
> > + EFI_MEMORY_DESCRIPTOR *MemoryMapPtr;
> > + UINTN Index;
> > + struct efi_info *Efi;
> > + struct e820_entry *LastE820;
>
> [...]
>
> > + LastE820 = &Bp->e820_map[0];
>
> [...]
>
> > +
> > + if ((LastE820 != NULL) &&
> > + (LastE820->type == (UINT32) E820Type) &&
> > + (MemoryMap->PhysicalStart == LastEndAddr)) {
> > + LastE820->size += EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);
>
> Is the (LastE820 != NULL) expression ever false?
I think it is set just below whenever a new E820 entry is modified.
> > + } else {
> > + if (E820EntryCount >= (sizeof (Bp->e820_map) / sizeof
> > (Bp->e820_map[0]))) {
> > + break;
> > + }
> > + E820->type = (UINT32) E820Type;
> > + E820->addr = MemoryMap->PhysicalStart;
> > + E820->size = EFI_PAGES_TO_SIZE (MemoryMap->NumberOfPages);
> > + LastE820 = E820;
> > + LastEndAddr = E820->addr + E820->size;
> > + E820++;
> > + E820EntryCount++;
> > + }
> > +
> > + //
> > + // Get next item
> > + //
> > + MemoryMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemoryMap +
> > DescriptorSize);
> > + }
> > + Bp->e820_entries = (UINT8) E820EntryCount;
>
> I think Laszlo has already mentioned that this code doesn't handle the
> case where, even after merging adjacent entries of the same time, we
> have more than 128 entries.
I took Laszlo's comment to mean I wasn't checking if I overflowed
the e820 entries. At least that should be handled in the
'if (...) break' code just above.
> The efilinux code doesn't either but such
> machines do exist. It's something that's been on my TODO list for a
> while. You need to stuff the extra entries in a setup_data entry with
> type SETUP_E280_EXT.
I think I'll wait for you to add this, and then port it over. :)
> > +EFI_STATUS
> > +EFIAPI
> > +LoadLinuxSetInitrd (
> > + IN OUT VOID *KernelSetup,
> > + IN VOID *Initrd,
> > + IN UINTN InitrdSize
> > + )
> > +{
> > + struct boot_params *Bp;
> > +
> > + RETURN_STATUS_ON_ERROR (BasicKernelSetupCheck (KernelSetup));
> > +
> > + Bp = (struct boot_params*) KernelSetup;
> > +
> > + Bp->hdr.ramdisk_start = (UINT32)(UINTN) Initrd;
> > + Bp->hdr.ramdisk_len = (UINT32) InitrdSize;
> > + Bp->hdr.ramdisk_max = Bp->hdr.ramdisk_start + Bp->hdr.ramdisk_len;
>
> 'ramdisk_max' is a read-only field. It tells you the maximum address at
> which you can allocate memory to hold the initrd. The kernel doesn't
> read it.
Got it.
> > +STATIC
> > +EFI_STATUS
> > +SetupLinuxBootParams (
> > + IN VOID *Kernel,
> > + IN OUT struct boot_params *Bp
> > + )
> > +{
> > + Bp->alt_mem_k = SIZE_32KB;
>
> This is a bit of legacy code and shouldn't be needed (it shouldn't be in
> efilinux either).
Will it possibly allow some older kernels to boot? Or, should I
just toss it out?
Thanks for the review Matt!
-Jordan
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel