grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH]: Add sparc64 boot block implementation.


From: David Miller
Subject: [PATCH]: Add sparc64 boot block implementation.
Date: Sat, 11 Apr 2009 01:38:00 -0700 (PDT)

This adds the sparc64 boot block implementation for GRUB.
There might end up being minor changes to this in the end,
depending upon how we end up handling openfirmware path names.

But by in large this is the final way the code will look.

I've documented how these boot blocks work on several
occaisions here.  This is a link to one such posting:

        http://lists.gnu.org/archive/html/grub-devel/2009-03/msg00059.html

2009-04-11 David S. Miller <address@hidden>

        * include/grub/sparc64/ieee1275/boot.h: New file.
        * boot/sparc64/ieee1275/boot.S: Likewise.
        * boot/sparc64/ieee1275/diskboot.S: Likewise.
---
 boot/sparc64/ieee1275/boot.S         |  196 ++++++++++++++++++++++++++++++++++
 boot/sparc64/ieee1275/diskboot.S     |  145 +++++++++++++++++++++++++
 include/grub/sparc64/ieee1275/boot.h |   58 ++++++++++
 3 files changed, 399 insertions(+), 0 deletions(-)
 create mode 100644 boot/sparc64/ieee1275/boot.S
 create mode 100644 boot/sparc64/ieee1275/diskboot.S
 create mode 100644 include/grub/sparc64/ieee1275/boot.h

diff --git a/boot/sparc64/ieee1275/boot.S b/boot/sparc64/ieee1275/boot.S
new file mode 100644
index 0000000..74f4ee0
--- /dev/null
+++ b/boot/sparc64/ieee1275/boot.S
@@ -0,0 +1,196 @@
+/* -*-Asm-*- */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  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 <grub/boot.h>
+#include <grub/machine/boot.h>
+
+       .text
+       .align  4
+       .globl  _start
+_start:
+       /* OF CIF entry point arrives in %o4 */
+pic_base:
+       call    boot_continue
+        mov    %o4, CIF_REG
+
+       . = _start + GRUB_BOOT_MACHINE_VER_MAJ
+boot_version:          .byte   GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
+
+       /* The offsets to these locations are defined by the
+        * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h,
+        * and grub-setup uses this to patch these next three values as needed.
+        *
+        * The boot_path will be the OF device path of the partition where the
+        * rest of the GRUB kernel image resides.  kernel_sector will be set to
+        * the location of the first block of the GRUB kernel, and
+        * kernel_address is the location where we should load that first block.
+        *
+        * After loading in that block we will execute it by jumping to the
+        * load address plus the size of the prepended A.OUT header (32 bytes).
+        */
+boot_path:
+       . = _start + GRUB_BOOT_MACHINE_KERNEL_SECTOR
+kernel_sector:         .xword 2
+kernel_address:                .word  GRUB_BOOT_MACHINE_KERNEL_ADDR
+
+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 "
+#define GRUB_NAME_LEN  5
+
+       .align  4
+
+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
+
+boot_continue:
+       mov     %o7, PIC_REG            /* PIC base */
+       sethi   %hi(SCRATCH_PAD), %l1   /* OF argument slots */
+
+       /* Find the /chosen node so we can fetch the stdout handle,
+        * and thus perform console output.
+        *
+        * chosen_node = prom_finddevice("/chosen")
+        */
+       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
+
+       /* getprop(chosen_node, "stdout", &buffer, buffer_size) */
+        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
+
+       /* write(stdout_node, "GRUB ", strlen("GRUB ")) */
+        GET_ABS(grub_name, %o2)
+       call    console_write
+        mov    GRUB_NAME_LEN, %o3
+
+       /* Open up the boot_path, and use that handle to read the
+        * first block of the GRUB kernel image.
+        *
+        * bootdev_handle = open(boot_path)
+        */
+       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
+
+       /* Since we have 64-bit cells, the high cell of the seek offset
+        * is zero and the low cell is the entire value.
+        *
+        * seek(bootdev, 0, *kernel_sector << 9)
+        */
+        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
+
+       /* read(bootdev, *kernel_address, 512) */
+       GET_ABS(prom_read_name, %o0)
+       mov     BOOTDEV_REG, %o1
+       LDUW_ABS(kernel_address, 0x00, %o2)
+       call    prom_call_3_1
+        mov    512, %o3
+
+       LDUW_ABS(kernel_address, 0x00, %o2)
+       jmpl    %o2, %o7
+        nop
+
+1:     ba,a    1b
+
+       . = _start + GRUB_BOOT_MACHINE_CODE_END
+
+/* the last 4 bytes in the sector 0 contain the signature */
+       .word   GRUB_BOOT_MACHINE_SIGNATURE
diff --git a/boot/sparc64/ieee1275/diskboot.S b/boot/sparc64/ieee1275/diskboot.S
new file mode 100644
index 0000000..68ed0ee
--- /dev/null
+++ b/boot/sparc64/ieee1275/diskboot.S
@@ -0,0 +1,145 @@
+/* -*-Asm-*- */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  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 <grub/boot.h>
+#include <grub/machine/boot.h>
+
+       .text
+       .align  4
+       .globl  _start
+_start:
+       /* First stage boot block jumps to us here.  */
+pic_base:
+       call    after_info_block
+        mov    %o7, PIC_REG
+
+prom_write_name:               .asciz "write"
+prom_seek_name:                        .asciz "seek"
+prom_read_name:                        .asciz "read"
+prom_close_name:               .asciz "close"
+
+notification_string:           .asciz "Loading kernel"
+#define NOTIFICATION_STRING_LEN        14
+
+notification_step:             .asciz "."
+#define NOTIFICATION_STEP_LEN  1
+
+notification_done:             .asciz "\r\n"
+#define NOTIFICATION_DONE_LEN  2
+
+       .align  4
+
+       /* %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
+
+
+after_info_block:
+       sethi   %hi(SCRATCH_PAD), %l1   /* OF argument slots */
+
+       GET_ABS(notification_string, %o2)
+       call    console_write
+        mov    NOTIFICATION_STRING_LEN, %o3
+
+       GET_ABS(firstlist - GRUB_BOOT_MACHINE_LIST_SIZE, %l2)
+       set     GRUB_BOOT_MACHINE_IMAGE_ADDRESS, %l3
+bootloop:
+       lduw    [%l2 + 0x08], %o0
+       brz     %o0, bootit
+        lduw   [%l2 + 0x00], %o3
+       sllx    %o3, 32, %o3
+       lduw    [%l2 + 0x04], %o4
+       or      %o3, %o4, %o3
+       GET_ABS(prom_seek_name, %o0)
+       mov     BOOTDEV_REG, %o1
+       clr     %o2
+       call    prom_call_3_1
+        sllx   %o3, 9, %o3
+
+       GET_ABS(prom_read_name, %o0)
+       mov     BOOTDEV_REG, %o1
+       lduw    [%l2 + 0x08], %o3
+       sllx    %o3, 9, %o3
+       mov     %l3, %o2
+       call    prom_call_3_1
+        add    %l3, %o3, %l3
+
+       GET_ABS(notification_step, %o2)
+       call    console_write
+        mov    NOTIFICATION_STEP_LEN, %o3
+
+       ba      bootloop
+        sub    %l2, GRUB_BOOT_MACHINE_LIST_SIZE, %l2
+
+bootit:
+       GET_ABS(prom_close_name, %o0)
+       mov     1, %g1
+       mov     0, %o5
+       call    prom_call
+        mov    BOOTDEV_REG, %o1
+
+       GET_ABS(notification_done, %o2)
+       call    console_write
+        mov    NOTIFICATION_DONE_LEN, %o3
+       sethi   %hi(GRUB_BOOT_MACHINE_IMAGE_ADDRESS), %o2
+       jmpl    %o2 + %lo(GRUB_BOOT_MACHINE_IMAGE_ADDRESS), %o7
+        mov    CIF_REG, %o0
+1:     ba,a    1b
+
+lastlist:
+       .word   0
+       .word   0
+
+       . = _start + (0x200 - GRUB_BOOT_MACHINE_LIST_SIZE)
+blocklist_default_start:
+       .word   0
+       .word   2
+blocklist_default_len:
+       .word   0
+firstlist:
diff --git a/include/grub/sparc64/ieee1275/boot.h 
b/include/grub/sparc64/ieee1275/boot.h
new file mode 100644
index 0000000..95f311c
--- /dev/null
+++ b/include/grub/sparc64/ieee1275/boot.h
@@ -0,0 +1,58 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009   Free Software Foundation, Inc.
+ *
+ *  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/>.
+ */
+
+#ifndef GRUB_BOOT_MACHINE_HEADER
+#define GRUB_BOOT_MACHINE_HEADER       1
+
+#define CIF_REG                                %l0
+#define CHOSEN_NODE_REG                        %l4
+#define STDOUT_NODE_REG                        %l5
+#define BOOTDEV_REG                    %l6
+#define PIC_REG                                %l7
+
+#define        SCRATCH_PAD                     0x10000
+
+#define GET_ABS(symbol, reg)   \
+       add     PIC_REG, (symbol - pic_base), reg
+#define LDUW_ABS(symbol, offset, reg)  \
+       lduw    [PIC_REG + (symbol - pic_base) + (offset)], reg
+#define LDX_ABS(symbol, offset, reg)   \
+       ldx     [PIC_REG + (symbol - pic_base) + (offset)], reg
+
+#define GRUB_BOOT_AOUT_HEADER_SIZE     32
+
+#define GRUB_BOOT_MACHINE_SIGNATURE    0xbb44aa55
+
+#define GRUB_BOOT_MACHINE_VER_MAJ      0x08
+
+#define GRUB_BOOT_MACHINE_BOOT_DEVPATH 0x0a
+
+#define GRUB_BOOT_MACHINE_BOOT_DEVPATH_END 0x80
+
+#define GRUB_BOOT_MACHINE_KERNEL_SECTOR 0x88
+
+#define GRUB_BOOT_MACHINE_CODE_END \
+       (0x1fc - GRUB_BOOT_AOUT_HEADER_SIZE)
+
+#define GRUB_BOOT_MACHINE_LIST_SIZE    12
+
+#define GRUB_BOOT_MACHINE_IMAGE_ADDRESS        0x200000
+
+#define GRUB_BOOT_MACHINE_KERNEL_ADDR 0x4200
+
+#endif /* ! BOOT_MACHINE_HEADER */
-- 
1.6.2.1.222.g570cc





reply via email to

[Prev in Thread] Current Thread [Next in Thread]