Commit b2c5f619 authored by Mark A. Greer's avatar Mark A. Greer Committed by Paul Mackerras

[POWERPC] Start arch/powerpc/boot code reorganization

This abstracts the operations used in the bootwrapper, and defines
the operations needed for the bootwrapper to run on an OF platform.

The operations have been divided up into platform ops (platform_ops),
firmware ops (fw_ops), device tree ops (dt_ops), and console ops
(console_ops).

The proper operations will be hooked up at runtime to provide the
functionality that you need.
Signed-off-by: default avatarMark A. Greer <mgreer@mvista.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent a4dc7ff0
......@@ -36,7 +36,8 @@ zliblinuxheader := zlib.h zconf.h zutil.h
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
src-boot-$(CONFIG_PPC_MULTIPLATFORM) := of.c
src-boot := crt0.S string.S stdio.c main.c div64.S $(src-boot-y)
src-boot += $(zlib)
src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
......
/*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef FLATDEVTREE_H
#define FLATDEVTREE_H
#include "types.h"
/* Definitions used by the flattened device tree */
#define OF_DT_HEADER 0xd00dfeed /* marker */
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
#define OF_DT_END_NODE 0x2 /* End node */
#define OF_DT_PROP 0x3 /* Property: name off, size, content */
#define OF_DT_NOP 0x4 /* nop */
#define OF_DT_END 0x9
#define OF_DT_VERSION 0x10
struct boot_param_header {
u32 magic; /* magic word OF_DT_HEADER */
u32 totalsize; /* total size of DT block */
u32 off_dt_struct; /* offset to structure */
u32 off_dt_strings; /* offset to strings */
u32 off_mem_rsvmap; /* offset to memory reserve map */
u32 version; /* format version */
u32 last_comp_version; /* last compatible version */
/* version 2 fields below */
u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
/* version 3 fields below */
u32 dt_strings_size; /* size of the DT strings block */
};
#endif /* FLATDEVTREE_H */
This diff is collapsed.
......@@ -8,15 +8,29 @@
*/
#include <stdarg.h>
#include <stddef.h>
#include "types.h"
#include "elf.h"
#include "string.h"
#include "stdio.h"
#include "prom.h"
#include "page.h"
#include "ops.h"
int (*prom)(void *);
phandle chosen_handle;
ihandle stdout;
typedef void *ihandle;
typedef void *phandle;
int call_prom(const char *service, int nargs, int nret, ...)
extern char _end[];
/* Value picked to match that used by yaboot */
#define PROG_START 0x01400000 /* only used on 64-bit systems */
#define RAM_END (512<<20) /* Fixme: use OF */
#define ONE_MB 0x100000
int (*prom) (void *);
static unsigned long claim_base;
static int call_prom(const char *service, int nargs, int nret, ...)
{
int i;
struct prom_args {
......@@ -45,7 +59,7 @@ int call_prom(const char *service, int nargs, int nret, ...)
return (nret > 0)? args.args[nargs]: 0;
}
int call_prom_ret(const char *service, int nargs, int nret,
static int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...)
{
int i;
......@@ -79,11 +93,6 @@ int call_prom_ret(const char *service, int nargs, int nret,
return (nret > 0)? args.args[nargs]: 0;
}
int write(void *handle, void *ptr, int nb)
{
return call_prom("write", 3, 1, handle, ptr, nb);
}
/*
* Older OF's require that when claiming a specific range of addresses,
* we claim the physical space in the /memory node and the virtual
......@@ -142,7 +151,7 @@ static int check_of_version(void)
return 1;
}
void *claim(unsigned long virt, unsigned long size, unsigned long align)
static void *claim(unsigned long virt, unsigned long size, unsigned long align)
{
int ret;
unsigned int result;
......@@ -151,7 +160,7 @@ void *claim(unsigned long virt, unsigned long size, unsigned long align)
need_map = check_of_version();
if (align || !need_map)
return (void *) call_prom("claim", 3, 1, virt, size, align);
ret = call_prom_ret("call-method", 5, 2, &result, "claim", memory,
align, size, virt);
if (ret != 0 || result == -1)
......@@ -163,3 +172,112 @@ void *claim(unsigned long virt, unsigned long size, unsigned long align)
0x12, size, virt, virt);
return (void *) virt;
}
static void *of_try_claim(u32 size)
{
unsigned long addr = 0;
static u8 first_time = 1;
if (first_time) {
claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
first_time = 0;
}
for(; claim_base < RAM_END; claim_base += ONE_MB) {
#ifdef DEBUG
printf(" trying: 0x%08lx\n\r", claim_base);
#endif
addr = (unsigned long)claim(claim_base, size, 0);
if ((void *)addr != (void *)-1)
break;
}
if (addr == 0)
return NULL;
claim_base = PAGE_ALIGN(claim_base + size);
return (void *)addr;
}
static void of_image_hdr(const void *hdr)
{
const Elf64_Ehdr *elf64 = hdr;
if (elf64->e_ident[EI_CLASS] == ELFCLASS64) {
/*
* Maintain a "magic" minimum address. This keeps some older
* firmware platforms running.
*/
if (claim_base < PROG_START)
claim_base = PROG_START;
}
}
static void of_exit(void)
{
call_prom("exit", 0, 0);
}
/*
* OF device tree routines
*/
static void *of_finddevice(const char *name)
{
return (phandle) call_prom("finddevice", 1, 1, name);
}
static int of_getprop(const void *phandle, const char *name, void *buf,
const int buflen)
{
return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
}
static int of_setprop(const void *phandle, const char *name, const void *buf,
const int buflen)
{
return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
}
/*
* OF console routines
*/
static void *of_stdout_handle;
static int of_console_open(void)
{
void *devp;
if (((devp = finddevice("/chosen")) != NULL)
&& (getprop(devp, "stdout", &of_stdout_handle,
sizeof(of_stdout_handle))
== sizeof(of_stdout_handle)))
return 0;
return -1;
}
static void of_console_write(char *buf, int len)
{
call_prom("write", 3, 1, of_stdout_handle, buf, len);
}
int platform_init(void *promptr)
{
platform_ops.fixups = NULL;
platform_ops.image_hdr = of_image_hdr;
platform_ops.malloc = of_try_claim;
platform_ops.free = NULL;
platform_ops.exit = of_exit;
dt_ops.finddevice = of_finddevice;
dt_ops.getprop = of_getprop;
dt_ops.setprop = of_setprop;
dt_ops.translate_addr = NULL;
console_ops.open = of_console_open;
console_ops.write = of_console_write;
console_ops.edit_cmdline = NULL;
console_ops.close = NULL;
console_ops.data = NULL;
prom = (int (*)(void *))promptr;
return 0;
}
/*
* Global definition of all the bootwrapper operations.
*
* Author: Mark A. Greer <mgreer@mvista.com>
*
* 2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef _PPC_BOOT_OPS_H_
#define _PPC_BOOT_OPS_H_
#include "types.h"
#define COMMAND_LINE_SIZE 512
#define MAX_PATH_LEN 256
#define MAX_PROP_LEN 256 /* What should this be? */
/* Platform specific operations */
struct platform_ops {
void (*fixups)(void);
void (*image_hdr)(const void *);
void * (*malloc)(u32 size);
void (*free)(void *ptr, u32 size);
void (*exit)(void);
};
extern struct platform_ops platform_ops;
/* Device Tree operations */
struct dt_ops {
void * (*finddevice)(const char *name);
int (*getprop)(const void *node, const char *name, void *buf,
const int buflen);
int (*setprop)(const void *node, const char *name,
const void *buf, const int buflen);
u64 (*translate_addr)(const char *path, const u32 *in_addr,
const u32 addr_len);
unsigned long (*ft_addr)(void);
};
extern struct dt_ops dt_ops;
/* Console operations */
struct console_ops {
int (*open)(void);
void (*write)(char *buf, int len);
void (*edit_cmdline)(char *buf, int len);
void (*close)(void);
void *data;
};
extern struct console_ops console_ops;
/* Serial console operations */
struct serial_console_data {
int (*open)(void);
void (*putc)(unsigned char c);
unsigned char (*getc)(void);
u8 (*tstc)(void);
void (*close)(void);
};
extern int platform_init(void *promptr);
extern void simple_alloc_init(void);
extern void ft_init(void *dt_blob);
extern int serial_console_init(void);
static inline void *finddevice(const char *name)
{
return (dt_ops.finddevice) ? dt_ops.finddevice(name) : NULL;
}
static inline int getprop(void *devp, const char *name, void *buf, int buflen)
{
return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1;
}
static inline int setprop(void *devp, const char *name, void *buf, int buflen)
{
return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1;
}
static inline void *malloc(u32 size)
{
return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
}
static inline void free(void *ptr, u32 size)
{
if (platform_ops.free)
platform_ops.free(ptr, size);
}
static inline void exit(void)
{
if (platform_ops.exit)
platform_ops.exit();
for(;;);
}
#endif /* _PPC_BOOT_OPS_H_ */
#ifndef _PPC_BOOT_PROM_H_
#define _PPC_BOOT_PROM_H_
typedef void *phandle;
typedef void *ihandle;
extern int (*prom) (void *);
extern phandle chosen_handle;
extern ihandle stdout;
int call_prom(const char *service, int nargs, int nret, ...);
int call_prom_ret(const char *service, int nargs, int nret,
unsigned int *rets, ...);
extern int write(void *handle, void *ptr, int nb);
extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
static inline void exit(void)
{
call_prom("exit", 0, 0);
}
static inline phandle finddevice(const char *name)
{
return (phandle) call_prom("finddevice", 1, 1, name);
}
static inline int getprop(void *phandle, const char *name,
void *buf, int buflen)
{
return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
}
static inline int setprop(void *phandle, const char *name,
void *buf, int buflen)
{
return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
}
#endif /* _PPC_BOOT_PROM_H_ */
......@@ -10,7 +10,7 @@
#include <stddef.h>
#include "string.h"
#include "stdio.h"
#include "prom.h"
#include "ops.h"
size_t strnlen(const char * s, size_t count)
{
......@@ -320,6 +320,6 @@ printf(const char *fmt, ...)
va_start(args, fmt);
n = vsprintf(sprint_buf, fmt, args);
va_end(args);
write(stdout, sprint_buf, n);
console_ops.write(sprint_buf, n);
return n;
}
#ifndef _PPC_BOOT_STDIO_H_
#define _PPC_BOOT_STDIO_H_
#include <stdarg.h>
#define ENOMEM 12 /* Out of Memory */
#define EINVAL 22 /* Invalid argument */
#define ENOSPC 28 /* No space left on device */
extern int printf(const char *fmt, ...);
#define fprintf(fmt, args...) printf(args)
extern int sprintf(char *buf, const char *fmt, ...);
extern int vsprintf(char *buf, const char *fmt, va_list args);
......
#ifndef _TYPES_H_
#define _TYPES_H_
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; })
#define max(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x > _y ? _x : _y; })
#endif /* _TYPES_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment