[Top][All Lists]
[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH]: Add sparc64 boot block implementation.,
David Miller <=