[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 9/10]: Add sparc64 boot block code.
From: |
David Miller |
Subject: |
[PATCH 9/10]: Add sparc64 boot block code. |
Date: |
Wed, 04 Mar 2009 17:32:40 -0800 (PST) |
2009-03-04 David S. Miller <address@hidden>
* include/grub/sparc64/ieee1275/boot.h: New file.
* boot/sparc/ieee1275/boot.S: Likewise.
* boot/sparc/ieee1275/diskboot.S: Likewise.
* conf/sparc64-ieee1275.rmk: Build sparc boot blocks.
* conf/sparc64-ieee1275.mk: Regenerate.
---
boot/sparc/ieee1275/boot.S | 196 ++++++++++++++++++++++++++++++++++
boot/sparc/ieee1275/diskboot.S | 145 +++++++++++++++++++++++++
conf/sparc64-ieee1275.rmk | 12 ++
include/grub/sparc64/ieee1275/boot.h | 60 ++++++++++
4 files changed, 413 insertions(+), 0 deletions(-)
create mode 100644 boot/sparc/ieee1275/boot.S
create mode 100644 boot/sparc/ieee1275/diskboot.S
create mode 100644 include/grub/sparc64/ieee1275/boot.h
diff --git a/boot/sparc/ieee1275/boot.S b/boot/sparc/ieee1275/boot.S
new file mode 100644
index 0000000..a9ea0b6
--- /dev/null
+++ b/boot/sparc/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_ADDRESS
+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 + GRUB_BOOT_AOUT_HEADER_SIZE, %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/sparc/ieee1275/diskboot.S b/boot/sparc/ieee1275/diskboot.S
new file mode 100644
index 0000000..e9bc854
--- /dev/null
+++ b/boot/sparc/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_AOUT_HEADER_SIZE -
GRUB_BOOT_MACHINE_LIST_SIZE)
+blocklist_default_start:
+ .word 0
+ .word 2
+blocklist_default_len:
+ .word 0
+firstlist:
diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk
index 5be3eeb..f07e891 100644
--- a/conf/sparc64-ieee1275.rmk
+++ b/conf/sparc64-ieee1275.rmk
@@ -9,6 +9,18 @@ COMMON_LDFLAGS = -melf64_sparc -nostdlib -mno-relax
normal/lexer.c_DEPENDENCIES = grub_script.tab.h
# Images.
+IMG_FMT = a.out-sunos-big
+pkglib_IMAGES = boot.img diskboot.img
+
+# For boot.img.
+boot_img_SOURCES = boot/sparc/ieee1275/boot.S
+boot_img_ASFLAGS = $(COMMON_ASFLAGS)
+boot_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-Ttext,0x4000
+
+# For diskboot.img.
+diskboot_img_SOURCES = boot/sparc/ieee1275/diskboot.S
+diskboot_img_ASFLAGS = $(COMMON_ASFLAGS)
+diskboot_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-Ttext,0x4200
MOSTLYCLEANFILES += symlist.c kernel_syms.lst
DEFSYMFILES += kernel_syms.lst
diff --git a/include/grub/sparc64/ieee1275/boot.h
b/include/grub/sparc64/ieee1275/boot.h
new file mode 100644
index 0000000..0160e06
--- /dev/null
+++ b/include/grub/sparc64/ieee1275/boot.h
@@ -0,0 +1,60 @@
+/*
+ * 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 0x80
+
+#define GRUB_BOOT_MACHINE_KERNEL_ADDRESS 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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH 9/10]: Add sparc64 boot block code.,
David Miller <=