I'm currently writing a patch for GRUB intended for the Qubes OS project (though I may later try to upstream it if it proves to work well downstream). [1] The patch's goal is to allow Xen hypervisor users to pass data to GRUB via command line arguments. This data is exposed as environment variables within GRUB itself, which can then be used in grub.cfg for customizing various parts of the boot process as the user desires. The patch is coming together pretty well (we're still discussing the details downstream), but I have hit one particularly tricky question that I don't know how to get a good answer to.
When booting a VM in PV mode, Xen simply passes a start_info structure to the guest, which can then use it directly. This structure includes a cmd_line member, which can then be parsed with minimal additional effort. GRUB's startup code for Xen PV simply takes the start_info struct address and places it in grub_xen_start_page_addr, so it's already loaded with the existing GRUB code. Since Xen PV mode and GRUB work together at all, I assume everything related to memory Unfortunately, this is not the case when using PVH mode - Xen seems to pass an hvm_start_info struct instead, which also contains a pointer to the command line passed by Xen... sorta. What it passes is a physical address in the form of a 64-bit integer. Now I did test this on my machine; in grub-core/kern/i386/xen/pvh.c:grub_xen_setup_pvh, I added code that casts the address to a char * and then grub_strcpy's what it points to into grub_xen_start_page_addr->cmd_line. This appears to work without problems, the command line from Xen ends up accessible to my parsing code elsewhere in GRUB. However, I feel like I'm playing with fire here - I'm assuming that either paging is disabled or the pages I'm working with are identity-mapped when I do this, and I'm assuming that writing into the cmd_line array at this point is safe at all. (I suspect the latter is safe given that grub_xen_start_page_addr is being dereferenced and members of the struct written to in this very function, but I'm really dubious about the former, just because it happens to work for me now doesn't mean it will work anywhere else.) I don't know how to determine for sure what state the page tables are in at any given point in GRUB's codebase. I did spot some other code in GRUB that assumes disabled paging or identity paging (specifically grub-core/commands/i386/pc/drivemap.c:install_int13_handler), but that's specifically for the i386-pc platform and I don't know if that will apply on any other platform GRUB supports. I can't follow the bits of assembly code that handle enabling and disabling of paging well enough to know what exactly they affect (mostly because I don't know x86 assembly, or any assembly language for that matter), I can tell that there are situations where paging is used, and sometimes those situations use identity paging, but that's about it. Is what I'm doing with physical address handling safe? And is there a good way (other than dissecting the assembly code) to determine what is and isn't safe when dealing with these kinds of situations? [1] https://github.com/QubesOS/qubes-linux-pvgrub2/pull/16 -- Aaron
pgp_tjOO_ka1T.pgp
Description: OpenPGP digital signature
_______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel