* [PATCH] Start arch/powerpc/boot code reorganization
@ 2006-09-19 3:21 Paul Mackerras
2006-09-19 4:22 ` Michael Ellerman
0 siblings, 1 reply; 36+ messages in thread
From: Paul Mackerras @ 2006-09-19 3:21 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
This is a reworked version of Mark's patches 1/6 and 2/6. This boots
on powermac (newworld) and pseries (power5 partition) at least.
I intend to commit this with Mark as the author and a suitable commit
message, unless there are adverse comments.
Paul.
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index afc776f..e737741 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -36,7 +36,8 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(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)))
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index b66634c..d719bb9 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -14,17 +14,12 @@ #include "elf.h"
#include "page.h"
#include "string.h"
#include "stdio.h"
-#include "prom.h"
#include "zlib.h"
+#include "ops.h"
+#include "flatdevtree.h"
extern void flush_cache(void *, unsigned long);
-
-/* 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
-
extern char _start[];
extern char __bss_start[];
extern char _end[];
@@ -33,14 +28,6 @@ extern char _vmlinux_end[];
extern char _initrd_start[];
extern char _initrd_end[];
-/* A buffer that may be edited by tools operating on a zImage binary so as to
- * edit the command line passed to vmlinux (by setting /chosen/bootargs).
- * The buffer is put in it's own section so that tools may locate it easier.
- */
-static char builtin_cmdline[512]
- __attribute__((section("__builtin_cmdline")));
-
-
struct addr_range {
unsigned long addr;
unsigned long size;
@@ -51,21 +38,16 @@ static struct addr_range vmlinuz;
static struct addr_range initrd;
static unsigned long elfoffset;
+static int is_64bit;
-static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */
+/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
+static char scratch[46912];
static char elfheader[256];
-
-typedef void (*kernel_entry_t)( unsigned long,
- unsigned long,
- void *,
- void *);
-
+typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
#undef DEBUG
-static unsigned long claim_base;
-
#define HEAD_CRC 2
#define EXTRA_FIELD 4
#define ORIG_NAME 8
@@ -123,24 +105,6 @@ static void gunzip(void *dst, int dstlen
zlib_inflateEnd(&s);
}
-static unsigned long try_claim(unsigned long size)
-{
- unsigned long addr = 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 0;
- claim_base = PAGE_ALIGN(claim_base + size);
- return addr;
-}
-
static int is_elf64(void *hdr)
{
Elf64_Ehdr *elf64 = hdr;
@@ -169,16 +133,7 @@ static int is_elf64(void *hdr)
vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
-#if defined(PROG_START)
- /*
- * Maintain a "magic" minimum address. This keeps some older
- * firmware platforms running.
- */
-
- if (claim_base < PROG_START)
- claim_base = PROG_START;
-#endif
-
+ is_64bit = 1;
return 1;
}
@@ -212,47 +167,9 @@ static int is_elf32(void *hdr)
return 1;
}
-void export_cmdline(void* chosen_handle)
-{
- int len;
- char cmdline[2] = { 0, 0 };
-
- if (builtin_cmdline[0] == 0)
- return;
-
- len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
- if (len > 0 && cmdline[0] != 0)
- return;
-
- setprop(chosen_handle, "bootargs", builtin_cmdline,
- strlen(builtin_cmdline) + 1);
-}
-
-
-void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+static void prep_kernel(unsigned long *a1, unsigned long *a2)
{
int len;
- kernel_entry_t kernel_entry;
-
- memset(__bss_start, 0, _end - __bss_start);
-
- prom = (int (*)(void *)) promptr;
- chosen_handle = finddevice("/chosen");
- if (chosen_handle == (void *) -1)
- exit();
- if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
- exit();
-
- printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
-
- /*
- * The first available claim_base must be above the end of the
- * the loaded kernel wrapper file (_start to _end includes the
- * initrd image if it is present) and rounded up to a nice
- * 1 MB boundary for good measure.
- */
-
- claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
@@ -263,43 +180,51 @@ void start(unsigned long a1, unsigned lo
gunzip(elfheader, sizeof(elfheader),
(unsigned char *)vmlinuz.addr, &len);
} else
- memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
+ memcpy(elfheader, (const void *)vmlinuz.addr,
+ sizeof(elfheader));
if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
exit();
}
+ if (platform_ops.image_hdr)
+ platform_ops.image_hdr(elfheader);
- /* We need to claim the memsize plus the file offset since gzip
+ /* We need to alloc the memsize plus the file offset since gzip
* will expand the header (file offset), then the kernel, then
* possible rubbish we don't care about. But the kernel bss must
* be claimed (it will be zero'd by the kernel itself)
*/
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
- vmlinux.addr = try_claim(vmlinux.memsize);
+ vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
if (vmlinux.addr == 0) {
printf("Can't allocate memory for kernel image !\n\r");
exit();
}
/*
- * Now we try to claim memory for the initrd (and copy it there)
+ * Now we try to alloc memory for the initrd (and copy it there)
*/
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
initrd.memsize = initrd.size;
if ( initrd.size > 0 ) {
- printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
- initrd.addr = try_claim(initrd.size);
+ printf("Allocating 0x%lx bytes for initrd ...\n\r",
+ initrd.size);
+ initrd.addr = (unsigned long)malloc((u32)initrd.size);
if (initrd.addr == 0) {
- printf("Can't allocate memory for initial ramdisk !\n\r");
+ printf("Can't allocate memory for initial "
+ "ramdisk !\n\r");
exit();
}
- a1 = initrd.addr;
- a2 = initrd.size;
- printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r",
- initrd.addr, (unsigned long)_initrd_start, initrd.size);
- memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
- printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr));
+ *a1 = initrd.addr;
+ *a2 = initrd.size;
+ printf("initial ramdisk moving 0x%lx <- 0x%lx "
+ "(0x%lx bytes)\n\r", initrd.addr,
+ (unsigned long)_initrd_start, initrd.size);
+ memmove((void *)initrd.addr, (void *)_initrd_start,
+ initrd.size);
+ printf("initrd head: 0x%lx\n\r",
+ *((unsigned long *)initrd.addr));
}
/* Eventually gunzip the kernel */
@@ -311,11 +236,10 @@ void start(unsigned long a1, unsigned lo
(unsigned char *)vmlinuz.addr, &len);
printf("done 0x%lx bytes\n\r", len);
} else {
- memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
+ memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,
+ vmlinuz.size);
}
- export_cmdline(chosen_handle);
-
/* Skip over the ELF header */
#ifdef DEBUG
printf("... skipping 0x%lx bytes of ELF header\n\r",
@@ -324,23 +248,107 @@ #endif
vmlinux.addr += elfoffset;
flush_cache((void *)vmlinux.addr, vmlinux.size);
+}
- kernel_entry = (kernel_entry_t)vmlinux.addr;
-#ifdef DEBUG
- printf( "kernel:\n\r"
- " entry addr = 0x%lx\n\r"
- " a1 = 0x%lx,\n\r"
- " a2 = 0x%lx,\n\r"
- " prom = 0x%lx,\n\r"
- " bi_recs = 0x%lx,\n\r",
- (unsigned long)kernel_entry, a1, a2,
- (unsigned long)prom, NULL);
-#endif
+void __attribute__ ((weak)) ft_init(void *dt_blob)
+{
+}
- kernel_entry(a1, a2, prom, NULL);
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char builtin_cmdline[COMMAND_LINE_SIZE]
+ __attribute__((__section__("__builtin_cmdline")));
- printf("Error: Linux kernel returned to zImage bootloader!\n\r");
+static void get_cmdline(char *buf, int size)
+{
+ void *devp;
+ int len = strlen(builtin_cmdline);
- exit();
+ buf[0] = '\0';
+
+ if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
+ len = min(len, size-1);
+ strncpy(buf, builtin_cmdline, len);
+ buf[len] = '\0';
+ }
+ else if ((devp = finddevice("/chosen")))
+ getprop(devp, "bootargs", buf, size);
+}
+
+static void set_cmdline(char *buf)
+{
+ void *devp;
+
+ if ((devp = finddevice("/chosen")))
+ setprop(devp, "bootargs", buf, strlen(buf) + 1);
}
+/* Section where ft can be tacked on after zImage is built */
+union blobspace {
+ struct boot_param_header hdr;
+ char space[8*1024];
+} dt_blob __attribute__((__section__("__builtin_ft")));
+
+struct platform_ops platform_ops;
+struct dt_ops dt_ops;
+struct console_ops console_ops;
+
+void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+{
+ int have_dt = 0;
+ kernel_entry_t kentry;
+ char cmdline[COMMAND_LINE_SIZE];
+
+ memset(__bss_start, 0, _end - __bss_start);
+ memset(&platform_ops, 0, sizeof(platform_ops));
+ memset(&dt_ops, 0, sizeof(dt_ops));
+ memset(&console_ops, 0, sizeof(console_ops));
+
+ /* Override the dt_ops and device tree if there was an flat dev
+ * tree attached to the zImage.
+ */
+ if (dt_blob.hdr.magic == OF_DT_HEADER) {
+ have_dt = 1;
+ ft_init(&dt_blob);
+ }
+
+ if (platform_init(promptr))
+ exit();
+ if (console_ops.open && (console_ops.open() < 0))
+ exit();
+ if (platform_ops.fixups)
+ platform_ops.fixups();
+
+ printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
+ _start, sp);
+
+ prep_kernel(&a1, &a2);
+
+ /* If cmdline came from zimage wrapper or if we can edit the one
+ * in the dt, print it out and edit it, if possible.
+ */
+ if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) {
+ get_cmdline(cmdline, COMMAND_LINE_SIZE);
+ printf("\n\rLinux/PowerPC load: %s", cmdline);
+ if (console_ops.edit_cmdline)
+ console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
+ printf("\n\r");
+ set_cmdline(cmdline);
+ }
+
+ if (console_ops.close)
+ console_ops.close();
+
+ kentry = (kernel_entry_t) vmlinux.addr;
+ if (have_dt)
+ kentry(dt_ops.ft_addr(), 0, NULL);
+ else
+ /* XXX initrd addr/size should be passed in properties */
+ kentry(a1, a2, promptr);
+
+ /* console closed so printf below may not work */
+ printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");
+ exit();
+}
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c
deleted file mode 100644
index fa00577..0000000
--- a/arch/powerpc/boot/prom.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-#include <stdarg.h>
-#include <stddef.h>
-#include "string.h"
-#include "stdio.h"
-#include "prom.h"
-
-int (*prom)(void *);
-phandle chosen_handle;
-ihandle stdout;
-
-int call_prom(const char *service, int nargs, int nret, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, nret);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- return (nret > 0)? args.args[nargs]: 0;
-}
-
-int call_prom_ret(const char *service, int nargs, int nret,
- unsigned int *rets, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, rets);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- if (rets != (void *) 0)
- for (i = 1; i < nret; ++i)
- rets[i-1] = args.args[nargs+i];
-
- 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
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
- for (; *s2; ++s2)
- if (*s1++ != *s2)
- return 0;
- return 1;
-}
-
-static int check_of_version(void)
-{
- phandle oprom, chosen;
- char version[64];
-
- oprom = finddevice("/openprom");
- if (oprom == (phandle) -1)
- return 0;
- if (getprop(oprom, "model", version, sizeof(version)) <= 0)
- return 0;
- version[sizeof(version)-1] = 0;
- printf("OF version = '%s'\r\n", version);
- if (!string_match(version, "Open Firmware, 1.")
- && !string_match(version, "FirmWorks,3."))
- return 0;
- chosen = finddevice("/chosen");
- if (chosen == (phandle) -1) {
- chosen = finddevice("/chosen@0");
- if (chosen == (phandle) -1) {
- printf("no chosen\n");
- return 0;
- }
- }
- if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
- printf("no mmu\n");
- return 0;
- }
- memory = (ihandle) call_prom("open", 1, 1, "/memory");
- if (memory == (ihandle) -1) {
- memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
- if (memory == (ihandle) -1) {
- printf("no memory node\n");
- return 0;
- }
- }
- printf("old OF detected\r\n");
- return 1;
-}
-
-void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
- int ret;
- unsigned int result;
-
- if (need_map < 0)
- 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)
- return (void *) -1;
- ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
- align, size, virt);
- /* 0x12 == coherent + read/write */
- ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
- 0x12, size, virt, virt);
- return (void *) virt;
-}
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
deleted file mode 100644
index a57b184..0000000
--- a/arch/powerpc/boot/prom.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#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_ */
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index b5aa522..6d5f638 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -10,7 +10,7 @@ #include <stdarg.h>
#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;
}
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h
index eb9e16c..73b8a91 100644
--- a/arch/powerpc/boot/stdio.h
+++ b/arch/powerpc/boot/stdio.h
@@ -1,8 +1,16 @@
#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);
--- /dev/null 2006-09-18 11:33:23.687982711 +1000
+++ arch/powerpc/boot/flatdevtree.h 2006-09-19 11:46:47.000000000 +1000
@@ -0,0 +1,46 @@
+/*
+ * 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 */
--- /dev/null 2006-09-18 11:33:23.687982711 +1000
+++ arch/powerpc/boot/of.c 2006-09-18 17:35:59.000000000 +1000
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+typedef void *ihandle;
+typedef void *phandle;
+
+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 {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, nret);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int call_prom_ret(const char *service, int nargs, int nret,
+ unsigned int *rets, ...)
+{
+ int i;
+ struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, rets);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ if (rets != (void *) 0)
+ for (i = 1; i < nret; ++i)
+ rets[i-1] = args.args[nargs+i];
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+ for (; *s2; ++s2)
+ if (*s1++ != *s2)
+ return 0;
+ return 1;
+}
+
+static int check_of_version(void)
+{
+ phandle oprom, chosen;
+ char version[64];
+
+ oprom = finddevice("/openprom");
+ if (oprom == (phandle) -1)
+ return 0;
+ if (getprop(oprom, "model", version, sizeof(version)) <= 0)
+ return 0;
+ version[sizeof(version)-1] = 0;
+ printf("OF version = '%s'\r\n", version);
+ if (!string_match(version, "Open Firmware, 1.")
+ && !string_match(version, "FirmWorks,3."))
+ return 0;
+ chosen = finddevice("/chosen");
+ if (chosen == (phandle) -1) {
+ chosen = finddevice("/chosen@0");
+ if (chosen == (phandle) -1) {
+ printf("no chosen\n");
+ return 0;
+ }
+ }
+ if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+ printf("no mmu\n");
+ return 0;
+ }
+ memory = (ihandle) call_prom("open", 1, 1, "/memory");
+ if (memory == (ihandle) -1) {
+ memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+ if (memory == (ihandle) -1) {
+ printf("no memory node\n");
+ return 0;
+ }
+ }
+ printf("old OF detected\r\n");
+ return 1;
+}
+
+static void *claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+ int ret;
+ unsigned int result;
+
+ if (need_map < 0)
+ 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)
+ return (void *) -1;
+ ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+ align, size, virt);
+ /* 0x12 == coherent + read/write */
+ ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+ 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;
+}
--- /dev/null 2006-09-18 11:33:23.687982711 +1000
+++ arch/powerpc/boot/types.h 2006-09-18 13:48:20.000000000 +1000
@@ -0,0 +1,23 @@
+#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_ */
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-19 3:21 [PATCH] Start arch/powerpc/boot code reorganization Paul Mackerras
@ 2006-09-19 4:22 ` Michael Ellerman
2006-09-19 4:29 ` Paul Mackerras
0 siblings, 1 reply; 36+ messages in thread
From: Michael Ellerman @ 2006-09-19 4:22 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 1142 bytes --]
On Tue, 2006-09-19 at 13:21 +1000, Paul Mackerras wrote:
> This is a reworked version of Mark's patches 1/6 and 2/6. This boots
> on powermac (newworld) and pseries (power5 partition) at least.
>
> --- /dev/null 2006-09-18 11:33:23.687982711 +1000
> +++ arch/powerpc/boot/of.c 2006-09-18 17:35:59.000000000 +1000
> @@ -0,0 +1,283 @@
> +/*
> + * Copyright (C) Paul Mackerras 1997.
> + *
> + * 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.
> + */
> +#include <stdarg.h>
> +#include <stddef.h>
> +#include "types.h"
> +#include "elf.h"
> +#include "string.h"
> +#include "stdio.h"
> +#include "page.h"
> +#include "ops.h"
Where do I get ops.h?
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 191 bytes --]
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-19 4:22 ` Michael Ellerman
@ 2006-09-19 4:29 ` Paul Mackerras
0 siblings, 0 replies; 36+ messages in thread
From: Paul Mackerras @ 2006-09-19 4:29 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev
Michael Ellerman writes:
> Where do I get ops.h?
Oops... here it is.
Paul.
diff --git /dev/null b/arch/powerpc/boot/ops.h
--- /dev/null 2006-09-18 11:33:23.687982711 +1000
+++ b/arch/powerpc/boot/ops.h 2006-09-19 14:09:38.000000000 +1000
@@ -0,0 +1,100 @@
+/*
+ * 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 * (*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);
+ void (*call_kernel)(void *entry_addr, unsigned long a1,
+ unsigned long a2, void *promptr, void *sp);
+};
+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_ */
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH] Start arch/powerpc/boot code reorganization
@ 2006-09-19 23:00 Paul Mackerras
2006-09-20 1:20 ` Mark A. Greer
0 siblings, 1 reply; 36+ messages in thread
From: Paul Mackerras @ 2006-09-19 23:00 UTC (permalink / raw)
To: linuxppc-dev
From: Mark A. Greer <mgreer@mvista.com>
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: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index afc776f..e737741 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -36,7 +36,8 @@ zliblinuxheader := zlib.h zconf.h zutil.
$(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)))
diff --git a/arch/powerpc/boot/flatdevtree.h b/arch/powerpc/boot/flatdevtree.h
new file mode 100644
index 0000000..761c8dc
--- /dev/null
+++ b/arch/powerpc/boot/flatdevtree.h
@@ -0,0 +1,46 @@
+/*
+ * 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 */
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index b66634c..d719bb9 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -14,17 +14,12 @@ #include "elf.h"
#include "page.h"
#include "string.h"
#include "stdio.h"
-#include "prom.h"
#include "zlib.h"
+#include "ops.h"
+#include "flatdevtree.h"
extern void flush_cache(void *, unsigned long);
-
-/* 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
-
extern char _start[];
extern char __bss_start[];
extern char _end[];
@@ -33,14 +28,6 @@ extern char _vmlinux_end[];
extern char _initrd_start[];
extern char _initrd_end[];
-/* A buffer that may be edited by tools operating on a zImage binary so as to
- * edit the command line passed to vmlinux (by setting /chosen/bootargs).
- * The buffer is put in it's own section so that tools may locate it easier.
- */
-static char builtin_cmdline[512]
- __attribute__((section("__builtin_cmdline")));
-
-
struct addr_range {
unsigned long addr;
unsigned long size;
@@ -51,21 +38,16 @@ static struct addr_range vmlinuz;
static struct addr_range initrd;
static unsigned long elfoffset;
+static int is_64bit;
-static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */
+/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
+static char scratch[46912];
static char elfheader[256];
-
-typedef void (*kernel_entry_t)( unsigned long,
- unsigned long,
- void *,
- void *);
-
+typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
#undef DEBUG
-static unsigned long claim_base;
-
#define HEAD_CRC 2
#define EXTRA_FIELD 4
#define ORIG_NAME 8
@@ -123,24 +105,6 @@ static void gunzip(void *dst, int dstlen
zlib_inflateEnd(&s);
}
-static unsigned long try_claim(unsigned long size)
-{
- unsigned long addr = 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 0;
- claim_base = PAGE_ALIGN(claim_base + size);
- return addr;
-}
-
static int is_elf64(void *hdr)
{
Elf64_Ehdr *elf64 = hdr;
@@ -169,16 +133,7 @@ static int is_elf64(void *hdr)
vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
-#if defined(PROG_START)
- /*
- * Maintain a "magic" minimum address. This keeps some older
- * firmware platforms running.
- */
-
- if (claim_base < PROG_START)
- claim_base = PROG_START;
-#endif
-
+ is_64bit = 1;
return 1;
}
@@ -212,47 +167,9 @@ static int is_elf32(void *hdr)
return 1;
}
-void export_cmdline(void* chosen_handle)
-{
- int len;
- char cmdline[2] = { 0, 0 };
-
- if (builtin_cmdline[0] == 0)
- return;
-
- len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
- if (len > 0 && cmdline[0] != 0)
- return;
-
- setprop(chosen_handle, "bootargs", builtin_cmdline,
- strlen(builtin_cmdline) + 1);
-}
-
-
-void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+static void prep_kernel(unsigned long *a1, unsigned long *a2)
{
int len;
- kernel_entry_t kernel_entry;
-
- memset(__bss_start, 0, _end - __bss_start);
-
- prom = (int (*)(void *)) promptr;
- chosen_handle = finddevice("/chosen");
- if (chosen_handle == (void *) -1)
- exit();
- if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
- exit();
-
- printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
-
- /*
- * The first available claim_base must be above the end of the
- * the loaded kernel wrapper file (_start to _end includes the
- * initrd image if it is present) and rounded up to a nice
- * 1 MB boundary for good measure.
- */
-
- claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
vmlinuz.addr = (unsigned long)_vmlinux_start;
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
@@ -263,43 +180,51 @@ void start(unsigned long a1, unsigned lo
gunzip(elfheader, sizeof(elfheader),
(unsigned char *)vmlinuz.addr, &len);
} else
- memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
+ memcpy(elfheader, (const void *)vmlinuz.addr,
+ sizeof(elfheader));
if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
exit();
}
+ if (platform_ops.image_hdr)
+ platform_ops.image_hdr(elfheader);
- /* We need to claim the memsize plus the file offset since gzip
+ /* We need to alloc the memsize plus the file offset since gzip
* will expand the header (file offset), then the kernel, then
* possible rubbish we don't care about. But the kernel bss must
* be claimed (it will be zero'd by the kernel itself)
*/
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
- vmlinux.addr = try_claim(vmlinux.memsize);
+ vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
if (vmlinux.addr == 0) {
printf("Can't allocate memory for kernel image !\n\r");
exit();
}
/*
- * Now we try to claim memory for the initrd (and copy it there)
+ * Now we try to alloc memory for the initrd (and copy it there)
*/
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
initrd.memsize = initrd.size;
if ( initrd.size > 0 ) {
- printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
- initrd.addr = try_claim(initrd.size);
+ printf("Allocating 0x%lx bytes for initrd ...\n\r",
+ initrd.size);
+ initrd.addr = (unsigned long)malloc((u32)initrd.size);
if (initrd.addr == 0) {
- printf("Can't allocate memory for initial ramdisk !\n\r");
+ printf("Can't allocate memory for initial "
+ "ramdisk !\n\r");
exit();
}
- a1 = initrd.addr;
- a2 = initrd.size;
- printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r",
- initrd.addr, (unsigned long)_initrd_start, initrd.size);
- memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
- printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr));
+ *a1 = initrd.addr;
+ *a2 = initrd.size;
+ printf("initial ramdisk moving 0x%lx <- 0x%lx "
+ "(0x%lx bytes)\n\r", initrd.addr,
+ (unsigned long)_initrd_start, initrd.size);
+ memmove((void *)initrd.addr, (void *)_initrd_start,
+ initrd.size);
+ printf("initrd head: 0x%lx\n\r",
+ *((unsigned long *)initrd.addr));
}
/* Eventually gunzip the kernel */
@@ -311,11 +236,10 @@ void start(unsigned long a1, unsigned lo
(unsigned char *)vmlinuz.addr, &len);
printf("done 0x%lx bytes\n\r", len);
} else {
- memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
+ memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,
+ vmlinuz.size);
}
- export_cmdline(chosen_handle);
-
/* Skip over the ELF header */
#ifdef DEBUG
printf("... skipping 0x%lx bytes of ELF header\n\r",
@@ -324,23 +248,107 @@ #endif
vmlinux.addr += elfoffset;
flush_cache((void *)vmlinux.addr, vmlinux.size);
+}
- kernel_entry = (kernel_entry_t)vmlinux.addr;
-#ifdef DEBUG
- printf( "kernel:\n\r"
- " entry addr = 0x%lx\n\r"
- " a1 = 0x%lx,\n\r"
- " a2 = 0x%lx,\n\r"
- " prom = 0x%lx,\n\r"
- " bi_recs = 0x%lx,\n\r",
- (unsigned long)kernel_entry, a1, a2,
- (unsigned long)prom, NULL);
-#endif
+void __attribute__ ((weak)) ft_init(void *dt_blob)
+{
+}
- kernel_entry(a1, a2, prom, NULL);
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char builtin_cmdline[COMMAND_LINE_SIZE]
+ __attribute__((__section__("__builtin_cmdline")));
- printf("Error: Linux kernel returned to zImage bootloader!\n\r");
+static void get_cmdline(char *buf, int size)
+{
+ void *devp;
+ int len = strlen(builtin_cmdline);
- exit();
+ buf[0] = '\0';
+
+ if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
+ len = min(len, size-1);
+ strncpy(buf, builtin_cmdline, len);
+ buf[len] = '\0';
+ }
+ else if ((devp = finddevice("/chosen")))
+ getprop(devp, "bootargs", buf, size);
+}
+
+static void set_cmdline(char *buf)
+{
+ void *devp;
+
+ if ((devp = finddevice("/chosen")))
+ setprop(devp, "bootargs", buf, strlen(buf) + 1);
}
+/* Section where ft can be tacked on after zImage is built */
+union blobspace {
+ struct boot_param_header hdr;
+ char space[8*1024];
+} dt_blob __attribute__((__section__("__builtin_ft")));
+
+struct platform_ops platform_ops;
+struct dt_ops dt_ops;
+struct console_ops console_ops;
+
+void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
+{
+ int have_dt = 0;
+ kernel_entry_t kentry;
+ char cmdline[COMMAND_LINE_SIZE];
+
+ memset(__bss_start, 0, _end - __bss_start);
+ memset(&platform_ops, 0, sizeof(platform_ops));
+ memset(&dt_ops, 0, sizeof(dt_ops));
+ memset(&console_ops, 0, sizeof(console_ops));
+
+ /* Override the dt_ops and device tree if there was an flat dev
+ * tree attached to the zImage.
+ */
+ if (dt_blob.hdr.magic == OF_DT_HEADER) {
+ have_dt = 1;
+ ft_init(&dt_blob);
+ }
+
+ if (platform_init(promptr))
+ exit();
+ if (console_ops.open && (console_ops.open() < 0))
+ exit();
+ if (platform_ops.fixups)
+ platform_ops.fixups();
+
+ printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
+ _start, sp);
+
+ prep_kernel(&a1, &a2);
+
+ /* If cmdline came from zimage wrapper or if we can edit the one
+ * in the dt, print it out and edit it, if possible.
+ */
+ if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) {
+ get_cmdline(cmdline, COMMAND_LINE_SIZE);
+ printf("\n\rLinux/PowerPC load: %s", cmdline);
+ if (console_ops.edit_cmdline)
+ console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
+ printf("\n\r");
+ set_cmdline(cmdline);
+ }
+
+ if (console_ops.close)
+ console_ops.close();
+
+ kentry = (kernel_entry_t) vmlinux.addr;
+ if (have_dt)
+ kentry(dt_ops.ft_addr(), 0, NULL);
+ else
+ /* XXX initrd addr/size should be passed in properties */
+ kentry(a1, a2, promptr);
+
+ /* console closed so printf below may not work */
+ printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");
+ exit();
+}
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
new file mode 100644
index 0000000..fd99f78
--- /dev/null
+++ b/arch/powerpc/boot/of.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * 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.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+
+typedef void *ihandle;
+typedef void *phandle;
+
+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 {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, nret);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+static int call_prom_ret(const char *service, int nargs, int nret,
+ unsigned int *rets, ...)
+{
+ int i;
+ struct prom_args {
+ const char *service;
+ int nargs;
+ int nret;
+ unsigned int args[12];
+ } args;
+ va_list list;
+
+ args.service = service;
+ args.nargs = nargs;
+ args.nret = nret;
+
+ va_start(list, rets);
+ for (i = 0; i < nargs; i++)
+ args.args[i] = va_arg(list, unsigned int);
+ va_end(list);
+
+ for (i = 0; i < nret; i++)
+ args.args[nargs+i] = 0;
+
+ if (prom(&args) < 0)
+ return -1;
+
+ if (rets != (void *) 0)
+ for (i = 1; i < nret; ++i)
+ rets[i-1] = args.args[nargs+i];
+
+ return (nret > 0)? args.args[nargs]: 0;
+}
+
+/*
+ * Older OF's require that when claiming a specific range of addresses,
+ * we claim the physical space in the /memory node and the virtual
+ * space in the chosen mmu node, and then do a map operation to
+ * map virtual to physical.
+ */
+static int need_map = -1;
+static ihandle chosen_mmu;
+static phandle memory;
+
+/* returns true if s2 is a prefix of s1 */
+static int string_match(const char *s1, const char *s2)
+{
+ for (; *s2; ++s2)
+ if (*s1++ != *s2)
+ return 0;
+ return 1;
+}
+
+static int check_of_version(void)
+{
+ phandle oprom, chosen;
+ char version[64];
+
+ oprom = finddevice("/openprom");
+ if (oprom == (phandle) -1)
+ return 0;
+ if (getprop(oprom, "model", version, sizeof(version)) <= 0)
+ return 0;
+ version[sizeof(version)-1] = 0;
+ printf("OF version = '%s'\r\n", version);
+ if (!string_match(version, "Open Firmware, 1.")
+ && !string_match(version, "FirmWorks,3."))
+ return 0;
+ chosen = finddevice("/chosen");
+ if (chosen == (phandle) -1) {
+ chosen = finddevice("/chosen@0");
+ if (chosen == (phandle) -1) {
+ printf("no chosen\n");
+ return 0;
+ }
+ }
+ if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
+ printf("no mmu\n");
+ return 0;
+ }
+ memory = (ihandle) call_prom("open", 1, 1, "/memory");
+ if (memory == (ihandle) -1) {
+ memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
+ if (memory == (ihandle) -1) {
+ printf("no memory node\n");
+ return 0;
+ }
+ }
+ printf("old OF detected\r\n");
+ return 1;
+}
+
+static void *claim(unsigned long virt, unsigned long size, unsigned long align)
+{
+ int ret;
+ unsigned int result;
+
+ if (need_map < 0)
+ 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)
+ return (void *) -1;
+ ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
+ align, size, virt);
+ /* 0x12 == coherent + read/write */
+ ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
+ 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;
+}
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
new file mode 100644
index 0000000..135eb4b
--- /dev/null
+++ b/arch/powerpc/boot/ops.h
@@ -0,0 +1,100 @@
+/*
+ * 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_ */
diff --git a/arch/powerpc/boot/prom.c b/arch/powerpc/boot/prom.c
deleted file mode 100644
index fa00577..0000000
--- a/arch/powerpc/boot/prom.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-#include <stdarg.h>
-#include <stddef.h>
-#include "string.h"
-#include "stdio.h"
-#include "prom.h"
-
-int (*prom)(void *);
-phandle chosen_handle;
-ihandle stdout;
-
-int call_prom(const char *service, int nargs, int nret, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, nret);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- return (nret > 0)? args.args[nargs]: 0;
-}
-
-int call_prom_ret(const char *service, int nargs, int nret,
- unsigned int *rets, ...)
-{
- int i;
- struct prom_args {
- const char *service;
- int nargs;
- int nret;
- unsigned int args[12];
- } args;
- va_list list;
-
- args.service = service;
- args.nargs = nargs;
- args.nret = nret;
-
- va_start(list, rets);
- for (i = 0; i < nargs; i++)
- args.args[i] = va_arg(list, unsigned int);
- va_end(list);
-
- for (i = 0; i < nret; i++)
- args.args[nargs+i] = 0;
-
- if (prom(&args) < 0)
- return -1;
-
- if (rets != (void *) 0)
- for (i = 1; i < nret; ++i)
- rets[i-1] = args.args[nargs+i];
-
- 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
- * space in the chosen mmu node, and then do a map operation to
- * map virtual to physical.
- */
-static int need_map = -1;
-static ihandle chosen_mmu;
-static phandle memory;
-
-/* returns true if s2 is a prefix of s1 */
-static int string_match(const char *s1, const char *s2)
-{
- for (; *s2; ++s2)
- if (*s1++ != *s2)
- return 0;
- return 1;
-}
-
-static int check_of_version(void)
-{
- phandle oprom, chosen;
- char version[64];
-
- oprom = finddevice("/openprom");
- if (oprom == (phandle) -1)
- return 0;
- if (getprop(oprom, "model", version, sizeof(version)) <= 0)
- return 0;
- version[sizeof(version)-1] = 0;
- printf("OF version = '%s'\r\n", version);
- if (!string_match(version, "Open Firmware, 1.")
- && !string_match(version, "FirmWorks,3."))
- return 0;
- chosen = finddevice("/chosen");
- if (chosen == (phandle) -1) {
- chosen = finddevice("/chosen@0");
- if (chosen == (phandle) -1) {
- printf("no chosen\n");
- return 0;
- }
- }
- if (getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) {
- printf("no mmu\n");
- return 0;
- }
- memory = (ihandle) call_prom("open", 1, 1, "/memory");
- if (memory == (ihandle) -1) {
- memory = (ihandle) call_prom("open", 1, 1, "/memory@0");
- if (memory == (ihandle) -1) {
- printf("no memory node\n");
- return 0;
- }
- }
- printf("old OF detected\r\n");
- return 1;
-}
-
-void *claim(unsigned long virt, unsigned long size, unsigned long align)
-{
- int ret;
- unsigned int result;
-
- if (need_map < 0)
- 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)
- return (void *) -1;
- ret = call_prom_ret("call-method", 5, 2, &result, "claim", chosen_mmu,
- align, size, virt);
- /* 0x12 == coherent + read/write */
- ret = call_prom("call-method", 6, 1, "map", chosen_mmu,
- 0x12, size, virt, virt);
- return (void *) virt;
-}
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
deleted file mode 100644
index a57b184..0000000
--- a/arch/powerpc/boot/prom.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#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_ */
diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index b5aa522..6d5f638 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -10,7 +10,7 @@ #include <stdarg.h>
#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;
}
diff --git a/arch/powerpc/boot/stdio.h b/arch/powerpc/boot/stdio.h
index eb9e16c..73b8a91 100644
--- a/arch/powerpc/boot/stdio.h
+++ b/arch/powerpc/boot/stdio.h
@@ -1,8 +1,16 @@
#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);
diff --git a/arch/powerpc/boot/types.h b/arch/powerpc/boot/types.h
new file mode 100644
index 0000000..79d26e7
--- /dev/null
+++ b/arch/powerpc/boot/types.h
@@ -0,0 +1,23 @@
+#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_ */
^ permalink raw reply related [flat|nested] 36+ messages in thread* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-19 23:00 Paul Mackerras
@ 2006-09-20 1:20 ` Mark A. Greer
2006-09-20 1:28 ` Mark A. Greer
2006-09-20 3:10 ` Josh Boyer
0 siblings, 2 replies; 36+ messages in thread
From: Mark A. Greer @ 2006-09-20 1:20 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
Paul,
Regarding our earlier conversation about ft_translate_addr and
ft_parentize. I just realized that on IRC today Matt Porter pointed
out that using the "reg" property in ns16550.c is wrong. We--several
of us on #mklinux--decided that the "address" property is the correct
thing to use because we should really be using a virtual address from
the fw (bootwrapper has no ioremap). So, unless someone objects,
we'll all add the "address" property to our uart device nodes in our
fdt's (if they can be used as the console).
A couple consequences, if that happens:
- It removes the requirement for ft_translate_addr (and
dt_ops.translate_addr) in the bootwrapper. That cleans up
flatdevtree_misc.c a lot.
- Since ft_find_node/device will be the only caller of ft_parentize
now, that may change your plans for ft_parentize.
Do you have any objections to using "address" property instead of "reg"?
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 1:20 ` Mark A. Greer
@ 2006-09-20 1:28 ` Mark A. Greer
2006-09-20 20:58 ` Mark A. Greer
2006-09-20 3:10 ` Josh Boyer
1 sibling, 1 reply; 36+ messages in thread
From: Mark A. Greer @ 2006-09-20 1:28 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
On Tue, Sep 19, 2006 at 06:20:42PM -0700, Mark A. Greer wrote:
> Paul,
>
> Regarding our earlier conversation about ft_translate_addr and
...
BTW, the only changes to your patch would be removing translate_addr from
dt_ops in ops.h and removing the "dt_ops.translate_addr = NULL;" line
in of.c.
I'll respin the other patches.
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 1:28 ` Mark A. Greer
@ 2006-09-20 20:58 ` Mark A. Greer
0 siblings, 0 replies; 36+ messages in thread
From: Mark A. Greer @ 2006-09-20 20:58 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev, Paul Mackerras
On Tue, Sep 19, 2006 at 06:28:43PM -0700, Mark A. Greer wrote:
> On Tue, Sep 19, 2006 at 06:20:42PM -0700, Mark A. Greer wrote:
> > Paul,
> >
> > Regarding our earlier conversation about ft_translate_addr and
> ...
>
> BTW, the only changes to your patch would be removing translate_addr from
> dt_ops in ops.h and removing the "dt_ops.translate_addr = NULL;" line
> in of.c.
FWIW, here is a patch to do this:
diff -u b/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c
--- b/arch/powerpc/boot/of.c
+++ b/arch/powerpc/boot/of.c
@@ -270,7 +270,6 @@
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;
diff -u b/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h
--- b/arch/powerpc/boot/ops.h
+++ b/arch/powerpc/boot/ops.h
@@ -34,8 +34,6 @@
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;
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 1:20 ` Mark A. Greer
2006-09-20 1:28 ` Mark A. Greer
@ 2006-09-20 3:10 ` Josh Boyer
2006-09-20 20:23 ` Segher Boessenkool
1 sibling, 1 reply; 36+ messages in thread
From: Josh Boyer @ 2006-09-20 3:10 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev, Paul Mackerras
On Tue, 2006-09-19 at 18:20 -0700, Mark A. Greer wrote:
> Paul,
>
> Regarding our earlier conversation about ft_translate_addr and
> ft_parentize. I just realized that on IRC today Matt Porter pointed
> out that using the "reg" property in ns16550.c is wrong. We--several
> of us on #mklinux--decided that the "address" property is the correct
> thing to use because we should really be using a virtual address from
> the fw (bootwrapper has no ioremap). So, unless someone objects,
> we'll all add the "address" property to our uart device nodes in our
> fdt's (if they can be used as the console).
An example of where this is needed is 4xx. Lots of boards rely on the
openbios mapping created for the UART in the zImage wrapper. However,
the kernel doesn't rely on that, and the "reg" property of the .dts
should contain the physical address.
It was pointed out on IRC that the "address" property is defined in the
OF spec for specifying virtual address mappings. This is exactly what
we need in that it allows the zImage wrapper to use the fw defined UART
mapping, but the kernel still gets the real physical address later on.
And other things that don't use zImage wrappers, like u-boot, can simply
ignore the "address" property defined within the UART node.
The options that were discussed were this, hardcoding, or implementing
ioremap in the bootwraper. This seemed to be the most elegant way of
doing things.
josh
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 3:10 ` Josh Boyer
@ 2006-09-20 20:23 ` Segher Boessenkool
2006-09-20 21:04 ` Josh Boyer
2006-09-20 21:32 ` Benjamin Herrenschmidt
0 siblings, 2 replies; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-20 20:23 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev, Paul Mackerras
> It was pointed out on IRC that the "address" property is defined in
> the
> OF spec for specifying virtual address mappings. This is exactly what
> we need in that it allows the zImage wrapper to use the fw defined
> UART
> mapping, but the kernel still gets the real physical address later on.
> And other things that don't use zImage wrappers, like u-boot, can
> simply
> ignore the "address" property defined within the UART node.
The "address" property has several problems. An obvious one is that the
name is too generic. A nastier one is that once you start making new
MMU
mappings, you have to keep *all* old mappings, or blow away the mapping
for this "address" as well (you don't know the size of the mapping).
And
a third problem is that it can only encode 32-bit virtual addresses.
Now, if it's only used for the very-early-debug UART console on machines
that cannot accesses physical addresses directly, in things like a boot-
wrapper that cannot be bothered to set up a MMU mapping themselves (and
there might be good reasons not to), and only when there is no client
interface (i.e., it uses the flat tree only); then it might be a
reasonable
approach. All alternatives I can think of have their own nasty
problems.
So please comment the nastiness with a big "HACK HACK HACK" comment and
make sure it only ever gets used on systems where nothing better is
available, and all should be fine.
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 20:23 ` Segher Boessenkool
@ 2006-09-20 21:04 ` Josh Boyer
2006-09-20 21:32 ` Benjamin Herrenschmidt
1 sibling, 0 replies; 36+ messages in thread
From: Josh Boyer @ 2006-09-20 21:04 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, Paul Mackerras
On Wed, 2006-09-20 at 22:23 +0200, Segher Boessenkool wrote:
> > It was pointed out on IRC that the "address" property is defined in
> > the
> > OF spec for specifying virtual address mappings. This is exactly what
> > we need in that it allows the zImage wrapper to use the fw defined
> > UART
> > mapping, but the kernel still gets the real physical address later on.
> > And other things that don't use zImage wrappers, like u-boot, can
> > simply
> > ignore the "address" property defined within the UART node.
>
> The "address" property has several problems. An obvious one is that the
> name is too generic. A nastier one is that once you start making new
Well, I agree. But it's documented in the spec. Blame the spec
writers ;).
> MMU
> mappings, you have to keep *all* old mappings, or blow away the mapping
> for this "address" as well (you don't know the size of the mapping).
Which we do on 4xx in the kernel (the blow away part).
>
> And
> a third problem is that it can only encode 32-bit virtual addresses.
Which isn't a _current_ problem, since the use case here is the
bootwrapper and that limits itself to 32bit already anyway.
>
> Now, if it's only used for the very-early-debug UART console on machines
> that cannot accesses physical addresses directly, in things like a boot-
> wrapper that cannot be bothered to set up a MMU mapping themselves (and
> there might be good reasons not to), and only when there is no client
> interface (i.e., it uses the flat tree only); then it might be a
> reasonable
> approach. All alternatives I can think of have their own nasty
> problems.
Right, that's where we were at too.
> So please comment the nastiness with a big "HACK HACK HACK" comment and
> make sure it only ever gets used on systems where nothing better is
> available, and all should be fine.
I'll leave that to Mark ;)
josh
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 20:23 ` Segher Boessenkool
2006-09-20 21:04 ` Josh Boyer
@ 2006-09-20 21:32 ` Benjamin Herrenschmidt
2006-09-20 21:57 ` Mark A. Greer
1 sibling, 1 reply; 36+ messages in thread
From: Benjamin Herrenschmidt @ 2006-09-20 21:32 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, Paul Mackerras
> So please comment the nastiness with a big "HACK HACK HACK" comment and
> make sure it only ever gets used on systems where nothing better is
> available, and all should be fine.
An option is to call it something like fw,address to avoid confusion and
make it somewhat clearer that it's really a firmware address useable
within the context of the firmware...
Ben.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 21:32 ` Benjamin Herrenschmidt
@ 2006-09-20 21:57 ` Mark A. Greer
2006-09-21 0:07 ` Segher Boessenkool
0 siblings, 1 reply; 36+ messages in thread
From: Mark A. Greer @ 2006-09-20 21:57 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Paul Mackerras
On Thu, Sep 21, 2006 at 07:32:37AM +1000, Benjamin Herrenschmidt wrote:
>
> > So please comment the nastiness with a big "HACK HACK HACK" comment and
> > make sure it only ever gets used on systems where nothing better is
> > available, and all should be fine.
>
> An option is to call it something like fw,address to avoid confusion and
> make it somewhat clearer that it's really a firmware address useable
> within the context of the firmware...
Okay. We did talk about that but then we realized that "address"
was for vaddrs. We thought of other names like "bootwrapper-vaddr"
etc. but "fw,address" or "fw,vaddr" are probably better--they show that
the vaddr was setup by the fw.
Comments?
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-20 21:57 ` Mark A. Greer
@ 2006-09-21 0:07 ` Segher Boessenkool
2006-09-21 13:37 ` Matt Porter
0 siblings, 1 reply; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-21 0:07 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Paul Mackerras, linuxppc-dev
>>> So please comment the nastiness with a big "HACK HACK HACK"
>>> comment and
>>> make sure it only ever gets used on systems where nothing better is
>>> available, and all should be fine.
>>
>> An option is to call it something like fw,address to avoid
>> confusion and
>> make it somewhat clearer that it's really a firmware address useable
>> within the context of the firmware...
>
> Okay. We did talk about that but then we realized that "address"
> was for vaddrs. We thought of other names like "bootwrapper-vaddr"
> etc. but "fw,address" or "fw,vaddr" are probably better--they show
> that
> the vaddr was setup by the fw.
If you use a different name than "address", you're not bound to its
semantics either. And as those semantics have some problems, please
do change-em. How about:
The "reg-virtual-address" property contains the same regions as the
"reg" property, in the same order; each entry is #address-cells from
the root node 32-bit integers wide(*); the entry describes a
contiguous area of virtual memory of the same size as the
corresponding "reg" entry, mapping that area, or 0 if the area isn't
mapped.
Any holes in this definition?
Segher
(*) This isn't strictly correct, but OF doesn't describe the size of
virtual addresses anywhere. In practice, it's the same as the size
of physical addresses always. Oh, and the name "virtual" isn't correct
in PowerPC-speak anyway, heh.
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-21 0:07 ` Segher Boessenkool
@ 2006-09-21 13:37 ` Matt Porter
2006-09-21 14:15 ` Jon Loeliger
2006-09-21 15:31 ` Segher Boessenkool
0 siblings, 2 replies; 36+ messages in thread
From: Matt Porter @ 2006-09-21 13:37 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev, Paul Mackerras
On Thu, Sep 21, 2006 at 02:07:05AM +0200, Segher Boessenkool wrote:
> If you use a different name than "address", you're not bound to its
> semantics either. And as those semantics have some problems, please
> do change-em. How about:
>
> The "reg-virtual-address" property contains the same regions as the
> "reg" property, in the same order; each entry is #address-cells from
> the root node 32-bit integers wide(*); the entry describes a
> contiguous area of virtual memory of the same size as the
> corresponding "reg" entry, mapping that area, or 0 if the area isn't
> mapped.
>
> Any holes in this definition?
On PPC44x (and other PowerPC processors) the number of address cells
to represent a virtual address and a physical address differ due the
36-bits of physical address space. Regardless of the name of the
new property, it should be defined to allow a different number of
address cells to represent an address in virtual address space.
>
> (*) This isn't strictly correct, but OF doesn't describe the size of
> virtual addresses anywhere. In practice, it's the same as the size
> of physical addresses always. Oh, and the name "virtual" isn't correct
> in PowerPC-speak anyway, heh.
Actually, in practice, it's not always the same size as a physical
address. We have 36-bit physical addressing systems in the real world.
FWIW, I'd be happy with this property name or fw,address. When we
discussed this on IRC the thought was to conform to what already
existed for this purpose in the OF spec. Since the address prop sounds
like it will confuse some people I think it makes sense to add a
new property (might as well just throw out the spec :P).
-Matt
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-21 13:37 ` Matt Porter
@ 2006-09-21 14:15 ` Jon Loeliger
2006-09-21 14:26 ` Matt Porter
2006-09-21 15:31 ` Segher Boessenkool
1 sibling, 1 reply; 36+ messages in thread
From: Jon Loeliger @ 2006-09-21 14:15 UTC (permalink / raw)
To: Matt Porter; +Cc: linuxppc-dev, Paul Mackerras
So, like, the other day Matt Porter mumbled:
>
> Since the address prop sounds
> like it will confuse some people I think it makes sense to add a
> new property (might as well just throw out the spec :P).
Ayyyy, mate. She be not so much a "code" as she be a "guideline".
Huh? That was the other day? Neeeveeer mind.
jdl
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-21 14:15 ` Jon Loeliger
@ 2006-09-21 14:26 ` Matt Porter
0 siblings, 0 replies; 36+ messages in thread
From: Matt Porter @ 2006-09-21 14:26 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev, Paul Mackerras
On Thu, Sep 21, 2006 at 09:15:22AM -0500, Jon Loeliger wrote:
> So, like, the other day Matt Porter mumbled:
> >
> > Since the address prop sounds
> > like it will confuse some people I think it makes sense to add a
> > new property (might as well just throw out the spec :P).
>
> Ayyyy, mate. She be not so much a "code" as she be a "guideline".
Yeah, yeah, of course. We only use it when convenient.
> Huh? That was the other day? Neeeveeer mind.
:)
-Matt
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-21 13:37 ` Matt Porter
2006-09-21 14:15 ` Jon Loeliger
@ 2006-09-21 15:31 ` Segher Boessenkool
2006-09-22 1:24 ` Mark A. Greer
1 sibling, 1 reply; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-21 15:31 UTC (permalink / raw)
To: Matt Porter; +Cc: linuxppc-dev, Paul Mackerras
> On PPC44x (and other PowerPC processors) the number of address cells
> to represent a virtual address and a physical address differ due the
> 36-bits of physical address space.
The number of virtual address cells is always 1. A cell isn't always
32-bits though. Want more confusion? Lots of properties are called
"<something>-cells" etc., but those names are historical; the proper
name for the things encoded in properties is "32-bit integers".
> Regardless of the name of the
> new property, it should be defined to allow a different number of
> address cells to represent an address in virtual address space.
How about you check whether the "64-bit" property exists in the CPU
nodes?
>> (*) This isn't strictly correct, but OF doesn't describe the size of
>> virtual addresses anywhere. In practice, it's the same as the size
>> of physical addresses always. Oh, and the name "virtual" isn't
>> correct
>> in PowerPC-speak anyway, heh.
>
> Actually, in practice, it's not always the same size as a physical
> address. We have 36-bit physical addressing systems in the real world.
Darn, and you have #address-cells = 2 in the root node? It's allowed,
sure.
> FWIW, I'd be happy with this property name or fw,address. When we
> discussed this on IRC the thought was to conform to what already
> existed for this purpose in the OF spec. Since the address prop sounds
> like it will confuse some people I think it makes sense to add a
> new property (might as well just throw out the spec :P).
But if you do make something new, you'll have to make it better
than what you're replacing, or what's the point :-)
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-21 15:31 ` Segher Boessenkool
@ 2006-09-22 1:24 ` Mark A. Greer
2006-09-22 8:43 ` Segher Boessenkool
0 siblings, 1 reply; 36+ messages in thread
From: Mark A. Greer @ 2006-09-22 1:24 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
On Thu, Sep 21, 2006 at 05:31:18PM +0200, Segher Boessenkool wrote:
> >Regardless of the name of the
> >new property, it should be defined to allow a different number of
> >address cells to represent an address in virtual address space.
>
> How about you check whether the "64-bit" property exists in the CPU
> nodes?
That seemed like the right thing until I realized, its still specifying
the physical size, not the virtual size.
I don't think we can avoid making a new xxx-cells property for the virt
addr size. Ben suggested adding #virt-address-cells to the root node.
I like the name but prefer putting it directly under "/cpus" because
the virt addr size is really determined by the cpu. It doesn't matter
that much to me, though.
Comments?
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 1:24 ` Mark A. Greer
@ 2006-09-22 8:43 ` Segher Boessenkool
2006-09-22 18:59 ` Mark A. Greer
0 siblings, 1 reply; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-22 8:43 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
>> How about you check whether the "64-bit" property exists in the CPU
>> nodes?
>
> That seemed like the right thing until I realized, its still
> specifying
> the physical size, not the virtual size.
No, it says that the CPU supports the full PowerPC arch, not just the
32-bit subset. Every 64-bit PowerPC has a 64-bit effective address,
every 32-bit PowerPC has a 32-bit effective address. There's no way
around that unless you change most of the instruction set ;-)
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 8:43 ` Segher Boessenkool
@ 2006-09-22 18:59 ` Mark A. Greer
2006-09-22 19:36 ` Sergei Shtylyov
2006-09-23 0:54 ` Segher Boessenkool
0 siblings, 2 replies; 36+ messages in thread
From: Mark A. Greer @ 2006-09-22 18:59 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
On Fri, Sep 22, 2006 at 10:43:42AM +0200, Segher Boessenkool wrote:
> >>How about you check whether the "64-bit" property exists in the CPU
> >>nodes?
> >
> >That seemed like the right thing until I realized, its still
> >specifying
> >the physical size, not the virtual size.
>
> No, it says that the CPU supports the full PowerPC arch, not just the
> 32-bit subset. Every 64-bit PowerPC has a 64-bit effective address,
> every 32-bit PowerPC has a 32-bit effective address. There's no way
> around that unless you change most of the instruction set ;-)
Oh, okay. I didn't realize there was an actual "64-bit" property.
I thought you just meant "/cpus/#address-cells = <2>".
I should've googled first.
So, yes, that probably does give us the info we need.
--
Here is where I think we are for getting the effective base addr
of the regs for the console uart in the bootwrapper:
1) We add the "fw,address" property to the uart's dt node. That
property provides the effective base address of the uart's registers
left over by the firmware. The format is similar to that of the
"reg" property in that it contains an "address size" tuple.
2) The effective address width (32 or 64 bits) (i.e., the # cells in
the "address" portion of the tuple) is indicated by the presence of the
"/cpus/64-bit" property. If it exists, the effective addr space is
64-bits wide (2 cells); if not, its 32-bits wide (1 cell).
3) The number of cells in the "size" portion of the tuple is indicated
by the nearest #size-cells as you go up the tree. Just like the "reg"
property.
Comments?
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 18:59 ` Mark A. Greer
@ 2006-09-22 19:36 ` Sergei Shtylyov
2006-09-22 20:40 ` Mark A. Greer
2006-09-23 0:57 ` Segher Boessenkool
2006-09-23 0:54 ` Segher Boessenkool
1 sibling, 2 replies; 36+ messages in thread
From: Sergei Shtylyov @ 2006-09-22 19:36 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
Hello.
Mark A. Greer wrote:
> Here is where I think we are for getting the effective base addr
> of the regs for the console uart in the bootwrapper:
> 1) We add the "fw,address" property to the uart's dt node. That
> property provides the effective base address of the uart's registers
> left over by the firmware. The format is similar to that of the
> "reg" property in that it contains an "address size" tuple.
> 2) The effective address width (32 or 64 bits) (i.e., the # cells in
> the "address" portion of the tuple) is indicated by the presence of the
> "/cpus/64-bit" property. If it exists, the effective addr space is
> 64-bits wide (2 cells); if not, its 32-bits wide (1 cell).
>
> 3) The number of cells in the "size" portion of the tuple is indicated
> by the nearest #size-cells as you go up the tree. Just like the "reg"
> property.
Well, is there need for duplication of size if "reg" prop must be present
anyway?
WBR, Sergei
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 19:36 ` Sergei Shtylyov
@ 2006-09-22 20:40 ` Mark A. Greer
2006-09-22 20:43 ` Sergei Shtylyov
2006-09-23 0:57 ` Segher Boessenkool
1 sibling, 1 reply; 36+ messages in thread
From: Mark A. Greer @ 2006-09-22 20:40 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
On Fri, Sep 22, 2006 at 11:36:11PM +0400, Sergei Shtylyov wrote:
> >3) The number of cells in the "size" portion of the tuple is indicated
> >by the nearest #size-cells as you go up the tree. Just like the "reg"
> >property.
>
> Well, is there need for duplication of size if "reg" prop must be
> present anyway?
We're not adding another #size-cells, we're using the same one that
"reg" uses. No duplication, just reuse.
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 20:40 ` Mark A. Greer
@ 2006-09-22 20:43 ` Sergei Shtylyov
2006-09-22 20:52 ` Mark A. Greer
0 siblings, 1 reply; 36+ messages in thread
From: Sergei Shtylyov @ 2006-09-22 20:43 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
Hello.
Mark A. Greer wrote:
>>>3) The number of cells in the "size" portion of the tuple is indicated
>>>by the nearest #size-cells as you go up the tree. Just like the "reg"
>>>property.
>> Well, is there need for duplication of size if "reg" prop must be
>> present anyway?
> We're not adding another #size-cells, we're using the same one that
> "reg" uses. No duplication, just reuse.
I mean size could have been gotten from "reg" prop.
> Mark
WBR, Sergei
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 20:43 ` Sergei Shtylyov
@ 2006-09-22 20:52 ` Mark A. Greer
2006-09-22 20:56 ` Sergei Shtylyov
0 siblings, 1 reply; 36+ messages in thread
From: Mark A. Greer @ 2006-09-22 20:52 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
On Sat, Sep 23, 2006 at 12:43:39AM +0400, Sergei Shtylyov wrote:
> Hello.
>
> Mark A. Greer wrote:
>
> >>>3) The number of cells in the "size" portion of the tuple is indicated
> >>>by the nearest #size-cells as you go up the tree. Just like the "reg"
> >>>property.
>
> >> Well, is there need for duplication of size if "reg" prop must be
> >> present anyway?
>
> >We're not adding another #size-cells, we're using the same one that
> >"reg" uses. No duplication, just reuse.
>
> I mean size could have been gotten from "reg" prop.
Oh. Nah, seems like a violation of how things usually work and it only
adds work to look up yet another property.
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 20:52 ` Mark A. Greer
@ 2006-09-22 20:56 ` Sergei Shtylyov
0 siblings, 0 replies; 36+ messages in thread
From: Sergei Shtylyov @ 2006-09-22 20:56 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
Hello.
Mark A. Greer wrote:
>>>>>3) The number of cells in the "size" portion of the tuple is indicated
>>>>>by the nearest #size-cells as you go up the tree. Just like the "reg"
>>>>>property.
>>>> Well, is there need for duplication of size if "reg" prop must be
>>>> present anyway?
>>>We're not adding another #size-cells, we're using the same one that
>>>"reg" uses. No duplication, just reuse.
>> I mean size could have been gotten from "reg" prop.
> Oh. Nah, seems like a violation of how things usually work and it only
Since you're cloning the "address" prop which consisted only of the
address value, this doesn't seem so obvious.
> adds work to look up yet another property.
Oh, that's another story. :-)
> Mark
WBR, Sergei
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 19:36 ` Sergei Shtylyov
2006-09-22 20:40 ` Mark A. Greer
@ 2006-09-23 0:57 ` Segher Boessenkool
2006-09-23 15:48 ` Sergei Shtylyov
1 sibling, 1 reply; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-23 0:57 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
> Well, is there need for duplication of size if "reg" prop must
> be present anyway?
No, not really. But this way, "reg" can be absent, actually.
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-23 0:57 ` Segher Boessenkool
@ 2006-09-23 15:48 ` Sergei Shtylyov
0 siblings, 0 replies; 36+ messages in thread
From: Sergei Shtylyov @ 2006-09-23 15:48 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
Hello.
Segher Boessenkool wrote:
>> Well, is there need for duplication of size if "reg" prop must be
>> present anyway?
> No, not really. But this way, "reg" can be absent, actually.
Is this a joke? :-)
Or you're supposing that UART is only usable to the bootwrapper? Or you're
going to add support for this new prop to the main kernel as well?
> Segher
WBR, Sergei
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-22 18:59 ` Mark A. Greer
2006-09-22 19:36 ` Sergei Shtylyov
@ 2006-09-23 0:54 ` Segher Boessenkool
2006-09-23 8:18 ` Mark A. Greer
1 sibling, 1 reply; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-23 0:54 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
> Oh, okay. I didn't realize there was an actual "64-bit" property.
> I thought you just meant "/cpus/#address-cells = <2>".
> I should've googled first.
No, cpus/"#address-cells" is required to be 1, as that's the number
of address cells required to identify a CPU itself.
> So, yes, that probably does give us the info we need.
> Here is where I think we are for getting the effective base addr
> of the regs for the console uart in the bootwrapper:
>
> 1) We add the "fw,address" property to the uart's dt node. That
> property provides the effective base address of the uart's registers
> left over by the firmware. The format is similar to that of the
> "reg" property in that it contains an "address size" tuple.
I completely lost you here, sorry. Maybe it's me. Care to
repeat this in a (perhaps more verbose) way that I might
understand?
> 2) The effective address width (32 or 64 bits) (i.e., the # cells in
> the "address" portion of the tuple) is indicated by the presence of
> the
> "/cpus/64-bit" property. If it exists, the effective addr space is
> 64-bits wide (2 cells); if not, its 32-bits wide (1 cell).
Yes. Except a "cell" is not what you think it is. A "cell" is the
size of numbers OF deals with internally; just deal with it. Of
course, there's things like "#address-cells", which really mean
"#-32bit-things-per-address".
> 3) The number of cells in the "size" portion of the tuple is indicated
> by the nearest #size-cells as you go up the tree. Just like the "reg"
> property.
Yes, sounds fine.
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-23 0:54 ` Segher Boessenkool
@ 2006-09-23 8:18 ` Mark A. Greer
2006-09-23 10:15 ` Segher Boessenkool
0 siblings, 1 reply; 36+ messages in thread
From: Mark A. Greer @ 2006-09-23 8:18 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
On Sat, Sep 23, 2006 at 02:54:12AM +0200, Segher Boessenkool wrote:
> >Here is where I think we are for getting the effective base addr
> >of the regs for the console uart in the bootwrapper:
> >
> >1) We add the "fw,address" property to the uart's dt node. That
> >property provides the effective base address of the uart's registers
> >left over by the firmware. The format is similar to that of the
> >"reg" property in that it contains an "address size" tuple.
>
> I completely lost you here, sorry. Maybe it's me. Care to
> repeat this in a (perhaps more verbose) way that I might
> understand?
Well, I'm still new to the dt stuff and probably use the wrong
terminology all the time. I tried to use the same type of description
that is used in ./Documentation/powerpc/booting-without-of.txt.
For example:
'"reg" properties are always a tuple of the type "address size"
where the number of cells of address and size is specified by
the bus #address-cells and #size-cells.'
All I'm try to say is that "fw,address" is just like the "reg" property
except that it holds the effective addr not the physical addr and the
size of the address is determined by the existence of "/cpus/64-bit"
not #address-cells. That's all.
> >2) The effective address width (32 or 64 bits) (i.e., the # cells in
> >the "address" portion of the tuple) is indicated by the presence of
> >the
> >"/cpus/64-bit" property. If it exists, the effective addr space is
> >64-bits wide (2 cells); if not, its 32-bits wide (1 cell).
>
> Yes. Except a "cell" is not what you think it is. A "cell" is the
> size of numbers OF deals with internally; just deal with it. Of
> course, there's things like "#address-cells", which really mean
> "#-32bit-things-per-address".
Okay, well, when I talked about cells I meant "#-32bit-things-per-address".
Obviously it was silly of me to think that "#address-cells" meant the # of
address cells...
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-23 8:18 ` Mark A. Greer
@ 2006-09-23 10:15 ` Segher Boessenkool
2006-09-25 17:53 ` Mark A. Greer
2006-09-28 20:53 ` Sergei Shtylyov
0 siblings, 2 replies; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-23 10:15 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
> All I'm try to say is that "fw,address" is just like the "reg"
> property
> except that it holds the effective addr not the physical addr and the
> size of the address is determined by the existence of "/cpus/64-bit"
> not #address-cells. That's all.
Sounds good.
>> Yes. Except a "cell" is not what you think it is. A "cell" is the
>> size of numbers OF deals with internally; just deal with it. Of
>> course, there's things like "#address-cells", which really mean
>> "#-32bit-things-per-address".
>
> Okay, well, when I talked about cells I meant "#-32bit-things-per-
> address".
> Obviously it was silly of me to think that "#address-cells" meant
> the # of
> address cells...
Some background might clear things up (or not)... A "cell" is the
unit of data in a Forth system. When OF was young (and not yet
called OF), all systems were 32-bit, and the 32-bit-thingies in
the properties (which weren't yet called properties) in the device
tree were called cells as well. When 64-bit came into the picture,
everything fell apart. The "correct" name for the property thingies
now is "integers as encoded with encode-int". Maybe we can compromise
on calling it "property cells" or something.
The situation is even worse with "package", let's not go there :-)
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-23 10:15 ` Segher Boessenkool
@ 2006-09-25 17:53 ` Mark A. Greer
2006-09-25 23:40 ` Segher Boessenkool
2006-09-28 20:53 ` Sergei Shtylyov
1 sibling, 1 reply; 36+ messages in thread
From: Mark A. Greer @ 2006-09-25 17:53 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
On Sat, Sep 23, 2006 at 12:15:19PM +0200, Segher Boessenkool wrote:
> >All I'm try to say is that "fw,address" is just like the "reg"
> >property
> >except that it holds the effective addr not the physical addr and the
> >size of the address is determined by the existence of "/cpus/64-bit"
> >not #address-cells. That's all.
>
> Sounds good.
>
> >>Yes. Except a "cell" is not what you think it is. A "cell" is the
> >>size of numbers OF deals with internally; just deal with it. Of
> >>course, there's things like "#address-cells", which really mean
> >>"#-32bit-things-per-address".
> >
> >Okay, well, when I talked about cells I meant "#-32bit-things-per-
> >address".
> >Obviously it was silly of me to think that "#address-cells" meant
> >the # of
> >address cells...
>
> Some background might clear things up (or not)... A "cell" is the
> unit of data in a Forth system. When OF was young (and not yet
> called OF), all systems were 32-bit, and the 32-bit-thingies in
> the properties (which weren't yet called properties) in the device
> tree were called cells as well. When 64-bit came into the picture,
> everything fell apart. The "correct" name for the property thingies
> now is "integers as encoded with encode-int". Maybe we can compromise
> on calling it "property cells" or something.
Okay, fair enough. I think you understand what I was trying to say,
right? If so, do you have any objections to it?
> The situation is even worse with "package", let's not go there :-)
Heh. :)
Mark
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-25 17:53 ` Mark A. Greer
@ 2006-09-25 23:40 ` Segher Boessenkool
2006-09-25 23:44 ` Segher Boessenkool
2006-09-25 23:46 ` Mark A. Greer
0 siblings, 2 replies; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-25 23:40 UTC (permalink / raw)
To: Mark A. Greer; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
>>> All I'm try to say is that "fw,address" is just like the "reg"
>>> property
>>> except that it holds the effective addr not the physical addr and
>>> the
>>> size of the address is determined by the existence of "/cpus/64-bit"
>>> not #address-cells. That's all.
> Okay, fair enough. I think you understand what I was trying to say,
> right? If so, do you have any objections to it?
Yes: don't call it "<whatever>address", when you immediately say it
is more like "reg". How about "virtual-reg"?
>> The situation is even worse with "package", let's not go there :-)
>
> Heh. :)
Ooh your tempting me :-)
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-25 23:40 ` Segher Boessenkool
@ 2006-09-25 23:44 ` Segher Boessenkool
2006-09-25 23:46 ` Mark A. Greer
1 sibling, 0 replies; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-25 23:44 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
>>>> All I'm try to say is that "fw,address" is just like the "reg"
>>>> property
>>>> except that it holds the effective addr not the physical addr and
>>>> the
>>>> size of the address is determined by the existence of "/cpus/64-
>>>> bit"
>>>> not #address-cells. That's all.
Oh and use "/cpus/<some-cpu>/64-bit", not a property directly in
the "/cpus" node.
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-25 23:40 ` Segher Boessenkool
2006-09-25 23:44 ` Segher Boessenkool
@ 2006-09-25 23:46 ` Mark A. Greer
1 sibling, 0 replies; 36+ messages in thread
From: Mark A. Greer @ 2006-09-25 23:46 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Paul Mackerras, Matt Porter, linuxppc-dev
On Tue, Sep 26, 2006 at 01:40:15AM +0200, Segher Boessenkool wrote:
> >>>All I'm try to say is that "fw,address" is just like the "reg"
> >>>property
> >>>except that it holds the effective addr not the physical addr and
> >>>the
> >>>size of the address is determined by the existence of "/cpus/64-bit"
> >>>not #address-cells. That's all.
>
> >Okay, fair enough. I think you understand what I was trying to say,
> >right? If so, do you have any objections to it?
>
> Yes: don't call it "<whatever>address", when you immediately say it
> is more like "reg". How about "virtual-reg"?
Anyone have a problem with "virtual-reg"?
^ permalink raw reply [flat|nested] 36+ messages in thread
* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-23 10:15 ` Segher Boessenkool
2006-09-25 17:53 ` Mark A. Greer
@ 2006-09-28 20:53 ` Sergei Shtylyov
2006-09-30 8:36 ` Segher Boessenkool
1 sibling, 1 reply; 36+ messages in thread
From: Sergei Shtylyov @ 2006-09-28 20:53 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
Hello.
Segher Boessenkool wrote:
>>>Yes. Except a "cell" is not what you think it is. A "cell" is the
>>>size of numbers OF deals with internally; just deal with it. Of
>>>course, there's things like "#address-cells", which really mean
>>>"#-32bit-things-per-address".
>>Okay, well, when I talked about cells I meant "#-32bit-things-per-
>>address".
>>Obviously it was silly of me to think that "#address-cells" meant
>>the # of
>>address cells...
> Some background might clear things up (or not)... A "cell" is the
> unit of data in a Forth system. When OF was young (and not yet
> called OF), all systems were 32-bit, and the 32-bit-thingies in
> the properties (which weren't yet called properties) in the device
> tree were called cells as well. When 64-bit came into the picture,
> everything fell apart. The "correct" name for the property thingies
> now is "integers as encoded with encode-int".
I looked into the OF 64-bit extensions spec, and "cell" is 64-bit there.
So, "address" should look valid. I don't know whether PPC64 boxes support
64-bit OF, or only 32-bit, however, the kernel doesn't seem to deal with
64-bit ones correctly, so I'm assuming that 32-bit OF is at least available...
Anyway, I'm still missing the point of not using "address" which is
clearly intended for such case.
WBR, Sergei
^ permalink raw reply [flat|nested] 36+ messages in thread* Re: [PATCH] Start arch/powerpc/boot code reorganization
2006-09-28 20:53 ` Sergei Shtylyov
@ 2006-09-30 8:36 ` Segher Boessenkool
0 siblings, 0 replies; 36+ messages in thread
From: Segher Boessenkool @ 2006-09-30 8:36 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: Matt Porter, Paul Mackerras, linuxppc-dev
> I looked into the OF 64-bit extensions spec, and "cell" is 64-
> bit there.
Like I said before, a "cell" in OF has nothing to do with the items
in the device tree.
> So, "address" should look valid. I don't know whether PPC64 boxes
> support 64-bit OF, or only 32-bit, however, the kernel
Most OF's on 64-bit machines are 64 bit. The only defined client
interface for PowerPC is 32 bit though. And, again, the format
of the device tree is independent of machine word size or other
environmental factors.
> doesn't seem to deal with 64-bit ones correctly, so I'm assuming
> that 32-bit OF is at least available...
> Anyway, I'm still missing the point of not using "address" which
> is clearly intended for such case.
It also has many many problems and therefore should preferably
not be used.
Segher
^ permalink raw reply [flat|nested] 36+ messages in thread
end of thread, other threads:[~2006-09-30 8:37 UTC | newest]
Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-09-19 3:21 [PATCH] Start arch/powerpc/boot code reorganization Paul Mackerras
2006-09-19 4:22 ` Michael Ellerman
2006-09-19 4:29 ` Paul Mackerras
-- strict thread matches above, loose matches on Subject: below --
2006-09-19 23:00 Paul Mackerras
2006-09-20 1:20 ` Mark A. Greer
2006-09-20 1:28 ` Mark A. Greer
2006-09-20 20:58 ` Mark A. Greer
2006-09-20 3:10 ` Josh Boyer
2006-09-20 20:23 ` Segher Boessenkool
2006-09-20 21:04 ` Josh Boyer
2006-09-20 21:32 ` Benjamin Herrenschmidt
2006-09-20 21:57 ` Mark A. Greer
2006-09-21 0:07 ` Segher Boessenkool
2006-09-21 13:37 ` Matt Porter
2006-09-21 14:15 ` Jon Loeliger
2006-09-21 14:26 ` Matt Porter
2006-09-21 15:31 ` Segher Boessenkool
2006-09-22 1:24 ` Mark A. Greer
2006-09-22 8:43 ` Segher Boessenkool
2006-09-22 18:59 ` Mark A. Greer
2006-09-22 19:36 ` Sergei Shtylyov
2006-09-22 20:40 ` Mark A. Greer
2006-09-22 20:43 ` Sergei Shtylyov
2006-09-22 20:52 ` Mark A. Greer
2006-09-22 20:56 ` Sergei Shtylyov
2006-09-23 0:57 ` Segher Boessenkool
2006-09-23 15:48 ` Sergei Shtylyov
2006-09-23 0:54 ` Segher Boessenkool
2006-09-23 8:18 ` Mark A. Greer
2006-09-23 10:15 ` Segher Boessenkool
2006-09-25 17:53 ` Mark A. Greer
2006-09-25 23:40 ` Segher Boessenkool
2006-09-25 23:44 ` Segher Boessenkool
2006-09-25 23:46 ` Mark A. Greer
2006-09-28 20:53 ` Sergei Shtylyov
2006-09-30 8:36 ` Segher Boessenkool
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).