Re: EFI and multiboot2 devlopment work for Xen
On Mon, Oct 21, 2013 at 02:36:38PM +0100, Jan Beulich wrote: On 21.10.13 at 14:57, Daniel Kiper daniel.ki...@oracle.com wrote: [...] Separate multiboot2efi module should be established. It should verify system kernel and all loaded modules using shim on EFI platforms with enabled secure boot Each involved component verifies only the next image. I.e. the shim verifies the Xen image, and Xen verifies the Dom0 kernel binary. The Dom0 kernel (assuming it to be Linux) will then be responsible for dealing with its initrd. (One open question is how Currently Linux Kernel is only verified. Sorry, my fault. As I know Matthew Garrett would like to verify Linux Kernel modules too. However, I do not know details now. I think that we should take into account his work. Xen ought to deal with an eventual XSM module; I take it that Could you tell me more about that? What issues do you expect here? the CPUs themselves take care of the microcode blob.) This can't be different because the shim provided verification protocol assumes that it's being handed a PE image (hence the need for Linux to package itself as a fake PE image), and hence can't be used for verifying other than the Xen and Dom0 kernel binaries. At first I am going to prepare multiboot2 protocol implementation for Xen (there is about 80% of code ready) with above mentioned workaround. Is that really worthwhile as long as it's not clear whether ... Later I am going to work on multiboot2efi module. ... is going to be accepted? It is only proposal. I am not going to continue work until we agree all details. What do you think about that? Any comments, suggestions, objections? The complications here make it pretty clear to me that the GrUB2-less solution (or, if GruB2 absolutely has to be involved, its chain loading capability) I have been advocating continues to be the better (and, as said before, conceptually correct) model. In general I agree but real life is more complicated (sadly). EFI boot loader is not so flexible as GRUB2. Additionally, its configuration differs from platform to platform. I do not mention that if you would like to change EFI boot loader configuration from EFI platform configuration menu it is at least onerous. Until all above mentioned issues (and others) will be fixed I do not expect that everybody will use EFI boot loader as a standard way for system loading. Probably it will happen later than sooner (if at all). So I think we should find right solution for that problem instead of ignoring it. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
EFI and multiboot2 devlopment work for Xen
Hi, During work on multiboot2 protocol support for Xen it was discovered that memory map passed via relevant tag could not represent wide range of memory types available on EFI platforms. Additionally, GRUB2 implementation calls ExitBootServices() on them just before jumping into loaded image. In this situation loaded system could not clearly identify reserved memory regions, EFI runtime services regions and others. Normally, on EFI platform, system requires access to at least EFI runtime services. However, it is not possible to identify them in GRUB2 implementation of multiboot2 protocol because they are marked as reserved, like memory mapped IO regions, really reserved memory regions and others. Additionally, it is not possible to get memory map directly from EFI (similar solution is used on legacy BIOS platforms in Xen case) because ExitBootServices() was earlier called by GRUB2. So there is only one chance to do that today. Loaded image could map all reserved regions. However, this is not final solution because it could be dangerous. So this is rather workaround which should be used on currently existing multiboot2 protocol implementation only. At this stage extra tag could be added to multiboot2 protocol to pass plain EFI memory map to loaded image too. However, this solution requires some coordination with GRUB2 upstream and could take some time. Additionally, it should be mentioned that there is no possibility or it could be very difficult to implement secure boot on EFI platforms using GRUB2 as boot loader because, as it was mentioned earlier, it calls ExitBootServices(). At first there was a plan to use upstream GRUB2 as a reference multiboot2 protocol implementation. However, during discussion on LPC 2013 it was stated that every distribution uses tons of patches for GRUB2. So distros GRUB2 implementation substantially deviates form upstream. One of this deviation is linuxefi module which enables usage of secure boot protocol on EFI platforms with shim. However, it should be mentioned that this module still uses Linux x86 boot protocol. So I think that similar solution could be used in multiboot2 protocol case. Separate multiboot2efi module should be established. It should verify system kernel and all loaded modules using shim on EFI platforms with enabled secure boot (this step should be omitted on platforms without secure boot). If verification is successfully completed GRUB2 should transfer control to loaded image. Later it should get system memory map directly from EFI, do other needed things, call ExitBootServices() and finally start loaded system. I think that this proposal could solve above mentioned problems. Additionally, I think that multiboot2 protocol should be extended by adding extra tag which will be used to pass plain EFI memory map to loaded image. Just in case (we could also use this as transitional thing as I mentioned above). Work on this solution should be coordinated with upstream GRUB2 guys to ease its later introduction in distros and to avoid another deviation. At first I am going to prepare multiboot2 protocol implementation for Xen (there is about 80% of code ready) with above mentioned workaround. Later I am going to work on multiboot2efi module. What do you think about that? Any comments, suggestions, objections? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Mon, Oct 21, 2013 at 09:54:38AM -0400, Peter Jones wrote: On Mon, Oct 21, 2013 at 02:57:56PM +0200, Daniel Kiper wrote: Hi, During work on multiboot2 protocol support for Xen it was discovered that memory map passed via relevant tag could not represent wide range of memory types available on EFI platforms. Additionally, GRUB2 implementation calls ExitBootServices() on them just before jumping into loaded image. In this situation loaded system could not clearly identify reserved memory regions, EFI runtime services regions and others. I think you'll find that many distros are shipping patches to grub2 to add a linuxefi command that starts the kernel through its EFISTUB code. You may want to look in to that. I am referring to that patches in my initial email. However, I think that we are not able to use them directly (correct me if I am wrong) because Xen does not use Linux Boot protocol. I thought that it is worth to migrate to multiboot2 protocol if Xen supports earlier multiboot protocol version. As I understood you are suggesting to drop multiboot2 idea and prepare something similar to linuxefi. It should pass only needed things to Xen and later Xen itself should get required stuff from EFI directly. Finally it should call ExitBootSerices(). Is it correct? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Mon, Oct 21, 2013 at 03:37:21PM +0100, Jan Beulich wrote: On 21.10.13 at 16:23, Konrad Rzeszutek Wilk konrad.w...@oracle.com wrote: On Mon, Oct 21, 2013 at 02:36:38PM +0100, Jan Beulich wrote: On 21.10.13 at 14:57, Daniel Kiper daniel.ki...@oracle.com wrote: [...] What do you think about that? Any comments, suggestions, objections? The complications here make it pretty clear to me that the GrUB2-less solution (or, if GruB2 absolutely has to be involved, its chain loading capability) I have been advocating continues to be the better (and, as said before, conceptually correct) model. However my understanding is that the general distro approach is to use GRUB2 and I think we want to follow the mainstream on this. Which means using GRUB2 and making sense of the myrid of patches that each distro has. As does ours - and we simply use the chain loading mechanism as I'm told (and as I suggested - I'm only occasionally involved in the secure boot stuff). Do you think about GRUB2 chainloader command? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Tue, Oct 22, 2013 at 03:42:42PM +, Woodhouse, David wrote: On Tue, 2013-10-22 at 16:32 +0100, Matthew Garrett wrote: There are two problems with this: 1) The kernel will only boot if it's signed with a key in db, not a key in MOK. 2) grub will read the kernel, but the kernel will have to read the initramfs using EFI calls. That means your initramfs must be on a FAT partition. If you're happy with those limitations then just use the chainloader command. If you're not, use the linuxefi command. Well, we're talking about booting the Xen hypervisor aren't we? So yes, there are reasons the Linux kernel uses the 'boot stub' the way it does, but I'm not sure we advocate that Xen should emulate that in all its 'glory'? Right, I think that sensible mixture of multiboot2 protocol (it is needed to pass at least modules list to Xen; IIRC, linuxefi uses Linux Boot protocol for it) with extension proposed by Vladimir and something similar to linuxefi command will solve our problem (I proposed it in my first email). Users which do not need SB may use upstream GRUB2 and others could use 'multiboot2efi extension'. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Tue, Oct 22, 2013 at 05:08:03PM +0100, Ian Campbell wrote: On Tue, 2013-10-22 at 18:01 +0200, Daniel Kiper wrote: On Tue, Oct 22, 2013 at 03:42:42PM +, Woodhouse, David wrote: On Tue, 2013-10-22 at 16:32 +0100, Matthew Garrett wrote: There are two problems with this: 1) The kernel will only boot if it's signed with a key in db, not a key in MOK. 2) grub will read the kernel, but the kernel will have to read the initramfs using EFI calls. That means your initramfs must be on a FAT partition. If you're happy with those limitations then just use the chainloader command. If you're not, use the linuxefi command. Well, we're talking about booting the Xen hypervisor aren't we? So yes, there are reasons the Linux kernel uses the 'boot stub' the way it does, but I'm not sure we advocate that Xen should emulate that in all its 'glory'? Right, I think that sensible mixture of multiboot2 protocol (it is needed to pass at least modules list to Xen; IIRC, linuxefi uses Linux Boot protocol for it) with extension proposed by Vladimir and something similar to linuxefi command will solve our problem (I proposed it in my first email). Users which do not need SB may use upstream GRUB2 and others could use 'multiboot2efi extension'. Are you (going to be) in Edinburgh? Matthew was just explaining a bunch of this stuff to me, it might be useful for you to get it from the horses mouth instead of laundered through my brain (which is a bit addled afterwards ;-)). Sadly no. However, if it is possible/needed I could participate in conference call. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Tue, Oct 22, 2013 at 04:36:04PM +, Maliszewski, Richard L wrote: I may be off-base, but when I was wading through the grub2 code earlier this year, it looked to me like it was going to refuse to launch anything via MB1 or MB2 if the current state was a secure boot launch. Are you talking about upstream GRUB2 or GRUB2 with tons of distros patches including linuxefi one. If later one it could be the case. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Tue, Oct 22, 2013 at 09:42:52AM -0400, Konrad Rzeszutek Wilk wrote: On Tue, Oct 22, 2013 at 10:59:33AM +0100, Jan Beulich wrote: On 22.10.13 at 11:45, Ian Campbell ian.campb...@citrix.com wrote: On Tue, 2013-10-22 at 10:31 +0100, Jan Beulich wrote: On 22.10.13 at 11:26, Ian Campbell ian.campb...@citrix.com wrote: AIUI efilinux is somewhat badly named and does not use the Linux Boot Protocol (i.e. the (b)zImage stuff with real mode entry point) either. It actually loads and executes the kernel binary as a PE/COFF executable (the native UEFI binary executable format). xen.efi is a PE/COFF binary too and could equally well be launched by linuxefi in this way. Except that unless I'm mistaken linuxefi still expects to find certain Linux-specific internal data structures inside the PE image, which I don't see us wanting to be emulating. That's the main difference to chainloader afaict. Ah, I'd been led to believe it was just the lack of a call to ExitBootServices, but I didn't check. What you say sounds completely plausible. Do you know what sort of Linux specific data structures are we talking about? The setup header I would assume (i.e. the bits surrounding the HdrS signature). But I'm only guessing anyway. This is a bit lengthy email, so please get your coffee/tea ready. [...] We can also support all three: PE/COFF by itself launched from GRUB2 (ExitBootServices called, not too good), multiboot2 support, and linuxefi, I think? The disadvantage of multiboot2 is that it is not upstream. But the patches do exist and it looks like they could be put in GRUB2 upstream. The neat about them is that it also supports Solaris and can support any other multboot payload type kernels (ie, non-Linux centric). The advantage of linuxefi is that it is supported by all Linux distros right now - so we would fit right away. We still have to fiddle with the linux_kernel_parameters to get everything we want from it - which is probably just the EFI stuff and we can ditch the rest. Usage of Linux Boot protocol is quiet complicated in our case. It pases one pointer to all initrd images loaded one by one into memory. So if we would like to use it we will be forced to parse this blob to find separate images. Not good. multiboot2 protocol passes list of pointers to all loaded modules. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Tue, Oct 22, 2013 at 10:54:44AM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote: On 21.10.2013 23:16, Vladimir 'φ-coder/phcoder' Serbinenko wrote: Mail is big, I think I got your essential points but I didn't read it whole. On 21.10.2013 14:57, Daniel Kiper wrote: Hi, During work on multiboot2 protocol support for Xen it was discovered that memory map passed via relevant tag could not represent wide range of memory types available on EFI platforms. Additionally, GRUB2 implementation calls ExitBootServices() on them just before jumping into loaded image. In this situation loaded system could not clearly identify reserved memory regions, EFI runtime services regions and others. Will a multiboot2 tag with whole EFI memory map solve your problem? I added such a tag in documentation and wrote a patch for it (attached). Thanks. Could you send me a pointer to current multiboot2 protocol docs? Awaiting for someone to test it to commit On first sight it looks quite nice. However, as I know Solaris guys prepared similar solution. I am not sure it was discussed with GRUB2 guys. However, I think that it is worth coordinating both works and do not break existing solution if it is possible. I will try to get more details about Solaris implementation. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Mon, Oct 21, 2013 at 11:16:24PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote: Mail is big, I think I got your essential points but I didn't read it whole. On 21.10.2013 14:57, Daniel Kiper wrote: Hi, During work on multiboot2 protocol support for Xen it was discovered that memory map passed via relevant tag could not represent wide range of memory types available on EFI platforms. Additionally, GRUB2 implementation calls ExitBootServices() on them just before jumping into loaded image. In this situation loaded system could not clearly identify reserved memory regions, EFI runtime services regions and others. Will a multiboot2 tag with whole EFI memory map solve your problem? Additionally, it should be mentioned that there is no possibility or it could be very difficult to implement secure boot on EFI platforms using GRUB2 as boot loader because, as it was mentioned earlier, it calls ExitBootServices(). GRUB has generic support for signing kernels/modules/whatsoever using GnuPG signatures. You'd just have to ship xen.sig and kernel.sig. This method doesn't have any controversy associated with EFI stuff but at this particular case does exactly the same thing: verify signature. multiboot2 is mainly memory structure specification so probably how the files are checked is outside of its scope. But it's possible to add specification on how to embed signatures in kernel. I think that EFI signatures should be supported because they are quite common right now. However, I think that it is also worth to support GnuPG signatures. This way anybody will be able to choose good solution for a given case. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI and multiboot2 devlopment work for Xen
On Tue, Oct 22, 2013 at 05:21:15PM +, Maliszewski, Richard L wrote: The latter. The code I was looking at definitely has the linuxefi directive. FWIW, if you install FC18/19 on an EFI system, the grub2 config file uses the linuxefi and companion initrd directives for launch. --Richard On 10/22/13 9:51 AM, Daniel Kiper daniel.ki...@oracle.com wrote: On Tue, Oct 22, 2013 at 04:36:04PM +, Maliszewski, Richard L wrote: I may be off-base, but when I was wading through the grub2 code earlier this year, it looked to me like it was going to refuse to launch anything via MB1 or MB2 if the current state was a secure boot launch. Are you talking about upstream GRUB2 or GRUB2 with tons of distros patches including linuxefi one. If later one it could be the case. I realized that in SB case GRUB2 with linuefi patches does not have a lot features (correct me if I am wrong). So you are able to just load Linux or something which supports Linux Boot protocol. It is not so flexible as it was designed. I think that it should be changed and support for others systems/hypervisors should be added without breaking SB support of course. GRUB2 upstream solution is preferred. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Is: Wrap-up Was: Re: EFI and multiboot2 devlopment work for Xen
Hi, Here is a short summary of our discussion. It looks that we have two choices right now: - chainloader, - multiboot2 protocol. chainloader solution could be implemented quite easily. Some code should be added for command line parsing. However, all arguments for Xen itself and modules must be passed as single line with special separators (e.g. ///; correct me if I am wrong). This thing makes that solution not very convenient, especially if you would like to edit boot command line directly from boot loader. chainloader will support PE images directly. However, it could load only PE image with Xen. Xen image should load all other parts but they could be loaded from FAT filesystem only. This works because it was implemented in original Xen EFI implementation. Support for secure boot and shim loader could be added. It was implemented by SUSE guys and is available in latest SUSE distros. However, it is not merged into GRUB2 upstream (like linuxefi). I do not know what are GRUB2 and SUSE guys plans to upstream this solution. multiboot2 protocol requires some more changes. However, about 80% of code is ready. In this case Xen and modules are loaded by GRUB2 itself. It means that all images could be placed on any filesystem recognized by GRUB2. Options for Xen and modules are passed separately which simplifies command line editing in boot loader and parsing. multiboot2 protocol is very flexible and could be easily extended in the future if a need arises. Support for secure boot and shim loader could be added. However, it was not implemented yet. Probably linuxefi module could be used as a reference or even as a base for development. However, I do not know are there plans to support such solution by GRUB2 community. Currently, support for native PE images signatures and GPG signatures is under development for GRUB2 upstream. Personally I prefer multiboot2 protocol solution because it is much more flexible and easier for use (even if it is more difficult to implement). There is still open question that ExitBootServices() should be called by GRUB2 loader or by loaded image itself on EFI platform. UEFI spec 2.4 states in many places that it is OS loader or Operating System responsibility. However, I think that OS loader should be understood as a integral piece of Operating System responsible for its load into memory without usage of any additional loader like GRUB2. So in this situation it looks that Operating System should call ExitBootServices() on EFI platforms instead of GRUB2. Even if we agree that this assumption is wrong I think that it is better to give an Operating System a choice to use boot services. This way OS could decide which source of information is more convenient in its case, do extra things with EFI platform support (e.g. get memory map directly from EFI) and call ExitBootServices() in relevant time. There is also third solution for issues with ExitBootServices(). In case of multiboot2 protocol OS could request that EFI should be left as is. Solution was proposed by Vladimir and I think that it makes sense. However, this does not solve problem with ExitBootServices() in case of other boot loaders/protocols. So we should take a decision accordingly to above considerations in regards to linux, chainloader and similar stuff. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [Xen-devel] [PATCH, RFC] Allow running with non-terminated boot services in multiboot2
On Mon, Dec 09, 2013 at 10:22:25AM +0100, Vladimir 'φ-coder/phcoder' Serbinenko wrote: On 09.12.2013 09:40, Daniel Kiper wrote: On Sat, Dec 07, 2013 at 12:13:05PM +0100, Vladimir '??-coder/phcoder' Serbinenko wrote: Patch to spec and GRUB attached. @ xen: don't forget to put wlan card to sleep when you finish boot services Thank you for your work. At first sight it looks quite nice but I am not able to do tests right now. I am going to continue my work on GRUB2/EFI stuff for Xen at the beginning of next year. Can you confirm that that's what you want? I'd like it to make into 2.02 release but it would be useless if it's not what you want. Just one nitpick. FinishBootServices() should be replaced by ExitBootServices() in doc/multiboot.texi file. Yes, it is what I want but I think that it will be nice to test this new feature. However, I am busy right now and I am not able to do that. When are you going to make 2.02 release? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
EFI + GRUB2 + Xen - Boot Services issues
Hi, Vladimir, during my work on final multiboot2 protocol support in Xen on EFI platform I stated that GRUB2 patch 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) may not give access to Boot Services as we earlier expected. In general above mentioned patch gives a way to prevent ExitBootServices() call in GRUB2 which is good. However, it looks that this is only part of the bigger puzzle. Sadly GRUB2 before jumping into the loaded image switches x86 processor mode to 32-bit and disables PG bit in CR0. This is not native EFI processor mode. Especially it is very painful on 64-bit EFI implementations. Even if you can disable ExitBootServices() call later you are not able to call Boot Services functions without switching processor mode (this is quite simple) and recreating page tables (this could be quite complicated). I do not mention that system table could be unavailable in 32-bit mode because pointer to it is 64-bit and there is no guarantee that it will be placed below 4 GiB. However, worst thing is that there is no access to ImageHandle which is needed to call ExitBootServices(). Hence, I think that if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force at least GRUB2 loader should not touch processor mode on EFI platform and it should pass pointer to ImageHandle. I am aware that this is very intrusive change and maybe we should consider reverting 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) patch from GRUB2 version 2.02 at this stage of development because there is no guarantee that this change will solve all problems with BS. This way we avoid situation in which new feature is broken from the beginning and we are not able to remove it. Additionally, I discovered that BS could be overwritten during relocation because grub_relocator32_boot() is called with last argument (avoid_efi_bootservices) set to 0 even if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI + GRUB2 + Xen - Boot Services issues
Hey, On Thu, Mar 06, 2014 at 08:29:25PM +0100, Daniel Kiper wrote: Hi, Vladimir, during my work on final multiboot2 protocol support in Xen on EFI platform I stated that GRUB2 patch 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) may not give access to Boot Services as we earlier expected. In general above mentioned patch gives a way to prevent ExitBootServices() call in GRUB2 which is good. However, it looks that this is only part of the bigger puzzle. Sadly GRUB2 before jumping into the loaded image switches x86 processor mode to 32-bit and disables PG bit in CR0. This is not native EFI processor mode. Especially it is very painful on 64-bit EFI implementations. Even if you can disable ExitBootServices() call later you are not able to call Boot Services functions without switching processor mode (this is quite simple) and recreating page tables (this could be quite complicated). I do not mention that system table could be unavailable in 32-bit mode because pointer to it is 64-bit and there is no guarantee that it will be placed below 4 GiB. However, worst thing is that there is no access to ImageHandle which is needed to call ExitBootServices(). Hence, I think that if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force at least GRUB2 loader should not touch processor mode on EFI platform and it should pass pointer to ImageHandle. I am aware that this is very intrusive change and maybe we should consider reverting 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) patch from GRUB2 version 2.02 at this stage of development because there is no guarantee that this change will solve all problems with BS. This way we avoid situation in which new feature is broken from the beginning and we are not able to remove it. Additionally, I discovered that BS could be overwritten during relocation because grub_relocator32_boot() is called with last argument (avoid_efi_bootservices) set to 0 even if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force. Ping? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI + GRUB2 + Xen - Boot Services issues
Hey, On Thu, Mar 06, 2014 at 08:29:25PM +0100, Daniel Kiper wrote: Hi, Vladimir, during my work on final multiboot2 protocol support in Xen on EFI platform I stated that GRUB2 patch 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) may not give access to Boot Services as we earlier expected. In general above mentioned patch gives a way to prevent ExitBootServices() call in GRUB2 which is good. However, it looks that this is only part of the bigger puzzle. Sadly GRUB2 before jumping into the loaded image switches x86 processor mode to 32-bit and disables PG bit in CR0. This is not native EFI processor mode. Especially it is very painful on 64-bit EFI implementations. Even if you can disable ExitBootServices() call later you are not able to call Boot Services functions without switching processor mode (this is quite simple) and recreating page tables (this could be quite complicated). I do not mention that system table could be unavailable in 32-bit mode because pointer to it is 64-bit and there is no guarantee that it will be placed below 4 GiB. However, worst thing is that there is no access to ImageHandle which is needed to call ExitBootServices(). Hence, I think that if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force at least GRUB2 loader should not touch processor mode on EFI platform and it should pass pointer to ImageHandle. I am aware that this is very intrusive change and maybe we should consider reverting 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) patch from GRUB2 version 2.02 at this stage of development because there is no guarantee that this change will solve all problems with BS. This way we avoid situation in which new feature is broken from the beginning and we are not able to remove it. Additionally, I discovered that BS could be overwritten during relocation because grub_relocator32_boot() is called with last argument (avoid_efi_bootservices) set to 0 even if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force. Is there anybody out there? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: EFI + GRUB2 + Xen - Boot Services issues
Hi, On Wed, Mar 19, 2014 at 08:58:43PM +0800, Vladimir 'φ-coder/phcoder' Serbinenko wrote: On 19.03.2014 17:42, Daniel Kiper wrote: [...] Is there anybody out there? Sorry, I was travelling. I've seen your mail, just didn't respond to it No problem. yet. In nutshell, I think that even in current form it's still useful to allow payloads to follow 32-bit path as long as they wish to keep it and still use BS if they need to. I'll fix clobbering problem. As for long mode entry, it's separate issue, I'm thinking about. There are couple of problems including where to place the paging tables. Great... I could wait a bit because I am working on EFI and Xen Linux Kernel patches right now. Drop me a line if you need my help. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[Xen Hackathon] EFI + GRUB2 + Xen
Hey, Below you could find some ideas how to solve issues related to EFI + GRUB2 + Xen. I would like to discuss them during Xen Hackathon. Here is the excerpt from EFI + GRUB2 + Xen - Boot Services issues thread which will paint current picture (http://lists.xen.org/archives/html/xen-devel/2014-03/msg00554.html): *** Hi, Vladimir, during my work on final multiboot2 protocol support in Xen on EFI platform I stated that GRUB2 patch 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) may not give access to Boot Services as we earlier expected. In general above mentioned patch gives a way to prevent ExitBootServices() call in GRUB2 which is good. However, it looks that this is only part of the bigger puzzle. Sadly GRUB2 before jumping into the loaded image switches x86 processor mode to 32-bit and disables PG bit in CR0. This is not native EFI processor mode. Especially it is very painful on 64-bit EFI implementations. Even if you can disable ExitBootServices() call later you are not able to call Boot Services functions without switching processor mode (this is quite simple) and recreating page tables (this could be quite complicated). I do not mention that system table could be unavailable in 32-bit mode because pointer to it is 64-bit and there is no guarantee that it will be placed below 4 GiB. However, worst thing is that there is no access to ImageHandle which is needed to call ExitBootServices(). Hence, I think that if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force at least GRUB2 loader should not touch processor mode on EFI platform and it should pass pointer to ImageHandle. I am aware that this is very intrusive change and maybe we should consider reverting 0df77d793c0436be656f982d96d4edaea4993f96 (Implement multiboot2 EFI BS specification) patch from GRUB2 version 2.02 at this stage of development because there is no guarantee that this change will solve all problems with BS. This way we avoid situation in which new feature is broken from the beginning and we are not able to remove it. Additionally, I discovered that BS could be overwritten during relocation because grub_relocator32_boot() is called with last argument (avoid_efi_bootservices) set to 0 even if MULTIBOOT2_HEADER_TAG_EFI_BS tag is in force. Daniel *** Right now there is not solution for those issues. So let's think what we can do to solve these problems. What knowledge we need from EFI 64-bit platform to run Xen on it: - EFI tables/functions, - ACPI data, - memory map, - VGA (graphic card) mode, - EDD data, - MBR data. Does GRUB2 provide above mentioned stuff on EFI 64-bit platform: - EFI tables/functions: YES, - ACPI data: YES, - memory map: YES, - VGA (graphic card) mode: YES as MULTIBOOT2_TAG_TYPE_FRAMEBUFFER tag; it is a chance to use that but it requires more investigation, - EDD data: NO, - MBR data: NO. How we can get EDD and MBR from EFI 64-bit platform: 1. use EFI Boot Services directly from Xen: a. jump into Xen code in multiboot2 protocol 32-bit mode, b. jump into Xen code in EFI 64-bit native platform mode, 2. add EDD and MBR tags to multiboot2 protocol specification. Solution 1a: - no major changes in GRUB2 are required but at least one minor fix should be applied (look above), - jump into Xen code in multiboot2 protocol 32-bit mode, - must switch back to EFI 64-bit native platform mode in Xen (switch processor to 64-bit mode and build identity page tables; former is quite simple but later could be quite difficult because we cannot overwrite EFI code, Xen code and modules code/data), - use EFI Boot Services from Xen to get EDD and MBR, - call ExitBootServices() from Xen code, - execute Xen code as usual. Solution 1b: - add specification for multiboot2 protocol 64-bit mode; currently only 32-bit mode is specified and implemented, - implement this mode in GRUB2 and Xen, - use EFI calls/data and multiboot2 protocol tags as needed. Solution 2: - add two new tags to multiboot2 protocol specification which will describe EDD and MBR, - GRUB2 could safely call ExitBootServices(); still there is open question how to use Secure Boot feature in connection with GRUB2; in theory in the future we could use SB stuff or GnuPG detached signatures; look here for more details: http://lists.xen.org/archives/html/xen-devel/2013-10/msg01823.html, - jump into and execute Xen code as usual. These are rough ideas and I hope that we work out something which could be quite quickly implemented. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[Xen Hackathon] EFI + GRUB2 + Xen - minutes
Hi, Below you could find minutes taken by Konrad (thanks!) during EFI + GRUB2 + Xen session which happened on Xen Hackathon. I made some minor fixes/cleanups. Session was led by me. Here you could find detailed description of the problem: http://lists.xen.org/archives/html/xen-devel/2014-05/msg02928.html *** EFI support written by Jan - but there is a requirement for GRUB2 loader instead of loading an Xen EFI binary. Working prototype exists but before we venture in that, lets start with questions. What Xen needs from an EFI platform: EFI T/F (tables/functions), ACPI, MMAP (EFI memory map), VGA, EDD, MBR. If you run Xen EFI on the platform it has all of that directly. However GRUB2 it calls ExitBootServices which means you cannot get EDD or MBR information. That is one problem. Transition from GRUB2 - Xen is 32-bit mode which is strictly specified in the multiboot spec (and the source code). The EFI T/F are 64-bit mode so this pointer might not be accessible - it is now, but might not be in the future. GRUB2 drops to 32-bit because multiboot requires even though EFI platform calls GRUB2 in 64-bit mode. The reason this is a problem, is that to get EDD/MBR you must switch to 64-bit mode - and must create new pagetables without over-writting any existing ones. The EFI memory map in GRUB2 has the reserved and runtime memory map and the separation (loader data, boot data). Passed in through GRUB2 stock EFI via multiboot2 protocol - which can solve the rebuilding the Xen pagetables. EFI application - everything would need to done before start_xen. In this situation (where we don't have the EFI T/F) we need to create the identity pagetables for EFI. Low half is needed for the 1-1 page-tables. With the EFI you can do it at the same time - low half for 1-1 page tables and the high memory for the rest. This is solution 1a in Daniel's email. Solution 2, would be to extend the multiboot2, but the maintainer is not responsive. Or GRUB2 before passing ExitBootServices would require EDD and MBR to extend the mulitboot. But that has the danger that anything there is something in the future we would need to extend it. If you use 'linuxefi', then everything is OK. If you use 'linux' then ExitBootServices is. But we can't use it because it can only do use one payload (initrd). Things we need: - Don't call ExitBootServices (done) - Flag for launching in 64-bit mode. We can work with the 32-bit and recreate the pagetables. - Flag for entertain in standard EFI calling method. - Flag for separate entry point (ImageHandler). However we cannot call ExitBootServices from Xen because ImageHandler is not passed. What we need is to combine multiboot2 and EFI. SecureBoot - the shim can only sit between two EFI images (shim is an EFI image). What the shim calls must be EFI image too. We don't know the constraint of what the GRUB2 has to call EFI with SecureBoot enabled. We can move multiboot header as it does not have to be in the 512 bytes. New multiboot2-EFI which looks like EFI and can do extra things - pass in the parameters. But the shim does not know the multiboot2-EFI protocol. If this protocol is installed in the shim. GRUB2 calls the EFI with the multiboot2 protocol. The SecureBoot requires each party to verify the next executable. Meaning GRUB2 needs to verify xen.gz. Xen.gz needs to verify kernel.gz, etc. GRUB2 is the first on the chain. Load shim, Xen, dom0, initrd, microcode. In the distro acceptance we don't want to diverge. The multiboot2 would be passed on the EFI. Only the ImageHandler and system tables get passed. Can each system table be expanded - yes. Xen's job to check the kernel. The multiboot protocol checks. The multiboot2 has to do it. EFI - shim - grub - calls back to shim to validate - calls Linux In this scenario we can use the shim. We need ImageHandler. --- We would to need to detect whether we are loaded via EFI or multiboot2. -- Ian suggested flags. We need GRUB2 to call with standard EFI (as specified). Call that efi_entry point in the multboot2 as an normal EFI application. (Xen.EFI?) Can't do with xen.gz because SecureBoot won't work in there. And Xen can look in its multiboot2 header to figure this out? And the extra flag and the offset (handover). Codewise the EFI code needs to be split. ImageHandler is only needed for ExitBootServices. We want the same prototype - efi_main. The code (EFI Xen code) would check the multiboot structure if it has been modified. This has the benefit that we can interrogate the EFI system table to interrogate this. -- Xen already has the signature checking of its payload! *** I am going to prepare solution based on above findings and post relevant patches for GRUB2 and Xen. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org
EFI + GRUB2 + Xen - WIP
Hi all, I was going to send EFI + GRUB2 + Xen upstream patches based on my internal work for Xen 4.3.1 last week. Sadly, I was killing various bugs surfacing on various machines in unexpected places in this almost fully featured solution. This means I was not able to do that as I planned. Additionally, I am on holiday until Christmas. So, I hope that I will be able to release first version of EFI + GRUB2 + Xen upstream patch series at the beginning of next year. However, if you wish to take a look at our internal version, which have most ideas set in stone (e.g. I am going to post GRUB2 patches almost without any changes), please drop me a line. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 00/18] x86: multiboot2 protocol support
On Mon, Feb 02, 2015 at 09:28:49AM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: - xen.efi build will not so strongly depend on a given GCC and binutils version. While I can see the possibility of making the binutils version dependency go away (by manually creating the PE header), I can't see how you'd overcome the gcc one: The MS calling convention support is still going to be needed (not having looked at the patches Right, I forgot about that one. themselves yet, I can't see myself accepting the introduction of stubs to convert between calling conventions). I am not going to do that thing. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 03/18] x86/boot: use %ecx instead of %eax
On Tue, Feb 03, 2015 at 10:02:09AM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: /* Save the Multiboot info struct (after relocation) for later use. */ mov $sym_phys(cpu0_stack)+1024,%esp -push%ebx -callreloc +mov %ecx,%eax +push%ebx/* Multiboot information address */ +callreloc /* %eax contains trampoline address */ This last part looks completely unrelated to the change made here (and contrary to the description, as here you clobber %eax while the description says reloc() needs it unclobbered); afaict it belongs in whatever patch add the consumption of this value in reloc(). Yep, this is confusing. I should change reloc.c:_start() in this patch too. That said - passing parameters to reloc() by two different means looks very odd too. I'm clearly of the opinion that parameter passing should follow an existing convention unless entirely unfeasible. Which then raises the question whether this patch is So, I think that we should add another patch which fixes this issue and put all arguments on the stack according to the cdecl calling convention on x86. really needed: Rather than fiddling with a lot of code, can't you just copy the incoming %eax into some other register, making this a single line change that can again simply be done in the patch where you actually consume the new information? If we do thing(s) mentioned above then this issue will disappear too. Additionally, I think that we should not use another register if it is not really required. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/head.S | 174 +++-- xen/arch/x86/efi/efi-boot.h | 29 +++ xen/arch/x86/setup.c | 23 ++--- xen/arch/x86/x86_64/asm-offsets.c |2 + xen/common/efi/boot.c | 11 +++ 5 files changed, 222 insertions(+), 17 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 7861057..89f5aa7 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -8,6 +8,7 @@ #include asm/page.h #include asm/msr.h #include asm/cpufeature.h +#include asm/processor.h .text .code32 @@ -57,6 +58,9 @@ ENTRY(start) .long .Lmultiboot2_info_req_end - .Lmultiboot2_info_req .long MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO .long MULTIBOOT2_TAG_TYPE_MMAP +.long MULTIBOOT2_TAG_TYPE_EFI_BS +.long MULTIBOOT2_TAG_TYPE_EFI64 +.long MULTIBOOT2_TAG_TYPE_EFI64_IH .Lmultiboot2_info_req_end: .align MULTIBOOT2_TAG_ALIGN @@ -80,6 +84,19 @@ ENTRY(start) .long 0 /* Number of the lines - no preference. */ .long 0 /* Number of bits per pixel - no preference. */ +/* Do not disable EFI boot services. */ +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_EFI_BS +.short MULTIBOOT2_HEADER_TAG_OPTIONAL +.long 8 /* Tag size. */ + +/* EFI64 entry point. */ +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI64 +.short MULTIBOOT2_HEADER_TAG_OPTIONAL +.long 12 /* Tag size. */ +.long sym_phys(__efi64_start) + /* Multiboot2 header end tag. */ .align MULTIBOOT2_TAG_ALIGN .short MULTIBOOT2_HEADER_TAG_END @@ -94,6 +111,17 @@ ENTRY(start) gdt_boot_descr: .word 6*8-1 .long sym_phys(trampoline_gdt) +.long 0 /* Needed for 64-bit lgdt */ + +cs32_switch_addr: +.long sym_phys(cs32_switch) +.long BOOT_CS32 + +efi_st: +.quad 0 + +efi_ih: +.quad 0 .Lbad_cpu_msg: .asciz ERR: Not a 64-bit CPU! .Lbad_ldr_msg: .asciz ERR: Not a Multiboot bootloader! @@ -124,6 +152,133 @@ print_err: .Lhalt: hlt jmp .Lhalt +.code64 + +__efi64_start: +cld + +/* Bootloaders may set multiboot[12].mem_lower to a nonzero value */ +xor %edx,%edx + +/* Check for Multiboot2 bootloader */ +cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax +je efi_multiboot2_proto + +jmp not_multiboot + +efi_multiboot2_proto: +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx + +0: +/* Get mem_lower from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,(%ecx) +jne 1f + +mov MB2_mem_lower(%ecx),%edx +jmp 4f + +1: +/* Get EFI SystemTable address from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_EFI64,(%ecx) +jne 2f + +lea MB2_efi64_st(%ecx),%esi +lea efi_st(%rip),%edi +movsq + +/* Do not go into real mode on EFI platform */ +movb$1,skip_realmode(%rip) + +jmp 4f + +2: +/* Get EFI ImageHandle address from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_EFI64_IH,(%ecx) +jne 3f + +lea MB2_efi64_ih(%ecx),%esi +lea efi_ih(%rip),%edi +movsq +jmp 4f + +3: +/* Is it the end of Multiboot2 information? */ +cmpl$MULTIBOOT2_TAG_TYPE_END,(%ecx) +je run_bs + +4: +/* Go to next Multiboot2 information tag */ +add MB2_tag_size(%ecx),%ecx +add $(MULTIBOOT2_TAG_ALIGN-1),%ecx +and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx +jmp 0b + +run_bs: +push%rax +push%rdx + +/* Initialize BSS (no nasty surprises!) */ +lea __bss_start(%rip),%rdi +lea _end(%rip),%rcx +sub %rdi,%rcx +xor %rax,%rax +rep stosb + +mov efi_ih(%rip),%rdi /* EFI ImageHandle */ +mov efi_st(%rip),%rsi /* EFI SystemTable */ +callefi_multiboot2 + +pop %rcx +pop %rax + +shl $10-4,%rcx /* Convert multiboot2.mem_lower to bytes/16 */ + +cli + +/* Initialise GDT */ +lgdtgdt_boot_descr(%rip) + +/* Reload code selector */ +ljmpl *cs32_switch_addr(%rip) + +.code32 + +cs32_switch: +/* Initialise basic data segments */ +mov $BOOT_DS,%edx +mov %edx,%ds +mov %edx,%es +mov %edx,%fs +mov %edx,%gs +mov %edx,%ss + +mov $sym_phys(cpu0_stack)+1024,%esp + +/* Disable paging */ +mov
[PATCH 15/18] efi: create efi_set_gop_mode()
..which sets chosen GOP mode. We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 35 +-- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 2379022..63c930d 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -845,6 +845,25 @@ static void __init efi_variables(void) } } +static void __init efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop_mode) +{ +EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; +EFI_STATUS status; +UINTN info_size; + +if ( !gop ) +return; + +/* Set graphics mode. */ +if ( gop_mode gop-Mode-MaxMode gop_mode != gop-Mode-Mode ) +gop-SetMode(gop, gop_mode); + +/* Get graphics and frame buffer info. */ +status = gop-QueryMode(gop, gop-Mode-Mode, info_size, mode_info); +if ( !EFI_ERROR(status) ) +efi_arch_video_init(gop, info_size, mode_info); +} + static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz) { if ( bpp 0 ) @@ -869,10 +888,9 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) EFI_STATUS status; unsigned int i, argc; CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL; -UINTN map_key, info_size, gop_mode = ~0; +UINTN map_key, gop_mode = ~0; EFI_SHIM_LOCK_PROTOCOL *shim_lock; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; -EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; union string section = { NULL }, name; bool_t base_video = 0, retry; char *option_str; @@ -1088,18 +1106,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_arch_memory_setup(); -if ( gop ) -{ - -/* Set graphics mode. */ -if ( gop_mode gop-Mode-MaxMode gop_mode != gop-Mode-Mode ) -gop-SetMode(gop, gop_mode); - -/* Get graphics and frame buffer info. */ -status = gop-QueryMode(gop, gop-Mode-Mode, info_size, mode_info); -if ( !EFI_ERROR(status) ) -efi_arch_video_init(gop, info_size, mode_info); -} +efi_set_gop_mode(gop, gop_mode); efi_bs-GetMemoryMap(efi_memmap_size, NULL, map_key, efi_mdesc_size, mdesc_ver); -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 00/18] x86: multiboot2 protocol support
On Fri, Jan 30, 2015 at 06:54:04PM +0100, Daniel Kiper wrote: Hi, I am sending, long awaited, first version of multiboot2 protocol support for legacy BIOS and EFI platforms. By mistake I forgot to thank you Andrew and Konrad for support during development of this series. Sorry guys. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 12/18] efi: create efi_find_gop_mode()
..which finds suitable GOP mode. We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 94 - 1 file changed, 54 insertions(+), 40 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 6bbcb3b..114019e 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -655,6 +655,58 @@ static EFI_GRAPHICS_OUTPUT_PROTOCOL __init *efi_get_gop(void) return gop; } +static UINTN __init efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, + UINTN cols, UINTN rows, UINTN depth) +{ +EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; +EFI_STATUS status; +UINTN gop_mode = ~0, info_size, size; +unsigned int i; + +if ( !gop ) +return gop_mode; + +for ( i = size = 0; i gop-Mode-MaxMode; ++i ) +{ +unsigned int bpp = 0; + +status = gop-QueryMode(gop, i, info_size, mode_info); +if ( EFI_ERROR(status) ) +continue; +switch ( mode_info-PixelFormat ) +{ +case PixelBitMask: +bpp = hweight32(mode_info-PixelInformation.RedMask | +mode_info-PixelInformation.GreenMask | +mode_info-PixelInformation.BlueMask); +break; +case PixelRedGreenBlueReserved8BitPerColor: +case PixelBlueGreenRedReserved8BitPerColor: +bpp = 24; +break; +default: +continue; +} +if ( cols == mode_info-HorizontalResolution + rows == mode_info-VerticalResolution + (!depth || bpp == depth) ) +{ +gop_mode = i; +break; +} +if ( !cols !rows + mode_info-HorizontalResolution * + mode_info-VerticalResolution size ) +{ +size = mode_info-HorizontalResolution * + mode_info-VerticalResolution; +gop_mode = i; +} +} + +return gop_mode; +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -966,46 +1018,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) dir_handle-Close(dir_handle); -if ( gop !base_video ) -{ -for ( i = size = 0; i gop-Mode-MaxMode; ++i ) -{ -unsigned int bpp = 0; - -status = gop-QueryMode(gop, i, info_size, mode_info); -if ( EFI_ERROR(status) ) -continue; -switch ( mode_info-PixelFormat ) -{ -case PixelBitMask: -bpp = hweight32(mode_info-PixelInformation.RedMask | -mode_info-PixelInformation.GreenMask | -mode_info-PixelInformation.BlueMask); -break; -case PixelRedGreenBlueReserved8BitPerColor: -case PixelBlueGreenRedReserved8BitPerColor: -bpp = 24; -break; -default: -continue; -} -if ( cols == mode_info-HorizontalResolution - rows == mode_info-VerticalResolution - (!depth || bpp == depth) ) -{ -gop_mode = i; -break; -} -if ( !cols !rows - mode_info-HorizontalResolution * - mode_info-VerticalResolution size ) -{ -size = mode_info-HorizontalResolution * - mode_info-VerticalResolution; -gop_mode = i; -} -} -} +if ( !base_video ) +gop_mode = efi_find_gop_mode(gop, cols, rows, depth); } efi_arch_edd(); -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 06/18] x86: remove commented out stale references to efi_enabled
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/e820.c | 29 ++--- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c index bf84bae..47920a3 100644 --- a/xen/arch/x86/e820.c +++ b/xen/arch/x86/e820.c @@ -74,20 +74,18 @@ static void __init add_memory_region(unsigned long long start, { int x; -/*if (!efi_enabled)*/ { -x = e820.nr_map; +x = e820.nr_map; -if (x == E820MAX) { -printk(KERN_ERR Ooops! Too many entries in the memory map!\n); -return; -} - -e820.map[x].addr = start; -e820.map[x].size = size; -e820.map[x].type = type; -e820.nr_map++; +if (x == E820MAX) { +printk(KERN_ERR Ooops! Too many entries in the memory map!\n); +return; } -} /* add_memory_region */ + +e820.map[x].addr = start; +e820.map[x].size = size; +e820.map[x].type = type; +e820.nr_map++; +} static void __init print_e820_memory_map(struct e820entry *map, unsigned int entries) { @@ -349,13 +347,6 @@ static unsigned long __init find_max_pfn(void) int i; unsigned long max_pfn = 0; -#if 0 -if (efi_enabled) { -efi_memmap_walk(efi_find_max_pfn, max_pfn); -return; -} -#endif - for (i = 0; i e820.nr_map; i++) { unsigned long start, end; /* RAM? */ -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 08/18] efi: build xen.gz with EFI code
Build xen.gz with EFI code. We need this to support multiboot2 protocol on EFI platforms. If we wish to load not ELF file using multiboot (v1) or multiboot2 then it must contain linear (or flat) representation of code and data. Currently, PE file contains many sections which are not linear (one after another without any holes) or even do not have representation in a file (e.g. BSS). In theory there is a chance that we could build proper PE file using current build system. However, it means that xen.efi further diverge from xen ELF file (in terms of contents and build method). ELF have all needed properties. So, it means that this is good starting point for further development. Additionally, I think that this is also good starting point for further xen.efi code and build optimizations. It looks that there is a chance that finaly we can generate xen.efi directly from xen ELF using just simple objcopy. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/Makefile | 17 +++-- xen/arch/x86/efi/Makefile | 12 ++-- xen/arch/x86/efi/stub.c | 42 -- xen/arch/x86/xen.lds.S|2 -- 4 files changed, 13 insertions(+), 60 deletions(-) delete mode 100644 xen/arch/x86/efi/stub.c diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 86ca5f8..5d63a1f 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -88,29 +88,29 @@ prelink-efi_lto.o: $(ALL_OBJS) efi/runtime.o efi/compat.o prelink.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink_lto.o $(LD) $(LDFLAGS) -r -o $@ $^ -prelink-efi.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink-efi_lto.o efi/boot.init.o +prelink-efi.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink-efi_lto.o $(guard) $(LD) $(LDFLAGS) -r -o $@ $^ else prelink.o: $(ALL_OBJS) $(LD) $(LDFLAGS) -r -o $@ $^ -prelink-efi.o: $(ALL_OBJS) efi/boot.init.o efi/runtime.o efi/compat.o - $(guard) $(LD) $(LDFLAGS) -r -o $@ $(filter-out %/efi/built_in.o,$^) +prelink-efi.o: $(ALL_OBJS) + $(guard) $(LD) $(LDFLAGS) -r -o $@ $^ endif $(BASEDIR)/common/symbols-dummy.o: $(MAKE) -f $(BASEDIR)/Rules.mk -C $(BASEDIR)/common symbols-dummy.o -$(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ +$(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o efi/relocs-dummy.o + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o efi/relocs-dummy.o \ $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0 $(NM) -n $(@D)/.$(@F).0 | $(BASEDIR)/tools/symbols $(@D)/.$(@F).0.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o efi/relocs-dummy.o \ $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1 $(NM) -n $(@D)/.$(@F).1 | $(BASEDIR)/tools/symbols $(@D)/.$(@F).1.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o - $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ + $(LD) $(LDFLAGS) -T xen.lds -N prelink.o efi/relocs-dummy.o \ $(@D)/.$(@F).1.o -o $@ rm -f $(@D)/.$(@F).[0-9]* @@ -144,9 +144,6 @@ $(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbol if $(guard) false; then rm -f $@; echo 'EFI support disabled'; fi rm -f $(@D)/.$(@F).[0-9]* -efi/boot.init.o efi/runtime.o efi/compat.o: $(BASEDIR)/arch/x86/efi/built_in.o -efi/boot.init.o efi/runtime.o efi/compat.o: ; - asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(CC) $(filter-out -flto,$(CFLAGS)) -S -o $@ $ diff --git a/xen/arch/x86/efi/Makefile b/xen/arch/x86/efi/Makefile index 1daa7ac..13e59dc 100644 --- a/xen/arch/x86/efi/Makefile +++ b/xen/arch/x86/efi/Makefile @@ -1,14 +1,14 @@ CFLAGS += -fshort-wchar -obj-y += stub.o +obj-y += boot.o +obj-y += compat.o +obj-y += runtime.o + +extra-y += relocs-dummy.o create = test -e $(1) || touch -t 19990101 $(1) efi := $(filter y,$(x86_64)$(shell rm -f disabled)) efi := $(if $(efi),$(shell $(CC) $(filter-out $(CFLAGS-y) .%.d,$(CFLAGS)) -c check.c 2disabled echo y)) efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 2disabled echo y)) -efi := $(if $(efi),$(shell rm disabled)y,$(shell $(call create,boot.init.o); $(call create,runtime.o))) - -extra-$(efi) += boot.init.o relocs-dummy.o runtime.o compat.o - -stub.o: $(extra-y) +efi := $(if $(efi),$(shell rm disabled)y) diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c deleted file mode 100644 index 5060e6f..000 --- a/xen/arch/x86/efi/stub.c +++ /dev/null @@ -1,42 +0,0 @@ -#include xen/efi.h -#include xen/errno.h -#include xen/init.h -#include xen/lib.h - -#ifndef efi_platform -bool_t efi_platform = 0; -bool_t efi_loader = 0; -#endif - -void __init efi_init_memory(void) { } - -paddr_t efi_rs_page_table(void) -{ -BUG(); -return 0
[PATCH 10/18] efi: create efi_console_set_mode()
..which sets console mode. We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 37 - 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 1bf88e4..9ce8a25 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -601,6 +601,25 @@ static void __init efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTabl StdErr = SystemTable-StdErr ?: StdOut; } +static void __init efi_console_set_mode(void) +{ +UINTN cols, rows, size; +unsigned int best, i; + +for ( i = 0, size = 0, best = StdOut-Mode-Mode; + i StdOut-Mode-MaxMode; ++i ) +{ +if ( StdOut-QueryMode(StdOut, i, cols, rows) == EFI_SUCCESS + cols * rows size ) +{ +size = cols * rows; +best = i; +} +} +if ( best != StdOut-Mode-Mode ) +StdOut-SetMode(StdOut, best); +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -787,23 +806,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) } if ( !base_video ) -{ -unsigned int best; -UINTN cols, rows, size; - -for ( i = 0, size = 0, best = StdOut-Mode-Mode; - i StdOut-Mode-MaxMode; ++i ) -{ -if ( StdOut-QueryMode(StdOut, i, cols, rows) == EFI_SUCCESS - cols * rows size ) -{ -size = cols * rows; -best = i; -} -} -if ( best != StdOut-Mode-Mode ) -StdOut-SetMode(StdOut, best); -} +efi_console_set_mode(); } PrintStr(LXen __stringify(XEN_VERSION) . __stringify(XEN_SUBVERSION) -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 04/18] xen/x86: add multiboot2 protocol support
Add multiboot2 protocol support. Alter min memory limit handling as we now may not find it from either multiboot (v1) or multiboot2. This way we are laying the foundation for EFI + GRUB2 + Xen development. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/Makefile|3 +- xen/arch/x86/boot/head.S | 104 -- xen/arch/x86/boot/reloc.c | 174 - xen/arch/x86/x86_64/asm-offsets.c |6 ++ xen/include/xen/multiboot2.h | 169 +++ 5 files changed, 429 insertions(+), 27 deletions(-) create mode 100644 xen/include/xen/multiboot2.h diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index 5fdb5ae..0efa7d2 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -1,6 +1,7 @@ obj-bin-y += head.o -RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h +RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/compiler.h \ +$(BASEDIR)/include/xen/multiboot.h $(BASEDIR)/include/xen/multiboot2.h head.o: reloc.S diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 6180783..7861057 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -1,5 +1,6 @@ #include xen/config.h #include xen/multiboot.h +#include xen/multiboot2.h #include public/xen.h #include asm/asm_defns.h #include asm/desc.h @@ -32,6 +33,59 @@ ENTRY(start) .long MULTIBOOT_HEADER_FLAGS /* Checksum: must be the negated sum of the first two fields. */ .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + +/*** MULTIBOOT2 HEADER / +/* Some ideas are taken from grub-2.00/grub-core/tests/boot/kernel-i386.S file. */ +.align MULTIBOOT2_HEADER_ALIGN + +.Lmultiboot2_header: +/* Magic number indicating a Multiboot2 header. */ +.long MULTIBOOT2_HEADER_MAGIC +/* Architecture: i386. */ +.long MULTIBOOT2_ARCHITECTURE_I386 +/* Multiboot2 header length. */ +.long .Lmultiboot2_header_end - .Lmultiboot2_header +/* Multiboot2 header checksum. */ +.long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 + \ +(.Lmultiboot2_header_end - .Lmultiboot2_header)) + +/* Multiboot2 tags... */ +.Lmultiboot2_info_req: +/* Multiboot2 information request tag. */ +.short MULTIBOOT2_HEADER_TAG_INFORMATION_REQUEST +.short MULTIBOOT2_HEADER_TAG_REQUIRED +.long .Lmultiboot2_info_req_end - .Lmultiboot2_info_req +.long MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO +.long MULTIBOOT2_TAG_TYPE_MMAP +.Lmultiboot2_info_req_end: + +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_MODULE_ALIGN +.short MULTIBOOT2_HEADER_TAG_REQUIRED +.long 8 /* Tag size. */ + +/* Console flags tag. */ +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_CONSOLE_FLAGS +.short MULTIBOOT2_HEADER_TAG_OPTIONAL +.long 12 /* Tag size. */ +.long MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED + +/* Framebuffer tag. */ +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_FRAMEBUFFER +.short MULTIBOOT2_HEADER_TAG_OPTIONAL +.long 20 /* Tag size. */ +.long 0 /* Number of the columns - no preference. */ +.long 0 /* Number of the lines - no preference. */ +.long 0 /* Number of bits per pixel - no preference. */ + +/* Multiboot2 header end tag. */ +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_END +.short 0 +.long 8 /* Tag size. */ +.Lmultiboot2_header_end: .section .init.rodata, a, @progbits .align 4 @@ -81,10 +135,51 @@ __start: mov %ecx,%es mov %ecx,%ss +/* Bootloaders may set multiboot[12].mem_lower to a nonzero value */ +xor %edx,%edx + /* Check for Multiboot bootloader */ cmp $MULTIBOOT_BOOTLOADER_MAGIC,%eax -jne not_multiboot +je multiboot1_proto +/* Check for Multiboot2 bootloader */ +cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax +je multiboot2_proto + +jmp not_multiboot + +multiboot1_proto: +/* Get mem_lower from Multiboot information */ +testb $MBI_MEMLIMITS,(%ebx) +jz trampoline_setup/* not available? BDA value will be fine */ + +mov MB_mem_lower(%ebx),%edx +jmp trampoline_setup + +multiboot2_proto: +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx + +0: +/* Get mem_lower from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,(%ecx) +jne 1f + +mov MB2_mem_lower(%ecx),%edx +jmp
[PATCH 07/18] efi: run EFI specific code on EFI platform only
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/shutdown.c |3 ++- xen/common/efi/boot.c|5 + xen/common/efi/runtime.c |6 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c index 21f6cf5..1c8336f 100644 --- a/xen/arch/x86/shutdown.c +++ b/xen/arch/x86/shutdown.c @@ -504,7 +504,8 @@ void machine_restart(unsigned int delay_millisecs) tboot_shutdown(TB_SHUTDOWN_REBOOT); } -efi_reset_system(reboot_mode != 0); +if ( efi_platform ) +efi_reset_system(reboot_mode != 0); /* Rebooting needs to touch the page at absolute address 0. */ *((unsigned short *)__va(0x472)) = reboot_mode; diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 8aafcfd..89d081d 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -1154,6 +1154,11 @@ void __init efi_init_memory(void) } *extra, *extra_head = NULL; #endif +#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */ +if ( !efi_platform ) +return; +#endif + printk(XENLOG_INFO EFI memory map:\n); for ( i = 0; i efi_memmap_size; i += efi_mdesc_size ) { diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c index b229c69..7c767e4 100644 --- a/xen/common/efi/runtime.c +++ b/xen/common/efi/runtime.c @@ -164,6 +164,9 @@ int efi_get_info(uint32_t idx, union xenpf_efi_info *info) { unsigned int i, n; +if ( !efi_platform ) +return -ENOSYS; + switch ( idx ) { case XEN_FW_EFI_VERSION: @@ -298,6 +301,9 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op) EFI_STATUS status = EFI_NOT_STARTED; int rc = 0; +if ( !efi_platform ) +return -ENOSYS; + switch ( op-function ) { case XEN_EFI_get_time: -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 11/18] efi: create efi_get_gop()
..which gets pointer to GOP device. We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 59 ++--- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 9ce8a25..6bbcb3b 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -620,6 +620,41 @@ static void __init efi_console_set_mode(void) StdOut-SetMode(StdOut, best); } +static EFI_GRAPHICS_OUTPUT_PROTOCOL __init *efi_get_gop(void) +{ +EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; +EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; +EFI_HANDLE *handles; +EFI_STATUS status; +UINTN info_size, size = 0; +static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; +unsigned int i; + +status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, NULL); +if ( status == EFI_BUFFER_TOO_SMALL ) +status = efi_bs-AllocatePool(EfiLoaderData, size, (void **)handles); +if ( !EFI_ERROR(status) ) +status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, + handles); +if ( EFI_ERROR(status) ) +size = 0; +for ( i = 0; i size / sizeof(*handles); ++i ) +{ +status = efi_bs-HandleProtocol(handles[i], gop_guid, (void **)gop); +if ( EFI_ERROR(status) ) +continue; +status = gop-QueryMode(gop, gop-Mode-Mode, info_size, mode_info); +if ( !EFI_ERROR(status) ) +break; +} +if ( handles ) +efi_bs-FreePool(handles); +if ( EFI_ERROR(status) ) +gop = NULL; + +return gop; +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -726,14 +761,12 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL; -static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; unsigned int i, argc; CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL; UINTN map_key, info_size, gop_mode = ~0; -EFI_HANDLE *handles = NULL; EFI_SHIM_LOCK_PROTOCOL *shim_lock; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; @@ -825,27 +858,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) cols, rows) == EFI_SUCCESS ) efi_arch_console_init(cols, rows); -status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, NULL); -if ( status == EFI_BUFFER_TOO_SMALL ) -status = efi_bs-AllocatePool(EfiLoaderData, size, (void **)handles); -if ( !EFI_ERROR(status) ) -status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, - handles); -if ( EFI_ERROR(status) ) -size = 0; -for ( i = 0; i size / sizeof(*handles); ++i ) -{ -status = efi_bs-HandleProtocol(handles[i], gop_guid, (void **)gop); -if ( EFI_ERROR(status) ) -continue; -status = gop-QueryMode(gop, gop-Mode-Mode, info_size, mode_info); -if ( !EFI_ERROR(status) ) -break; -} -if ( handles ) -efi_bs-FreePool(handles); -if ( EFI_ERROR(status) ) -gop = NULL; +gop = efi_get_gop(); /* Get the file system interface. */ dir_handle = get_parent_handle(loaded_image, file_name); -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 16/18] efi: create efi_exit_boot()
..which gets memory map and calls ExitBootServices(). We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 79 +++-- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 63c930d..f8be3dd 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -864,6 +864,47 @@ static void __init efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop efi_arch_video_init(gop, info_size, mode_info); } +static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ +EFI_STATUS status; +UINTN map_key; +bool_t retry; + +efi_bs-GetMemoryMap(efi_memmap_size, NULL, map_key, + efi_mdesc_size, mdesc_ver); +efi_memmap = efi_arch_allocate_mmap_buffer(efi_memmap_size); +if ( !efi_memmap ) +blexit(LUnable to allocate memory for EFI memory map); + +for ( retry = 0; ; retry = 1 ) +{ +status = efi_bs-GetMemoryMap(efi_memmap_size, efi_memmap, map_key, + efi_mdesc_size, mdesc_ver); +if ( EFI_ERROR(status) ) +PrintErrMesg(LCannot obtain memory map, status); + +efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size, +efi_mdesc_size, mdesc_ver); + +efi_arch_pre_exit_boot(); + +status = efi_bs-ExitBootServices(ImageHandle, map_key); +if ( status != EFI_INVALID_PARAMETER || retry ) +break; +} + +if ( EFI_ERROR(status) ) +PrintErrMesg(LCannot exit boot services, status); + +/* Adjust pointers into EFI. */ +efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START; +#ifdef USE_SET_VIRTUAL_ADDRESS_MAP +efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START; +#endif +efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START; +efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START; +} + static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz) { if ( bpp 0 ) @@ -888,11 +929,11 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) EFI_STATUS status; unsigned int i, argc; CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL; -UINTN map_key, gop_mode = ~0; +UINTN gop_mode = ~0; EFI_SHIM_LOCK_PROTOCOL *shim_lock; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; union string section = { NULL }, name; -bool_t base_video = 0, retry; +bool_t base_video = 0; char *option_str; bool_t use_cfg_file; @@ -1108,39 +1149,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_set_gop_mode(gop, gop_mode); -efi_bs-GetMemoryMap(efi_memmap_size, NULL, map_key, - efi_mdesc_size, mdesc_ver); -efi_memmap = efi_arch_allocate_mmap_buffer(efi_memmap_size); -if ( !efi_memmap ) -blexit(LUnable to allocate memory for EFI memory map); - -for ( retry = 0; ; retry = 1 ) -{ -status = efi_bs-GetMemoryMap(efi_memmap_size, efi_memmap, map_key, - efi_mdesc_size, mdesc_ver); -if ( EFI_ERROR(status) ) -PrintErrMesg(LCannot obtain memory map, status); - -efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size, -efi_mdesc_size, mdesc_ver); - -efi_arch_pre_exit_boot(); - -status = efi_bs-ExitBootServices(ImageHandle, map_key); -if ( status != EFI_INVALID_PARAMETER || retry ) -break; -} - -if ( EFI_ERROR(status) ) -PrintErrMesg(LCannot exit boot services, status); - -/* Adjust pointers into EFI. */ -efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START; -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP -efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START; -#endif -efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START; -efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START; +efi_exit_boot(ImageHandle, SystemTable); efi_arch_post_exit_boot(); for( ; ; ); /* not reached */ -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 09/18] efi: create efi_init()
..which initializes basic EFI variables. We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 26 -- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 89d081d..1bf88e4 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -586,6 +586,21 @@ static char *__init get_value(const struct file *cfg, const char *section, return NULL; } +static void __init efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ +efi_ih = ImageHandle; +efi_bs = SystemTable-BootServices; +efi_rs = SystemTable-RuntimeServices; +efi_ct = SystemTable-ConfigurationTable; +efi_num_ct = SystemTable-NumberOfTableEntries; +efi_version = SystemTable-Hdr.Revision; +efi_fw_vendor = SystemTable-FirmwareVendor; +efi_fw_revision = SystemTable-FirmwareRevision; + +StdOut = SystemTable-ConOut; +StdErr = SystemTable-StdErr ?: StdOut; +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -713,17 +728,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_loader = 1; #endif -efi_ih = ImageHandle; -efi_bs = SystemTable-BootServices; -efi_rs = SystemTable-RuntimeServices; -efi_ct = SystemTable-ConfigurationTable; -efi_num_ct = SystemTable-NumberOfTableEntries; -efi_version = SystemTable-Hdr.Revision; -efi_fw_vendor = SystemTable-FirmwareVendor; -efi_fw_revision = SystemTable-FirmwareRevision; +efi_init(ImageHandle, SystemTable); -StdOut = SystemTable-ConOut; -StdErr = SystemTable-StdErr ?: StdOut; use_cfg_file = efi_arch_use_config_file(SystemTable); status = efi_bs-HandleProtocol(ImageHandle, loaded_image_guid, -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 14/18] efi: create efi_variables()
..which collects variable store parameters. We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 41 - 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index cf0fbc2..2379022 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -822,6 +822,29 @@ static void __init setup_efi_pci(void) efi_bs-FreePool(handles); } +static void __init efi_variables(void) +{ +EFI_STATUS status; + +status = (efi_rs-Hdr.Revision 16) = 2 ? + efi_rs-QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + efi_boot_max_var_store_size, + efi_boot_remain_var_store_size, + efi_boot_max_var_size) : + EFI_INCOMPATIBLE_VERSION; +if ( EFI_ERROR(status) ) +{ +efi_boot_max_var_store_size = 0; +efi_boot_remain_var_store_size = 0; +efi_boot_max_var_size = status; +PrintStr(LWarning: Could not query variable store: ); +DisplayUint(status, 0); +PrintStr(newline); +} +} + static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz) { if ( bpp 0 ) @@ -1061,23 +1084,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) setup_efi_pci(); /* Get snapshot of variable store parameters. */ -status = (efi_rs-Hdr.Revision 16) = 2 ? - efi_rs-QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - efi_boot_max_var_store_size, - efi_boot_remain_var_store_size, - efi_boot_max_var_size) : - EFI_INCOMPATIBLE_VERSION; -if ( EFI_ERROR(status) ) -{ -efi_boot_max_var_store_size = 0; -efi_boot_remain_var_store_size = 0; -efi_boot_max_var_size = status; -PrintStr(LWarning: Could not query variable store: ); -DisplayUint(status, 0); -PrintStr(newline); -} +efi_variables(); efi_arch_memory_setup(); -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 13/18] efi: create efi_tables()
..which collects system tables data. We need this to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/common/efi/boot.c | 51 - 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 114019e..cf0fbc2 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -707,6 +707,34 @@ static UINTN __init efi_find_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, return gop_mode; } +static void __init efi_tables(void) +{ +unsigned int i; + +/* Obtain basic table pointers. */ +for ( i = 0; i efi_num_ct; ++i ) +{ +static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID; +static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID; +static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID; +static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID; + +if ( match_guid(acpi2_guid, efi_ct[i].VendorGuid) ) + efi.acpi20 = (long)efi_ct[i].VendorTable; +if ( match_guid(acpi_guid, efi_ct[i].VendorGuid) ) + efi.acpi = (long)efi_ct[i].VendorTable; +if ( match_guid(mps_guid, efi_ct[i].VendorGuid) ) + efi.mps = (long)efi_ct[i].VendorTable; +if ( match_guid(smbios_guid, efi_ct[i].VendorGuid) ) + efi.smbios = (long)efi_ct[i].VendorTable; +} + +#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */ +if (efi.smbios != EFI_INVALID_TABLE_ADDR) +dmi_efi_get_table((void *)(long)efi.smbios); +#endif +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -1027,28 +1055,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) /* XXX Collect EDID info. */ efi_arch_cpu(); -/* Obtain basic table pointers. */ -for ( i = 0; i efi_num_ct; ++i ) -{ -static EFI_GUID __initdata acpi2_guid = ACPI_20_TABLE_GUID; -static EFI_GUID __initdata acpi_guid = ACPI_TABLE_GUID; -static EFI_GUID __initdata mps_guid = MPS_TABLE_GUID; -static EFI_GUID __initdata smbios_guid = SMBIOS_TABLE_GUID; - -if ( match_guid(acpi2_guid, efi_ct[i].VendorGuid) ) - efi.acpi20 = (long)efi_ct[i].VendorTable; -if ( match_guid(acpi_guid, efi_ct[i].VendorGuid) ) - efi.acpi = (long)efi_ct[i].VendorTable; -if ( match_guid(mps_guid, efi_ct[i].VendorGuid) ) - efi.mps = (long)efi_ct[i].VendorTable; -if ( match_guid(smbios_guid, efi_ct[i].VendorGuid) ) - efi.smbios = (long)efi_ct[i].VendorTable; -} - -#ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */ -if (efi.smbios != EFI_INVALID_TABLE_ADDR) -dmi_efi_get_table((void *)(long)efi.smbios); -#endif +efi_tables(); /* Collect PCI ROM contents. */ setup_efi_pci(); -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 17/18] x86/efi: create new early memory allocator
There is a problem with place_string() which is used as early memory allocator. It gets memory chunks starting from start symbol and going down. Sadly this does not work when Xen is loaded using multiboot2 protocol because start lives on 1 MiB address. So, I tried to use mem_lower address calculated by GRUB2. However, it works only on some machines. There are machines in the wild (e.g. Dell PowerEdge R820) which uses first ~640 KiB for boot services code or data... :-((( In case of multiboot2 protocol we need that place_string() only allocate memory chunk for EFI memory map. However, I think that it should be fixed instead of making another function used just in one case. I thought about two solutions. 1) We could use native EFI allocation functions (e.g. AllocatePool() or AllocatePages()) to get memory chunk. However, later (somewhere in __start_xen()) we must copy its contents to safe place or reserve this in e820 memory map and map it in Xen virtual address space. In later case we must also care about conflicts with e.g. crash kernel regions which could be quite difficult. 2) We may allocate memory area statically somewhere in Xen code which could be used as memory pool for early dynamic allocations. Looks quite simple. Additionally, it would not depend on EFI at all and could be used on legacy BIOS platforms if we need it. However, we must carefully choose size of this pool. We do not want increase Xen binary size too much and waste too much memory but also we must fit at least memory map on x86 EFI platforms. As I saw on small machine, e.g. IBM System x3550 M2 with 8 GiB RAM, memory map my contain more than 200 entries. Every entry on x86-64 platform is 40 bytes in size. So, it means that we need more than 8 KiB for EFI memory map only. Additionally, if we want to use this memory pool for Xen and modules command line storage (it would be used when xen.efi is executed as EFI application) then we should add, I think, about 1 KiB. In this case, to be on safe side, we should assume at least 64 KiB pool for early memory allocations, which is about 4 times of our earlier calculations. If we think that we should not waste unallocated memory in the pool on running system then we can mark this region as __initdata and move all required data to dynamically allocated places somewhere in __start_xen(). Now solution #2 is implemented but maybe we should consider #1 too. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/efi/efi-boot.h | 37 + xen/arch/x86/setup.c|3 +-- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index 3a3b4fe..6e98bc8 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -103,9 +103,35 @@ static void __init relocate_trampoline(unsigned long phys) *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys 4; } +#define __MALLOC_SIZE 65536 + +static char __malloc_mem[__MALLOC_SIZE]; +static char *__malloc_free = NULL; + +static void __init *__malloc(size_t size) +{ +void *ptr; + +/* + * Init __malloc_free on runtime. Static initialization + * will not work because it puts virtual address there. + */ +if ( __malloc_free == NULL ) +__malloc_free = __malloc_mem; + +ptr = __malloc_free; + +__malloc_free += size; + +if ( __malloc_free - __malloc_mem sizeof(__malloc_mem) ) +blexit(LOut of static memory\r\n); + +return ptr; +} + static void __init place_string(u32 *addr, const char *s) { -static char *__initdata alloc = start; +char *alloc = NULL; if ( s *s ) { @@ -113,7 +139,7 @@ static void __init place_string(u32 *addr, const char *s) const char *old = (char *)(long)*addr; size_t len2 = *addr ? strlen(old) + 1 : 0; -alloc -= len1 + len2; +alloc = __malloc(len1 + len2); /* * Insert new string before already existing one. This is needed * for options passed on the command line to override options from @@ -192,12 +218,7 @@ static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable, static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size) { -place_string(mbi.mem_upper, NULL); -mbi.mem_upper -= *map_size; -mbi.mem_upper = -__alignof__(EFI_MEMORY_DESCRIPTOR); -if ( mbi.mem_upper xen_phys_start ) -return NULL; -return (void *)(long)mbi.mem_upper; +return __malloc(*map_size); } static void __init efi_arch_pre_exit_boot(void) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 711fdb0..aebd010 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -962,8 +962,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) if ( !xen_phys_start ) panic(Not enough memory to relocate Xen.); -reserve_e820_ram(boot_e820
[PATCH 2/5] i386/relocator: Remove unused extern grub_relocator64_rip_addr
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- grub-core/lib/i386/relocator.c |1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index ffaf25f..71dd4f0 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -64,7 +64,6 @@ extern grub_uint64_t grub_relocator64_rbx; extern grub_uint64_t grub_relocator64_rcx; extern grub_uint64_t grub_relocator64_rdx; extern grub_uint64_t grub_relocator64_rip; -extern grub_uint64_t grub_relocator64_rip_addr; extern grub_uint64_t grub_relocator64_rsp; extern grub_uint64_t grub_relocator64_rsi; extern grub_addr_t grub_relocator64_cr3; -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 4/5] i386/relocator: Add grub_relocator64_efi relocator
Add grub_relocator64_efi relocator. It will be used on EFI 64-bit platforms when multiboot2 compatible image requests MULTIBOOT_TAG_TYPE_EFI_BS. Relocator will set lower parts of %rax and %rbx accordingly to multiboot2 specification. On the other hand processor mode, just before jumping into loaded image, will be set accordingly to Unified Extensible Firmware Interface Specification, Version 2.4 Errata B, section 2.3.4, x64 Platforms, boot services. This way loaded image will be able to use EFI boot services without any issues. If idea is accepted I will prepare grub_relocator32_efi relocator too. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- grub-core/Makefile.core.def |1 + grub-core/lib/i386/relocator.c | 53 +++ grub-core/lib/i386/relocator64_efi.S | 77 ++ grub-core/loader/multiboot.c | 29 +++-- grub-core/loader/multiboot_mbi2.c| 19 +++-- include/grub/i386/multiboot.h| 11 + include/grub/i386/relocator.h| 21 ++ include/multiboot2.h |9 8 files changed, 213 insertions(+), 7 deletions(-) create mode 100644 grub-core/lib/i386/relocator64_efi.S diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 42443bc..3a01189 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1533,6 +1533,7 @@ module = { x86 = lib/i386/relocator_common_c.c; ieee1275 = lib/ieee1275/relocator.c; efi = lib/efi/relocator.c; + x86_64_efi = lib/i386/relocator64_efi.S; mips = lib/mips/relocator_asm.S; mips = lib/mips/relocator.c; powerpc = lib/powerpc/relocator_asm.S; diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index b879e5b..f4d688e 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -69,6 +69,19 @@ extern grub_uint64_t grub_relocator64_rsi; extern grub_addr_t grub_relocator64_cr3; extern struct grub_i386_idt grub_relocator16_idt; +#ifdef GRUB_MACHINE_EFI +#ifdef __x86_64__ +extern grub_uint8_t grub_relocator64_efi_start; +extern grub_uint8_t grub_relocator64_efi_end; +extern grub_uint64_t grub_relocator64_efi_rax; +extern grub_uint64_t grub_relocator64_efi_rbx; +extern grub_uint64_t grub_relocator64_efi_rcx; +extern grub_uint64_t grub_relocator64_efi_rdx; +extern grub_uint64_t grub_relocator64_efi_rip; +extern grub_uint64_t grub_relocator64_efi_rsi; +#endif +#endif + #define RELOCATOR_SIZEOF(x)(grub_relocator##x##_end - grub_relocator##x##_start) grub_err_t @@ -213,3 +226,43 @@ grub_relocator64_boot (struct grub_relocator *rel, /* Not reached. */ return GRUB_ERR_NONE; } + +#ifdef GRUB_MACHINE_EFI +#ifdef __x86_64__ +grub_err_t +grub_relocator64_efi_boot (struct grub_relocator *rel, + struct grub_relocator64_efi_state state) +{ + grub_err_t err; + void *relst; + grub_relocator_chunk_t ch; + + err = grub_relocator_alloc_chunk_align (rel, ch, 0, + 0x4000 - RELOCATOR_SIZEOF (64_efi), + RELOCATOR_SIZEOF (64_efi), 16, + GRUB_RELOCATOR_PREFERENCE_NONE, 1); + if (err) +return err; + + grub_relocator64_efi_rax = state.rax; + grub_relocator64_efi_rbx = state.rbx; + grub_relocator64_efi_rcx = state.rcx; + grub_relocator64_efi_rdx = state.rdx; + grub_relocator64_efi_rip = state.rip; + grub_relocator64_efi_rsi = state.rsi; + + grub_memmove (get_virtual_current_address (ch), grub_relocator64_efi_start, + RELOCATOR_SIZEOF (64_efi)); + + err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch), + relst, NULL); + if (err) +return err; + + ((void (*) (void)) relst) (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} +#endif +#endif diff --git a/grub-core/lib/i386/relocator64_efi.S b/grub-core/lib/i386/relocator64_efi.S new file mode 100644 index 000..6baaec6 --- /dev/null +++ b/grub-core/lib/i386/relocator64_efi.S @@ -0,0 +1,77 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * Copyright (C) 2014,2015 Oracle Corp. + * Author: Daniel Kiper + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see http://www.gnu.org/licenses/. + */ + +#include relocator_common.S
[PATCH 5/5] multiboot2: Add tags used to pass ImageHandle to loaded image
Add tags used to pass ImageHandle to loaded image. It is used by at least ExitBootServices() function. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- grub-core/loader/multiboot_mbi2.c | 36 +++- include/multiboot2.h | 16 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 8d66e3f..865267c 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -172,6 +172,8 @@ grub_multiboot_load (grub_file_t file, const char *filename) case MULTIBOOT_TAG_TYPE_NETWORK: case MULTIBOOT_TAG_TYPE_EFI_MMAP: case MULTIBOOT_TAG_TYPE_EFI_BS: + case MULTIBOOT_TAG_TYPE_EFI32_IH: + case MULTIBOOT_TAG_TYPE_EFI64_IH: break; default: @@ -906,11 +908,35 @@ grub_multiboot_make_mbi (grub_uint32_t *target) if (keep_bs) { - struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; - tag-type = MULTIBOOT_TAG_TYPE_EFI_BS; - tag-size = sizeof (struct multiboot_tag); - ptrorig += ALIGN_UP (tag-size, MULTIBOOT_TAG_ALIGN) - / sizeof (grub_properly_aligned_t); + { + struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; + tag-type = MULTIBOOT_TAG_TYPE_EFI_BS; + tag-size = sizeof (struct multiboot_tag); + ptrorig += ALIGN_UP (tag-size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); + } + +#ifdef __x86_64__ + { + struct multiboot_tag_efi64_ih *tag = (struct multiboot_tag_efi64_ih *) ptrorig; + tag-type = MULTIBOOT_TAG_TYPE_EFI64_IH; + tag-size = sizeof (*tag); + tag-pointer = (grub_addr_t) grub_efi_image_handle; + ptrorig += ALIGN_UP (tag-size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); + } +#endif + +#ifdef __i386__ + { + struct multiboot_tag_efi32_ih *tag = (struct multiboot_tag_efi32_ih *) ptrorig; + tag-type = MULTIBOOT_TAG_TYPE_EFI32_IH; + tag-size = sizeof (*tag); + tag-pointer = (grub_addr_t) grub_efi_image_handle; + ptrorig += ALIGN_UP (tag-size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); + } +#endif } #endif diff --git a/include/multiboot2.h b/include/multiboot2.h index 75cc99b..36372f4 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -60,6 +60,8 @@ #define MULTIBOOT_TAG_TYPE_NETWORK 16 #define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 #define MULTIBOOT_TAG_TYPE_EFI_BS18 +#define MULTIBOOT_TAG_TYPE_EFI32_IH 19 +#define MULTIBOOT_TAG_TYPE_EFI64_IH 20 #define MULTIBOOT_HEADER_TAG_END 0 #define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 @@ -382,6 +384,20 @@ struct multiboot_tag_efi_mmap multiboot_uint8_t efi_mmap[0]; }; +struct multiboot_tag_efi32_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + #endif /* ! ASM_FILE */ #endif /* ! MULTIBOOT_HEADER */ -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 1/5] multiboot2: Fix information request tag size calculation
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- grub-core/loader/multiboot_mbi2.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 6f74aee..d7c19bc 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -150,7 +150,7 @@ grub_multiboot_load (grub_file_t file, const char *filename) = (struct multiboot_header_tag_information_request *) tag; if (request_tag-flags MULTIBOOT_HEADER_TAG_OPTIONAL) break; - for (i = 0; i (request_tag-size - sizeof (request_tag)) + for (i = 0; i (request_tag-size - sizeof (*request_tag)) / sizeof (request_tag-requests[0]); i++) switch (request_tag-requests[i]) { -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 3/5] i386/relocator: Remove unused avoid_efi_bootservices argument
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- grub-core/lib/i386/relocator.c |5 ++--- grub-core/loader/i386/bsd.c |6 +++--- grub-core/loader/i386/coreboot/chainloader.c |2 +- grub-core/loader/i386/linux.c|2 +- grub-core/loader/i386/pc/plan9.c |2 +- grub-core/loader/i386/xnu.c |4 ++-- grub-core/loader/multiboot.c |4 include/grub/i386/relocator.h|3 +-- 8 files changed, 11 insertions(+), 17 deletions(-) diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index 71dd4f0..b879e5b 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -73,8 +73,7 @@ extern struct grub_i386_idt grub_relocator16_idt; grub_err_t grub_relocator32_boot (struct grub_relocator *rel, - struct grub_relocator32_state state, - int avoid_efi_bootservices) + struct grub_relocator32_state state) { grub_err_t err; void *relst; @@ -87,7 +86,7 @@ grub_relocator32_boot (struct grub_relocator *rel, 0x9a000 - RELOCATOR_SIZEOF (32), RELOCATOR_SIZEOF (32), 16, GRUB_RELOCATOR_PREFERENCE_LOW, - avoid_efi_bootservices); + 0); if (err) return err; diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index bc377b3..c2bf09f 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -797,7 +797,7 @@ grub_freebsd_boot (void) stack[6] = stack_target + 9 * sizeof (grub_uint32_t); stack[7] = bi.tags; stack[8] = kern_end; - return grub_relocator32_boot (relocator, state, 0); + return grub_relocator32_boot (relocator, state); } /* Not reached. */ @@ -913,7 +913,7 @@ grub_openbsd_boot (void) stack[7] = (grub_uint8_t *) curarg - (grub_uint8_t *) arg0; stack[8] = ((grub_uint8_t *) arg0 - (grub_uint8_t *) buf0) + buf_target; - return grub_relocator32_boot (relocator, state, 0); + return grub_relocator32_boot (relocator, state); } static grub_err_t @@ -1228,7 +1228,7 @@ grub_netbsd_boot (void) stack[5] = grub_mmap_get_upper () 10; stack[6] = grub_mmap_get_lower () 10; - return grub_relocator32_boot (relocator, state, 0); + return grub_relocator32_boot (relocator, state); } static grub_err_t diff --git a/grub-core/loader/i386/coreboot/chainloader.c b/grub-core/loader/i386/coreboot/chainloader.c index d4cc40b..4bf6dff 100644 --- a/grub-core/loader/i386/coreboot/chainloader.c +++ b/grub-core/loader/i386/coreboot/chainloader.c @@ -47,7 +47,7 @@ grub_chain_boot (void) grub_video_set_mode (text, 0, 0); state.eip = entry; - return grub_relocator32_boot (relocator, state, 0); + return grub_relocator32_boot (relocator, state); } static grub_err_t diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 291f728..a554da8 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -661,7 +661,7 @@ grub_linux_boot (void) state.esi = ctx.real_mode_target; state.esp = ctx.real_mode_target; state.eip = ctx.params-code32_start; - return grub_relocator32_boot (relocator, state, 0); + return grub_relocator32_boot (relocator, state); } static grub_err_t diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 814a49d..bfff497 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -90,7 +90,7 @@ grub_plan9_boot (void) }; grub_video_set_mode (text, 0, 0); - return grub_relocator32_boot (rel, state, 0); + return grub_relocator32_boot (rel, state); } static grub_err_t diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index e0506a6..a2bc876 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -791,7 +791,7 @@ grub_xnu_boot_resume (void) state.eip = grub_xnu_entry_point; state.eax = grub_xnu_arg1; - return grub_relocator32_boot (grub_xnu_relocator, state, 0); + return grub_relocator32_boot (grub_xnu_relocator, state); } /* Setup video for xnu. */ @@ -1099,7 +1099,7 @@ grub_xnu_boot (void) grub_outb (0xff, 0x21); grub_outb (0xff, 0xa1); - return grub_relocator32_boot (grub_xnu_relocator, state, 0); + return grub_relocator32_boot (grub_xnu_relocator, state); } static grub_command_t cmd_devprop_load; diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 4b71f33..307da32 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -131,11 +131,7 @@ grub_multiboot_boot (void) if (err) return err; -#if defined (__i386__) || defined (__x86_64__) - grub_relocator32_boot (grub_multiboot_relocator, state, 0); -#else
[PATCH 0/5] multiboot2: Enable EFI boot services usage in loaded images
Hi, This patch series enable EFI boot services usage in loaded images by multiboot2 protocol. Daniel grub-core/Makefile.core.def |1 + grub-core/lib/i386/relocator.c | 59 ++ grub-core/lib/i386/relocator64_efi.S | 77 +++ grub-core/loader/i386/bsd.c |6 +++--- grub-core/loader/i386/coreboot/chainloader.c |2 +- grub-core/loader/i386/linux.c|2 +- grub-core/loader/i386/pc/plan9.c |2 +- grub-core/loader/i386/xnu.c |4 ++-- grub-core/loader/multiboot.c | 29 ++- grub-core/loader/multiboot_mbi2.c| 57 ++-- include/grub/i386/multiboot.h| 11 +++ include/grub/i386/relocator.h| 24 -- include/multiboot2.h | 25 +++ 13 files changed, 270 insertions(+), 29 deletions(-) Daniel Kiper (5): multiboot2: Fix information request tag size calculation i386/relocator: Remove unused extern grub_relocator64_rip_addr i386/relocator: Remove unused avoid_efi_bootservices argument i386/relocator: Add grub_relocator64_efi relocator multiboot2: Add tags used to pass ImageHandle to loaded image ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 00/18] x86: multiboot2 protocol support
Hi, I am sending, long awaited, first version of multiboot2 protocol support for legacy BIOS and EFI platforms. The final goal is xen.efi binary file which could be loaded by EFI loader, multiboot (v1) protocol (only on legacy BIOS platforms) and multiboot2 protocol. This way we will have: - smaller Xen code base, - one code base for xen.gz and xen.efi, - one build method for xen.gz and xen.efi; xen.efi will be extracted from xen file using objcopy; PE header will be contained in ELF file and will precede Xen code, - xen.efi build will not so strongly depend on a given GCC and binutils version. GRUB2 patch series will follow this patch series. GRUB2 guys should check patch #18 but I am sending to you all Xen related patches just in case. Daniel xen/arch/x86/Makefile | 17 ++-- xen/arch/x86/boot/Makefile|3 +- xen/arch/x86/boot/head.S | 291 ++ xen/arch/x86/boot/reloc.c | 219 ++--- xen/arch/x86/dmi_scan.c |4 +- xen/arch/x86/domain_page.c|2 +- xen/arch/x86/e820.c | 29 ++ xen/arch/x86/efi/Makefile | 12 +-- xen/arch/x86/efi/efi-boot.h | 66 +++-- xen/arch/x86/efi/stub.c | 41 xen/arch/x86/mpparse.c|4 +- xen/arch/x86/setup.c | 30 +++--- xen/arch/x86/shutdown.c |3 +- xen/arch/x86/time.c |2 +- xen/arch/x86/x86_64/asm-offsets.c |8 ++ xen/arch/x86/xen.lds.S|2 - xen/common/efi/boot.c | 441 +- xen/common/efi/runtime.c | 11 ++- xen/drivers/acpi/osl.c|2 +- xen/include/xen/efi.h |6 +- xen/include/xen/multiboot2.h | 169 21 files changed, 1018 insertions(+), 344 deletions(-) Daniel Kiper (18): x86/boot/reloc: mask out MBI_BOOTDEV from mbi flags x86/boot/reloc: create generic alloc and copy functions x86/boot: use %ecx instead of %eax xen/x86: add multiboot2 protocol support efi: split efi_enabled to efi_platform and efi_loader x86: remove commented out stale references to efi_enabled efi: run EFI specific code on EFI platform only efi: build xen.gz with EFI code efi: create efi_init() efi: create efi_console_set_mode() efi: create efi_get_gop() efi: create efi_find_gop_mode() efi: create efi_tables() efi: create efi_variables() efi: create efi_set_gop_mode() efi: create efi_exit_boot() x86/efi: create new early memory allocator x86: add multiboot2 protocol support for EFI platforms ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 01/18] x86/boot/reloc: mask out MBI_BOOTDEV from mbi flags
..because it is ignored by Xen. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/reloc.c |1 - 1 file changed, 1 deletion(-) diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c index f971920..63045c0 100644 --- a/xen/arch/x86/boot/reloc.c +++ b/xen/arch/x86/boot/reloc.c @@ -90,7 +90,6 @@ multiboot_info_t *reloc(multiboot_info_t *mbi_old) /* Mask features we don't understand or don't relocate. */ mbi-flags = (MBI_MEMLIMITS | - MBI_BOOTDEV | MBI_CMDLINE | MBI_MODULES | MBI_MEMMAP | -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 05/18] efi: split efi_enabled to efi_platform and efi_loader
We need more fine grained knowledge about EFI environment and check for EFI platform and EFI loader separately to properly support multiboot2 protocol. In general Xen loaded by this protocol uses memory mappings and loaded modules in simliar way to Xen loaded by multiboot (v1) protocol. Hence, split efi_enabled to efi_platform and efi_loader. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/dmi_scan.c|4 ++-- xen/arch/x86/domain_page.c |2 +- xen/arch/x86/efi/stub.c|5 +++-- xen/arch/x86/mpparse.c |4 ++-- xen/arch/x86/setup.c |8 xen/arch/x86/time.c|2 +- xen/common/efi/boot.c |5 + xen/common/efi/runtime.c |5 +++-- xen/drivers/acpi/osl.c |2 +- xen/include/xen/efi.h |6 +- 10 files changed, 27 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/dmi_scan.c b/xen/arch/x86/dmi_scan.c index 500133a..63b976c 100644 --- a/xen/arch/x86/dmi_scan.c +++ b/xen/arch/x86/dmi_scan.c @@ -150,7 +150,7 @@ int __init dmi_get_table(u32 *base, u32 *len) struct dmi_eps eps; char __iomem *p, *q; - if (efi_enabled) { + if (efi_platform) { if (!efi_dmi_size) return -1; *base = efi_dmi_address; @@ -516,7 +516,7 @@ static void __init dmi_decode(struct dmi_header *dm) void __init dmi_scan_machine(void) { - if ((!efi_enabled ? dmi_iterate(dmi_decode) : + if ((!efi_platform ? dmi_iterate(dmi_decode) : dmi_efi_iterate(dmi_decode)) == 0) dmi_check_system(dmi_blacklist); else diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c index 158a164..5d4564c 100644 --- a/xen/arch/x86/domain_page.c +++ b/xen/arch/x86/domain_page.c @@ -45,7 +45,7 @@ static inline struct vcpu *mapcache_current_vcpu(void) sync_local_execstate(); /* We must now be running on the idle page table. */ ASSERT((cr3 = read_cr3()) == __pa(idle_pg_table) || - (efi_enabled cr3 == efi_rs_page_table())); + (efi_platform cr3 == efi_rs_page_table())); } return v; diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c index b8f49f8..5060e6f 100644 --- a/xen/arch/x86/efi/stub.c +++ b/xen/arch/x86/efi/stub.c @@ -3,8 +3,9 @@ #include xen/init.h #include xen/lib.h -#ifndef efi_enabled -const bool_t efi_enabled = 0; +#ifndef efi_platform +bool_t efi_platform = 0; +bool_t efi_loader = 0; #endif void __init efi_init_memory(void) { } diff --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c index a38e016..c4e3041 100644 --- a/xen/arch/x86/mpparse.c +++ b/xen/arch/x86/mpparse.c @@ -540,7 +540,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) static __init void efi_unmap_mpf(void) { - if (efi_enabled) + if (efi_platform) __set_fixmap(FIX_EFI_MPF, 0, 0); } @@ -698,7 +698,7 @@ void __init find_smp_config (void) { unsigned int address; - if (efi_enabled) { + if (efi_platform) { efi_check_config(); return; } diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index c27c49c..711fdb0 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -431,7 +431,7 @@ static void __init parse_video_info(void) struct boot_video_info *bvi = bootsym(boot_vid_info); /* The EFI loader fills vga_console_info directly. */ -if ( efi_enabled ) +if ( efi_platform ) return; if ( (bvi-orig_video_isVGA == 1) (bvi-orig_video_mode == 3) ) @@ -663,7 +663,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) if ( ((unsigned long)cpu0_stack (STACK_SIZE-1)) != 0 ) panic(Misaligned CPU0 stack.); -if ( efi_enabled ) +if ( efi_loader ) { set_pdx_range(xen_phys_start PAGE_SHIFT, (xen_phys_start + BOOTSTRAP_MAP_BASE) PAGE_SHIFT); @@ -774,7 +774,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) * we can relocate the dom0 kernel and other multiboot modules. Also, on * x86/64, we relocate Xen to higher memory. */ -for ( i = 0; !efi_enabled i mbi-mods_count; i++ ) +for ( i = 0; !efi_loader i mbi-mods_count; i++ ) { if ( mod[i].mod_start (PAGE_SIZE - 1) ) panic(Bootloader didn't honor module alignment request.); @@ -962,7 +962,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) if ( !xen_phys_start ) panic(Not enough memory to relocate Xen.); -reserve_e820_ram(boot_e820, efi_enabled ? mbi-mem_upper : __pa(_start), +reserve_e820_ram(boot_e820, efi_loader ? mbi-mem_upper : __pa(_start), __pa(_end)); /* Late kexec reservation (dynamic start address). */ diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index 74c01e3..cdd17cb 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86
[PATCH 02/18] x86/boot/reloc: create generic alloc and copy functions
Create generic alloc and copy functions. We need separate tools for memory allocation and copy to provide multiboot2 protocol support. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/reloc.c | 52 - 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c index 63045c0..f964cda 100644 --- a/xen/arch/x86/boot/reloc.c +++ b/xen/arch/x86/boot/reloc.c @@ -33,9 +33,10 @@ asm ( typedef unsigned int u32; #include ../../../include/xen/multiboot.h -static void *reloc_mbi_struct(void *old, unsigned int bytes) +static u32 alloc_struct(u32 bytes) { -void *new; +u32 s; + asm( call 1f \n 1: pop %%edx \n @@ -43,50 +44,63 @@ static void *reloc_mbi_struct(void *old, unsigned int bytes) sub %1,%0 \n and $~15,%0 \n mov %0,alloc-1b(%%edx) \n -mov %0,%%edi\n -rep movsb \n - : =r (new), +c (bytes), +S (old) - : : edx, edi, memory); -return new; + : =r (s) : r (bytes) : edx, memory); + +return s; +} + +static u32 copy_struct(u32 src, u32 bytes) +{ +u32 dst, dst_asm; + +dst = alloc_struct(bytes); +dst_asm = dst; + +asm volatile(rep movsb : +S (src), +D (dst_asm), +c (bytes) : : memory); + +return dst; } -static char *reloc_mbi_string(char *old) +static u32 copy_string(u32 src) { char *p; -for ( p = old; *p != '\0'; p++ ) + +if ( src == 0 ) +return 0; + +for ( p = (char *)src; *p != '\0'; p++ ) continue; -return reloc_mbi_struct(old, p - old + 1); + +return copy_struct(src, p - (char *)src + 1); } multiboot_info_t *reloc(multiboot_info_t *mbi_old) { -multiboot_info_t *mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi)); +multiboot_info_t *mbi = (multiboot_info_t *)copy_struct((u32)mbi_old, sizeof(*mbi)); int i; if ( mbi-flags MBI_CMDLINE ) -mbi-cmdline = (u32)reloc_mbi_string((char *)mbi-cmdline); +mbi-cmdline = copy_string(mbi-cmdline); if ( mbi-flags MBI_MODULES ) { -module_t *mods = reloc_mbi_struct( -(module_t *)mbi-mods_addr, mbi-mods_count * sizeof(module_t)); +module_t *mods = (module_t *)copy_struct( +mbi-mods_addr, mbi-mods_count * sizeof(module_t)); mbi-mods_addr = (u32)mods; for ( i = 0; i mbi-mods_count; i++ ) { if ( mods[i].string ) -mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string); +mods[i].string = copy_string(mods[i].string); } } if ( mbi-flags MBI_MEMMAP ) -mbi-mmap_addr = (u32)reloc_mbi_struct( -(memory_map_t *)mbi-mmap_addr, mbi-mmap_length); +mbi-mmap_addr = copy_struct(mbi-mmap_addr, mbi-mmap_length); if ( mbi-flags MBI_LOADERNAME ) -mbi-boot_loader_name = (u32)reloc_mbi_string( -(char *)mbi-boot_loader_name); +mbi-boot_loader_name = copy_string(mbi-boot_loader_name); /* Mask features we don't understand or don't relocate. */ mbi-flags = (MBI_MEMLIMITS | -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH 03/18] x86/boot: use %ecx instead of %eax
Use %ecx instead of %eax to store low memory upper limit from EBDA. This way we do not wipe multiboot protocol identifier. It is needed in reloc() to differentiate between multiboot (v1) and multiboot2 protocol. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com Reviewed-by: Andrew Cooper andrew.coop...@citrix.com --- xen/arch/x86/boot/head.S | 27 ++- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index c99f739..6180783 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -86,14 +86,14 @@ __start: jne not_multiboot /* Set up trampoline segment 64k below EBDA */ -movzwl 0x40e,%eax /* EBDA segment */ -cmp $0xa000,%eax/* sanity check (high) */ +movzwl 0x40e,%ecx /* EBDA segment */ +cmp $0xa000,%ecx/* sanity check (high) */ jae 0f -cmp $0x4000,%eax/* sanity check (low) */ +cmp $0x4000,%ecx/* sanity check (low) */ jae 1f 0: -movzwl 0x413,%eax /* use base memory size on failure */ -shl $10-4,%eax +movzwl 0x413,%ecx /* use base memory size on failure */ +shl $10-4,%ecx 1: /* * Compare the value in the BDA with the information from the @@ -105,21 +105,22 @@ __start: cmp $0x100,%edx /* is the multiboot value too small? */ jb 2f /* if so, do not use it */ shl $10-4,%edx -cmp %eax,%edx /* compare with BDA value */ -cmovb %edx,%eax /* and use the smaller */ +cmp %ecx,%edx /* compare with BDA value */ +cmovb %edx,%ecx /* and use the smaller */ 2: /* Reserve 64kb for the trampoline */ -sub $0x1000,%eax +sub $0x1000,%ecx /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */ -xor %al, %al -shl $4, %eax -mov %eax,sym_phys(trampoline_phys) +xor %cl, %cl +shl $4, %ecx +mov %ecx,sym_phys(trampoline_phys) /* Save the Multiboot info struct (after relocation) for later use. */ mov $sym_phys(cpu0_stack)+1024,%esp -push%ebx -callreloc +mov %ecx,%eax +push%ebx/* Multiboot information address */ +callreloc /* %eax contains trampoline address */ mov %eax,sym_phys(multiboot_ptr) /* Initialize BSS (no nasty surprises!) */ -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Fri, Jan 30, 2015 at 07:06:53PM +, Andrew Cooper wrote: On 30/01/15 17:54, Daniel Kiper wrote: Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/head.S | 174 +++-- xen/arch/x86/efi/efi-boot.h | 29 +++ xen/arch/x86/setup.c | 23 ++--- xen/arch/x86/x86_64/asm-offsets.c |2 + xen/common/efi/boot.c | 11 +++ 5 files changed, 222 insertions(+), 17 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 7861057..89f5aa7 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -8,6 +8,7 @@ #include asm/page.h #include asm/msr.h #include asm/cpufeature.h +#include asm/processor.h .text .code32 @@ -57,6 +58,9 @@ ENTRY(start) .long .Lmultiboot2_info_req_end - .Lmultiboot2_info_req .long MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO .long MULTIBOOT2_TAG_TYPE_MMAP +.long MULTIBOOT2_TAG_TYPE_EFI_BS +.long MULTIBOOT2_TAG_TYPE_EFI64 +.long MULTIBOOT2_TAG_TYPE_EFI64_IH .Lmultiboot2_info_req_end: .align MULTIBOOT2_TAG_ALIGN @@ -80,6 +84,19 @@ ENTRY(start) .long 0 /* Number of the lines - no preference. */ .long 0 /* Number of bits per pixel - no preference. */ +/* Do not disable EFI boot services. */ +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_EFI_BS +.short MULTIBOOT2_HEADER_TAG_OPTIONAL +.long 8 /* Tag size. */ + +/* EFI64 entry point. */ +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_ENTRY_ADDRESS_EFI64 +.short MULTIBOOT2_HEADER_TAG_OPTIONAL +.long 12 /* Tag size. */ +.long sym_phys(__efi64_start) + /* Multiboot2 header end tag. */ .align MULTIBOOT2_TAG_ALIGN .short MULTIBOOT2_HEADER_TAG_END @@ -94,6 +111,17 @@ ENTRY(start) gdt_boot_descr: .word 6*8-1 .long sym_phys(trampoline_gdt) +.long 0 /* Needed for 64-bit lgdt */ + +cs32_switch_addr: +.long sym_phys(cs32_switch) +.long BOOT_CS32 .word ljmpl refers to an m32:16 not an m32:32 + +efi_st: +.quad 0 + +efi_ih: +.quad 0 .Lbad_cpu_msg: .asciz ERR: Not a 64-bit CPU! .Lbad_ldr_msg: .asciz ERR: Not a Multiboot bootloader! @@ -124,6 +152,133 @@ print_err: .Lhalt: hlt jmp .Lhalt +.code64 + +__efi64_start: +cld + +/* Bootloaders may set multiboot[12].mem_lower to a nonzero value */ +xor %edx,%edx + +/* Check for Multiboot2 bootloader */ +cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax +je efi_multiboot2_proto + +jmp not_multiboot not_multiboot is 32bit code. You must drop out of 64bit before using it, or make a 64bit variant. + +efi_multiboot2_proto: +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx + +0: +/* Get mem_lower from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,(%ecx) +jne 1f + +mov MB2_mem_lower(%ecx),%edx +jmp 4f + +1: +/* Get EFI SystemTable address from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_EFI64,(%ecx) +jne 2f + +lea MB2_efi64_st(%ecx),%esi +lea efi_st(%rip),%edi +movsq This is complete overkill for copying a 64bit variable out of the tag and into a local variable. Just use a plain 64bit load and store. I am not sure what do you mean by 64bit load and store but I have just realized that we do not need these variables. They are remnants from early developments when I thought that we need ImageHandle and SystemTable here and later somewhere else. +/* Do not go into real mode on EFI platform */ +movb$1,skip_realmode(%rip) + +jmp 4f + +2: +/* Get EFI ImageHandle address from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_EFI64_IH,(%ecx) +jne 3f + +lea MB2_efi64_ih(%ecx),%esi +lea efi_ih(%rip),%edi +movsq And here. Ditto. +jmp 4f + +3: +/* Is it the end of Multiboot2 information? */ +cmpl$MULTIBOOT2_TAG_TYPE_END,(%ecx) +je run_bs + +4: +/* Go to next Multiboot2 information tag */ +add MB2_tag_size(%ecx),%ecx +add $(MULTIBOOT2_TAG_ALIGN-1),%ecx +and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx +jmp 0b + +run_bs: +push%rax +push%rdx Does the EFI spec guarantee that we have a good stack
Re: [PATCH 0/5] multiboot2: Enable EFI boot services usage in loaded images
Hi all, On Fri, Jan 30, 2015 at 06:59:23PM +0100, Daniel Kiper wrote: Hi, This patch series enable EFI boot services usage in loaded images by multiboot2 protocol. Guys, do you have any comments on this patch series? Should I fix something? Could you apply them to GRUB2 tree? Daniel PS Please CC all interested parties. I suppose that there are some people here who are not subscribed to grub-devel list. ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 00/18] x86: multiboot2 protocol support
Hi all, On Fri, Jan 30, 2015 at 06:54:04PM +0100, Daniel Kiper wrote: Hi, I am sending, long awaited, first version of multiboot2 protocol support for legacy BIOS and EFI platforms. The final goal is xen.efi binary file which could be loaded by EFI loader, multiboot (v1) protocol (only on legacy BIOS platforms) and multiboot2 protocol. This way we will have: - smaller Xen code base, - one code base for xen.gz and xen.efi, - one build method for xen.gz and xen.efi; xen.efi will be extracted from xen file using objcopy; PE header will be contained in ELF file and will precede Xen code, - xen.efi build will not so strongly depend on a given GCC and binutils version. I have not received so many comments on this patch series. Is there no interest in having this feature in Xen? Is there anything wrong? Should I fix something? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Fri, Jan 30, 2015 at 06:54:22PM +0100, Daniel Kiper wrote: Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/head.S | 174 +++-- xen/arch/x86/efi/efi-boot.h | 29 +++ xen/arch/x86/setup.c | 23 ++--- xen/arch/x86/x86_64/asm-offsets.c |2 + xen/common/efi/boot.c | 11 +++ 5 files changed, 222 insertions(+), 17 deletions(-) After some testing we have found at least one machine on which this thing does not work. It is Dell PowerEdge R820 with latest firmware. Machine crashes/stops because early 32-bit code is not relocatable and must live under 0x10 address. (side note: I am surprised how it worked without any issue until now; Multiboot protocol, any version, does not guarantee that OS image will be loaded at specified/requested address; So, it looks that there are not any legacy BIOS machines with e.g. 1 MiB - 2 MiB region reserved in the wild or they are not very common; Am I missing something?). Sadly, this region is used by BS, so, GRUB2 loads Xen higher (at least above 64 MiB). Please look at memory map on this machine: Type StartEnd # Pages Attributes BS_Data0001-0009 0090 000F BS_Data0010-03FF 3F00 000F Available 0400-0FFFEFFF BFFF 000F BS_Code0000-1006CFFF 006E 000F Available 1006D000-B3E73FFF 000A3E07 000F [...] Additionally, early Xen boot code maps only first 16 MiB of memory. Hence, it means that jump into __high_start fails immediately. Now I see two solutions for these issues: 1) We can make early 32-bit code relocatable. We may use something similar to xen/arch/x86/boot/trampoline.S:bootsym_rel(). Additionally, I think that early code should not blindly map first 16 MiB of memory. It should map first 1 MiB of memory and then 16 MiB of memory starting from xen_phys_start. This way we also fix long standing bug in early code which I described earlier. 2) We can jump from EFI x86-64 mode directly into Xen x86-64 mode like it is done in case of EFI loader. However, then we must duplicate multiboot2 protocol implementation in x86-64 mode (if we wish that multiboot2 protocol can be used on legacy BIOS and EFI platforms; I think that we should support this protocol on both for users convenience). Additionally, we must use a workaround to relocate trampoline if boot services uses memory below 1 MiB (please check commit c1f2dfe8f6a559bc28935f24e31bb33d17d9713d, x86/EFI: make trampoline allocation more flexible, for more details). I prefer #1 because this way we do not duplicate multiboot2 protocol implementation (one for legacy BIOS and EFI) and we avoid issues with trampoline relocation when low memory is occupied by boot services and/or 1:1 EFI page tables. Daniel PS I have just realized that commit c1f2dfe8f6a559bc28935f24e31bb33d17d9713d will not work if trampoline code will overwrite some of EFI 1:1 page tables. Dell PowerEdge R820 store part of 1:1 page tables below 1 MiB. Xen loaded by native EFI loader boots but it is only lucky coincidence that it does not overwrite used entries. So, I tend to go and choose #1 even more. ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Sat, Feb 14, 2015 at 08:23:45PM +0300, Andrei Borzenkov wrote: В Wed, 11 Feb 2015 08:20:04 + Jan Beulich jbeul...@suse.com пишет: On 10.02.15 at 22:27, daniel.ki...@oracle.com wrote: After some testing we have found at least one machine on which this thing does not work. It is Dell PowerEdge R820 with latest firmware. Machine crashes/stops because early 32-bit code is not relocatable and must live under 0x10 address. (side note: I am surprised how it worked without any issue until now; Multiboot protocol, any version, does not guarantee that OS image will be loaded at specified/requested address; How does it not? It's an ELF binary without relocations that's being loaded - I can't see how such could be validly loaded anywhere but at the virtual address(es) its program header states (and I don't know whether grub [1 or 2] would correctly process relocations if there were any, but I doubt it). grub2 relocates own modules when loading them. It does not do Great! However, it also ignores MULTIBOOT_TAG_TYPE_EFI_BS flag and overwrite BS if it leaves in region requested by image. It is a bug which I have just discovered. I will fix it. relocation when loading Xen binary, but it does not sound impossible. Ugh... You are right. I was confused because multiboot2 command just allocate memory outside reserved regions. I thought that this is final destination. However, later if you execute boot command then image is relocated to final destination. Facepalm! Anyway, we must support relocatable images in multiboot2 protocol. I think that image (any format, e.g. PE) could inform loader that it can live anywhere below 4 GiB by setting special flag in multiboot2 header. Or ELF image could have relocation section which would be interpreted by loader. Both approaches make sense and are feasible. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Tue, Mar 17, 2015 at 10:32:01AM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: @@ -94,6 +111,17 @@ ENTRY(start) gdt_boot_descr: .word 6*8-1 .long sym_phys(trampoline_gdt) +.long 0 /* Needed for 64-bit lgdt */ + +cs32_switch_addr: +.long sym_phys(cs32_switch) +.long BOOT_CS32 + +efi_st: +.quad 0 + +efi_ih: +.quad 0 .Lbad_cpu_msg: .asciz ERR: Not a 64-bit CPU! .Lbad_ldr_msg: .asciz ERR: Not a Multiboot bootloader! @@ -124,6 +152,133 @@ print_err: .Lhalt: hlt jmp .Lhalt +.code64 + +__efi64_start: +cld + +/* Bootloaders may set multiboot[12].mem_lower to a nonzero value */ +xor %edx,%edx + +/* Check for Multiboot2 bootloader */ +cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax +je efi_multiboot2_proto + +jmp not_multiboot + +efi_multiboot2_proto: jne not_multiboot (and efi_multiboot2_proto dropped altogether) [...] Jan, thanks for your comments. Now I am working on relocatable early Xen code. I hope that I will finish that this week and start tests on this crazy UEFI platforms. Then I get back to this patch series and replay for your and other guys comments. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 00/18] x86: multiboot2 protocol support
On Fri, Jan 30, 2015 at 06:54:04PM +0100, Daniel Kiper wrote: Hi, I am sending, long awaited, first version of multiboot2 protocol support for legacy BIOS and EFI platforms. New version with relocatable Xen early boot code is under tests now. I hope that I will release new version in 2-3 weeks after polishing some details and taking into account your comments. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 08/18] efi: build xen.gz with EFI code
On Mon, Mar 02, 2015 at 04:14:22PM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: --- a/xen/arch/x86/efi/Makefile +++ b/xen/arch/x86/efi/Makefile @@ -1,14 +1,14 @@ CFLAGS += -fshort-wchar -obj-y += stub.o +obj-y += boot.o +obj-y += compat.o +obj-y += runtime.o So how is this going to work with a compiler not new enough to support the MS ABI (via function attribute)? README says: First, there are a number of prerequisites for building a Xen source release. Make sure you have all the following installed, either by visiting the project webpage or installing a pre-built package provided by your OS distributor: * GCC v4.1 or later IIRC, MS ABI is supported starting from GCC v4.0. Should we care about people using compilers older than we require? Though another question arises. Is it possible to build GCC v4.0 and newer with MS ABI disabled? If yes then we should take into account that thing. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 04/18] xen/x86: add multiboot2 protocol support
$MULTIBOOT2_BOOTLOADER_MAGIC,%eax +je multiboot2_proto + +jmp not_multiboot + +multiboot1_proto: +/* Get mem_lower from Multiboot information */ +testb $MBI_MEMLIMITS,(%ebx) MB_flags(%ebx) +jz trampoline_setup/* not available? BDA value will be fine */ + +mov MB_mem_lower(%ebx),%edx Please use cmovnz or or instead of jz and mov. +jmp trampoline_setup + +multiboot2_proto: +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx + +0: +/* Get mem_lower from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,(%ecx) +jne 1f + +mov MB2_mem_lower(%ecx),%edx +jmp trampoline_setup + +1: +/* Is it the end of Multiboot2 information? */ +cmpl$MULTIBOOT2_TAG_TYPE_END,(%ecx) This lacks the use a suitable MB2_* definition (even if that ends up being zero). --- a/xen/arch/x86/boot/reloc.c +++ b/xen/arch/x86/boot/reloc.c @@ -5,19 +5,26 @@ * and modules. This is most easily done early with paging disabled. * * Copyright (c) 2009, Citrix Systems, Inc. + * Copyright (c) 2013, 2014, 2015 Oracle Corp. * * Authors: *Keir Fraser k...@xen.org + *Daniel Kiper If you add yourself here, then please (following the existing example) with email address. -/* entered with %eax = BOOT_TRAMPOLINE */ +/* + * This entry point is entered from xen/arch/x86/boot/head.S with: + * - %eax = MULTIBOOT_MAGIC, + * - %ebx = MULTIBOOT_INFORMATION_ADDRESS, + * - %ecx = BOOT_TRAMPOLINE. Then why do you push %eax and %ebx above? @@ -31,7 +38,16 @@ asm ( ); typedef unsigned int u32; +typedef unsigned long long u64; + +#include ../../../include/xen/compiler.h Why? static multiboot_info_t __used *reloc(void *mbi_in, u32 mb_magic) Because of this -- ^^ @@ -74,40 +95,153 @@ static u32 copy_string(u32 src) return copy_struct(src, p - (char *)src + 1); } -multiboot_info_t *reloc(multiboot_info_t *mbi_old) +static multiboot_info_t *mbi_mbi(void *mbi_in) { -multiboot_info_t *mbi = (multiboot_info_t *)copy_struct((u32)mbi_old, sizeof(*mbi)); int i; +multiboot_info_t *mbi_out; -if ( mbi-flags MBI_CMDLINE ) -mbi-cmdline = copy_string(mbi-cmdline); +mbi_out = (multiboot_info_t *)copy_struct((u32)mbi_in, sizeof(*mbi_out)); Why can this not remain the initializer of the variable? Also the unrelated renaming mbi - mbi_out and mbi_old -mbi_in only makes reading the patch more cumbersome. If you absolutely feel like you need to rename them, do this in a separate patch. +static multiboot_info_t *mbi2_mbi(void *mbi_in) +{ +module_t *mbi_out_mods; +memory_map_t *mmap_dst; +multiboot2_memory_map_t *mmap_src; +multiboot2_tag_t *tag; +multiboot_info_t *mbi_out; +u32 ptr; +unsigned int i, mod_idx = 0; + +mbi_out = (multiboot_info_t *)alloc_struct(sizeof(*mbi_out)); +zero_struct((u32)mbi_out, sizeof(*mbi_out)); + +/* Skip Multiboot2 information fixed part. */ +tag = mbi_in + sizeof(multiboot2_fixed_t); + +for ( ; ; ) +{ +if ( tag-type == MULTIBOOT2_TAG_TYPE_MODULE ) +++mbi_out-mods_count; +else if ( tag-type == MULTIBOOT2_TAG_TYPE_END ) +{ +mbi_out-flags = MBI_MODULES; +mbi_out-mods_addr = alloc_struct(mbi_out-mods_count * sizeof(module_t)); +mbi_out_mods = (module_t *)mbi_out-mods_addr; +break; +} + +/* Go to next Multiboot2 information tag. */ +tag = (multiboot2_tag_t *)(ALIGN_UP((u32)tag + tag-size, MULTIBOOT2_TAG_ALIGN)); +} Shouldn't you also break out of the loop when mbi_in-total_size gets exceeded? Tag MULTIBOOT2_TAG_TYPE_END is always added as the end marker but we can check also mbi_in-total_size just in case. +#ifndef __ASSEMBLY__ +typedef struct { +u32 total_size; +u32 reserved; +} multiboot2_fixed_t; + +typedef struct { +u32 type; +u32 size; +} multiboot2_tag_t; + +typedef struct { +u32 type; +u32 size; +char string[0]; +} multiboot2_tag_string_t; Are these _tag_ parts of the name really needed? This is not a must but I tried to mimic things in GRUB2 as much as possible. + +typedef struct { +u32 type; +u32 size; +u32 mem_lower; +u32 mem_upper; +} multiboot2_tag_basic_meminfo_t; + +typedef struct __packed { Why __packed when all the others aren't? Ha! This thing was taken from GRUB2 source. I was asking this question myself many times. I have not found real explanation for this but if you wish I can dive into code and try to find one (if it exists). Daniel
Re: [PATCH 17/18] x86/efi: create new early memory allocator
On Mon, Mar 02, 2015 at 05:23:49PM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -103,9 +103,35 @@ static void __init relocate_trampoline(unsigned long phys) *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys 4; } +#define __MALLOC_SIZE 65536 + +static char __malloc_mem[__MALLOC_SIZE]; +static char *__malloc_free = NULL; + +static void __init *__malloc(size_t size) Please do away with all these prefixing underscores. +{ +void *ptr; + +/* + * Init __malloc_free on runtime. Static initialization + * will not work because it puts virtual address there. + */ +if ( __malloc_free == NULL ) +__malloc_free = __malloc_mem; + +ptr = __malloc_free; + +__malloc_free += size; + +if ( __malloc_free - __malloc_mem sizeof(__malloc_mem) ) +blexit(LOut of static memory\r\n); + +return ptr; +} You're ignoring alignment requirements here altogether. I can understand why __malloc_mem should be let's say page aligned but I am not sure why we should care here about alignment inside of __malloc_mem array like... @@ -192,12 +218,7 @@ static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable, static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size) { -place_string(mbi.mem_upper, NULL); -mbi.mem_upper -= *map_size; -mbi.mem_upper = -__alignof__(EFI_MEMORY_DESCRIPTOR); ...here... -if ( mbi.mem_upper xen_phys_start ) -return NULL; -return (void *)(long)mbi.mem_upper; +return __malloc(*map_size); } Which then even suggests that _if_ we go this route, this could be shared with ARM (and hence become common code again). So, go or no go this route? If not what do you suggest? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 16/18] efi: create efi_exit_boot()
On Mon, Mar 02, 2015 at 04:45:47PM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: ..which gets memory map and calls ExitBootServices(). We need this to support multiboot2 protocol on EFI platforms. Patches from 9 up to here all make sense on the basis that patch 18 does and assuming that you really need all this code moved out to separate functions. How much different is efi_multiboot2() introduced in #18 from what is left of efi_start() at this point? I.e. is splitting out More or less efi_multiboot2() does not parse command line and do not load modules itself as efi_start() does. all of this code really needed? I think that it is worth doing. First of all efi_start() is huge and its analysis is very difficult right now. So, splitting code into smaller chunks will improve readability a lot (I am still thinking about extracting command line parser and module loader from efi_start() even if both functions will be used only in efi_start(); this way we will have very simple functions doing one thing easy to understand). Additionally, we create pieces which are very easy to reuse in efi_multiboot2() which is very simple and again easy for analysis. Potentially we can reuse efi_start() in multiboot2 case. However, I prefer to have separate function because this way it is clear that multiboot2 case is different thing then native EFI loader stuff. Additionally, efi_start() is architecture independent and efi_multiboot2() is x86 only and it should live in x86 files. If it is, please don't title all these patches create ... but split out ... or some such - you don't really create the code. Similarly the second sentence above is too imprecise for my taste - we want to re-use this code to support ... would seem more to the point. OK. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 04/18] xen/x86: add multiboot2 protocol support
On Fri, Mar 27, 2015 at 11:20:10AM +, Jan Beulich wrote: On 27.03.15 at 11:56, daniel.ki...@oracle.com wrote: On Fri, Feb 20, 2015 at 04:06:26PM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -1,6 +1,7 @@ obj-bin-y += head.o -RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h +RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/compiler.h \ + $(BASEDIR)/include/xen/multiboot.h $(BASEDIR)/include/xen/multiboot2.h Perhaps we should rather have the compiler generate the dependencies for us when compiling reloc.o? Hmmm... I am a bit confused. Here http://lists.xen.org/archives/html/xen-devel/2014-10/msg02094.html you told a bit different thing and relevant patch was accepted as commit c42070df66c9fcedf477959b8371b85aa4ac4933 (x86/boot: fix reloc.S build dependencies). I can try to do what you suggest, this is not a problem for me, however, I would like to be sure what is your final decision in that case. First of all I wasn't anticipating that this list of dependencies would further grow. And then I didn't say don't do this, I only pointed out (albeit maybe a little too implicitly) that this would be a more complex patch. So, I understand this as Go for it!. +.long MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO +.long MULTIBOOT2_TAG_TYPE_MMAP +.Lmultiboot2_info_req_end: + +.align MULTIBOOT2_TAG_ALIGN +.short MULTIBOOT2_HEADER_TAG_MODULE_ALIGN +.short MULTIBOOT2_HEADER_TAG_REQUIRED +.long 8 /* Tag size. */ ... here and further down you hard-code it. Please be consistent (and if you go the calculation route, perhaps introduce some redundancy reducing macro). I did this deliberately. I calculate size using labels when it is really needed, e.g. in tags which size depends on number of elements. However, most tags have strictly defined sizes. So, that is why I dropped labels and entered simple numbers. Though I agree that it can be improved. I think that we can define relevant tag structures in multiboot2.h and generate relevant constants using asm-offsets.c. Is it OK for you? That would mean exposing stuff to other parts of the tree which doesn't need to be exposed. I don't see why you can't just do proper size calculations here. OK, I will do this as you wish. @@ -81,10 +135,51 @@ __start: mov %ecx,%es mov %ecx,%ss +/* Bootloaders may set multiboot[12].mem_lower to a nonzero value */ Above you meet coding style requirements, but here you stop to do so (ongoing below)? Even if pre-existing neighboring comments aren't well formed, please don't make the situation worse. Do you ask about ending fullstops? Am I right? Yes. @@ -31,7 +38,16 @@ asm ( ); typedef unsigned int u32; +typedef unsigned long long u64; + +#include ../../../include/xen/compiler.h Why? static multiboot_info_t __used *reloc(void *mbi_in, u32 mb_magic) Because of this -- ^^ And what keeps you from leaving out the static, making the __used unnecessary? This func is clearly static. Why do not mark it as is and use __used. What is wrong with that? + +typedef struct { +u32 type; +u32 size; +u32 mem_lower; +u32 mem_upper; +} multiboot2_tag_basic_meminfo_t; + +typedef struct __packed { Why __packed when all the others aren't? Ha! This thing was taken from GRUB2 source. I was asking this question myself many times. I have not found real explanation for this but if you wish I can dive into code and try to find one (if it exists). Or even better just drop the __packed. Should not we be in line with GRUB2 source? Even it sounds strange. Anyway, I will check GRUB2 source and maybe we can also remove __packed from it. This way everything will be OK. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 16/18] efi: create efi_exit_boot()
On Fri, Mar 27, 2015 at 12:10:56PM +, Jan Beulich wrote: On 27.03.15 at 13:00, daniel.ki...@oracle.com wrote: Additionally, efi_start() is architecture independent and efi_multiboot2() is x86 only and it should live in x86 files. Is that really the case? Looking at the grub2 sources I see support for other than x86... Well... In theory multiboot protocol was designed as arch independet. However, docs define more precisely stuff for i386 and MIPS (multiboot2 protocol only). As I know we do not care about MIPS. Additionally, so called muliboot protocol for ARM is completely different thing then multiboot protocols mentioned above (it is a mixture of EFI native loader with DT). So, it looks that from our point of view efi_multiboot2() is x86 only stuff (right now, I am not fortune teller, so, I am not able to tell what happens in the future ;-))) ). Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Tue, Mar 17, 2015 at 10:32:01AM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: @@ -94,6 +111,17 @@ ENTRY(start) gdt_boot_descr: .word 6*8-1 .long sym_phys(trampoline_gdt) +.long 0 /* Needed for 64-bit lgdt */ + +cs32_switch_addr: +.long sym_phys(cs32_switch) +.long BOOT_CS32 + +efi_st: +.quad 0 + +efi_ih: +.quad 0 .Lbad_cpu_msg: .asciz ERR: Not a 64-bit CPU! .Lbad_ldr_msg: .asciz ERR: Not a Multiboot bootloader! @@ -124,6 +152,133 @@ print_err: .Lhalt: hlt jmp .Lhalt +.code64 + +__efi64_start: +cld + +/* Bootloaders may set multiboot[12].mem_lower to a nonzero value */ +xor %edx,%edx + +/* Check for Multiboot2 bootloader */ +cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax +je efi_multiboot2_proto + +jmp not_multiboot + +efi_multiboot2_proto: jne not_multiboot (and efi_multiboot2_proto dropped altogether) +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx Let's please not add more assumptions than necessary about stuff being below 4G. I am not sure what do you mean by that. + +0: +/* Get mem_lower from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_BASIC_MEMINFO,(%ecx) +jne 1f + +mov MB2_mem_lower(%ecx),%edx +jmp 4f + +1: +/* Get EFI SystemTable address from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_EFI64,(%ecx) +jne 2f + +lea MB2_efi64_st(%ecx),%esi +lea efi_st(%rip),%edi +movsq A simple pair of mov-s please, assuming all of this really needs to be done in assembly in the first place. Also please use .Lname labels in this assembly coded switch statement to ease reading. + +/* Do not go into real mode on EFI platform */ +movb$1,skip_realmode(%rip) + +jmp 4f + +2: +/* Get EFI ImageHandle address from Multiboot2 information */ +cmpl$MULTIBOOT2_TAG_TYPE_EFI64_IH,(%ecx) +jne 3f + +lea MB2_efi64_ih(%ecx),%esi +lea efi_ih(%rip),%edi +movsq +jmp 4f + +3: +/* Is it the end of Multiboot2 information? */ +cmpl$MULTIBOOT2_TAG_TYPE_END,(%ecx) +je run_bs + +4: Please switch the order so that 2 can fall through into 4 (and you then won't need the run_bs label, which otherwise should also becom .Lrun_bs). +/* Go to next Multiboot2 information tag */ +add MB2_tag_size(%ecx),%ecx +add $(MULTIBOOT2_TAG_ALIGN-1),%ecx +and $~(MULTIBOOT2_TAG_ALIGN-1),%ecx +jmp 0b + +run_bs: +push%rax +push%rdx + +/* Initialize BSS (no nasty surprises!) */ +lea __bss_start(%rip),%rdi +lea _end(%rip),%rcx +sub %rdi,%rcx +xor %rax,%rax +rep stosb rep stosb + +mov efi_ih(%rip),%rdi /* EFI ImageHandle */ +mov efi_st(%rip),%rsi /* EFI SystemTable */ +callefi_multiboot2 With efi_multiboot2 being a C function it really looks like much of the above doesn't need to be done in assembly. Potentially make sense. I will try to do that. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 05/18] efi: split efi_enabled to efi_platform and efi_loader
On Fri, Feb 20, 2015 at 04:17:35PM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: We need more fine grained knowledge about EFI environment and check for EFI platform and EFI loader separately to properly support multiboot2 protocol. ... because of ... (i.e. I can't see from the description what the separation is good for). Looking at the comments you placed aside the variables doesn't help me either. In general Xen loaded by this protocol uses memory mappings and loaded modules in simliar way to Xen loaded by multiboot (v1) protocol. Hence, split efi_enabled to efi_platform and efi_loader. And if I'm guessing things right, then introducing efi_loader but leaving efi_enabled alone (only converting where needed) would efi_enabled is not fortunate name for new usage. Currently it means that Xen binary have or does not have EFI support build in. However, if we build in multiboot2 protocol into xen.gz then it means that it can ran on legacy BIOS or EFI platform. So, I think that we should rename efi_enabled to efi_platform because it will mean that Xen runs on EFI platform or not. efi_loader is used to differentiate between EFI native loader and multiboot2 protocol. seem the right approach. [...] --- a/xen/include/xen/efi.h +++ b/xen/include/xen/efi.h @@ -5,7 +5,11 @@ #include xen/types.h #endif -extern const bool_t efi_enabled; +/* If true then Xen runs on EFI platform. */ +extern bool_t efi_platform; + +/* If true then Xen was loaded by native EFI loader as PE application. */ +extern bool_t efi_loader; I don't see why you're losing the constness. Both of them could be set during runtime. Please look above for more details. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 17/18] x86/efi: create new early memory allocator
On Fri, Mar 27, 2015 at 01:35:11PM +, Jan Beulich wrote: On 27.03.15 at 13:57, daniel.ki...@oracle.com wrote: On Mon, Mar 02, 2015 at 05:23:49PM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: +{ +void *ptr; + +/* + * Init __malloc_free on runtime. Static initialization + * will not work because it puts virtual address there. + */ +if ( __malloc_free == NULL ) +__malloc_free = __malloc_mem; + +ptr = __malloc_free; + +__malloc_free += size; + +if ( __malloc_free - __malloc_mem sizeof(__malloc_mem) ) +blexit(LOut of static memory\r\n); + +return ptr; +} You're ignoring alignment requirements here altogether. I can understand why __malloc_mem should be let's say page aligned but I am not sure why we should care here about alignment inside of __malloc_mem array like... @@ -192,12 +218,7 @@ static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable, static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size) { -place_string(mbi.mem_upper, NULL); -mbi.mem_upper -= *map_size; -mbi.mem_upper = -__alignof__(EFI_MEMORY_DESCRIPTOR); ...here... Specifically with the later mentioned potential for sharing this with ARM I think you have to make sure that things are suitably aligned, or else you cause aborts. -if ( mbi.mem_upper xen_phys_start ) -return NULL; -return (void *)(long)mbi.mem_upper; +return __malloc(*map_size); } Which then even suggests that _if_ we go this route, this could be shared with ARM (and hence become common code again). So, go or no go this route? As long as it's being done properly, I'm not wildly opposed. So, AIUI, general idea is OK but fix all stuff which should be fixed. Right? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Fri, Mar 27, 2015 at 01:36:32PM +, Jan Beulich wrote: On 27.03.15 at 14:06, daniel.ki...@oracle.com wrote: On Tue, Mar 17, 2015 at 10:32:01AM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx Let's please not add more assumptions than necessary about stuff being below 4G. I am not sure what do you mean by that. See the 32-bit register used for addressing here (and in many more places)? This is what I expected but I was confused because you were referring only here to this problem. Anyway, is it possible to do this in different way? Should we care if image is always loaded at 0x10 right now? Even with Xen early boot code being relocatable loader could not load image higher than 0x - 14 MiB. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Fri, Mar 27, 2015 at 02:34:19PM +, Jan Beulich wrote: On 27.03.15 at 15:26, daniel.ki...@oracle.com wrote: On Fri, Mar 27, 2015 at 01:36:32PM +, Jan Beulich wrote: On 27.03.15 at 14:06, daniel.ki...@oracle.com wrote: On Tue, Mar 17, 2015 at 10:32:01AM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx Let's please not add more assumptions than necessary about stuff being below 4G. I am not sure what do you mean by that. See the 32-bit register used for addressing here (and in many more places)? This is what I expected but I was confused because you were referring only here to this problem. Anyway, is it possible to do this in different way? Should we care if image is always loaded at 0x10 right now? Even with Xen early boot code being relocatable loader could not load image higher than 0x - 14 MiB. I don't understand what you're alluding to. Just use 64-bit registers for memory accesses and LEAs, and be done. This will result in smaller code as a benefit. Well... How can I do that here if processor is in 32-bit mode? Maybe, we could that things after switching to 64-bit mode. However, I think this requires separate patch to do these changes. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 18/18] x86: add multiboot2 protocol support for EFI platforms
On Fri, Mar 27, 2015 at 03:06:43PM +, Jan Beulich wrote: On 27.03.15 at 15:57, daniel.ki...@oracle.com wrote: On Fri, Mar 27, 2015 at 02:34:19PM +, Jan Beulich wrote: On 27.03.15 at 15:26, daniel.ki...@oracle.com wrote: On Fri, Mar 27, 2015 at 01:36:32PM +, Jan Beulich wrote: On 27.03.15 at 14:06, daniel.ki...@oracle.com wrote: On Tue, Mar 17, 2015 at 10:32:01AM +, Jan Beulich wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: +/* Skip Multiboot2 information fixed part */ +lea MB2_fixed_sizeof(%ebx),%ecx Let's please not add more assumptions than necessary about stuff being below 4G. I am not sure what do you mean by that. See the 32-bit register used for addressing here (and in many more places)? This is what I expected but I was confused because you were referring only here to this problem. Anyway, is it possible to do this in different way? Should we care if image is always loaded at 0x10 right now? Even with Xen early boot code being relocatable loader could not load image higher than 0x - 14 MiB. I don't understand what you're alluding to. Just use 64-bit registers for memory accesses and LEAs, and be done. This will result in smaller code as a benefit. Well... How can I do that here if processor is in 32-bit mode? Maybe, we could that things after switching to 64-bit mode. However, I think this requires separate patch to do these changes. No, if the processor is in 32-bit mode, then using 32-bit registers is fine of course. But I'm pretty certain I spotted at least some cases where it looked like you used 32-bit registers in 64-bit mode. OK, I will double check. If I find something then I will fix it. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 00/18] x86: multiboot2 protocol support
On Tue, Mar 03, 2015 at 12:10:35PM +, Ian Campbell wrote: On Fri, 2015-01-30 at 18:54 +0100, Daniel Kiper wrote: xen/arch/x86/Makefile | 17 ++-- xen/arch/x86/boot/Makefile|3 +- xen/arch/x86/boot/head.S | 291 ++ xen/arch/x86/boot/reloc.c | 219 ++--- xen/arch/x86/dmi_scan.c |4 +- xen/arch/x86/domain_page.c|2 +- xen/arch/x86/e820.c | 29 ++ xen/arch/x86/efi/Makefile | 12 +-- xen/arch/x86/efi/efi-boot.h | 66 +++-- xen/arch/x86/efi/stub.c | 41 xen/arch/x86/mpparse.c|4 +- xen/arch/x86/setup.c | 30 +++--- xen/arch/x86/shutdown.c |3 +- xen/arch/x86/time.c |2 +- xen/arch/x86/x86_64/asm-offsets.c |8 ++ xen/arch/x86/xen.lds.S|2 - xen/common/efi/boot.c | 441 +- xen/common/efi/runtime.c | 11 ++- xen/drivers/acpi/osl.c|2 +- xen/include/xen/efi.h |6 +- xen/include/xen/multiboot2.h | 169 21 files changed, 1018 insertions(+), 344 deletions(-) From the diffstat I'm not sure: is there any ARM impact I should worry about reviewing? Any patches in particular my feedback is needed on? There are not any functional changes in ARM here. There are some small changes which are needed to make new x86 stuff coexist with ARM. Additionally, I thought that you are still interested in x86 things. Am I right? If you do not have a time right now ignore this patch series. New thing will appear in 3-4 weeks. Or if you completely not interested in that stuff just drop me a line and I will drop you from distribution list. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 00/18] x86: multiboot2 protocol support
On Tue, Mar 03, 2015 at 12:39:45PM +, Ian Campbell wrote: On Tue, 2015-03-03 at 13:36 +0100, Daniel Kiper wrote: On Tue, Mar 03, 2015 at 12:10:35PM +, Ian Campbell wrote: On Fri, 2015-01-30 at 18:54 +0100, Daniel Kiper wrote: xen/arch/x86/Makefile | 17 ++-- xen/arch/x86/boot/Makefile|3 +- xen/arch/x86/boot/head.S | 291 ++ xen/arch/x86/boot/reloc.c | 219 ++--- xen/arch/x86/dmi_scan.c |4 +- xen/arch/x86/domain_page.c|2 +- xen/arch/x86/e820.c | 29 ++ xen/arch/x86/efi/Makefile | 12 +-- xen/arch/x86/efi/efi-boot.h | 66 +++-- xen/arch/x86/efi/stub.c | 41 xen/arch/x86/mpparse.c|4 +- xen/arch/x86/setup.c | 30 +++--- xen/arch/x86/shutdown.c |3 +- xen/arch/x86/time.c |2 +- xen/arch/x86/x86_64/asm-offsets.c |8 ++ xen/arch/x86/xen.lds.S|2 - xen/common/efi/boot.c | 441 +- xen/common/efi/runtime.c | 11 ++- xen/drivers/acpi/osl.c|2 +- xen/include/xen/efi.h |6 +- xen/include/xen/multiboot2.h | 169 21 files changed, 1018 insertions(+), 344 deletions(-) From the diffstat I'm not sure: is there any ARM impact I should worry about reviewing? Any patches in particular my feedback is needed on? There are not any functional changes in ARM here. There are some small changes which are needed to make new x86 stuff coexist with ARM. Additionally, I thought that you are still interested in x86 things. Not totally disinterested in x86 things, but not especially interested in x86/EFI/multiboot unless I have to be. Roger. Am I right? If you do not have a time right now ignore this patch series. New thing will appear in 3-4 weeks. OK, thanks. Or if you completely not interested in that stuff just drop me a line and I will drop you from distribution list. If you could just CC me on the bits which impact ARM (or generic code) that would be ok, but otherwise I can cope with ignoring irrelevant parts of a series. Wilco. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 17/18] x86/efi: create new early memory allocator
On Tue, Mar 03, 2015 at 08:04:09AM +, Jan Beulich wrote: On 02.03.15 at 21:25, roy.fr...@linaro.org wrote: On Mon, Mar 2, 2015 at 9:23 AM, Jan Beulich jbeul...@suse.com wrote: On 30.01.15 at 18:54, daniel.ki...@oracle.com wrote: @@ -192,12 +218,7 @@ static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable, static void *__init efi_arch_allocate_mmap_buffer(UINTN *map_size) { -place_string(mbi.mem_upper, NULL); -mbi.mem_upper -= *map_size; -mbi.mem_upper = -__alignof__(EFI_MEMORY_DESCRIPTOR); -if ( mbi.mem_upper xen_phys_start ) -return NULL; -return (void *)(long)mbi.mem_upper; +return __malloc(*map_size); } Which then even suggests that _if_ we go this route, this could be shared with ARM (and hence become common code again). We could do the same thing on ARM. For ARM, 2 allocations are done: 1 for the FDT, and this one for the EFI memory map. Both of these are currently allocated with EFI allocation functions, so don't have fixed size limits. If we go with the fixed size pool, I don't think that 64k will be enough for the ARM case, as FDTs can be 20-50k in size. The 64k size here is to be debated anyway I think. We currently have about 1Mb in the x86 variant, and I'd much rather see the pool be this size initially, properly taking care of releasing to the allocator any unused portions of it. Thanks for your comments guys. I will reply for all of them probably next week. Now I am busy with bugs in GRUB2. Please stay tuned. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 3/5] i386/relocator: Remove unused avoid_efi_bootservices argument
Hey, Sorry for late reply but I was busy with our internal EFI stuff. We did more tests and some fixes and it seems that everything is going in right direction. Well, I hope... :-))) Right now I am going to continue my work on upstream EFI + GRUB2 + Xen stuff. I think that I will be able to release new patch series for GRUB2 and Xen in second or third week of June (next week we have 2 days holiday in Poland). Stay tuned... On Thu, May 07, 2015 at 06:04:21PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote: Not unused: grub_efi_mmap_iterate (grub_relocator_alloc_chunk_align_iter, ctx, avoid_efi_boot_services); In general I have a problem with avoid_efi_boot_services stuff in GRUB2. By default it is disabled and GRUB2 assumes that boot services (BS) memory regions (code and data) are free. This means that it may put there loaded image and/or fills memory maps (MULTIBOOT_TAG_TYPE_BASIC_MEMINFO, MULTIBOOT_TAG_TYPE_MMAP) with above mentioned regions marked as free. This is OK when BS are disabled before loaded image exaction. However, we introduced new feature like MULTIBOOT_TAG_TYPE_EFI_BS (I am going to improve/extend it) and this makes this behavior more problematic. It means that now GRUB2 with MULTIBOOT_TAG_TYPE_EFI_BS enabled may overwrite BS regions and/or memory maps are bogus. In turn, this means that BS are potentially unusable by loaded image which asked for BS with above mentioned tag. So, I think that we should find a solution for that issues. The simplest fix for that problem seems total removal of avoid_efi_boot_services and assumption that BS memory regions are not free. I did some tests with that but not so many and not so deep. I discovered that at least linux loader (IIRC) has some issues with this solution. Maybe it could be fixed easily but I did not investigated this issue so long. Additionally, I realized that boot services regions are quite big (dozens or even about 100 MiB) and maybe this is not very nice idea to assume them used in all cases. So, maybe we should just focus on multiboot2 loader only. In that case GRUB2 should at first assume that BS regions are used. Then it should check image header. If it does not contain MULTIBOOT_TAG_TYPE_EFI_BS tag then starting from that point it should assume that BS regions are free and behave as it behaves right now. However, if multiboot2 loader encounters MULTIBOOT_TAG_TYPE_EFI_BS tag then it should still assume that BS regions are not free. Additionally, GRUB2 should not pass any memory map info (i.e, MULTIBOOT_TAG_TYPE_BASIC_MEMINFO, MULTIBOOT_TAG_TYPE_MMAP, MULTIBOOT_TAG_TYPE_EFI_MMAP, etc.) because they are bogus. In that case loaded image should take memory map itself using relevant BS calls. Does it make sense? Another questions is why grub_relocator_alloc_chunk_addr() does not consult EFI memory map if grub_relocator_alloc_chunk_align() does. Should not we fix it? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 05/23] x86/boot/reloc: create generic alloc and copy functions
On Mon, Aug 17, 2015 at 09:51:58AM -0600, Jan Beulich wrote: On 20.07.15 at 16:29, daniel.ki...@oracle.com wrote: Create generic alloc and copy functions. We need separate tools for memory allocation and copy to provide multiboot2 protocol support. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com Reviewed-by: Andrew Cooper andrew.coop...@citrix.com --- v2 - suggestions/fixes: - generalize new functions names (suggested by Jan Beulich), - reduce number of casts (suggested by Jan Beulich). This contradicts retaining Andrew's R-b tag. Please remember to drop tags for everything you make non-trivial changes to. OK. @@ -55,50 +56,64 @@ static void *reloc_mbi_struct(void *old, unsigned int bytes) sub %1,%0 \n and $~15,%0 \n mov %0,alloc-1b(%%edx) \n -mov %0,%%edi\n -rep movsb \n - : =r (new), +c (bytes), +S (old) - : : edx, edi, memory); -return new; + : =r (s) : r (bytes) : edx, memory); Can't bytes use a simple g constraint now? Works... Preferably (i.e. if correct) this changed ..., so, I will change that. Acked-by: Jan Beulich jbeul...@suse.com Thanks! Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 08/23] x86: add multiboot2 protocol support
On Tue, Aug 18, 2015 at 02:12:58AM -0600, Jan Beulich wrote: On 20.07.15 at 16:29, daniel.ki...@oracle.com wrote: [...] @@ -119,10 +213,11 @@ __start: /* Save the Multiboot info struct (after relocation) for later use. */ mov $sym_phys(cpu0_stack)+1024,%esp +push%eax/* Multiboot magic. */ push%ebx/* Multiboot information address. */ push%ecx/* Boot trampoline address. */ callreloc -add $8,%esp /* Remove reloc() args from stack. */ +add $12,%esp/* Remove reloc() args from stack. */ The latest now it becomes clear that the arguments passed are kind of backwards: One would expect the qualifying value (i.e. the magic) to come first, then the info pointer, and last the trampoline address. Yep, you are right. However, I wanted to avoid changing order of arguments to not confuse reader. If you wish I can change that thing. [...] +case MULTIBOOT2_TAG_TYPE_MMAP: +mbi_out-flags |= MBI_MEMMAP; +mbi_out-mmap_length = get_mb2_data(tag, multiboot2_tag_mmap_t, size); +mbi_out-mmap_length -= sizeof(multiboot2_tag_mmap_t); +mbi_out-mmap_length += sizeof(((multiboot2_tag_mmap_t){0}).entries); Afaict this sizeof() evaluates to zero. And even if it didn't I can't see what the line is good for. Right, I have missed that. However, if it does not evaluate to zero then you must add back relevant number of entries which you subtracted one line above. Otherwise count of entries will be incorrect. [...] Dropping the static would permit to also drop the used attribute. Since it was that way before, why didn't you keep it that way? Yep, but I do not like this solution. Lack of static suggests that this function is used elsewhere. I prefer to explicitly say that there are not external users of that function and silence compiler warnings with __used. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 6/6] multiboot2: Do not pass memory maps to image if EFI boot services are enabled
On Tue, Aug 11, 2015 at 02:59:56PM -0400, Konrad Rzeszutek Wilk wrote: On Mon, Jul 20, 2015 at 04:35:54PM +0200, Daniel Kiper wrote: Do not pass memory maps to image if it asked for EFI boot services. Maps are usually invalid in that case and they can confuse potential user. Image should get memory map itself just before ExitBootServices() call. Can we point to some commits in Linux or Xen in which these situations arose? Wait, I think there even was one commit in grub. Aha: ommit e75fdee420a7ad95e9a465c9699adc2e2e970440 Author: Vladimir 'phcoder' Serbinenko phco...@gmail.com Date: Tue Mar 26 11:34:56 2013 +0100 * grub-core/kern/efi/mm.c (grub_efi_finish_boot_services): Try terminating EFI services several times due to quirks in some implementations. Otherwise: Reviewed-by: Konrad Rzeszutek Wilk konrad.w...@oracle.com Nope, this is a bit different problem. In general GRUB2 assumes that EFI boot services memory regions are free and specify them as such in relevant maps. However, this is not true if you jump into loaded image with EFI boot services enabled. So, we should not expose this maps to the user when he/she asked for access to EFI boot services. This is not very big issue for him/her because he/she can get memory map from EFI just before ExitBootServices() call. This way they will have latest valid memory map. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 09/23] efi: create efi_enabled()
On Thu, Aug 20, 2015 at 09:18:17AM -0600, Jan Beulich wrote: On 20.07.15 at 16:29, daniel.ki...@oracle.com wrote: --- a/xen/arch/x86/efi/stub.c +++ b/xen/arch/x86/efi/stub.c @@ -4,9 +4,14 @@ #include xen/lib.h #include asm/page.h -#ifndef efi_enabled -const bool_t efi_enabled = 0; -#endif +struct efi __read_mostly efi = { + .flags = 0, /* Initialized later. */ + .acpi= EFI_INVALID_TABLE_ADDR, + .acpi20 = EFI_INVALID_TABLE_ADDR, + .mps = EFI_INVALID_TABLE_ADDR, + .smbios = EFI_INVALID_TABLE_ADDR, + .smbios3 = EFI_INVALID_TABLE_ADDR +}; How is this change related to the subject of the patch? I need to add this struct because... --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -191,8 +191,6 @@ SECTIONS .pad : { . = ALIGN(MB(16)); } :text -#else - efi = .; #endif Same here. ...this creates efi symbol to just satisfy linker and I am removing it. However, existing solution does not allocate space for this symbol and any references to acpi20, etc. does not make sense. As I saw any efi.* references are protected by relevant ifs but we should not do that because it makes code very fragile. If somebody does not know how efi symbol is created he/she may assume that it always represent valid structure and do invalid references somewhere. So, I still think that stub.c should define efi struct properly even if we assume that flags should not be there. However, I agree that this could be separate patch. By the way why did you choose so strange way to satisfy liker needs? --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -717,6 +717,10 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) char *option_str; bool_t use_cfg_file; +#ifndef CONFIG_ARM /* Disabled until runtime services implemented. */ +set_bit(EFI_PLATFORM, efi.flags); +#endif Just for this to work? I don't see the need for all the pointers in the stub case - why can't this be a separate variable? We don't Could be but if we create struct with so generic name like just simple efi it suggest that this is good place to put flags there. If it is not how to call it? efi_flags? Or maybe we should rename efi to efi_tables too. Then everything will be clear. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 10/23] efi: build xen.gz with EFI code
On Thu, Aug 20, 2015 at 09:39:39AM -0600, Jan Beulich wrote: On 20.07.15 at 16:29, daniel.ki...@oracle.com wrote: Build xen.gz with EFI code. We need this to support multiboot2 protocol on EFI platforms. If we wish to load not ELF file using multiboot (v1) or multiboot2 then DYM a non-ELF file? it must contain linear (or flat) representation of code and data. Why? Please don't just put out statements, but also reasons (i.e. at least which component is unable to deal with the current [valid afaict] PE image we have). This is a requirement of multiboot (v1) or multiboot2 protocol. They both know nothing about PE image format. Currently, PE file contains many sections which are not linear (one after another without any holes) or even do not have representation in a file (e.g. BSS). In theory there is a chance that we could build proper PE file using current build system. However, it means that What is improper about the currently built PE file? And if there is anything improper, did you inform the binutils maintainers of the problem? From PE loader point of view everything is OK. However, current Xen PE image (at least build on my machines) is not usable by multiboot (v1) or multiboot2 protocol compatible loader because it is not linear (one section does not live immediately after another without any voids). Potentially we can change that (probably by playing with linker script or using objcopy or just simply building proper PE file ourselves; I did some experiments once but they are not exhaustive and I am not able to tell which solution will be the best in our case), however, this is next step and it will be investigated after applying this patch series to Xen source. --- a/xen/arch/x86/efi/Makefile +++ b/xen/arch/x86/efi/Makefile @@ -1,14 +1,16 @@ CFLAGS += -fshort-wchar -obj-y += stub.o - -create = test -e $(1) || touch -t 19990101 $(1) - efi := $(filter y,$(x86_64)$(shell rm -f disabled)) efi := $(if $(efi),$(shell $(CC) $(filter-out $(CFLAGS-y) .%.d,$(CFLAGS)) -c check.c 2disabled echo y)) efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 2disabled echo y)) -efi := $(if $(efi),$(shell rm disabled)y,$(shell $(call create,boot.init.o); $(call create,runtime.o))) +efi := $(if $(efi),$(shell rm disabled)y) -extra-$(efi) += boot.init.o relocs-dummy.o runtime.o compat.o +extra-y += relocs-dummy.o Why is this no longer extra-$(efi)? Because we need proper EFI code in xen.gz to support boot via multiboot2 on EFI platforms. -stub.o: $(extra-y) With this dependency removed (instead of perhaps replaced or extended) - what will trigger relocs-dummy.o to be (re)built? It is triggered by prelink.o build rule in xen/arch/x86/Makefile. Looks that it will suffice but I am not sure right now this is good solution. Hmmm... If it is OK then we can remove extra-y += relocs-dummy.o. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 0/6] multiboot2: Add two extensions and fix some issues
Guys, especially GRUB2 maintainers, On Mon, Jul 20, 2015 at 04:35:48PM +0200, Daniel Kiper wrote: Hi, This patch series: - enables EFI boot services usage in loaded images by multiboot2 protocol, - add support for multiboot2 protocol compatible relocatable images, - fixes two minor issues. Is it possible to get your comments to this patch series (I would like to thank you Andrei and Konrad for review)? We need this functionality as Xen community and as Oracle. Hence, it will be nice to know that we go in good direction. So, if you think that we should change something please drop me a line. I know that you are busy but please, at least, tell us when you take a look at it. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [Xen-devel] [PATCH v2 08/23] x86: add multiboot2 protocol support
On Mon, Aug 10, 2015 at 03:17:48PM -0400, Konrad Rzeszutek Wilk wrote: On Mon, Jul 20, 2015 at 04:29:03PM +0200, Daniel Kiper wrote: Add multiboot2 protocol support. Alter min memory limit handling as we now may not find it from either multiboot (v1) or multiboot2. This way we are laying the foundation for EFI + GRUB2 + Xen development. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com Reviewed-by: Andrew Cooper andrew.coop...@citrix.com --- v2 - suggestions/fixes: - generate multiboot2 header using macros (suggested by Jan Beulich), - improve comments (suggested by Jan Beulich), - simplify assembly in xen/arch/x86/boot/head.S (suggested by Jan Beulich), - do not include include/xen/compiler.h in xen/arch/x86/boot/reloc.c (suggested by Jan Beulich), - do not read data beyond the end of Multiboot2 information (suggested by Jan Beulich). v2 - not fixed yet: You have two 'v2' Yep, but it says not fixed in v2. - dynamic dependency generation for xen/arch/x86/boot/reloc.S; this requires more work; I am not sure that it pays because potential patch requires more changes than addition of just multiboot2.h to Makefile (suggested by Jan Beulich), - isolated/stray __packed attribute usage for multiboot2_memory_map_t (suggested by Jan Beulich). --- xen/arch/x86/boot/Makefile|3 +- xen/arch/x86/boot/head.S | 105 +-- xen/arch/x86/boot/reloc.c | 146 +++- xen/arch/x86/x86_64/asm-offsets.c |7 ++ xen/include/xen/multiboot2.h | 169 + 5 files changed, 420 insertions(+), 10 deletions(-) create mode 100644 xen/include/xen/multiboot2.h diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index 5fdb5ae..06893d8 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -1,6 +1,7 @@ obj-bin-y += head.o -RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h +RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h \ +$(BASEDIR)/include/xen/multiboot2.h head.o: reloc.S diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 77e7da9..57197db 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -1,5 +1,6 @@ #include xen/config.h #include xen/multiboot.h +#include xen/multiboot2.h #include public/xen.h #include asm/asm_defns.h #include asm/desc.h @@ -19,6 +20,28 @@ #define BOOT_PSEUDORM_CS 0x0020 #define BOOT_PSEUDORM_DS 0x0028 +#define MB2_HT(name) (MULTIBOOT2_HEADER_TAG_##name) +#define MB2_TT(name) (MULTIBOOT2_TAG_TYPE_##name) + +.macro mb2ht_args arg, args:vararg +.long \arg +.ifnb \args +mb2ht_args \args +.endif +.endm + +.macro mb2ht_init type, req, args:vararg +.align MULTIBOOT2_TAG_ALIGN +0: +.short \type +.short \req +.long 1f - 0b +.ifnb \args +mb2ht_args \args +.endif +1: +.endm + ENTRY(start) jmp __start @@ -34,6 +57,42 @@ multiboot1_header_start: /*** MULTIBOOT1 HEADER / .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) multiboot1_header_end: +/*** MULTIBOOT2 HEADER / +/* Some ideas are taken from grub-2.00/grub-core/tests/boot/kernel-i386.S file. */ +.align MULTIBOOT2_HEADER_ALIGN + +.Lmultiboot2_header: How come you use .L? It makes this hidden while the multiboot1 headers are visible? Makes it a bit harder to see the contents of this under an debugger. Good point. IIRC, Jan asked about that. I will remove .L if he does not object. +/* Magic number indicating a Multiboot2 header. */ +.long MULTIBOOT2_HEADER_MAGIC +/* Architecture: i386. */ +.long MULTIBOOT2_ARCHITECTURE_I386 +/* Multiboot2 header length. */ +.long .Lmultiboot2_header_end - .Lmultiboot2_header +/* Multiboot2 header checksum. */ +.long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 + \ +(.Lmultiboot2_header_end - .Lmultiboot2_header)) + +/* Multiboot2 information request tag. */ +mb2ht_init MB2_HT(INFORMATION_REQUEST), MB2_HT(REQUIRED), \ + MB2_TT(BASIC_MEMINFO), MB2_TT(MMAP) + +/* Align modules at page boundry. */ +mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED) + +/* Console flags tag. */ +mb2ht_init MB2_HT(CONSOLE_FLAGS), MB2_HT(OPTIONAL), \ + MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED + +/* Framebuffer tag. */ +mb2ht_init MB2_HT
Re: [Xen-devel] [PATCH v2 22/23] x86: make Xen early boot code relocatable
On Tue, Aug 11, 2015 at 12:48:06PM -0400, Konrad Rzeszutek Wilk wrote: On Mon, Jul 20, 2015 at 04:29:17PM +0200, Daniel Kiper wrote: Every multiboot protocol (regardless of version) compatible image must specify its load address (in ELF or multiboot header). Multiboot protocol compatible loader have to load image at specified address. However, there is no guarantee that the requested memory region (in case of Xen it starts at 1 MiB and ends at 17 MiB) where image should be loaded initially is a RAM and it is free (legacy BIOS platforms are merciful for Xen but I found at least one EFI platform on which Xen load address conflicts with EFI boot services; it is Dell PowerEdge R820 with latest firmware). To cope with that problem we must make Xen early boot code relocatable. This patch does that. However, it does not add multiboot2 protocol interface which is done in next patch. s/next patch/x86: add multiboot2 protocol support for relocatable image. This patch changes following things: - default load address is changed from 1 MiB to 2 MiB; I did that because initial page tables are using 2 MiB huge pages and this way required updates for them are quite easy; it means that e.g. we avoid spacial cases for beginning and end of required memory region if it live at address not aligned to 2 MiB, - %ebp register is used as a storage for Xen image base address; this way we can get this value very quickly if it is needed; however, %ebp register is not used directly to access a given memory region, - %fs register is filled with segment descriptor which describes memory region with Xen image (it could be relocated or not); it is used to access some of 'memory region with Xen image' ? Not sure I follow? Perhaps: segment descriptor which starts (0) at Xen image base (_start). Xen data in early boot code; potentially we can use above mentioned segment descriptor to access data using %ds:%esi and/or %es:%esi (e.g. movs*); however, I think that it could unnecessarily obfuscate code (e.g. we need at least to operations to reload a given segment descriptor) and current solution s/to/two/ ? looks quite optimal. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com [...] diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 3f1054d..d484f68 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S [...] trampoline_bios_setup: +mov %ebp,%esi + +/* Initialise GDT and basic data segments. */ +add %ebp,sym_offset(gdt_boot_descr_addr)(%esi) +lgdtsym_offset(gdt_boot_descr)(%esi) + +mov $BOOT_DS,%ecx +mov %ecx,%ds +mov %ecx,%es +mov %ecx,%fs +mov %ecx,%gs +mov %ecx,%ss + The non-EFI boot path is now: start \- __start \- multiboot2_proto |jmp trampoline_bios_setup | \-and if not MB2: jmp trampoline_bios_setup. In here you tweak the GDT and reload the %ds - but during this call chain we do touch the %ds - via: __start+27:testb $0x1,(%rbx) __start+30:cmovne 0x4(%rbx),%edx which is OK (as MB1 says that the %ds has to cover up to 4GB). But I wonder why the __start code had the segments reloaded so early? Was the bootloader not setting the proper segments? This is very good question. I was asking myself about that thing at least once. Sadly, I cannot find real explanation. Let me double-check what SYSLINUX's mboot.c32 does. Perhaps it had done something odd in the past. Good idea! /* Set up trampoline segment 64k below EBDA */ movzwl 0x40e,%ecx /* EBDA segment */ cmp $0xa000,%ecx/* sanity check (high) */ @@ -340,33 +357,58 @@ trampoline_bios_setup: cmovb %edx,%ecx /* and use the smaller */ trampoline_setup: Would it make sense to add: /* Gets called from EFI (from x86_32_switch) and legacy (see above) boot loaders. */ +mov %ebp,%esi + +/* Initialize 0-15 bits of BOOT_FS segment descriptor base address. */ +mov %ebp,%edx +shl $16,%edx +or %edx,(sym_offset(trampoline_gdt)+BOOT_FS)(%esi) + +/* Initialize 16-23 bits of BOOT_FS segment descriptor base address. */ +mov %ebp,%edx +shr $16,%edx +and $0x00ff,%edx +or %edx,(sym_offset(trampoline_gdt)+BOOT_FS+4)(%esi) + +/* Initialize 24-31 bits of BOOT_FS segment descriptor base address. */ +mov %ebp,%edx +and $0xff00,%edx +or %edx,(sym_offset(trampoline_gdt)+BOOT_FS+4)(%esi) + +/* Initialize %fs and later use it to access Xen data if possible. */ +mov $BOOT_FS,%edx +mov
Re: [Xen-devel] [PATCH v2 22/23] x86: make Xen early boot code relocatable
On Fri, Aug 14, 2015 at 06:49:18AM -0600, Jan Beulich wrote: On 14.08.15 at 13:52, daniel.ki...@oracle.com wrote: On Tue, Aug 11, 2015 at 12:48:06PM -0400, Konrad Rzeszutek Wilk wrote: On Mon, Jul 20, 2015 at 04:29:17PM +0200, Daniel Kiper wrote: diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 87b3341..27481ac 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -283,7 +283,7 @@ extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES]; extern l2_pgentry_t *compat_idle_pg_table_l2; extern unsigned int m2p_compat_vstart; extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES], -l2_bootmap[L2_PAGETABLE_ENTRIES]; +l2_bootmap[4*L2_PAGETABLE_ENTRIES]; ? Why do we need to expand this to be 16kB? TBH, we need 8 KiB in the worst case. The worst case is when next GiB starts (e.g. 1 GiB ends and 2 GiB starts) in the middle of Xen image. In this situation we must hook up lower l2_bootmap table with lower l3_bootmap entry, higher l2_bootmap table with higher l3_bootmap entry and finally fill l2_bootmap relevant tables in proper way. Sadly, this method requires more calculations. To avoid that I have added 3 l2_bootmap tables and simply hook up one after another with relevant l3_bootmap entries. However, if you wish we can reduce number of l2_bootmap tables to two. This way code will be more complicated but we will save about 8 KiB. Wouldn't it be better (simpler) to enforce, say, 16Mb alignment in the PE32+ header (which the EFI loader would then honor)? Good idea but then we must enforce this for multiboot protocol (v1 and v2) too. multiboot2 with my patches supports that solution. However, multiboot (v1) could be a bit problematic because it means that we must set load address to 16 MiB. Are we sure that this region is available on all machines like region starting at 1 MiB? Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [Xen-devel] [PATCH v2 22/23] x86: make Xen early boot code relocatable
On Fri, Aug 14, 2015 at 08:32:05AM -0600, Jan Beulich wrote: On 14.08.15 at 15:59, daniel.ki...@oracle.com wrote: On Fri, Aug 14, 2015 at 06:49:18AM -0600, Jan Beulich wrote: On 14.08.15 at 13:52, daniel.ki...@oracle.com wrote: On Tue, Aug 11, 2015 at 12:48:06PM -0400, Konrad Rzeszutek Wilk wrote: On Mon, Jul 20, 2015 at 04:29:17PM +0200, Daniel Kiper wrote: diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 87b3341..27481ac 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -283,7 +283,7 @@ extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES]; extern l2_pgentry_t *compat_idle_pg_table_l2; extern unsigned int m2p_compat_vstart; extern l2_pgentry_t l2_xenmap[L2_PAGETABLE_ENTRIES], -l2_bootmap[L2_PAGETABLE_ENTRIES]; +l2_bootmap[4*L2_PAGETABLE_ENTRIES]; ? Why do we need to expand this to be 16kB? TBH, we need 8 KiB in the worst case. The worst case is when next GiB starts (e.g. 1 GiB ends and 2 GiB starts) in the middle of Xen image. In this situation we must hook up lower l2_bootmap table with lower l3_bootmap entry, higher l2_bootmap table with higher l3_bootmap entry and finally fill l2_bootmap relevant tables in proper way. Sadly, this method requires more calculations. To avoid that I have added 3 l2_bootmap tables and simply hook up one after another with relevant l3_bootmap entries. However, if you wish we can reduce number of l2_bootmap tables to two. This way code will be more complicated but we will save about 8 KiB. Wouldn't it be better (simpler) to enforce, say, 16Mb alignment in the PE32+ header (which the EFI loader would then honor)? Good idea but then we must enforce this for multiboot protocol (v1 and v2) too. multiboot2 with my patches supports that solution. However, multiboot (v1) could be a bit problematic because it means that we must set load address to 16 MiB. Are we sure that this region is available on all machines like region starting at 1 MiB? This region being which one? 16 MiB - 32 MiB. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 23/23] x86: add multiboot2 protocol support for relocatable images
On Tue, Aug 11, 2015 at 12:56:58PM -0400, Konrad Rzeszutek Wilk wrote: On Mon, Jul 20, 2015 at 04:29:18PM +0200, Daniel Kiper wrote: Add multiboot2 protocol support for relocatable images. Only GRUB2 with relevant patches understands that feature. Older multiboot You may want to enumerate what those 'relevant' patches are. protocol (regardless of version) compatible loaders ignore it and everything works as usual. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/head.S | 46 + xen/arch/x86/x86_64/asm-offsets.c |1 + xen/include/xen/multiboot2.h | 13 +++ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index d484f68..2520e48 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -81,6 +81,13 @@ multiboot1_header_end: /* Align modules at page boundry. */ mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED) +/* Load address preference. */ +mb2ht_init MB2_HT(RELOCATABLE), MB2_HT(OPTIONAL), \ + sym_phys(start), /* Min load address. */ \ We could go straight to __start? This specifies lowest load address not entry point. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH v2 01/23] x86/boot: remove unneeded instruction
On Fri, Jul 24, 2015 at 12:22:57PM -0400, Konrad Rzeszutek Wilk wrote: On Mon, Jul 20, 2015 at 04:28:56PM +0200, Daniel Kiper wrote: Signed-off-by: Daniel Kiper daniel.ki...@oracle.com Don't you use it in: /* Switch to low-memory stack. */ 193 mov sym_phys(trampoline_phys),%edi 194 lea 0x1(%edi),%esp 195 lea trampoline_boot_cpu_entry-trampoline_start(%edi),%eax ? Yep, but... --- xen/arch/x86/boot/head.S |1 - 1 file changed, 1 deletion(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index cfd59dc..f63b349 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -169,7 +169,6 @@ __start: /* Apply relocations to bootstrap trampoline. */ mov sym_phys(trampoline_phys),%edx ...relevant value is stored in sym_phys(trampoline_phys) earlier then it is read into %edx here and... mov $sym_phys(__trampoline_rel_start),%edi -mov %edx,sym_phys(trampoline_phys) ...it is put back to sym_phys(trampoline_phys) without any change here :-))). So, I suppose this is remnant from something which was removed once but somebody forgot to remove this instruction too... This patch fixes it. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
Re: [PATCH 3/5] i386/relocator: Remove unused avoid_efi_bootservices argument
On Wed, Jul 15, 2015 at 07:50:51PM +0200, Vladimir 'φ-coder/phcoder' Serbinenko wrote: On 30.05.2015 07:25, Andrei Borzenkov wrote: В Fri, 29 May 2015 22:58:43 +0200 Daniel Kiper daniel.ki...@oracle.com пишет: Another questions is why grub_relocator_alloc_chunk_addr() does not consult EFI memory map if grub_relocator_alloc_chunk_align() does. Should not we fix it? My best guess is that grub_relocator_alloc_chunk_addr() gets target from elsewhere so there is nothing to consult (it is caller responsibility); while grub_relocator_alloc_chunk_align() needs to actually search for suitable memory region. My suggestion would be to pass avoid_boot_services = 1 in multiboot2 iff we don't terminate the services. Any problems with this approach? I am just working on new GRUB2 patches. I thought to go that way. I hope this is good idea. Probably I will post new version of patches next week. Daniel ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 00/23] x86: multiboot2 protocol support
Hi, I am sending, long awaited, second version of multiboot2 protocol support for legacy BIOS and EFI platforms. It fixes all major issues discovered until now. There are still some minor problems which should be fixed in one way or another. I will address them in next releases. This series, in general, is not targeted to Xen 4.6. However, there are some fixes at the beginning of it which are worth considering, I think. The final goal is xen.efi binary file which could be loaded by EFI loader, multiboot (v1) protocol (only on legacy BIOS platforms) and multiboot2 protocol. This way we will have: - smaller Xen code base, - one code base for xen.gz and xen.efi, - one build method for xen.gz and xen.efi; xen.efi will be extracted from xen file using objcopy; PE header will be contained in ELF file and will precede Xen code, - xen.efi build will not so strongly depend on a given GCC and binutils version. ARM guys should check at least patches #9 - #18 and #20. In general earlier mentioned patches touches common EFI code but they are not change functionality significantly. GRUB2 patch series will follow this patch series. GRUB2 guys should check patches #20 and #23 but I am sending to you all Xen related patches just in case. If you are not interested in this patch series at all please drop me a line and I will remove you from distribution list. Daniel .gitignore|5 +- xen/arch/x86/Makefile | 21 ++-- xen/arch/x86/Rules.mk |4 + xen/arch/x86/boot/Makefile| 10 +- xen/arch/x86/boot/build32.mk |4 +- xen/arch/x86/boot/cmdline.S | 367 --- xen/arch/x86/boot/cmdline.c | 396 xen/arch/x86/boot/edd.S |3 - xen/arch/x86/boot/head.S | 474 -- xen/arch/x86/boot/reloc.c | 242 +++--- xen/arch/x86/boot/trampoline.S| 25 - xen/arch/x86/boot/video.S |6 -- xen/arch/x86/boot/wakeup.S|6 +- xen/arch/x86/boot/x86_64.S| 34 +++--- xen/arch/x86/dmi_scan.c |4 +- xen/arch/x86/domain_page.c|2 +- xen/arch/x86/efi/Makefile | 16 +-- xen/arch/x86/efi/efi-boot.h | 68 ++-- xen/arch/x86/efi/stub.c | 16 ++- xen/arch/x86/mm.c |3 +- xen/arch/x86/mpparse.c|4 +- xen/arch/x86/setup.c | 50 - xen/arch/x86/shutdown.c |2 +- xen/arch/x86/time.c |2 +- xen/arch/x86/x86_64/asm-offsets.c | 10 ++ xen/arch/x86/x86_64/mm.c |2 +- xen/arch/x86/xen.lds.S|6 +- xen/common/efi/boot.c | 461 ++- xen/common/efi/runtime.c | 23 ++-- xen/drivers/acpi/osl.c|2 +- xen/include/asm-x86/config.h |3 + xen/include/asm-x86/page.h|2 +- xen/include/xen/efi.h | 17 ++- xen/include/xen/multiboot2.h | 182 34 files changed, 1709 insertions(+), 763 deletions(-) Daniel Kiper (23): x86/boot: remove unneeded instruction x86/boot: copy only text section from *.lnk file to *.bin file x86: zero BSS using stosl instead of stosb x86/boot: call reloc() using cdecl calling convention x86/boot/reloc: create generic alloc and copy functions x86/boot: use %ecx instead of %eax x86/boot/reloc: Rename some variables and rearrange code a bit x86: add multiboot2 protocol support efi: create efi_enabled() efi: build xen.gz with EFI code efi: split out efi_init() efi: split out efi_console_set_mode() efi: split out efi_get_gop() efi: split out efi_find_gop_mode() efi: split out efi_tables() efi: split out efi_variables() efi: split out efi_set_gop_mode() efi: split out efi_exit_boot() x86/efi: create new early memory allocator x86: add multiboot2 protocol support for EFI platforms x86/boot: implement early command line parser in C x86: make Xen early boot code relocatable x86: add multiboot2 protocol support for relocatable images ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 01/23] x86/boot: remove unneeded instruction
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/head.S |1 - 1 file changed, 1 deletion(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index cfd59dc..f63b349 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -169,7 +169,6 @@ __start: /* Apply relocations to bootstrap trampoline. */ mov sym_phys(trampoline_phys),%edx mov $sym_phys(__trampoline_rel_start),%edi -mov %edx,sym_phys(trampoline_phys) 1: mov (%edi),%eax add %edx,(%edi,%eax) -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 04/23] x86/boot: call reloc() using cdecl calling convention
Suggested-by: Jan Beulich jbeul...@suse.com Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/head.S |4 +++- xen/arch/x86/boot/reloc.c | 20 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index ed42782..3cbb2e6 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -119,8 +119,10 @@ __start: /* Save the Multiboot info struct (after relocation) for later use. */ mov $sym_phys(cpu0_stack)+1024,%esp -push%ebx +push%ebx/* Multiboot information address. */ +push%eax/* Boot trampoline address. */ callreloc +add $8,%esp /* Remove reloc() args from stack. */ mov %eax,sym_phys(multiboot_ptr) /* Initialize BSS (no nasty surprises!). */ diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c index 63045c0..708898f 100644 --- a/xen/arch/x86/boot/reloc.c +++ b/xen/arch/x86/boot/reloc.c @@ -10,15 +10,27 @@ *Keir Fraser k...@xen.org */ -/* entered with %eax = BOOT_TRAMPOLINE */ +/* + * This entry point is entered from xen/arch/x86/boot/head.S with: + * - 0x4(%esp) = BOOT_TRAMPOLINE_ADDRESS, + * - 0x8(%esp) = MULTIBOOT_INFORMATION_ADDRESS. + */ asm ( .text \n .globl _start \n _start: \n +push %ebp \n +mov %esp,%ebp\n call 1f \n -1: pop %ebx \n -mov %eax,alloc-1b(%ebx) \n -jmp reloc\n +1: pop %ecx \n +mov 0x8(%ebp),%eax \n +mov %eax,alloc-1b(%ecx) \n +mov 0xc(%ebp),%eax \n +push %eax \n +call reloc\n +add $4,%esp \n +pop %ebp \n +ret \n ); /* -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 03/23] x86: zero BSS using stosl instead of stosb
Additionally, align relevant comment to coding style. Suggested-by: Andrew Cooper andrew.coop...@citrix.com Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/head.S |5 +++-- xen/arch/x86/xen.lds.S |2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index f63b349..ed42782 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -123,12 +123,13 @@ __start: callreloc mov %eax,sym_phys(multiboot_ptr) -/* Initialize BSS (no nasty surprises!) */ +/* Initialize BSS (no nasty surprises!). */ mov $sym_phys(__bss_start),%edi mov $sym_phys(__bss_end),%ecx sub %edi,%ecx +shr $2,%ecx xor %eax,%eax -rep stosb +rep stosl /* Interrogate CPU extended features via CPUID. */ mov $0x8000,%eax diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S index 6553cff..3e1f2af 100644 --- a/xen/arch/x86/xen.lds.S +++ b/xen/arch/x86/xen.lds.S @@ -162,6 +162,7 @@ SECTIONS . = ALIGN(STACK_SIZE); __init_end = .; + . = ALIGN(4); .bss : { /* BSS */ __bss_start = .; *(.bss.stack_aligned) @@ -175,6 +176,7 @@ SECTIONS *(.bss.percpu.read_mostly) . = ALIGN(SMP_CACHE_BYTES); __per_cpu_data_end = .; + . = ALIGN(4); __bss_end = .; } :text _end = . ; -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 05/23] x86/boot/reloc: create generic alloc and copy functions
Create generic alloc and copy functions. We need separate tools for memory allocation and copy to provide multiboot2 protocol support. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com Reviewed-by: Andrew Cooper andrew.coop...@citrix.com --- v2 - suggestions/fixes: - generalize new functions names (suggested by Jan Beulich), - reduce number of casts (suggested by Jan Beulich). --- xen/arch/x86/boot/reloc.c | 59 - 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c index 708898f..09fd540 100644 --- a/xen/arch/x86/boot/reloc.c +++ b/xen/arch/x86/boot/reloc.c @@ -45,9 +45,10 @@ asm ( typedef unsigned int u32; #include ../../../include/xen/multiboot.h -static void *reloc_mbi_struct(void *old, unsigned int bytes) +static u32 alloc_mem(u32 bytes) { -void *new; +u32 s; + asm( call 1f \n 1: pop %%edx \n @@ -55,50 +56,64 @@ static void *reloc_mbi_struct(void *old, unsigned int bytes) sub %1,%0 \n and $~15,%0 \n mov %0,alloc-1b(%%edx) \n -mov %0,%%edi\n -rep movsb \n - : =r (new), +c (bytes), +S (old) - : : edx, edi, memory); -return new; + : =r (s) : r (bytes) : edx, memory); + +return s; } -static char *reloc_mbi_string(char *old) +static u32 copy_mem(u32 src, u32 bytes) { -char *p; -for ( p = old; *p != '\0'; p++ ) +u32 dst, dst_asm; + +dst = alloc_mem(bytes); +dst_asm = dst; + +asm volatile(rep movsb : +S (src), +D (dst_asm), +c (bytes) : : memory); + +return dst; +} + +static u32 copy_string(u32 src) +{ +u32 p; + +if ( src == 0 ) +return 0; + +for ( p = src; *(char *)p != '\0'; p++ ) continue; -return reloc_mbi_struct(old, p - old + 1); + +return copy_mem(src, p - src + 1); } -multiboot_info_t *reloc(multiboot_info_t *mbi_old) +multiboot_info_t *reloc(u32 mbi_old) { -multiboot_info_t *mbi = reloc_mbi_struct(mbi_old, sizeof(*mbi)); +multiboot_info_t *mbi = (multiboot_info_t *)copy_mem(mbi_old, sizeof(*mbi)); int i; if ( mbi-flags MBI_CMDLINE ) -mbi-cmdline = (u32)reloc_mbi_string((char *)mbi-cmdline); +mbi-cmdline = copy_string(mbi-cmdline); if ( mbi-flags MBI_MODULES ) { -module_t *mods = reloc_mbi_struct( -(module_t *)mbi-mods_addr, mbi-mods_count * sizeof(module_t)); +module_t *mods; -mbi-mods_addr = (u32)mods; +mbi-mods_addr = copy_mem(mbi-mods_addr, mbi-mods_count * sizeof(module_t)); + +mods = (module_t *)mbi-mods_addr; for ( i = 0; i mbi-mods_count; i++ ) { if ( mods[i].string ) -mods[i].string = (u32)reloc_mbi_string((char *)mods[i].string); +mods[i].string = copy_string(mods[i].string); } } if ( mbi-flags MBI_MEMMAP ) -mbi-mmap_addr = (u32)reloc_mbi_struct( -(memory_map_t *)mbi-mmap_addr, mbi-mmap_length); +mbi-mmap_addr = copy_mem(mbi-mmap_addr, mbi-mmap_length); if ( mbi-flags MBI_LOADERNAME ) -mbi-boot_loader_name = (u32)reloc_mbi_string( -(char *)mbi-boot_loader_name); +mbi-boot_loader_name = copy_string(mbi-boot_loader_name); /* Mask features we don't understand or don't relocate. */ mbi-flags = (MBI_MEMLIMITS | -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 06/23] x86/boot: use %ecx instead of %eax
Use %ecx instead of %eax to store low memory upper limit from EBDA. This way we do not wipe multiboot protocol identifier. It is needed in reloc() to differentiate between multiboot (v1) and multiboot2 protocol. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com Reviewed-by: Andrew Cooper andrew.coop...@citrix.com --- xen/arch/x86/boot/head.S | 24 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 3cbb2e6..77e7da9 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -87,14 +87,14 @@ __start: jne not_multiboot /* Set up trampoline segment 64k below EBDA */ -movzwl 0x40e,%eax /* EBDA segment */ -cmp $0xa000,%eax/* sanity check (high) */ +movzwl 0x40e,%ecx /* EBDA segment */ +cmp $0xa000,%ecx/* sanity check (high) */ jae 0f -cmp $0x4000,%eax/* sanity check (low) */ +cmp $0x4000,%ecx/* sanity check (low) */ jae 1f 0: -movzwl 0x413,%eax /* use base memory size on failure */ -shl $10-4,%eax +movzwl 0x413,%ecx /* use base memory size on failure */ +shl $10-4,%ecx 1: /* * Compare the value in the BDA with the information from the @@ -106,21 +106,21 @@ __start: cmp $0x100,%edx /* is the multiboot value too small? */ jb 2f /* if so, do not use it */ shl $10-4,%edx -cmp %eax,%edx /* compare with BDA value */ -cmovb %edx,%eax /* and use the smaller */ +cmp %ecx,%edx /* compare with BDA value */ +cmovb %edx,%ecx /* and use the smaller */ 2: /* Reserve 64kb for the trampoline */ -sub $0x1000,%eax +sub $0x1000,%ecx /* From arch/x86/smpboot.c: start_eip had better be page-aligned! */ -xor %al, %al -shl $4, %eax -mov %eax,sym_phys(trampoline_phys) +xor %cl, %cl +shl $4, %ecx +mov %ecx,sym_phys(trampoline_phys) /* Save the Multiboot info struct (after relocation) for later use. */ mov $sym_phys(cpu0_stack)+1024,%esp push%ebx/* Multiboot information address. */ -push%eax/* Boot trampoline address. */ +push%ecx/* Boot trampoline address. */ callreloc add $8,%esp /* Remove reloc() args from stack. */ mov %eax,sym_phys(multiboot_ptr) -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 02/23] x86/boot: copy only text section from *.lnk file to *.bin file
Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/boot/build32.mk |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/x86/boot/build32.mk b/xen/arch/x86/boot/build32.mk index c208249..c83effe 100644 --- a/xen/arch/x86/boot/build32.mk +++ b/xen/arch/x86/boot/build32.mk @@ -13,7 +13,7 @@ CFLAGS := $(filter-out -flto,$(CFLAGS)) sed 's/ /,0x/g' | sed 's/,0x$$//' | sed 's/^[0-9]*,/ .long /') $@ %.bin: %.lnk - $(OBJCOPY) -O binary $ $@ + $(OBJCOPY) -O binary -j .text $ $@ %.lnk: %.o $(LD) $(LDFLAGS_DIRECT) -N -Ttext 0 -o $@ $ -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 13/23] efi: split out efi_get_gop()
..which gets pointer to GOP device. We want to re-use this code to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- v2 - suggestions/fixes: - improve commit message (suggested by Jan Beulich). --- xen/common/efi/boot.c | 59 ++--- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 4614146..6fad230 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -630,6 +630,41 @@ static void __init efi_console_set_mode(void) StdOut-SetMode(StdOut, best); } +static EFI_GRAPHICS_OUTPUT_PROTOCOL __init *efi_get_gop(void) +{ +EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; +EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; +EFI_HANDLE *handles; +EFI_STATUS status; +UINTN info_size, size = 0; +static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; +unsigned int i; + +status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, NULL); +if ( status == EFI_BUFFER_TOO_SMALL ) +status = efi_bs-AllocatePool(EfiLoaderData, size, (void **)handles); +if ( !EFI_ERROR(status) ) +status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, + handles); +if ( EFI_ERROR(status) ) +size = 0; +for ( i = 0; i size / sizeof(*handles); ++i ) +{ +status = efi_bs-HandleProtocol(handles[i], gop_guid, (void **)gop); +if ( EFI_ERROR(status) ) +continue; +status = gop-QueryMode(gop, gop-Mode-Mode, info_size, mode_info); +if ( !EFI_ERROR(status) ) +break; +} +if ( handles ) +efi_bs-FreePool(handles); +if ( EFI_ERROR(status) ) +gop = NULL; + +return gop; +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -736,14 +771,12 @@ void EFIAPI __init noreturn efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { static EFI_GUID __initdata loaded_image_guid = LOADED_IMAGE_PROTOCOL; -static EFI_GUID __initdata gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; static EFI_GUID __initdata shim_lock_guid = SHIM_LOCK_PROTOCOL_GUID; EFI_LOADED_IMAGE *loaded_image; EFI_STATUS status; unsigned int i, argc; CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL; UINTN map_key, info_size, gop_mode = ~0; -EFI_HANDLE *handles = NULL; EFI_SHIM_LOCK_PROTOCOL *shim_lock; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mode_info; @@ -837,27 +870,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) cols, rows) == EFI_SUCCESS ) efi_arch_console_init(cols, rows); -status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, NULL); -if ( status == EFI_BUFFER_TOO_SMALL ) -status = efi_bs-AllocatePool(EfiLoaderData, size, (void **)handles); -if ( !EFI_ERROR(status) ) -status = efi_bs-LocateHandle(ByProtocol, gop_guid, NULL, size, - handles); -if ( EFI_ERROR(status) ) -size = 0; -for ( i = 0; i size / sizeof(*handles); ++i ) -{ -status = efi_bs-HandleProtocol(handles[i], gop_guid, (void **)gop); -if ( EFI_ERROR(status) ) -continue; -status = gop-QueryMode(gop, gop-Mode-Mode, info_size, mode_info); -if ( !EFI_ERROR(status) ) -break; -} -if ( handles ) -efi_bs-FreePool(handles); -if ( EFI_ERROR(status) ) -gop = NULL; +gop = efi_get_gop(); /* Get the file system interface. */ dir_handle = get_parent_handle(loaded_image, file_name); -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 18/23] efi: split out efi_exit_boot()
..which gets memory map and calls ExitBootServices(). We want to re-use this code to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- v2 - suggestions/fixes: - improve commit message (suggested by Jan Beulich). --- xen/common/efi/boot.c | 92 +++-- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 04b9c7e..bf2f198 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -879,6 +879,53 @@ static void __init efi_set_gop_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, UINTN gop efi_arch_video_init(gop, info_size, mode_info); } +static void __init efi_exit_boot(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ +EFI_STATUS status; +UINTN info_size = 0, map_key; +bool_t retry; + +efi_bs-GetMemoryMap(info_size, NULL, map_key, + efi_mdesc_size, mdesc_ver); +info_size += 8 * efi_mdesc_size; +efi_memmap = efi_arch_allocate_mmap_buffer(info_size); +if ( !efi_memmap ) +blexit(LUnable to allocate memory for EFI memory map); + +for ( retry = 0; ; retry = 1 ) +{ +efi_memmap_size = info_size; +status = SystemTable-BootServices-GetMemoryMap(efi_memmap_size, + efi_memmap, map_key, + efi_mdesc_size, + mdesc_ver); +if ( EFI_ERROR(status) ) +PrintErrMesg(LCannot obtain memory map, status); + +efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size, +efi_mdesc_size, mdesc_ver); + +efi_arch_pre_exit_boot(); + +status = SystemTable-BootServices-ExitBootServices(ImageHandle, + map_key); +efi_bs = NULL; +if ( status != EFI_INVALID_PARAMETER || retry ) +break; +} + +if ( EFI_ERROR(status) ) +PrintErrMesg(LCannot exit boot services, status); + +/* Adjust pointers into EFI. */ +efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START; +#ifdef USE_SET_VIRTUAL_ADDRESS_MAP +efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START; +#endif +efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START; +efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START; +} + static int __init __maybe_unused set_color(u32 mask, int bpp, u8 *pos, u8 *sz) { if ( bpp 0 ) @@ -903,11 +950,11 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) EFI_STATUS status; unsigned int i, argc; CHAR16 **argv, *file_name, *cfg_file_name = NULL, *options = NULL; -UINTN map_key, info_size, gop_mode = ~0; +UINTN gop_mode = ~0; EFI_SHIM_LOCK_PROTOCOL *shim_lock; EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; union string section = { NULL }, name; -bool_t base_video = 0, retry; +bool_t base_video = 0; char *option_str; bool_t use_cfg_file; @@ -1125,46 +1172,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) efi_set_gop_mode(gop, gop_mode); -info_size = 0; -efi_bs-GetMemoryMap(info_size, NULL, map_key, - efi_mdesc_size, mdesc_ver); -info_size += 8 * efi_mdesc_size; -efi_memmap = efi_arch_allocate_mmap_buffer(info_size); -if ( !efi_memmap ) -blexit(LUnable to allocate memory for EFI memory map); - -for ( retry = 0; ; retry = 1 ) -{ -efi_memmap_size = info_size; -status = SystemTable-BootServices-GetMemoryMap(efi_memmap_size, - efi_memmap, map_key, - efi_mdesc_size, - mdesc_ver); -if ( EFI_ERROR(status) ) -PrintErrMesg(LCannot obtain memory map, status); - -efi_arch_process_memory_map(SystemTable, efi_memmap, efi_memmap_size, -efi_mdesc_size, mdesc_ver); - -efi_arch_pre_exit_boot(); - -status = SystemTable-BootServices-ExitBootServices(ImageHandle, - map_key); -efi_bs = NULL; -if ( status != EFI_INVALID_PARAMETER || retry ) -break; -} - -if ( EFI_ERROR(status) ) -PrintErrMesg(LCannot exit boot services, status); - -/* Adjust pointers into EFI. */ -efi_ct = (void *)efi_ct + DIRECTMAP_VIRT_START; -#ifdef USE_SET_VIRTUAL_ADDRESS_MAP -efi_rs = (void *)efi_rs + DIRECTMAP_VIRT_START; -#endif -efi_memmap = (void *)efi_memmap + DIRECTMAP_VIRT_START; -efi_fw_vendor = (void *)efi_fw_vendor + DIRECTMAP_VIRT_START; +efi_exit_boot(ImageHandle, SystemTable); efi_arch_post_exit_boot
[PATCH v2 12/23] efi: split out efi_console_set_mode()
..which sets console mode. We want to re-use this code to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- v2 - suggestions/fixes: - improve commit message (suggested by Jan Beulich). --- xen/common/efi/boot.c | 37 - 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 6f327cd..4614146 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -611,6 +611,25 @@ static void __init efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTabl StdErr = SystemTable-StdErr ?: StdOut; } +static void __init efi_console_set_mode(void) +{ +UINTN cols, rows, size; +unsigned int best, i; + +for ( i = 0, size = 0, best = StdOut-Mode-Mode; + i StdOut-Mode-MaxMode; ++i ) +{ +if ( StdOut-QueryMode(StdOut, i, cols, rows) == EFI_SUCCESS + cols * rows size ) +{ +size = cols * rows; +best = i; +} +} +if ( best != StdOut-Mode-Mode ) +StdOut-SetMode(StdOut, best); +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -799,23 +818,7 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) } if ( !base_video ) -{ -unsigned int best; -UINTN cols, rows, size; - -for ( i = 0, size = 0, best = StdOut-Mode-Mode; - i StdOut-Mode-MaxMode; ++i ) -{ -if ( StdOut-QueryMode(StdOut, i, cols, rows) == EFI_SUCCESS - cols * rows size ) -{ -size = cols * rows; -best = i; -} -} -if ( best != StdOut-Mode-Mode ) -StdOut-SetMode(StdOut, best); -} +efi_console_set_mode(); } PrintStr(LXen __stringify(XEN_VERSION) . __stringify(XEN_SUBVERSION) -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 07/23] x86/boot/reloc: Rename some variables and rearrange code a bit
Rename mbi and mbi_old variables and rearrange code a bit to make it more readable. Additionally, this way multiboot (v1) protocol implementation and future multiboot2 protocol implementation will use the same variable naming convention. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- v2 - suggestions/fixes: - extract this change from main mutliboot2 protocol implementation (suggested by Jan Beulich). --- xen/arch/x86/boot/reloc.c | 39 +-- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/xen/arch/x86/boot/reloc.c b/xen/arch/x86/boot/reloc.c index 09fd540..feb1d72 100644 --- a/xen/arch/x86/boot/reloc.c +++ b/xen/arch/x86/boot/reloc.c @@ -86,41 +86,44 @@ static u32 copy_string(u32 src) return copy_mem(src, p - src + 1); } -multiboot_info_t *reloc(u32 mbi_old) +multiboot_info_t *reloc(u32 mbi_in) { -multiboot_info_t *mbi = (multiboot_info_t *)copy_mem(mbi_old, sizeof(*mbi)); int i; +multiboot_info_t *mbi_out; -if ( mbi-flags MBI_CMDLINE ) -mbi-cmdline = copy_string(mbi-cmdline); +mbi_out = (multiboot_info_t *)copy_mem(mbi_in, sizeof(*mbi_out)); -if ( mbi-flags MBI_MODULES ) +if ( mbi_out-flags MBI_CMDLINE ) +mbi_out-cmdline = copy_string(mbi_out-cmdline); + +if ( mbi_out-flags MBI_MODULES ) { module_t *mods; -mbi-mods_addr = copy_mem(mbi-mods_addr, mbi-mods_count * sizeof(module_t)); +mbi_out-mods_addr = copy_mem(mbi_out-mods_addr, + mbi_out-mods_count * sizeof(module_t)); -mods = (module_t *)mbi-mods_addr; +mods = (module_t *)mbi_out-mods_addr; -for ( i = 0; i mbi-mods_count; i++ ) +for ( i = 0; i mbi_out-mods_count; i++ ) { if ( mods[i].string ) mods[i].string = copy_string(mods[i].string); } } -if ( mbi-flags MBI_MEMMAP ) -mbi-mmap_addr = copy_mem(mbi-mmap_addr, mbi-mmap_length); +if ( mbi_out-flags MBI_MEMMAP ) +mbi_out-mmap_addr = copy_mem(mbi_out-mmap_addr, mbi_out-mmap_length); -if ( mbi-flags MBI_LOADERNAME ) -mbi-boot_loader_name = copy_string(mbi-boot_loader_name); +if ( mbi_out-flags MBI_LOADERNAME ) +mbi_out-boot_loader_name = copy_string(mbi_out-boot_loader_name); /* Mask features we don't understand or don't relocate. */ -mbi-flags = (MBI_MEMLIMITS | - MBI_CMDLINE | - MBI_MODULES | - MBI_MEMMAP | - MBI_LOADERNAME); +mbi_out-flags = (MBI_MEMLIMITS | + MBI_CMDLINE | + MBI_MODULES | + MBI_MEMMAP | + MBI_LOADERNAME); -return mbi; +return mbi_out; } -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel
[PATCH v2 10/23] efi: build xen.gz with EFI code
Build xen.gz with EFI code. We need this to support multiboot2 protocol on EFI platforms. If we wish to load not ELF file using multiboot (v1) or multiboot2 then it must contain linear (or flat) representation of code and data. Currently, PE file contains many sections which are not linear (one after another without any holes) or even do not have representation in a file (e.g. BSS). In theory there is a chance that we could build proper PE file using current build system. However, it means that xen.efi further diverge from xen ELF file (in terms of contents and build method). ELF have all needed properties. So, it means that this is good starting point for further development. Additionally, I think that this is also good starting point for further xen.efi code and build optimizations. It looks that there is a chance that finally we can generate xen.efi directly from xen ELF using just simple objcopy. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- v2 - suggestions/fixes: - build EFI code only if it is supported in a given build environment (suggested by Jan Beulich). --- xen/arch/x86/Makefile | 13 + xen/arch/x86/efi/Makefile | 16 +--- xen/arch/x86/mm.c |3 ++- xen/common/efi/runtime.c |6 ++ 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 5f24951..0335445 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -80,7 +80,7 @@ ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o $(BASEDIR)/arch/x86/efi/built_in ifeq ($(lto),y) # Gather all LTO objects together -prelink_lto.o: $(ALL_OBJS) +prelink_lto.o: $(ALL_OBJS) efi/relocs-dummy.o $(LD_LTO) -r -o $@ $^ prelink-efi_lto.o: $(ALL_OBJS) efi/runtime.o efi/compat.o @@ -90,14 +90,14 @@ prelink-efi_lto.o: $(ALL_OBJS) efi/runtime.o efi/compat.o prelink.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink_lto.o $(LD) $(LDFLAGS) -r -o $@ $^ -prelink-efi.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink-efi_lto.o efi/boot.init.o +prelink-efi.o: $(patsubst %/built_in.o,%/built_in_bin.o,$(ALL_OBJS)) prelink-efi_lto.o $(guard) $(LD) $(LDFLAGS) -r -o $@ $^ else -prelink.o: $(ALL_OBJS) +prelink.o: $(ALL_OBJS) efi/relocs-dummy.o $(LD) $(LDFLAGS) -r -o $@ $^ -prelink-efi.o: $(ALL_OBJS) efi/boot.init.o efi/runtime.o efi/compat.o - $(guard) $(LD) $(LDFLAGS) -r -o $@ $(filter-out %/efi/built_in.o,$^) +prelink-efi.o: $(ALL_OBJS) + $(guard) $(LD) $(LDFLAGS) -r -o $@ $^ endif $(BASEDIR)/common/symbols-dummy.o: @@ -146,9 +146,6 @@ $(TARGET).efi: prelink-efi.o efi.lds efi/relocs-dummy.o $(BASEDIR)/common/symbol if $(guard) false; then rm -f $@; echo 'EFI support disabled'; fi rm -f $(@D)/.$(@F).[0-9]* -efi/boot.init.o efi/runtime.o efi/compat.o: $(BASEDIR)/arch/x86/efi/built_in.o -efi/boot.init.o efi/runtime.o efi/compat.o: ; - asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(CC) $(filter-out -flto,$(CFLAGS)) -S -o $@ $ diff --git a/xen/arch/x86/efi/Makefile b/xen/arch/x86/efi/Makefile index 1daa7ac..b1e8883 100644 --- a/xen/arch/x86/efi/Makefile +++ b/xen/arch/x86/efi/Makefile @@ -1,14 +1,16 @@ CFLAGS += -fshort-wchar -obj-y += stub.o - -create = test -e $(1) || touch -t 19990101 $(1) - efi := $(filter y,$(x86_64)$(shell rm -f disabled)) efi := $(if $(efi),$(shell $(CC) $(filter-out $(CFLAGS-y) .%.d,$(CFLAGS)) -c check.c 2disabled echo y)) efi := $(if $(efi),$(shell $(LD) -mi386pep --subsystem=10 -o check.efi check.o 2disabled echo y)) -efi := $(if $(efi),$(shell rm disabled)y,$(shell $(call create,boot.init.o); $(call create,runtime.o))) +efi := $(if $(efi),$(shell rm disabled)y) -extra-$(efi) += boot.init.o relocs-dummy.o runtime.o compat.o +extra-y += relocs-dummy.o -stub.o: $(extra-y) +ifeq ($(efi),y) +obj-y += boot.init.o +obj-y += compat.o +obj-y += runtime.o +else +obj-y += stub.o +endif diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 342414f..cef2eb6 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -344,7 +344,8 @@ void __init arch_init_memory(void) subarch_init_memory(); -efi_init_memory(); +if ( efi_enabled(EFI_PLATFORM) ) +efi_init_memory(); mem_sharing_init(); diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c index aa064e7..3eb21c1 100644 --- a/xen/common/efi/runtime.c +++ b/xen/common/efi/runtime.c @@ -167,6 +167,9 @@ int efi_get_info(uint32_t idx, union xenpf_efi_info *info) { unsigned int i, n; +if ( !efi_enabled(EFI_PLATFORM) ) +return -EOPNOTSUPP; + switch ( idx ) { case XEN_FW_EFI_VERSION: @@ -301,6 +304,9 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op) EFI_STATUS status = EFI_NOT_STARTED; int rc = 0; +if ( !efi_enabled(EFI_PLATFORM) ) +return -EOPNOTSUPP; + switch ( op-function ) { case XEN_EFI_get_time: -- 1.7.10.4
[PATCH v2 08/23] x86: add multiboot2 protocol support
Add multiboot2 protocol support. Alter min memory limit handling as we now may not find it from either multiboot (v1) or multiboot2. This way we are laying the foundation for EFI + GRUB2 + Xen development. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com Reviewed-by: Andrew Cooper andrew.coop...@citrix.com --- v2 - suggestions/fixes: - generate multiboot2 header using macros (suggested by Jan Beulich), - improve comments (suggested by Jan Beulich), - simplify assembly in xen/arch/x86/boot/head.S (suggested by Jan Beulich), - do not include include/xen/compiler.h in xen/arch/x86/boot/reloc.c (suggested by Jan Beulich), - do not read data beyond the end of Multiboot2 information (suggested by Jan Beulich). v2 - not fixed yet: - dynamic dependency generation for xen/arch/x86/boot/reloc.S; this requires more work; I am not sure that it pays because potential patch requires more changes than addition of just multiboot2.h to Makefile (suggested by Jan Beulich), - isolated/stray __packed attribute usage for multiboot2_memory_map_t (suggested by Jan Beulich). --- xen/arch/x86/boot/Makefile|3 +- xen/arch/x86/boot/head.S | 105 +-- xen/arch/x86/boot/reloc.c | 146 +++- xen/arch/x86/x86_64/asm-offsets.c |7 ++ xen/include/xen/multiboot2.h | 169 + 5 files changed, 420 insertions(+), 10 deletions(-) create mode 100644 xen/include/xen/multiboot2.h diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index 5fdb5ae..06893d8 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -1,6 +1,7 @@ obj-bin-y += head.o -RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h +RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h \ +$(BASEDIR)/include/xen/multiboot2.h head.o: reloc.S diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 77e7da9..57197db 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -1,5 +1,6 @@ #include xen/config.h #include xen/multiboot.h +#include xen/multiboot2.h #include public/xen.h #include asm/asm_defns.h #include asm/desc.h @@ -19,6 +20,28 @@ #define BOOT_PSEUDORM_CS 0x0020 #define BOOT_PSEUDORM_DS 0x0028 +#define MB2_HT(name) (MULTIBOOT2_HEADER_TAG_##name) +#define MB2_TT(name) (MULTIBOOT2_TAG_TYPE_##name) + +.macro mb2ht_args arg, args:vararg +.long \arg +.ifnb \args +mb2ht_args \args +.endif +.endm + +.macro mb2ht_init type, req, args:vararg +.align MULTIBOOT2_TAG_ALIGN +0: +.short \type +.short \req +.long 1f - 0b +.ifnb \args +mb2ht_args \args +.endif +1: +.endm + ENTRY(start) jmp __start @@ -34,6 +57,42 @@ multiboot1_header_start: /*** MULTIBOOT1 HEADER / .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) multiboot1_header_end: +/*** MULTIBOOT2 HEADER / +/* Some ideas are taken from grub-2.00/grub-core/tests/boot/kernel-i386.S file. */ +.align MULTIBOOT2_HEADER_ALIGN + +.Lmultiboot2_header: +/* Magic number indicating a Multiboot2 header. */ +.long MULTIBOOT2_HEADER_MAGIC +/* Architecture: i386. */ +.long MULTIBOOT2_ARCHITECTURE_I386 +/* Multiboot2 header length. */ +.long .Lmultiboot2_header_end - .Lmultiboot2_header +/* Multiboot2 header checksum. */ +.long -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT2_ARCHITECTURE_I386 + \ +(.Lmultiboot2_header_end - .Lmultiboot2_header)) + +/* Multiboot2 information request tag. */ +mb2ht_init MB2_HT(INFORMATION_REQUEST), MB2_HT(REQUIRED), \ + MB2_TT(BASIC_MEMINFO), MB2_TT(MMAP) + +/* Align modules at page boundry. */ +mb2ht_init MB2_HT(MODULE_ALIGN), MB2_HT(REQUIRED) + +/* Console flags tag. */ +mb2ht_init MB2_HT(CONSOLE_FLAGS), MB2_HT(OPTIONAL), \ + MULTIBOOT2_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED + +/* Framebuffer tag. */ +mb2ht_init MB2_HT(FRAMEBUFFER), MB2_HT(OPTIONAL), \ + 0, /* Number of the columns - no preference. */ \ + 0, /* Number of the lines - no preference. */ \ + 0 /* Number of bits per pixel - no preference. */ + +/* Multiboot2 header end tag. */ +mb2ht_init MB2_HT(END), MB2_HT(REQUIRED) +.Lmultiboot2_header_end: + .section .init.rodata, a, @progbits .align 4 @@ -82,10 +141,48 @@ __start: mov %ecx,%es mov %ecx,%ss -/* Check for Multiboot bootloader */ +/* Bootloaders may set multiboot{1,2}.mem_lower to a nonzero value. */ +xor %edx,%edx
[PATCH v2 19/23] x86/efi: create new early memory allocator
There is a problem with place_string() which is used as early memory allocator. It gets memory chunks starting from start symbol and going down. Sadly this does not work when Xen is loaded using multiboot2 protocol because start lives on 1 MiB address. So, I tried to use mem_lower address calculated by GRUB2. However, it works only on some machines. There are machines in the wild (e.g. Dell PowerEdge R820) which uses first ~640 KiB for boot services code or data... :-((( In case of multiboot2 protocol we need that place_string() only allocate memory chunk for EFI memory map. However, I think that it should be fixed instead of making another function used just in one case. I thought about two solutions. 1) We could use native EFI allocation functions (e.g. AllocatePool() or AllocatePages()) to get memory chunk. However, later (somewhere in __start_xen()) we must copy its contents to safe place or reserve this in e820 memory map and map it in Xen virtual address space. In later case we must also care about conflicts with e.g. crash kernel regions which could be quite difficult. 2) We may allocate memory area statically somewhere in Xen code which could be used as memory pool for early dynamic allocations. Looks quite simple. Additionally, it would not depend on EFI at all and could be used on legacy BIOS platforms if we need it. However, we must carefully choose size of this pool. We do not want increase Xen binary size too much and waste too much memory but also we must fit at least memory map on x86 EFI platforms. As I saw on small machine, e.g. IBM System x3550 M2 with 8 GiB RAM, memory map may contain more than 200 entries. Every entry on x86-64 platform is 40 bytes in size. So, it means that we need more than 8 KiB for EFI memory map only. Additionally, if we want to use this memory pool for Xen and modules command line storage (it would be used when xen.efi is executed as EFI application) then we should add, I think, about 1 KiB. In this case, to be on safe side, we should assume at least 64 KiB pool for early memory allocations, which is about 4 times of our earlier calculations. However, during discussion on Xen-devel Jan Beulich suggested that just in case we should use 1 MiB memory pool like it was in original place_string() implementation. So, let's use 1 MiB as it was proposed. If we think that we should not waste unallocated memory in the pool on running system then we can mark this region as __initdata and move all required data to dynamically allocated places somewhere in __start_xen(). Now solution #2 is implemented but maybe we should consider #1 one day. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- xen/arch/x86/efi/efi-boot.h | 38 ++ xen/arch/x86/setup.c|3 +-- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index 2dd69f6..3d25c48 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -103,9 +103,36 @@ static void __init relocate_trampoline(unsigned long phys) *(u16 *)(*trampoline_ptr + (long)trampoline_ptr) = phys 4; } +#define EBMALLOC_SIZE MB(1) + +static char __initdata ebmalloc_mem[EBMALLOC_SIZE]; +static char __initdata *ebmalloc_free = NULL; + +/* EFI boot allocator. */ +static void __init *ebmalloc(size_t size) +{ +void *ptr; + +/* + * Init ebmalloc_free on runtime. Static initialization + * will not work because it puts virtual address there. + */ +if ( ebmalloc_free == NULL ) +ebmalloc_free = ebmalloc_mem; + +ptr = ebmalloc_free; + +ebmalloc_free += size; + +if ( ebmalloc_free - ebmalloc_mem sizeof(ebmalloc_mem) ) +blexit(LOut of static memory\r\n); + +return ptr; +} + static void __init place_string(u32 *addr, const char *s) { -static char *__initdata alloc = start; +char *alloc = NULL; if ( s *s ) { @@ -113,7 +140,7 @@ static void __init place_string(u32 *addr, const char *s) const char *old = (char *)(long)*addr; size_t len2 = *addr ? strlen(old) + 1 : 0; -alloc -= len1 + len2; +alloc = ebmalloc(len1 + len2); /* * Insert new string before already existing one. This is needed * for options passed on the command line to override options from @@ -196,12 +223,7 @@ static void __init efi_arch_process_memory_map(EFI_SYSTEM_TABLE *SystemTable, static void *__init efi_arch_allocate_mmap_buffer(UINTN map_size) { -place_string(mbi.mem_upper, NULL); -mbi.mem_upper -= map_size; -mbi.mem_upper = -__alignof__(EFI_MEMORY_DESCRIPTOR); -if ( mbi.mem_upper xen_phys_start ) -return NULL; -return (void *)(long)mbi.mem_upper; +return ebmalloc(map_size); } static void __init efi_arch_pre_exit_boot(void) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index
[PATCH v2 21/23] x86/boot: implement early command line parser in C
Current early command line parser implementation in assembler is very difficult to change to relocatable stuff using segment registers. This requires a lot of changes in very weird and fragile code. So, reimplement this functionality in C. This way code will be relocatable out of the box and much easier to maintain. Suggested-by: Andrew Cooper andrew.coop...@citrix.com Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- .gitignore |5 +- xen/arch/x86/Makefile |2 +- xen/arch/x86/boot/Makefile |7 +- xen/arch/x86/boot/build32.mk |2 + xen/arch/x86/boot/cmdline.S| 367 - xen/arch/x86/boot/cmdline.c| 396 xen/arch/x86/boot/edd.S|3 - xen/arch/x86/boot/head.S | 17 ++ xen/arch/x86/boot/trampoline.S | 14 ++ xen/arch/x86/boot/video.S |6 - 10 files changed, 439 insertions(+), 380 deletions(-) delete mode 100644 xen/arch/x86/boot/cmdline.S create mode 100644 xen/arch/x86/boot/cmdline.c diff --git a/.gitignore b/.gitignore index f6ddb00..e0618b9 100644 --- a/.gitignore +++ b/.gitignore @@ -223,9 +223,10 @@ xen/arch/arm/xen.lds xen/arch/x86/asm-offsets.s xen/arch/x86/boot/mkelf32 xen/arch/x86/xen.lds +xen/arch/x86/boot/cmdline.S xen/arch/x86/boot/reloc.S -xen/arch/x86/boot/reloc.bin -xen/arch/x86/boot/reloc.lnk +xen/arch/x86/boot/*.bin +xen/arch/x86/boot/*.lnk xen/arch/x86/efi.lds xen/arch/x86/efi/check.efi xen/arch/x86/efi/disabled diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 0335445..82c5a93 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -170,4 +170,4 @@ clean:: rm -f asm-offsets.s *.lds boot/*.o boot/*~ boot/core boot/mkelf32 rm -f $(BASEDIR)/.xen-syms.[0-9]* boot/.*.d rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/.*.d efi/*.efi efi/disabled efi/mkreloc - rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin + rm -f boot/cmdline.S boot/reloc.S boot/*.lnk boot/*.bin diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index 06893d8..d73cc76 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -1,9 +1,14 @@ obj-bin-y += head.o +CMDLINE_DEPS = video.h + RELOC_DEPS = $(BASEDIR)/include/asm-x86/config.h $(BASEDIR)/include/xen/multiboot.h \ $(BASEDIR)/include/xen/multiboot2.h -head.o: reloc.S +head.o: cmdline.S reloc.S + +cmdline.S: cmdline.c $(CMDLINE_DEPS) + $(MAKE) -f build32.mk $@ CMDLINE_DEPS=$(CMDLINE_DEPS) reloc.S: reloc.c $(RELOC_DEPS) $(MAKE) -f build32.mk $@ RELOC_DEPS=$(RELOC_DEPS) diff --git a/xen/arch/x86/boot/build32.mk b/xen/arch/x86/boot/build32.mk index c83effe..d681643 100644 --- a/xen/arch/x86/boot/build32.mk +++ b/xen/arch/x86/boot/build32.mk @@ -30,6 +30,8 @@ CFLAGS := $(filter-out -flto,$(CFLAGS)) esac; \ done +cmdline.o: cmdline.c $(CMDLINE_DEPS) + reloc.o: reloc.c $(RELOC_DEPS) .PRECIOUS: %.bin %.lnk diff --git a/xen/arch/x86/boot/cmdline.S b/xen/arch/x86/boot/cmdline.S deleted file mode 100644 index 00687eb..000 --- a/xen/arch/x86/boot/cmdline.S +++ /dev/null @@ -1,367 +0,0 @@ -/** - * cmdline.S - * - * Early command-line parsing. - */ - -.code32 - -#include video.h - -# NB. String pointer on stack is modified to point past parsed digits. -.Latoi: -push%ebx -push%ecx -push%edx -push%esi -xor %ebx,%ebx /* %ebx = accumulator */ -mov $10,%ecx/* %ecx = base (default base 10) */ -mov 16+4(%esp),%esi /* %esi = pointer into ascii string. */ -lodsb -cmpb$'0',%al -jne 2f -mov $8,%ecx /* Prefix '0' = octal (base 8) */ -lodsb -cmpb$'x',%al -jne 2f -mov $16,%ecx/* Prefix '0x' = hex (base 16) */ -1: lodsb -2: sub $'0',%al -jb 4f -cmp $9,%al -jbe 3f -sub $'A'-'0'-10,%al -jb 4f -cmp $15,%al -jbe 3f -sub $'a'-'A',%al -jb 4f -3: cmp %cl,%al -jae 4f -movzbl %al,%eax -xchg%eax,%ebx -mul %ecx -xchg%eax,%ebx -add %eax,%ebx -jmp 1b -4: mov %ebx,%eax -dec %esi -mov %esi,16+4(%esp) -pop %esi -pop %edx -pop %ecx -pop %ebx -ret - -.Lstrstr: -push%ecx -push%edx -push%esi -push%edi -xor %eax,%eax -xor %ecx,%ecx -not %ecx -mov 16+4(%esp),%esi -mov 16+8(%esp),%edi -repne scasb -not %ecx -dec %ecx -mov %ecx,%edx -1
[PATCH v2 11/23] efi: split out efi_init()
..which initializes basic EFI variables. We want to re-use this code to support multiboot2 protocol on EFI platforms. Signed-off-by: Daniel Kiper daniel.ki...@oracle.com --- v2 - suggestions/fixes: - improve commit message (suggested by Jan Beulich). --- xen/common/efi/boot.c | 28 +--- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 1f188fe..6f327cd 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -595,6 +595,22 @@ static char *__init get_value(const struct file *cfg, const char *section, return NULL; } +static void __init efi_init(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +{ +efi_ih = ImageHandle; +efi_bs = SystemTable-BootServices; +efi_bs_revision = efi_bs-Hdr.Revision; +efi_rs = SystemTable-RuntimeServices; +efi_ct = SystemTable-ConfigurationTable; +efi_num_ct = SystemTable-NumberOfTableEntries; +efi_version = SystemTable-Hdr.Revision; +efi_fw_vendor = SystemTable-FirmwareVendor; +efi_fw_revision = SystemTable-FirmwareRevision; + +StdOut = SystemTable-ConOut; +StdErr = SystemTable-StdErr ?: StdOut; +} + static void __init setup_efi_pci(void) { EFI_STATUS status; @@ -721,18 +737,8 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) set_bit(EFI_PLATFORM, efi.flags); #endif -efi_ih = ImageHandle; -efi_bs = SystemTable-BootServices; -efi_bs_revision = efi_bs-Hdr.Revision; -efi_rs = SystemTable-RuntimeServices; -efi_ct = SystemTable-ConfigurationTable; -efi_num_ct = SystemTable-NumberOfTableEntries; -efi_version = SystemTable-Hdr.Revision; -efi_fw_vendor = SystemTable-FirmwareVendor; -efi_fw_revision = SystemTable-FirmwareRevision; +efi_init(ImageHandle, SystemTable); -StdOut = SystemTable-ConOut; -StdErr = SystemTable-StdErr ?: StdOut; use_cfg_file = efi_arch_use_config_file(SystemTable); status = efi_bs-HandleProtocol(ImageHandle, loaded_image_guid, -- 1.7.10.4 ___ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel