#include "asm/processor.h"
#include "errors.h"
#include "debug.h"
+#include "string.h"
#define READ_BLOCKS_USE_READ 1
+static int yaboot_debug;
+
prom_entry prom;
ihandle prom_stdin, prom_stdout;
-//extern int vsprintf(char *buf, const char *fmt, va_list args);
-
static ihandle prom_mem, prom_mmu;
static ihandle prom_chosen, prom_options;
char tmp[64];
if (strstr(device, TOK_ISCSI))
- device = strcpy(tmp, "/vdevice/gscsi/disk");
+ return FILE_DEVICE_ISCSI;
/* Find OF device phandle */
dev = prom_finddevice(device);
if (prom_get_chosen ("mmu", &prom_mmu, sizeof(prom_mmu)) <= 0)
prom_abort ("\nCan't get mmu handle");
+ yaboot_debug = 0;
+ prom_get_options("linux,yaboot-debug", &yaboot_debug, sizeof(yaboot_debug));
+
// move cursor to fresh line
prom_printf ("\n");
int
prom_getchar ()
{
- char c[4];
+ char c;
int a;
- while ((a = (int)call_prom ("read", 3, 1, prom_stdin, c, 4)) == 0)
+ while ((a = (int)call_prom ("read", 3, 1, prom_stdin, &c, 1)) == 0)
;
if (a == -1)
prom_abort ("EOF on console\n");
- if (a == 3 && c[0] == '\e' && c[1] == '[')
- return 0x100 | c[2];
- return c[0];
+ return c;
}
int
va_end (ap);
}
+void
+prom_debug (char *fmt, ...)
+{
+ va_list ap;
+
+ if (!yaboot_debug)
+ return;
+
+ va_start (ap, fmt);
+ prom_vfprintf (prom_stdout, fmt, ap);
+ va_end (ap);
+}
+
void
prom_perror (int error, char *filename)
{
while (i < len-1 && (c = prom_getchar ()) != '\r')
{
- if (c >= 0x100)
- continue;
if (c == 8)
{
if (i > 0)
while (prom_getms() <= end);
}
+/* if address given is claimed look for other addresses to get the needed
+ * space before giving up
+ */
+void *
+prom_claim_chunk(void *virt, unsigned int size, unsigned int align)
+{
+ void *found, *addr;
+ for(addr=virt; addr <= (void*)PROM_CLAIM_MAX_ADDR;
+ addr+=(0x100000/sizeof(addr))) {
+ found = call_prom("claim", 3, 1, addr, size, 0);
+ if (found != (void *)-1) {
+ prom_debug("claim of 0x%x at 0x%x returned 0x%x\n", size, (int)addr, (int)found);
+ return(found);
+ }
+ }
+ prom_printf("ERROR: claim of 0x%x in range 0x%x-0x%x failed\n", size, (int)virt, PROM_CLAIM_MAX_ADDR);
+ return((void*)-1);
+}
+
+/* Start from top of memory and work down to get the needed space */
+void *
+prom_claim_chunk_top(unsigned int size, unsigned int align)
+{
+ void *found, *addr;
+ for(addr=(void*)PROM_CLAIM_MAX_ADDR; addr >= (void *)size;
+ addr-=(0x100000/sizeof(addr))) {
+ found = call_prom("claim", 3, 1, addr, size, 0);
+ if (found != (void *)-1) {
+ prom_debug("claim of 0x%x at 0x%x returned 0x%x\n", size, (int)addr, (int)found);
+ return(found);
+ }
+ }
+ prom_printf("ERROR: claim of 0x%x in range 0x0-0x%x failed\n", size, PROM_CLAIM_MAX_ADDR);
+ return((void*)-1);
+}
+
void *
prom_claim (void *virt, unsigned int size, unsigned int align)
{
- return call_prom ("claim", 3, 1, virt, size, align);
+ void *ret;
+
+ ret = call_prom ("claim", 3, 1, virt, size, align);
+ if (ret == (void *)-1)
+ prom_printf("ERROR: claim of 0x%x at 0x%x failed\n", size, (int)virt);
+ else
+ prom_debug("claim of 0x%x at 0x%x returned 0x%x\n", size, (int)virt, (int)ret);
+
+ return ret;
}
void
prom_release(void *virt, unsigned int size)
{
- call_prom ("release", 2, 0, virt, size);
-#if 0 /* this is bullshit, newworld OF RELEASE method works fine. */
+ void *ret;
- /* release in not enough, it needs also an unmap call. This bit of forth
- * code inspired from Darwin's bootloader but could be replaced by direct
- * calls to the MMU package if needed
- */
- call_prom ("interpret", 3, 1,
-#if DEBUG
- ".\" ReleaseMem:\" 2dup . . cr "
-#endif
- "over \" translate\" ^mmu " // Find out physical base
- "^on0 " // Bail if translation failed
- "drop " // Leaving phys on top of stack
- "2dup \" unmap\" ^mmu " // Unmap the space first
- "2dup \" release\" ^mmu " // Then free the virtual pages
- "\" release\" ^mem " // Then free the physical pages
- ,size, virt
- );
-#endif /* bullshit */
+ ret = call_prom ("release", 2, 0, virt, size);
+ prom_debug("release of 0x%x at 0x%x returned 0x%x\n", size, (int)virt, (int)ret);
}
void
void
prom_pause(void)
{
+ prom_print_available();
call_prom("enter", 0, 0);
}
void *bootp_response = NULL;
char *propname;
struct bootp_packet *packet;
+ /* struct bootp_packet contains a VLA, so sizeof won't work.
+ the VLA /must/ be the last field in the structure so use it's
+ offset as a good estimate of the packet size */
+ size_t packet_size = offsetof(struct bootp_packet, options);
int i = 0, size, offset = 0;
prom_handle chosen;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
if (size <= 0)
return NULL;
- if (sizeof(*packet) > size - offset) {
+ if (packet_size > size - offset) {
prom_printf("Malformed %s property?\n", propname);
return NULL;
}
return conf_path;
}
+/* We call this too early to use malloc, 128 cells should be large enough */
+#define NR_AVAILABLE 128
+
+void prom_print_available(void)
+{
+ prom_handle root;
+ unsigned int addr_cells, size_cells;
+ ihandle mem;
+ unsigned int available[NR_AVAILABLE];
+ unsigned int len;
+ unsigned int *p;
+
+ if (!yaboot_debug)
+ return;
+
+ root = prom_finddevice("/");
+ if (!root)
+ return;
+
+ addr_cells = 2;
+ prom_getprop(root, "#address-cells", &addr_cells, sizeof(addr_cells));
+
+ size_cells = 1;
+ prom_getprop(root, "#size-cells", &size_cells, sizeof(size_cells));
+
+ mem = prom_finddevice("/memory@0");
+ if (mem == PROM_INVALID_HANDLE)
+ return;
+
+ len = prom_getprop(mem, "available", available, sizeof(available));
+ if (len == -1)
+ return;
+ len /= 4;
+
+ prom_printf("\nAvailable memory ranges:\n");
+
+ p = available;
+ while (len > 0) {
+ unsigned int addr, size;
+
+ /*
+ * Since we are in 32bit mode it should be safe to only print the
+ * bottom 32bits of each range.
+ */
+ p += (addr_cells - 1);
+ addr = *p;
+ p++;
+
+ p += (size_cells - 1);
+ size = *p;
+ p++;
+
+ if (size)
+ prom_printf("0x%08x-0x%08x (%3d MB)\n", addr, addr + size,
+ size/1024/1024);
+
+ len -= (addr_cells + size_cells);
+ }
+
+ prom_printf("\n");
+}
+
/*
* Local variables:
* c-file-style: "k&r"