From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1LlBrX-0006qS-D5 for mharc-grub-devel@gnu.org; Sat, 21 Mar 2009 20:48:27 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LlBrT-0006pm-Io for grub-devel@gnu.org; Sat, 21 Mar 2009 20:48:23 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LlBrO-0006pa-RF for grub-devel@gnu.org; Sat, 21 Mar 2009 20:48:22 -0400 Received: from [199.232.76.173] (port=37043 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LlBrO-0006pX-Lg for grub-devel@gnu.org; Sat, 21 Mar 2009 20:48:18 -0400 Received: from fg-out-1718.google.com ([72.14.220.156]:8372) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LlBrN-0001l5-SD for grub-devel@gnu.org; Sat, 21 Mar 2009 20:48:18 -0400 Received: by fg-out-1718.google.com with SMTP id l27so207079fgb.7 for ; Sat, 21 Mar 2009 17:48:16 -0700 (PDT) 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:references:in-reply-to :content-type:content-transfer-encoding; bh=A2ZKE/rXg5YWzL/pEXr2+ctmHRdwZgT/8PZ1zrbAZNs=; b=gTuwdvL/A8LlqIK6EEv4RtG08J1FE/vf/wpdJfy5ro5eoreuIjAzeco2x20BJ0DT76 S3n/dPAZDGTbhQ5q/MY+cwdh4k74/b+53cxtDBe6J+hU549fMqn13h6ScCrjD1+stI32 X2Ww+c7bWNCMacnLLV+j31qtwPC4Q97nhPYWk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type:content-transfer-encoding; b=BD8Posf68lvlxd8AUJ9nCnF6mm88YAx6KJhrdTpdD/dWG/a8KCS4MHbEHKnR65+R3N jLlh7gvnRUjq1Zr1T9pPT4vL7kmzphY3v+9C5hbKO6gxFCrMyd+uoSmszbajvhzIJ/2P elngBYJTZzmrGoiCcQw37ueEcZGj3FTWzLg5U= Received: by 10.86.53.11 with SMTP id b11mr2511231fga.70.1237682896210; Sat, 21 Mar 2009 17:48:16 -0700 (PDT) Received: from ?192.168.1.25? (217-154.203-62.cust.bluewin.ch [62.203.154.217]) by mx.google.com with ESMTPS id d6sm5381806fga.2.2009.03.21.17.48.15 (version=SSLv3 cipher=RC4-MD5); Sat, 21 Mar 2009 17:48:15 -0700 (PDT) Message-ID: <49C58ACE.6020309@gmail.com> Date: Sun, 22 Mar 2009 01:48:14 +0100 From: phcoder User-Agent: Thunderbird 2.0.0.21 (X11/20090318) MIME-Version: 1.0 To: The development of GRUB 2 References: <20090315.154116.198032129.davem@davemloft.net> <20090318101846.GD20072@thorin> <20090318.135522.254268985.davem@davemloft.net> <20090318.140153.206376672.davem@davemloft.net> <49C58950.90104@gmail.com> In-Reply-To: <49C58950.90104@gmail.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: Re: GRUB device names wrt. ieee1275 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: Sun, 22 Mar 2009 00:48:24 -0000 phcoder wrote: > Device name in boot block will anyway be written in it's complete raw > OFW form, no matter how the rest of the grub2 accessing the disks. Using > UUIDs in this place would be nice. On IRC you said that we have 120 > bytes for the name. UUID is 16 or 32 bytes depending on FS. Is it > possible to fit something like of every disk, > ? Could we use label checksum for finding right disk? > I don't agree that all devices should be accessed exclusively by UUID. > It makes things difficult to maintain because of internal naming. IMO > quoting and escaping offers the best universal solution. I don't see why > sth like > (/pci@1e\,600000/pci@0/pci@9/pci@0/scsi@1/disk@0,1) > is a problem. Anyway you don't type such a thing manually and probably > use tab-completition instead > > > David Miller wrote: >> From: David Miller >> Date: Wed, 18 Mar 2009 13:55:22 -0700 (PDT) >> >>> From: Robert Millan >>> Date: Wed, 18 Mar 2009 11:18:46 +0100 >>> >>>> On Sun, Mar 15, 2009 at 03:41:16PM -0700, David Miller wrote: >>>>> From: Robert Millan >>>>> Date: Sun, 15 Mar 2009 16:45:31 +0100 >>>>> >>>>>> It's not an absolute must that device names are unique. You can >>>>>> still >>>>>> identify partitions by their filesystem UUID or label, and in fact >>>>>> this >>>>>> is what our default scripts (grub-mkconfig) do anyway. >>>>> Things like UUID and labels are not an option for the 512-byte >>>>> boot block where I have to know the exact OBP path of the boot >>>>> device, and this is what the GRUB kernel fetches from the >>>>> 'bootpath' environment variable to compose the root device >>>>> and path. >>>> What 512-byte boot block? >>> The one I add in my sparc64 support changes. >>> >>> Included here for reference: >> >> BTW, I explained exactly how this 512 byte boot block works, in >> extreme detail, when I first posted my grub sparc64 patches. >> >> I am including it here _again_, please read it, it's informative, >> I promise, and I didn't post it the first time for my health! >> >> Thanks! >> >> -------------------- >> >> The first task is to get the first stage boot block going. There are >> two choices on how to do this. When you type "boot" for a block >> device, the firmware loads 7.5K starting at the second 512-byte >> block. If this block device is the third partition (the "all disk" >> partition in the Sun disk label) this bootblock starts after the disk >> label. >> >> Under Linux we really can only use 512 bytes of that boot block area, >> because it's possible for the filesystem superblock to show up as >> early as the very next 512 byte block. >> >> The firmware lets you put in the block some sparc executable image >> (tried by the firmware as 64-bit ELF, then 32-bit ELF, and finally as >> A.OUT) or tokenized forth. Since 1) we only have 512 bytes and 2) >> there are no fully GPL'd forth tokenizer implementations (the openbios >> folks use something that is BSD and MIT licensed) we'll need to go the >> sparc image route. >> >> The task of this 512 byte sequence of code is to load the next stage >> of the bootloader. For GRUB I've choosen a multi-tiered scheme similar >> to how the x86 stuff works. The first stage bootloader loads a single >> block from the disk and jumps to it. This block we load is actually a >> header block of the main boot loader binary, a second stage loader, >> which loads the rest of the image. >> >> This first stage loader therefore needs a few parameters. It needs to >> know the OF device path where the second stage header block >> resides. It needs to know the block to read, and finally it needs to >> know where to load that block and thus where to jump to it for >> execution. >> >> We'd also like to print some status messages to the screen while this >> happens and have at least some minimal error handling. Not a small >> feat in 512 bytes. >> >> We put everything in the text section, and the first thing we do is >> jump over our embedded data bits: >> >> .text >> .align 4 >> .globl _start >> _start: >> /* OF CIF entry point arrives in %o4 */ >> pic_base: >> call boot_continue >> mov %o4, CIF_REG >> >> The "CIF" is the client interface to openfirmware. Calls are made by >> initializing an array of cells (64-bits on sparc64) in memory which >> describe the call to be made, the input arguments, and the return >> values (if any). This value provided in %o4 is the OF entry point we >> jump to when making calls. The only register argument goes in %o0 and >> is the base of the aforementioned array of cells. >> >> The offsets into the bits coming up are defined in a GRUB boot.h >> header file so that tools can patch in values during bootblock >> installation. >> >> . = _start + GRUB_BOOT_MACHINE_VER_MAJ >> boot_version: .byte GRUB_BOOT_VERSION_MAJOR, >> GRUB_BOOT_VERSION_MINOR >> boot_path: >> . = _start + GRUB_BOOT_MACHINE_KERNEL_ADDRESS >> kernel_sector: .xword 2 >> kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR >> >> The boot_version is just a version blob that various tools and >> sub-bootloaders could validate for compatibility if they wanted to. It >> is unused currently. >> >> The boot_path will be filled in by the boot block installation tools >> with the boot device OF path. kernel_sector and kernel_address tell >> where to load the image from the device into memory. Next, we have >> string constants we'll need to make OF calls and put messages onto the >> console: >> >> prom_finddev_name: .asciz "finddevice" >> prom_chosen_path: .asciz "/chosen" >> prom_getprop_name: .asciz "getprop" >> prom_stdout_name: .asciz "stdout" >> prom_write_name: .asciz "write" >> prom_bootpath_name: .asciz "bootpath" >> prom_open_name: .asciz "open" >> prom_seek_name: .asciz "seek" >> prom_read_name: .asciz "read" >> prom_exit_name: .asciz "exit" >> grub_name: .asciz "GRUB " >> >> To simplify things we'll write all of our code as position >> independent. There are other macros in the boot.h header which >> describe these register name macros such as CIF_REG, PIC_REG, >> etc. most are local registers which are not volatils across OF calls, >> so we can keep stable values in them. It also defines macros to >> compute absolute addresses of a symbol using this PIC_REG, into a >> register. >> >> The next chunk of code are helpers for doing OF calls with various >> sets of input and output arguments. >> >> prom_open_error: >> GET_ABS(prom_open_name, %o2) >> call console_write >> mov 4, %o3 >> /* fallthru */ >> >> prom_error: >> GET_ABS(prom_exit_name, %o0) >> /* fallthru */ >> >> /* %o0: OF call name >> * %o1: input arg 1 >> */ >> prom_call_1_1: >> mov 1, %g1 >> ba prom_call >> mov 1, %o5 >> >> /* %o2: message string >> * %o3: message length >> */ >> console_write: >> GET_ABS(prom_write_name, %o0) >> mov STDOUT_NODE_REG, %o1 >> /* fallthru */ >> >> /* %o0: OF call name >> * %o1: input arg 1 >> * %o2: input arg 2 >> * %o3: input arg 3 >> */ >> prom_call_3_1: >> mov 3, %g1 >> mov 1, %o5 >> /* fallthru */ >> >> /* %o0: OF call name >> * %g1: num inputs >> * %o5: num outputs >> * %o1-%o4: inputs >> */ >> prom_call: >> stx %o0, [%l1 + 0x00] >> stx %g1, [%l1 + 0x08] >> stx %o5, [%l1 + 0x10] >> stx %o1, [%l1 + 0x18] >> stx %o2, [%l1 + 0x20] >> stx %o3, [%l1 + 0x28] >> stx %o4, [%l1 + 0x30] >> jmpl CIF_REG, %g0 >> mov %l1, %o0 >> >> All of those routines are "call" invoked, and we do the CIF OF call >> using "jmpl" with no return register write in order to make the CIF OF >> call return to the stub caller, ie. a tail call. This way we don't >> need to allocate a register window here or anything complicated like >> that. >> >> Now for the code we jumped to at the _start header. Our first task is >> to save away the PIC_REG (%o7 was set by the initial "call" >> instruction, and will be equal to _start, we use it to reference our >> data blobs PC relative). Also we setup register %l1 which holds the >> base of the OF cell argument data block used above. SCRATCH_PAD is >> defined to 0x10000, which is guarenteed to be mapped by OF and outside >> of where we will be executing (which is at 0x4000). >> >> boot_continue: >> mov %o7, PIC_REG /* PIC base */ >> sethi %hi(SCRATCH_PAD), %l1 /* OF argument slots */ >> >> We need the console stdout handle to write console messages, this is >> done by finding the "/chosen" directory in the OF device tree, and >> fetching from there the "stdout" property which is a 32-bit handle. >> >> GET_ABS(prom_finddev_name, %o0) >> GET_ABS(prom_chosen_path, %o1) >> call prom_call_1_1 >> clr %o2 >> ldx [%l1 + 0x20], CHOSEN_NODE_REG >> brz CHOSEN_NODE_REG, prom_error >> GET_ABS(prom_getprop_name, %o0) >> mov 4, %g1 >> mov 1, %o5 >> mov CHOSEN_NODE_REG, %o1 >> GET_ABS(prom_stdout_name, %o2) >> add %l1, 256, %o3 >> mov 1024, %o4 >> call prom_call >> stx %g1, [%l1 + 256] >> lduw [%l1 + 256], STDOUT_NODE_REG >> brz,pn STDOUT_NODE_REG, prom_error >> >> Since we have very little space, the error handling has to be >> small. The "clr %o2" in the prom_call_1_1 invocation causes the return >> value cell slot (at %l1 + 0x20) to be cleared by the prom_call >> code. Zero is not a prom handle we'll get back, so if the slot stays >> zero we took an error. In the getprop call to get the 'stdout' handle, >> we rely upon OF providing us with zero'd memory outside of the boot >> block image. >> >> Now that we have the console output cookie, we can print out a message: >> >> GET_ABS(grub_name, %o2) >> call console_write >> mov 5, %o3 >> >> Next, we open up the boot device: >> >> GET_ABS(prom_open_name, %o0) >> GET_ABS(boot_path, %o1) >> call prom_call_1_1 >> clr %o2 >> >> ldx [%l1 + 0x20], BOOTDEV_REG >> brz,pn BOOTDEV_REG, prom_open_error >> >> We now seek to the appropriate block: >> >> GET_ABS(prom_seek_name, %o0) >> mov BOOTDEV_REG, %o1 >> clr %o2 >> LDX_ABS(kernel_sector, 0x00, %o3) >> call prom_call_3_1 >> sllx %o3, 9, %o3 >> >> and finally read the block into memory: >> >> GET_ABS(prom_read_name, %o0) >> mov BOOTDEV_REG, %o1 >> LDUW_ABS(kernel_address, 0x00, %o2) >> call prom_call_3_1 >> mov 512, %o3 >> >> This image will be an A.OUT image as well, so we jump into it right >> past the A.OUT header: >> >> LDUW_ABS(kernel_address, 0x00, %o2) >> jmpl %o2 + GRUB_BOOT_AOUT_HEADER_SIZE, %o7 >> nop >> 1: ba,a 1b >> >> Just for fun we put an endless loop after the jump in case it does >> return for some reason. We could, alternatively, call prom_error >> instead. Now skip to 4 bytes right before the end of the 512-byte >> block and write a signature cookie. >> >> . = _start + GRUB_BOOT_MACHINE_CODE_END >> >> /* the last 4 bytes in the sector 0 contain the signature */ >> .word GRUB_BOOT_MACHINE_SIGNATURE >> >> And that's the whole boot block implementation. This file is compiled >> normally into first an ELF image using GCC. Then we strip out all the >> symbols and other junk, and finally use objcopy to output an A.OUT >> object. It is exactly 512 bytes in size and the bootblock installer >> verifies this. >> >> The second stage header block code now can take advantage of all of >> the values the first stage has computed, such as the stdout handle, >> the handle for the boot device, etc. In the second stage image, it >> begins with assembler just like the first stage does above. But, it >> implements a block + length tuple list which grows down from the end >> of the block. This tells us where to read in the rest of the GRUB >> kernel from the actual file on the disk. >> >> The GRUB installer program links in with modules that understand how >> various filesystems work. It has a block traverser that can be run on >> arbitrary files. This is the mechanism used to build the block list >> which is patched into this second stage loader block list. >> >> I've tested both of these using a Sun LDOM guest, which is the fastest >> way to test low-level stuff like this since resetting (which you need >> to do every test boot attempt) is nearly instantaneous. >> >> The current task is to flesh out the installer programs and make sure >> the rest of the GRUB ieee1275 code is going to work properly on >> sparc. I already know some bits that will need some tweaking. For >> example, partitions on OF paths are indicated (aparently) by adding >> ":N" where N is a partition number. On sparc this "N" is instead a >> letter. >> >> >> _______________________________________________ >> Grub-devel mailing list >> Grub-devel@gnu.org >> http://lists.gnu.org/mailman/listinfo/grub-devel > > -- Regards Vladimir 'phcoder' Serbinenko