From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1LS3MN-0000Yo-Co for mharc-grub-devel@gnu.org; Wed, 28 Jan 2009 00:53:11 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LS3MK-0000WB-Eb for grub-devel@gnu.org; Wed, 28 Jan 2009 00:53:08 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LS3MJ-0000Vz-MY for grub-devel@gnu.org; Wed, 28 Jan 2009 00:53:08 -0500 Received: from [199.232.76.173] (port=58143 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LS3MJ-0000Vw-Hq for grub-devel@gnu.org; Wed, 28 Jan 2009 00:53:07 -0500 Received: from fg-out-1718.google.com ([72.14.220.154]:48943) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LS3MI-0006l6-PB for grub-devel@gnu.org; Wed, 28 Jan 2009 00:53:07 -0500 Received: by fg-out-1718.google.com with SMTP id e12so429499fga.30 for ; Tue, 27 Jan 2009 21:53:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:content-type; bh=bj/n+SQ8PmXWfTC9Rz65isapbEIEvaD88YqtHwHhGEo=; b=Slg8syVBhUUo7c1YFEzpI6KkThrbXobPlyzoBVzkhfHdaKAcp0fUD+rnyYib6VjyXx idF18j6Cg0fgW1NwaJViiTCjfmboLJYprPmSATZCvuGpnGEKuOfLlzj0i41tiI/wm7kM UXYiddN+5ZJ7539M2C6y7zdgg6S89JTRyDrmA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject :content-type; b=NuHjFiLqD9NVO0Bv8LbFOfnR0nlpX4ukI8CHr3RvzAkkKibYcc69L86THcdYhGwJk5 ALZ06nx5W6j0+66ZcfZK3bhnmQtVOk1lZ+YSg+6nHDTgPeaA267AbHIpHXqWEmGhnGgX pRzPUacPqABRJRrndhKUTmS30u2nh4QgkPK/o= Received: by 10.86.95.8 with SMTP id s8mr138072fgb.79.1233121984797; Tue, 27 Jan 2009 21:53:04 -0800 (PST) Received: from ?192.168.1.2? (108-141.79-83.cust.bluewin.ch [83.79.141.108]) by mx.google.com with ESMTPS id d6sm1532885fga.50.2009.01.27.21.53.03 (version=SSLv3 cipher=RC4-MD5); Tue, 27 Jan 2009 21:53:03 -0800 (PST) Message-ID: <497FF2BE.8050101@gmail.com> Date: Wed, 28 Jan 2009 06:53:02 +0100 From: phcoder User-Agent: Thunderbird 2.0.0.19 (X11/20090105) MIME-Version: 1.0 To: The development of GRUB 2 Content-Type: multipart/mixed; boundary="------------060600030508080805060204" X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: xnu support X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Jan 2009 05:53:08 -0000 This is a multi-part message in MIME format. --------------060600030508080805060204 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Hello, I'm working on xnu (darwin kernel, under OSI approved APSL) support and would like to discuss some interfaces about it. Issue 1) First in xnu world booter hands the loading of compressed hibernation image. Resuming doesn't need to load the kernel conventional way. And trying to resume from hibernate should be done before trying to load kernel. So I propose the following configuration entries: menuentry "my XNU" { if ! xnu_resume ; then xnu_kernel xnu_extensions --cache= --dir= xnu_loadenv fi } Issue 2) Also normally when hibernation succeeds kernel should invalidate the image. Unfortunately in some scenarios it doesn't. A reliable way to check the image is to compare modification timestamp of FS and image. I know where to find them on FS but unfortunately now grub has no way of interfacing this with FS code. I propose to modify /* Call HOOK with each file under DIR. */ grub_err_t (*dir) (grub_device_t device, const char *path, int (*hook) (const char *filename, int dir)); to /* Call HOOK with each file under DIR. */ grub_err_t (*dir) (grub_device_t device, const char *path, int (*hook) (const char *filename, int dir, grub_time_t modtime)); Or add grub_err_t (*file_modtime) (const char *name, grub_time_t *modtime); and add a function for retrieving FS modification type grub_err_t (*fs_modtime) (grub_device_t device, grub_time_t *modtime); to grub_fs_t This has an additional benefit of invalidating image if FS was modified by external tool. This may be overriden by --force option to override it. File modification timestamp are also needed to check if the extension cache is up to date. Issue 3) Kernel may theoretically request loading parts to any address. In practice it does it only in 1Mb-64Mb range. Is it possible to somehow secure this range from grub_malloc after xnu_kernel command? (I would like to avoid "just before boot" relocations if possible) I send an implementation of xnu_resume. Not for inclusion of course but for illustration Thanks Any opinion is appreciated Vladimir 'phcoder' Serbinenko --------------060600030508080805060204 Content-Type: text/x-diff; name="xnu1.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="xnu1.patch" Index: conf/i386.rmk =================================================================== --- conf/i386.rmk (revision 1962) +++ conf/i386.rmk (working copy) @@ -14,3 +14,8 @@ vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c vga_text_mod_CFLAGS = $(COMMON_CFLAGS) vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS) + +pkglib_MODULES += xnu.mod +xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c +xnu_mod_CFLAGS = $(COMMON_CFLAGS) +xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) Index: include/grub/i386/xnu.h =================================================================== --- include/grub/i386/xnu.h (revision 0) +++ include/grub/i386/xnu.h (revision 0) @@ -0,0 +1,9 @@ +#define XNU_MEMORY_START 0x100000 +#define XNU_MEMORY_END 0x4000000 +#define XNU_PAGESIZE 4096 + +grub_err_t grub_xnu_boot (void); +extern void *grub_xnu_entry_point; +extern void *grub_xnu_stack; +extern void *grub_xnu_arg1; + Index: include/grub/xnu.h =================================================================== --- include/grub/xnu.h (revision 0) +++ include/grub/xnu.h (revision 0) @@ -0,0 +1,18 @@ +#define XNU_HIBERNATE_MAGIC 0x73696d65 +struct xnu_hibernate_header +{ + grub_uint64_t image_size; + grub_uint8_t unknown1[8]; + grub_uint32_t restorepage; + grub_uint32_t numofpages; + grub_uint32_t entry_point; + grub_uint32_t stack; + grub_uint8_t unknown2[20]; + grub_uint32_t restored_checksum; + grub_uint8_t unknown3[20]; + grub_uint32_t magic; + grub_uint8_t unknown4[28]; + grub_uint64_t encoffset; + grub_uint8_t unknown5[360]; + grub_uint32_t extmapsize; +} __attribute__ ((packed)); Index: loader/i386/xnu.c =================================================================== --- loader/i386/xnu.c (revision 0) +++ loader/i386/xnu.c (revision 0) @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Registers on XNU boot: eip,esp and eax*/ +void *grub_xnu_entry_point=0; +void *grub_xnu_stack=0; +void *grub_xnu_arg1=0; + +grub_err_t +grub_xnu_boot (void) +{ + /*Setup regs and launch xnu*/ + asm volatile ("movl %0, %%eax" : : "m" (grub_xnu_arg1)); + asm volatile ("movl %0, %%ebx" : : "m" (grub_xnu_stack)); + asm volatile ("movl %0, %%ecx" : : "m" (grub_xnu_entry_point)); + asm volatile ("movl %%ebx, %%esp" : : ); + asm volatile ("jmp *%%ecx" : : ); +} Index: loader/xnu_resume.c =================================================================== --- loader/xnu_resume.c (revision 0) +++ loader/xnu_resume.c (revision 0) @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static grub_dl_t my_mod; +static void *grub_xnu_hibernate_image; + +static grub_err_t +grub_xnu_resume_unload (void) +{ + /* Free loaded image */ + if (grub_xnu_hibernate_image) + grub_free (grub_xnu_hibernate_image); + grub_xnu_hibernate_image = 0; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_xnu_resume (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) + +{ + grub_file_t file; + grub_size_t total_header_size; + struct xnu_hibernate_header hibhead; + void *buf; + grub_uint32_t csum1, csum2; + grub_uint8_t *ptr; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + + file = grub_file_open (args[0]); + if (! file) + return 0; + + /* Read the header */ + if (grub_file_read (file, (char *)&hibhead, sizeof (hibhead)) + !=sizeof (hibhead)) + { + grub_file_close (file); + return grub_error (GRUB_ERR_READ_ERROR, + "cannot read the hibernate header"); + } + + /* Check the header */ + if (hibhead.magic != XNU_HIBERNATE_MAGIC) + { + grub_file_close (file); + return grub_error (GRUB_ERR_BAD_OS, + "hibernate header has incorrect magick number"); + } + if (hibhead.encoffset) + { + grub_file_close (file); + return grub_error (GRUB_ERR_BAD_OS, + "encrypted images aren't supported yet"); + } + if (hibhead.restorepage*XNU_PAGESIZEXNU_MEMORY_END) + { + grub_file_close (file); + return grub_error (GRUB_ERR_BAD_OS, + "loading address isn't within allowable space"); + } + + /*calculate total size before pages to copy*/ + total_header_size=hibhead.extmapsize+sizeof (hibhead); + + /* Unload image if any*/ + if (grub_xnu_hibernate_image) + grub_free (grub_xnu_hibernate_image); + + /*Try to allocate necessary space*/ + grub_xnu_hibernate_image = buf = grub_malloc (hibhead.image_size); + if (!buf) + { + grub_file_close (file); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "not enough memory to load image"); + } + + /* Read image*/ + grub_file_seek (file, 0); + grub_file_read (file, buf, hibhead.image_size); + grub_file_close (file); + + /* Checksum the pages to copy */ + csum1=1; + csum2=0; + for (ptr=(grub_uint8_t*)buf+total_header_size; + ptr<(grub_uint8_t*)buf+total_header_size + +hibhead.numofpages*XNU_PAGESIZE; + ptr++) + { + csum1 += *ptr; + csum2 += csum1; + } + ((struct xnu_hibernate_header *)buf)->restored_checksum=(csum2<<16)|csum1; + + /* Move starting pages to appropriate locations */ + memcpy ((void *)(hibhead.restorepage*XNU_PAGESIZE), + (grub_uint8_t*)buf+total_header_size, + hibhead.restorepage*XNU_PAGESIZE); + + /* Setup variables needed by booter*/ + grub_xnu_stack=(void*)(hibhead.restorepage*XNU_PAGESIZE+hibhead.stack); + grub_xnu_entry_point + = (void*)(hibhead.restorepage*XNU_PAGESIZE+hibhead.entry_point); + grub_xnu_arg1 = buf; + + /* We're ready now */ + grub_loader_set (grub_xnu_boot, + grub_xnu_resume_unload, 1); + grub_dl_ref (my_mod); + + return GRUB_ERR_NONE; +} + + + +GRUB_MOD_INIT(xnu) +{ + (void) mod; /* To stop warning. */ + grub_register_command ("xnu_resume", grub_cmd_xnu_resume, + GRUB_COMMAND_FLAG_BOTH, + "xnu_resume FILE", "Load XNU hibernate image.", 0); + my_mod=mod; +} + +GRUB_MOD_FINI(xnu) +{ + grub_unregister_command ("xnu_resume"); +} --------------060600030508080805060204--