mirror of
https://git.savannah.gnu.org/git/grub.git
synced 2026-10-27 01:29:27 +00:00
Recommit my work on alpha
This commit is contained in:
1 parent
c6dc6fa175
commit
85872c8373
31 files changed
+1401
-10
No files matched your search
@@ -140,6 +140,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
endif
|
||||
|
||||
if COND_alpha_srm
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/alpha/divide.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
endif
|
||||
|
||||
if COND_mips
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h
|
||||
endif
|
||||
|
||||
@@ -70,6 +70,8 @@ kernel = {
|
||||
|
||||
ldadd = '$(LDADD_KERNEL)';
|
||||
|
||||
alpha_srm_cflags = '-mcpu=ev4 -mno-fp-regs -ffixed-8';
|
||||
|
||||
i386_coreboot_ldflags = '-Wl,-Ttext=0x8200';
|
||||
i386_multiboot_ldflags = '-Wl,-Ttext=0x8200';
|
||||
i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000';
|
||||
@@ -78,6 +80,7 @@ kernel = {
|
||||
sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400';
|
||||
mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)';
|
||||
mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000';
|
||||
alpha_srm_ldflags = '-Wl,-Ttext,0x20000000';
|
||||
|
||||
mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)';
|
||||
mips_loongson_cppflags = '-DUSE_ASCII_FALLBACK';
|
||||
@@ -97,6 +100,7 @@ kernel = {
|
||||
mips_startup = kern/mips/startup.S;
|
||||
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
|
||||
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
|
||||
alpha_srm_startup = kern/alpha/srm/startup.S;
|
||||
arm_uboot_startup = kern/arm/uboot/startup.S;
|
||||
arm_efi_startup = kern/arm/efi/startup.S;
|
||||
|
||||
@@ -125,6 +129,7 @@ kernel = {
|
||||
noemu_nodist = symlist.c;
|
||||
|
||||
mips = kern/generic/rtc_get_time_ms.c;
|
||||
alpha_srm = kern/generic/rtc_get_time_ms.c;
|
||||
|
||||
ieee1275 = disk/ieee1275/ofdisk.c;
|
||||
ieee1275 = kern/ieee1275/cmain.c;
|
||||
@@ -237,6 +242,15 @@ kernel = {
|
||||
arm = kern/arm/cache.c;
|
||||
arm = kern/arm/misc.S;
|
||||
|
||||
alpha_srm = kern/alpha/srm/dispatch.S;
|
||||
alpha_srm = kern/alpha/dl.c;
|
||||
alpha_srm = kern/alpha/cache.S;
|
||||
alpha_srm = kern/alpha/divide.S;
|
||||
alpha_srm = kern/alpha/srm/pal_init.c;
|
||||
alpha_srm = kern/alpha/srm/init.c;
|
||||
alpha_srm = term/alpha/srm/console.c;
|
||||
alpha_srm = disk/alpha/srm/srmdisk.c;
|
||||
|
||||
emu = disk/host.c;
|
||||
emu = kern/emu/cache_s.S;
|
||||
emu = kern/emu/hostdisk.c;
|
||||
@@ -792,6 +806,8 @@ module = {
|
||||
i386_qemu = lib/i386/halt.c;
|
||||
efi = lib/efi/halt.c;
|
||||
ieee1275 = lib/ieee1275/halt.c;
|
||||
alpha_srm = lib/alpha/srm/halt.c;
|
||||
|
||||
emu = lib/emu/halt.c;
|
||||
uboot = lib/uboot/halt.c;
|
||||
};
|
||||
@@ -1491,6 +1507,7 @@ module = {
|
||||
powerpc_ieee1275 = lib/ieee1275/cmos.c;
|
||||
|
||||
mips_arc = lib/arc/datetime.c;
|
||||
alpha_srm = lib/alpha/srm/datetime.c;
|
||||
enable = noemu;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
/* ofdisk.c - Open Firmware disk access. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2004,2006,2007,2008,2009,2011 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/misc.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/alpha/srm/srm.h>
|
||||
|
||||
static grub_srm_fileno_t last_handle = 0;
|
||||
static char *last_path = NULL;
|
||||
|
||||
static int lnum = 0;
|
||||
|
||||
struct srmdisk_hash_ent
|
||||
{
|
||||
char *devpath;
|
||||
int num;
|
||||
struct srmdisk_hash_ent *next;
|
||||
};
|
||||
|
||||
#define SRMDISK_HASH_SZ 8
|
||||
static struct srmdisk_hash_ent *srmdisk_hash[SRMDISK_HASH_SZ];
|
||||
|
||||
static int
|
||||
srmdisk_hash_fn (const char *devpath)
|
||||
{
|
||||
int hash = 0;
|
||||
while (*devpath)
|
||||
hash ^= *devpath++;
|
||||
return (hash & (SRMDISK_HASH_SZ - 1));
|
||||
}
|
||||
|
||||
static struct srmdisk_hash_ent *
|
||||
srmdisk_hash_find (const char *devpath)
|
||||
{
|
||||
struct srmdisk_hash_ent *p = srmdisk_hash[srmdisk_hash_fn (devpath)];
|
||||
|
||||
while (p)
|
||||
{
|
||||
if (!grub_strcmp (p->devpath, devpath))
|
||||
break;
|
||||
p = p->next;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct srmdisk_hash_ent *
|
||||
srmdisk_hash_add (char *devpath)
|
||||
{
|
||||
struct srmdisk_hash_ent *p;
|
||||
struct srmdisk_hash_ent **head = &srmdisk_hash[srmdisk_hash_fn(devpath)];
|
||||
|
||||
p = grub_malloc (sizeof (*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
p->devpath = devpath;
|
||||
p->next = *head;
|
||||
p->num = lnum++;
|
||||
*head = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
grub_srmdisk_iterate (int (*hook) (const char *name))
|
||||
{
|
||||
(void) hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
reopen (const char *name)
|
||||
{
|
||||
grub_uint64_t r;
|
||||
|
||||
if (last_path && grub_strcmp (last_path, name) == 0)
|
||||
{
|
||||
grub_dprintf ("srmdisk", "using already opened %s\n", name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (last_path)
|
||||
{
|
||||
grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_CLOSE, last_handle);
|
||||
grub_free (last_path);
|
||||
last_path = NULL;
|
||||
last_handle = 0;
|
||||
}
|
||||
|
||||
grub_dprintf ("srmdisk", "opening %s\n", name);
|
||||
r = grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_OPEN, name, grub_strlen (name));
|
||||
grub_printf ("<%lx>", r);
|
||||
while (1);
|
||||
if (r & (1ULL << 63))
|
||||
{
|
||||
grub_dprintf ("srmdisk", "couldn't open %s\n", name);
|
||||
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
|
||||
}
|
||||
last_path = grub_strdup (name);
|
||||
if (!last_path)
|
||||
return grub_errno;
|
||||
last_handle = r & 0xffffffff;
|
||||
grub_dprintf ("srmdisk", "opened %s\n", name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_srmdisk_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
char *fullname;
|
||||
grub_err_t err;
|
||||
struct srmdisk_hash_ent *hash;
|
||||
|
||||
if (grub_memcmp (name, "srm/", 4) != 0)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not srm device");
|
||||
fullname = grub_strdup (name + 4);
|
||||
if (!fullname)
|
||||
return grub_errno;
|
||||
disk->data = fullname;
|
||||
grub_dprintf ("srmdisk", "opening %s\n", fullname);
|
||||
|
||||
hash = srmdisk_hash_find (fullname);
|
||||
if (!hash)
|
||||
hash = srmdisk_hash_add (fullname);
|
||||
if (!hash)
|
||||
return grub_errno;
|
||||
|
||||
err = reopen (fullname);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
{
|
||||
grub_uint64_t res = 0;
|
||||
int i;
|
||||
|
||||
/* FIXME: findout the block size. */
|
||||
for (i = 31; i >= 0; i--)
|
||||
{
|
||||
char buf[512];
|
||||
grub_dprintf ("srmdisk",
|
||||
"seek to 0x%" PRIxGRUB_UINT64_T "\n",
|
||||
res | (1UL << i));
|
||||
if (grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_READ, last_handle, 512,
|
||||
buf, res | (1ULL << i)) & (1ULL << 63))
|
||||
continue;
|
||||
res |= (1ULL << i);
|
||||
}
|
||||
grub_dprintf ("srmdisk",
|
||||
"determined disk size 0x%" PRIxGRUB_UINT64_T "\n", res);
|
||||
disk->total_sectors = res;
|
||||
}
|
||||
|
||||
disk->id = hash->num;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_srmdisk_close (grub_disk_t disk)
|
||||
{
|
||||
grub_free (disk->data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_srmdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
err = reopen (disk->data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* FIXME: handle incomplete read. */
|
||||
if (grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_READ, last_handle,
|
||||
size << 9,
|
||||
buf, sector) & (1ULL << 63))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "read failed");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_srmdisk_write (grub_disk_t disk __attribute ((unused)),
|
||||
grub_disk_addr_t sector __attribute ((unused)),
|
||||
grub_size_t size __attribute ((unused)),
|
||||
const char *buf __attribute ((unused)))
|
||||
{
|
||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
}
|
||||
|
||||
static struct grub_disk_dev grub_srmdisk_dev =
|
||||
{
|
||||
.name = "srmdisk",
|
||||
.id = GRUB_DISK_DEVICE_SRMDISK_ID,
|
||||
.iterate = grub_srmdisk_iterate,
|
||||
.open = grub_srmdisk_open,
|
||||
.close = grub_srmdisk_close,
|
||||
.read = grub_srmdisk_read,
|
||||
.write = grub_srmdisk_write,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
void
|
||||
grub_srmdisk_init (void)
|
||||
{
|
||||
grub_disk_dev_register (&grub_srmdisk_dev);
|
||||
}
|
||||
|
||||
void
|
||||
grub_srmdisk_fini (void)
|
||||
{
|
||||
if (last_path)
|
||||
{
|
||||
grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_CLOSE, last_handle);
|
||||
grub_free (last_path);
|
||||
last_path = NULL;
|
||||
last_handle = 0;
|
||||
}
|
||||
|
||||
grub_disk_dev_unregister (&grub_srmdisk_dev);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
SCSI 0 1004 0 2 200 0 0
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
#include <grub/symbol.h>
|
||||
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
|
||||
FUNCTION (grub_arch_sync_all_caches)
|
||||
call_pal 134
|
||||
ret $31,($26)
|
||||
@@ -0,0 +1,114 @@
|
||||
|
||||
#include <grub/symbol.h>
|
||||
|
||||
.set noat
|
||||
|
||||
.macro PREAMBLE
|
||||
|
||||
subq $30, 31 * 8, $30
|
||||
stq $0, (0 * 8)($30)
|
||||
stq $1, (1 * 8)($30)
|
||||
stq $2, (2 * 8)($30)
|
||||
stq $3, (3 * 8)($30)
|
||||
stq $4, (4 * 8)($30)
|
||||
stq $5, (5 * 8)($30)
|
||||
stq $6, (6 * 8)($30)
|
||||
stq $7, (7 * 8)($30)
|
||||
stq $8, (8 * 8)($30)
|
||||
stq $9, (9 * 8)($30)
|
||||
stq $10, (10 * 8)($30)
|
||||
stq $11, (11 * 8)($30)
|
||||
stq $12, (12 * 8)($30)
|
||||
stq $13, (13 * 8)($30)
|
||||
stq $14, (14 * 8)($30)
|
||||
stq $15, (15 * 8)($30)
|
||||
stq $16, (16 * 8)($30)
|
||||
stq $17, (17 * 8)($30)
|
||||
stq $18, (18 * 8)($30)
|
||||
stq $19, (19 * 8)($30)
|
||||
stq $20, (20 * 8)($30)
|
||||
stq $21, (21 * 8)($30)
|
||||
stq $22, (22 * 8)($30)
|
||||
stq $23, (23 * 8)($30)
|
||||
stq $24, (24 * 8)($30)
|
||||
stq $25, (25 * 8)($30)
|
||||
stq $26, (26 * 8)($30)
|
||||
stq $28, (28 * 8)($30)
|
||||
stq $29, (29 * 8)($30)
|
||||
addq $30, (30 * 8), $18
|
||||
/* load GP. */
|
||||
br $27, 1f
|
||||
1: ldgp $29, 0($27)
|
||||
.endm
|
||||
|
||||
.macro POSTAMBLE
|
||||
ldq $0, (0 * 8)($30)
|
||||
ldq $1, (1 * 8)($30)
|
||||
ldq $2, (2 * 8)($30)
|
||||
ldq $3, (3 * 8)($30)
|
||||
ldq $4, (4 * 8)($30)
|
||||
ldq $5, (5 * 8)($30)
|
||||
ldq $6, (6 * 8)($30)
|
||||
ldq $7, (7 * 8)($30)
|
||||
ldq $8, (8 * 8)($30)
|
||||
ldq $9, (9 * 8)($30)
|
||||
ldq $10, (10 * 8)($30)
|
||||
ldq $11, (11 * 8)($30)
|
||||
ldq $12, (12 * 8)($30)
|
||||
ldq $13, (13 * 8)($30)
|
||||
ldq $14, (14 * 8)($30)
|
||||
ldq $15, (15 * 8)($30)
|
||||
ldq $16, (16 * 8)($30)
|
||||
ldq $17, (17 * 8)($30)
|
||||
ldq $18, (18 * 8)($30)
|
||||
ldq $19, (19 * 8)($30)
|
||||
ldq $20, (20 * 8)($30)
|
||||
ldq $21, (21 * 8)($30)
|
||||
ldq $22, (22 * 8)($30)
|
||||
ldq $23, (23 * 8)($30)
|
||||
ldq $24, (24 * 8)($30)
|
||||
ldq $25, (25 * 8)($30)
|
||||
ldq $26, (26 * 8)($30)
|
||||
ldq $28, (28 * 8)($30)
|
||||
ldq $29, (29 * 8)($30)
|
||||
addq $30, 31 * 8, $30
|
||||
ret $31,($23)
|
||||
.endm
|
||||
|
||||
FUNCTION (__divqu)
|
||||
PREAMBLE
|
||||
mov $24, $16
|
||||
mov $25, $17
|
||||
jsr $26, EXT_C (grub_divmod64)
|
||||
mov $0, $27
|
||||
POSTAMBLE
|
||||
|
||||
FUNCTION (__remqu)
|
||||
PREAMBLE
|
||||
mov $24, $16
|
||||
mov $25, $17
|
||||
jsr $26, EXT_C (grub_divmod64)
|
||||
ldq $27, (30 * 8)($30)
|
||||
POSTAMBLE
|
||||
|
||||
FUNCTION (__divlu)
|
||||
PREAMBLE
|
||||
sll $24, 32, $16
|
||||
sra $16, 32, $16
|
||||
sll $25, 32, $17
|
||||
sra $17, 32, $17
|
||||
mov $24, $16
|
||||
mov $25, $17
|
||||
jsr $26, EXT_C (grub_divmod64)
|
||||
mov $0, $27
|
||||
POSTAMBLE
|
||||
|
||||
FUNCTION (__remlu)
|
||||
PREAMBLE
|
||||
sll $24, 32, $16
|
||||
sra $16, 32, $16
|
||||
sll $25, 32, $17
|
||||
sra $17, 32, $17
|
||||
jsr $26, EXT_C (grub_divmod64)
|
||||
ldq $27, (30 * 8)($30)
|
||||
POSTAMBLE
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2011 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/dl.h>
|
||||
#include <grub/elf.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/cpu/types.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
void
|
||||
grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp,
|
||||
grub_size_t *got)
|
||||
{
|
||||
const Elf64_Ehdr *e = ehdr;
|
||||
grub_size_t cntt = 0, cntg = 0;;
|
||||
const Elf64_Shdr *s;
|
||||
Elf64_Word entsize;
|
||||
unsigned i;
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff));
|
||||
i < grub_le_to_cpu16 (e->e_shnum);
|
||||
i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
|
||||
if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
if (i == grub_le_to_cpu16 (e->e_shnum))
|
||||
return;
|
||||
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff));
|
||||
i < grub_le_to_cpu16 (e->e_shnum);
|
||||
i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize)))
|
||||
if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA)
|
||||
{
|
||||
Elf64_Rela *rel, *max;
|
||||
|
||||
for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)),
|
||||
max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize);
|
||||
rel < max; rel++)
|
||||
switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info)))
|
||||
{
|
||||
case R_ALPHA_LITERAL:
|
||||
cntg++;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
*tramp = cntt;
|
||||
*got = cntg;
|
||||
}
|
||||
|
||||
|
||||
/* Check if EHDR is a valid ELF header. */
|
||||
grub_err_t
|
||||
grub_arch_dl_check_header (void *ehdr)
|
||||
{
|
||||
Elf_Ehdr *e = ehdr;
|
||||
|
||||
/* Check the magic numbers. */
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS64
|
||||
|| e->e_ident[EI_DATA] != ELFDATA2LSB
|
||||
|| e->e_machine != EM_ALPHA)
|
||||
return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Relocate symbols. */
|
||||
grub_err_t
|
||||
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
|
||||
{
|
||||
Elf_Ehdr *e = ehdr;
|
||||
Elf_Shdr *s;
|
||||
Elf_Word entsize;
|
||||
unsigned i;
|
||||
grub_uint8_t *gp;
|
||||
grub_uint64_t *gpptr;
|
||||
|
||||
gp = (grub_uint8_t *) mod->got;
|
||||
gpptr = (grub_uint64_t *) mod->got;
|
||||
|
||||
/* Find a symbol table. */
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_SYMTAB)
|
||||
break;
|
||||
|
||||
if (i == e->e_shnum)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found");
|
||||
|
||||
entsize = s->sh_entsize;
|
||||
|
||||
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||||
i < e->e_shnum;
|
||||
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||||
if (s->sh_type == SHT_RELA)
|
||||
{
|
||||
grub_dl_segment_t seg;
|
||||
|
||||
/* Find the target segment. */
|
||||
for (seg = mod->segment; seg; seg = seg->next)
|
||||
if (seg->section == s->sh_info)
|
||||
break;
|
||||
|
||||
if (seg)
|
||||
{
|
||||
Elf_Rela *rel, *max;
|
||||
|
||||
for (rel = (Elf_Rela *) ((char *) e + s->sh_offset),
|
||||
max = (Elf_Rela *) ((char *) rel + s->sh_size);
|
||||
rel < max;
|
||||
rel++)
|
||||
{
|
||||
grub_uint8_t *addr;
|
||||
Elf_Sym *sym;
|
||||
grub_uint64_t value;
|
||||
|
||||
if (seg->size < rel->r_offset)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"reloc offset is out of the segment");
|
||||
|
||||
addr = (grub_uint8_t *) seg->addr + rel->r_offset;
|
||||
sym = (Elf_Sym *) ((char *) mod->symtab
|
||||
+ entsize * ELF_R_SYM (rel->r_info));
|
||||
|
||||
value = sym->st_value + rel->r_addend;
|
||||
switch (ELF_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_ALPHA_REFQUAD:
|
||||
*(grub_uint64_t *) addr += value;
|
||||
break;
|
||||
case R_ALPHA_REFLONG:
|
||||
*(grub_uint32_t *) addr += value;
|
||||
break;
|
||||
|
||||
case R_ALPHA_GPREL32:
|
||||
*(grub_uint32_t *) addr += value - (grub_addr_t) gp;
|
||||
break;
|
||||
|
||||
case R_ALPHA_GPDISP:
|
||||
{
|
||||
grub_int64_t off = gp - addr;
|
||||
|
||||
if (off < (-2147483647L - 1)
|
||||
|| off > 2147483647L)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"gpdisp offset too large");
|
||||
/* Lower part is
|
||||
treated as signed. Hence add 0x8000 to compensate.
|
||||
*/
|
||||
*(grub_uint16_t *) addr = (off + 0x8000) >> 16;
|
||||
*(grub_uint16_t *) (addr + rel->r_addend) = off;
|
||||
break;
|
||||
}
|
||||
|
||||
case R_ALPHA_GPRELHIGH:
|
||||
{
|
||||
Elf_Rela *rel2;
|
||||
|
||||
/* Handle partner lo16 relocation. Lower part is
|
||||
treated as signed. Hence add 0x8000 to compensate.
|
||||
*/
|
||||
value += (*(grub_uint16_t *) addr << 16);
|
||||
value -= (grub_addr_t) gp;
|
||||
for (rel2 = rel + 1; rel2 < max; rel2++)
|
||||
if (ELF_R_SYM (rel2->r_info)
|
||||
== ELF_R_SYM (rel->r_info)
|
||||
&& ELF_R_TYPE (rel2->r_info) == R_ALPHA_GPRELLOW)
|
||||
{
|
||||
value += *(grub_int16_t *)
|
||||
((char *) seg->addr + rel2->r_offset);
|
||||
break;
|
||||
}
|
||||
/* Handle partner lo16 relocation. Lower part is
|
||||
treated as signed. Hence add 0x8000 to compensate.
|
||||
*/
|
||||
if ((grub_int64_t) value < (-2147483647L - 1)
|
||||
|| (grub_int64_t) value > 2147483647L)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"gpdisp offset too large");
|
||||
value += 0x8000;
|
||||
*(grub_uint16_t *) addr = (value >> 16) & 0xffff;
|
||||
break;
|
||||
}
|
||||
case R_ALPHA_GPRELLOW:
|
||||
value -= (grub_addr_t) gp;
|
||||
*(grub_uint16_t *) addr += value & 0xffff;
|
||||
break;
|
||||
case R_ALPHA_LITERAL:
|
||||
*gpptr = value + *(grub_uint16_t *) addr;
|
||||
*(grub_uint16_t *) addr = ((grub_uint8_t *) gpptr - gp);
|
||||
gpptr++;
|
||||
break;
|
||||
case R_ALPHA_SREL32:
|
||||
*(grub_uint32_t *) addr += value - (grub_addr_t) seg->addr;
|
||||
break;
|
||||
case R_ALPHA_BRSGP:
|
||||
value += (((*(grub_uint32_t *) addr)
|
||||
& ((1 << 21) - 1)) << 2);
|
||||
value -= (grub_addr_t) addr;
|
||||
if (sym->st_other == STO_ALPHA_STD_GPLOAD)
|
||||
value += 4;
|
||||
else
|
||||
value -= 4;
|
||||
if (value & 3)
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"unaligned branch");
|
||||
|
||||
if ((value & ~((1UL << 22) - 1)) != 0
|
||||
&& (value & ~((1UL << 22) - 1)) != ~((1UL << 22) - 1))
|
||||
return grub_error (GRUB_ERR_BAD_MODULE,
|
||||
"brs offset too large (%lx)",
|
||||
value);
|
||||
|
||||
*(grub_uint32_t *) addr
|
||||
= ((*(grub_uint32_t *) addr & ~((1 << 21) - 1))
|
||||
| ((value >> 2) & ((1 << 21) - 1)));
|
||||
break;
|
||||
|
||||
case R_ALPHA_LITUSE:
|
||||
case R_ALPHA_HINT:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"Unknown relocation type %d\n",
|
||||
ELF_R_TYPE (rel->r_info));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2011 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/cache.h>
|
||||
#include <grub/kernel.h>
|
||||
#include <grub/memory.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/machine/srm.h>
|
||||
#include <grub/machine/console.h>
|
||||
|
||||
/* FIXME: determine va_size. */
|
||||
static void *kseg_addr = (void *) 0xfffffc0000000000;
|
||||
static grub_uint64_t log_page_size;
|
||||
|
||||
extern char _start[];
|
||||
extern char _end[];
|
||||
|
||||
grub_uint32_t grub_arch_pccclock;
|
||||
|
||||
/* FIXME: use interrupt to count high. */
|
||||
grub_uint64_t
|
||||
grub_get_rtc (void)
|
||||
{
|
||||
static grub_uint32_t high = 0;
|
||||
static grub_uint32_t last = 0;
|
||||
grub_uint32_t low;
|
||||
|
||||
asm volatile ("rpcc %0" : "=r" (low));
|
||||
if (low < last)
|
||||
high++;
|
||||
last = low;
|
||||
|
||||
return (((grub_uint64_t) high) << 32) | low;
|
||||
}
|
||||
|
||||
static grub_addr_t
|
||||
get_pfn (grub_addr_t va, grub_uint64_t ptbr)
|
||||
{
|
||||
grub_uint64_t *l1;
|
||||
grub_uint64_t l1n;
|
||||
grub_uint64_t *l2;
|
||||
grub_uint64_t l2n;
|
||||
grub_uint64_t *l3;
|
||||
grub_uint64_t l3n;
|
||||
|
||||
l3n = va >> log_page_size;
|
||||
l2n = l3n >> (log_page_size - 3);
|
||||
l1n = l2n >> (log_page_size - 3);
|
||||
l3n &= ((1 << (log_page_size - 3)) - 1);
|
||||
l2n &= ((1 << (log_page_size - 3)) - 1);
|
||||
l1n &= ((1 << (log_page_size - 3)) - 1);
|
||||
|
||||
l1 = ((grub_uint64_t *) kseg_addr + (ptbr << (log_page_size - 3))
|
||||
+ l1n);
|
||||
l2 = ((grub_uint64_t *) kseg_addr + ((*l1 >> 32) << (log_page_size - 3))
|
||||
+ l2n);
|
||||
l3 = ((grub_uint64_t *) kseg_addr + ((*l2 >> 32) << (log_page_size - 3))
|
||||
+ l3n);
|
||||
return (*l3 >> 32);
|
||||
}
|
||||
|
||||
void pal_init(void);
|
||||
|
||||
void
|
||||
grub_machine_init (void)
|
||||
{
|
||||
unsigned i;
|
||||
struct grub_alpha_srm_memdesc *memdesc;
|
||||
struct grub_alpha_srm_hwpcb *pcb;
|
||||
grub_addr_t a;
|
||||
grub_addr_t start, end;
|
||||
grub_uint64_t low_pfn = ~0ULL, high_pfn = 0;
|
||||
|
||||
grub_arch_pccclock = GRUB_ALPHA_SRM_HWRPB.pcc_freq;
|
||||
|
||||
grub_console_init_early ();
|
||||
|
||||
pal_init ();
|
||||
|
||||
grub_install_get_time_ms (grub_rtc_get_time_ms);
|
||||
|
||||
for (log_page_size = 0;
|
||||
!((1 << log_page_size) & GRUB_ALPHA_SRM_HWRPB.page_size);
|
||||
log_page_size++);
|
||||
|
||||
memdesc = (struct grub_alpha_srm_memdesc *)
|
||||
(GRUB_ALPHA_SRM_HWRPB_ADDR + GRUB_ALPHA_SRM_HWRPB.memory_descriptor_table);
|
||||
|
||||
pcb = (void *) (GRUB_ALPHA_SRM_HWRPB_ADDR
|
||||
+ GRUB_ALPHA_SRM_HWRPB.cpu_slots_offset
|
||||
+ (GRUB_ALPHA_SRM_HWRPB.primary_cpu_id
|
||||
* GRUB_ALPHA_SRM_HWRPB.cpu_slot_size));
|
||||
|
||||
start = ALIGN_DOWN ((grub_addr_t) (&_start[0]),
|
||||
GRUB_ALPHA_SRM_HWRPB.page_size);
|
||||
end = ALIGN_UP (grub_modules_get_end (), GRUB_ALPHA_SRM_HWRPB.page_size);
|
||||
for (a = start; a < end; a += GRUB_ALPHA_SRM_HWRPB.page_size)
|
||||
{
|
||||
grub_uint64_t curpfn = get_pfn (a, pcb->ptbr);
|
||||
if (curpfn > high_pfn)
|
||||
high_pfn = curpfn;
|
||||
if (curpfn < low_pfn)
|
||||
low_pfn = curpfn;
|
||||
}
|
||||
|
||||
for (i = 0; i < memdesc->num_entries; i++)
|
||||
{
|
||||
grub_uint64_t from, to;
|
||||
if (memdesc->entries[i].type
|
||||
!= GRUB_ALPHA_SRM_MEMDESC_ENTRY_TYPE_AVAILABLE)
|
||||
continue;
|
||||
from = memdesc->entries[i].start_page;
|
||||
to = memdesc->entries[i].start_page + memdesc->entries[i].num_pages;
|
||||
if ((to > low_pfn) && (from < high_pfn + 1))
|
||||
{
|
||||
if (from < low_pfn)
|
||||
/* from .. (lowpfn - 1) */
|
||||
grub_mm_init_region ((char *) kseg_addr + (from << log_page_size),
|
||||
(low_pfn - from) << log_page_size);
|
||||
if (high_pfn + 1 < to)
|
||||
/* (high_pfn + 1) .. (to - 1) */
|
||||
grub_mm_init_region ((char *) kseg_addr
|
||||
+ ((high_pfn + 1) << log_page_size),
|
||||
(to - high_pfn - 1) << log_page_size);
|
||||
}
|
||||
else
|
||||
/* from .. (to - 1) */
|
||||
grub_mm_init_region ((char *) kseg_addr
|
||||
+ (from << log_page_size),
|
||||
(to - from) << log_page_size);
|
||||
}
|
||||
|
||||
grub_console_init_lately ();
|
||||
|
||||
grub_srmdisk_init ();
|
||||
|
||||
char buf[512];
|
||||
grub_alpha_srm_dispatch (0x22, 2, buf, sizeof (buf));
|
||||
grub_printf ("Hello World %s\n", buf);
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_fini (void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
grub_machine_set_prefix (void)
|
||||
{
|
||||
grub_env_set ("prefix", grub_prefix);
|
||||
}
|
||||
|
||||
void
|
||||
grub_exit (void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
void
|
||||
grub_reboot (void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
grub_addr_t
|
||||
grub_arch_modules_addr (void)
|
||||
{
|
||||
return (grub_addr_t) _end;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_machine_mmap_iterate (grub_memory_hook_t hook)
|
||||
{
|
||||
struct grub_alpha_srm_memdesc *memdesc;
|
||||
unsigned i;
|
||||
|
||||
memdesc = (struct grub_alpha_srm_memdesc *)
|
||||
(GRUB_ALPHA_SRM_HWRPB_ADDR + GRUB_ALPHA_SRM_HWRPB.memory_descriptor_table);
|
||||
|
||||
for (i = 0; i < memdesc->num_entries; i++)
|
||||
switch (memdesc->entries[i].type)
|
||||
{
|
||||
case GRUB_ALPHA_SRM_MEMDESC_ENTRY_TYPE_AVAILABLE:
|
||||
hook (memdesc->entries[i].start_page << log_page_size,
|
||||
memdesc->entries[i].num_pages << log_page_size,
|
||||
GRUB_MEMORY_AVAILABLE);
|
||||
break;
|
||||
case GRUB_ALPHA_SRM_MEMDESC_ENTRY_TYPE_NONVOLATILE:
|
||||
hook (memdesc->entries[i].start_page << log_page_size,
|
||||
memdesc->entries[i].num_pages << log_page_size,
|
||||
GRUB_MEMORY_NVRAM);
|
||||
break;
|
||||
case GRUB_ALPHA_SRM_MEMDESC_ENTRY_TYPE_RESERVED1:
|
||||
case GRUB_ALPHA_SRM_MEMDESC_ENTRY_TYPE_RESERVED2:
|
||||
default:
|
||||
hook (memdesc->entries[i].start_page << log_page_size,
|
||||
memdesc->entries[i].num_pages << log_page_size,
|
||||
GRUB_MEMORY_RESERVED);
|
||||
break;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/offsets.h>
|
||||
|
||||
.set noreorder
|
||||
.globl _start
|
||||
.ent _start
|
||||
_start:
|
||||
.prologue 0
|
||||
/* load GP. */
|
||||
br $27, 1f
|
||||
1: ldgp $29, 0($27)
|
||||
|
||||
/* Move modules out of the BSS. */
|
||||
lda $1, __bss_start
|
||||
lda $2, _end
|
||||
lda $4, modsize
|
||||
ldq $3, 0($4)
|
||||
addq $3, 7, $3
|
||||
sra $3, 3, $3
|
||||
sll $3, 3, $4
|
||||
subq $4, 8, $4
|
||||
addq $1, $4, $1
|
||||
addq $2, $4, $2
|
||||
|
||||
2:
|
||||
beq $3, 3f
|
||||
ldq $4, 0($1)
|
||||
stq $4, 0($2)
|
||||
subq $3, 1, $3
|
||||
subq $1, 8, $1
|
||||
subq $2, 8, $2
|
||||
br 2b
|
||||
3:
|
||||
|
||||
/* Clean BSS. */
|
||||
lda $1, __bss_start
|
||||
lda $2, _end
|
||||
subq $2, $1, $2
|
||||
sra $2, 3, $2
|
||||
2:
|
||||
beq $2, 3f
|
||||
stq $31, 0($1)
|
||||
subq $2, 1, $2
|
||||
addq $1, 8, $1
|
||||
br 2b
|
||||
3:
|
||||
/* call main. */
|
||||
lda $27, EXT_C (grub_main)
|
||||
jmp ($27)
|
||||
.end _start
|
||||
. = _start + GRUB_KERNEL_ALPHA_SRM_TOTAL_MODULE_SIZE
|
||||
modsize:
|
||||
.quad 0
|
||||
+9
-5
@@ -229,7 +229,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
||||
unsigned i;
|
||||
Elf_Shdr *s;
|
||||
grub_size_t tsize = 0, talign = 1;
|
||||
#if defined (__ia64__) || defined (__powerpc__)
|
||||
#if defined (__ia64__) || defined (__alpha__) || defined (__powerpc__)
|
||||
grub_size_t tramp;
|
||||
grub_size_t got;
|
||||
#endif
|
||||
@@ -244,7 +244,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
||||
talign = s->sh_addralign;
|
||||
}
|
||||
|
||||
#if defined (__ia64__) || defined (__powerpc__)
|
||||
#if defined (__ia64__) || defined (__alpha__) || defined (__powerpc__)
|
||||
grub_arch_dl_get_tramp_got_size (e, &tramp, &got);
|
||||
tramp *= GRUB_ARCH_DL_TRAMP_SIZE;
|
||||
got *= sizeof (grub_uint64_t);
|
||||
@@ -313,7 +313,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e)
|
||||
mod->segment = seg;
|
||||
}
|
||||
}
|
||||
#if defined (__ia64__) || defined (__powerpc__)
|
||||
#if defined (__ia64__) || defined (__alpha__) || defined (__powerpc__)
|
||||
ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN);
|
||||
mod->tramp = ptr;
|
||||
ptr += tramp;
|
||||
@@ -359,7 +359,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
|
||||
str = (char *) e + s->sh_offset;
|
||||
|
||||
for (i = 0;
|
||||
i < size / entsize;
|
||||
i * entsize < size;
|
||||
i++, sym = (Elf_Sym *) ((char *) sym + entsize))
|
||||
{
|
||||
unsigned char type = ELF_ST_TYPE (sym->st_info);
|
||||
@@ -565,11 +565,15 @@ grub_dl_unref (grub_dl_t mod)
|
||||
}
|
||||
|
||||
static void
|
||||
grub_dl_flush_cache (grub_dl_t mod)
|
||||
grub_dl_flush_cache (grub_dl_t mod __attribute__ ((unused)))
|
||||
{
|
||||
grub_dprintf ("modules", "flushing 0x%lx bytes at %p\n",
|
||||
(unsigned long) mod->sz, mod->base);
|
||||
#ifdef __alpha__
|
||||
grub_arch_sync_all_caches ();
|
||||
#else
|
||||
grub_arch_sync_caches (mod->base, mod->sz);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Load a module from core memory. */
|
||||
|
||||
@@ -554,6 +554,7 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
|
||||
grub_uint64_t m = 0;
|
||||
|
||||
/* Skip the slow computation if 32-bit arithmetic is possible. */
|
||||
#ifndef __alpha__
|
||||
if (n < 0xffffffff && d < 0xffffffff)
|
||||
{
|
||||
if (r)
|
||||
@@ -561,6 +562,7 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r)
|
||||
|
||||
return ((grub_uint32_t) n) / (grub_uint32_t) d;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (bits--)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2011 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/datetime.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
grub_err_t
|
||||
grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
|
||||
{
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"getting time isn't supported");
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_set_datetime (struct grub_datetime *datetime __attribute__ ((unused)))
|
||||
{
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"setting time isn't supported");
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2011 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/misc.h>
|
||||
|
||||
void
|
||||
grub_halt (void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2011 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/machine/srm.h>
|
||||
#include <grub/machine/console.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/terminfo.h>
|
||||
|
||||
static int
|
||||
readkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
grub_uint64_t c;
|
||||
c = grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_GETC, 0);
|
||||
if (c & (1ULL << 63))
|
||||
return -1;
|
||||
|
||||
return c & 0xffffffff;
|
||||
}
|
||||
|
||||
#define NEWLINE " \r\n "
|
||||
|
||||
static void
|
||||
put (struct grub_term_output *term __attribute__ ((unused)), const int c)
|
||||
{
|
||||
char chr = c;
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
const char *str = NEWLINE, *ptr;
|
||||
for (ptr = str; ptr < str + sizeof (NEWLINE) - 1; )
|
||||
ptr += (grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_PUTS, 0, ptr,
|
||||
str + sizeof (NEWLINE) - 1 - ptr)
|
||||
& 0xff);
|
||||
return;
|
||||
}
|
||||
|
||||
grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_PUTS, 0, &chr, 1);
|
||||
}
|
||||
|
||||
static struct grub_terminfo_output_state grub_console_terminfo_output;
|
||||
|
||||
static grub_err_t
|
||||
grub_console_init_output (struct grub_term_output *term)
|
||||
{
|
||||
/* FIXME: get dimensions. */
|
||||
grub_terminfo_output_init (term);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct grub_terminfo_input_state grub_console_terminfo_input =
|
||||
{
|
||||
.readkey = readkey
|
||||
};
|
||||
|
||||
static struct grub_terminfo_output_state grub_console_terminfo_output =
|
||||
{
|
||||
.put = put,
|
||||
.width = 80,
|
||||
.height = 25
|
||||
};
|
||||
|
||||
static struct grub_term_input grub_console_term_input =
|
||||
{
|
||||
.name = "console",
|
||||
.init = grub_terminfo_input_init,
|
||||
.getkey = grub_terminfo_getkey,
|
||||
.data = &grub_console_terminfo_input
|
||||
};
|
||||
|
||||
static struct grub_term_output grub_console_term_output =
|
||||
{
|
||||
.name = "console",
|
||||
.init = grub_console_init_output,
|
||||
.putchar = grub_terminfo_putchar,
|
||||
.getxy = grub_terminfo_getxy,
|
||||
.getwh = grub_terminfo_getwh,
|
||||
.gotoxy = grub_terminfo_gotoxy,
|
||||
.cls = grub_terminfo_cls,
|
||||
.setcolorstate = grub_terminfo_setcolorstate,
|
||||
.setcursor = grub_terminfo_setcursor,
|
||||
.flags = GRUB_TERM_CODE_TYPE_ASCII,
|
||||
.data = &grub_console_terminfo_output,
|
||||
.normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
|
||||
.highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
|
||||
};
|
||||
|
||||
void
|
||||
grub_console_init_early (void)
|
||||
{
|
||||
grub_alpha_srm_dispatch (GRUB_ALPHA_SRM_OPEN_CONSOLE);
|
||||
|
||||
grub_term_register_input ("console", &grub_console_term_input);
|
||||
grub_term_register_output ("console", &grub_console_term_output);
|
||||
}
|
||||
|
||||
void grub_terminfo_init (void);
|
||||
|
||||
void
|
||||
grub_console_init_lately (void)
|
||||
{
|
||||
grub_terminfo_init ();
|
||||
/* FIXME */
|
||||
grub_terminfo_output_register (&grub_console_term_output, "srm");
|
||||
}
|
||||
|
||||
@@ -143,6 +143,19 @@ grub_terminfo_set_current (struct grub_term_output *term,
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_strcmp ("srm", str) == 0)
|
||||
{
|
||||
data->name = grub_strdup ("srm");
|
||||
data->gotoxy = grub_strdup ("\e[%i%p1%d;%p2%dH");
|
||||
data->cls = grub_strdup ("\e[2J");
|
||||
data->reverse_video_on = grub_strdup ("\e[7m");
|
||||
data->reverse_video_off = grub_strdup ("\e[0m");
|
||||
data->cursor_on = grub_strdup ("\e[?25h");
|
||||
data->cursor_off = grub_strdup ("\e[?25l");
|
||||
data->setcolor = 0;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_strcmp ("ieee1275", str) == 0
|
||||
|| grub_strcmp ("ieee1275-nocursor", str) == 0)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user