#include "asm/processor.h"
#include "errors.h"
#include "debug.h"
+#include "string.h"
#define READ_BLOCKS_USE_READ 1
va_list list;
int i;
struct prom_args prom_args;
-
+
prom_args.service = service;
prom_args.nargs = nargs;
prom_args.nret = nret;
int i;
void* result;
struct prom_args prom_args;
-
+
prom_args.service = service;
prom_args.nargs = nargs;
prom_args.nret = nret;
va_list list;
int i;
struct prom_args prom_args;
-
+
prom_args.service = "call-method";
prom_args.nargs = nargs+2;
prom_args.nret = 2;
va_end(list);
prom_args.args[2+nargs] = 0;
prom_args.args[2+nargs+1] = 0;
-
+
prom (&prom_args);
if (prom_args.args[2+nargs] != 0)
return (int)call_prom ("getprop", 4, 1, pack, name, mem, len);
}
+int
+prom_getproplen(prom_handle pack, const char *name)
+{
+ return (int)call_prom("getproplen", 2, 1, pack, name);
+}
+
+int
+prom_setprop (prom_handle pack, char *name, void *mem, int len)
+{
+ return (int)call_prom ("setprop", 4, 1, pack, name, mem, len);
+}
+
int
prom_get_chosen (char *name, void *mem, int len)
{
return prom_getprop (prom_options, name, mem, len);
}
+int
+prom_set_options (char *name, void *mem, int len)
+{
+ if (prom_options == (void *)-1)
+ return -1;
+ return prom_setprop (prom_options, name, mem, len);
+}
+
int
prom_get_devtype (char *device)
{
int result;
char tmp[64];
+ if (strstr(device, TOK_ISCSI))
+ device = strcpy(tmp, "/vdevice/gscsi/disk");
+
/* Find OF device phandle */
dev = prom_finddevice(device);
if (dev == PROM_INVALID_HANDLE) {
/* Add a few OF methods (thanks Darwin) */
#if DEBUG
prom_printf ("Adding OF methods...\n");
-#endif
+#endif
prom_interpret (
/* All values in this forth code are in hex */
- "hex "
+ "hex "
/* Those are a few utilities ripped from Apple */
": D2NIP decode-int nip nip ;\r" // A useful function to save space
": GPP$ get-package-property 0= ;\r" // Another useful function to save space
{
int result = 0;
int retries = 10;
-
+
if (n == 0)
return 0;
while(--retries) {
break;
call_prom("interpret", 1, 1, " 10 ms");
}
-
+
return result;
}
#if READ_BLOCKS_USE_READ
int status;
unsigned int blksize;
-
+
blksize = prom_getblksize(dev);
if (blksize <= 1)
blksize = 512;
return 0;
prom_printf("Can't seek to 0x%x\n", blockNum * blksize);
}
-
+
status = prom_read(dev, buffer, blockCount * blksize);
// prom_printf("prom_readblocks, bl: %d, cnt: %d, status: %d\n",
// blockNum, blockCount, status);
return status == (blockCount * blksize);
-#else
+#else
int result;
int retries = 10;
-
+
if (blockCount == 0)
return blockCount;
while(--retries) {
break;
call_prom("interpret", 1, 1, " 10 ms");
}
-
+
return result;
-#endif
+#endif
}
int
{
const char *p, *q;
- for (p = s; *p != 0; p = q)
+ for (p = s; *p != 0; p = q)
{
for (q = p; *q != 0 && *q != '\n'; ++q)
;
if (q > p)
call_prom ("write", 3, 1, file, p, q - p);
- if (*q != 0)
+ if (*q != 0)
{
++q;
call_prom ("write", 3, 1, file, "\r\n", 2);
}
}
}
-
+
void
prom_vfprintf (prom_handle file, char *fmt, va_list ap)
{
else if (error == FILE_IOERR)
prom_printf("%s: Input/output error\n", filename);
else if (error == FILE_BAD_PATH)
- prom_printf("%s: Path too long\n", filename);
+ prom_printf("%s: Path too long\n", filename);
else if (error == FILE_ERR_BAD_TYPE)
prom_printf("%s: Not a regular file\n", filename);
else if (error == FILE_ERR_NOTDIR)
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 = prom_claim(addr, size, 0);
+ if (found != (void *)-1) {
+ DEBUG_F("claimed %i at 0x%x (0x%x)\n",size,(int)found,(int)virt);
+ return(found);
+ }
+ }
+ prom_printf("Claim error, can't allocate %x at 0x%x\n",size,(int)virt);
+ return((void*)-1);
+}
+
void *
prom_claim (void *virt, unsigned int size, unsigned int align)
{
void
prom_release(void *virt, unsigned int size)
{
-// call_prom ("release", 2, 1, virt, size);
+ call_prom ("release", 2, 0, virt, size);
+#if 0 /* this is bullshit, newworld OF RELEASE method works fine. */
+
/* 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
"2dup \" unmap\" ^mmu " // Unmap the space first
"2dup \" release\" ^mmu " // Then free the virtual pages
"\" release\" ^mem " // Then free the physical pages
- ,size, virt
+ ,size, virt
);
+#endif /* bullshit */
}
void
call_prom("enter", 0, 0);
}
-/*
+/*
+ * prom_get_netinfo()
+ * returns the packet with all needed info for netboot
+ */
+struct bootp_packet * prom_get_netinfo (void)
+{
+ void *bootp_response = NULL;
+ char *propname;
+ struct bootp_packet *packet;
+ int i = 0, size, offset = 0;
+ prom_handle chosen;
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+ chosen = prom_finddevice("/chosen");
+ if (chosen < 0) {
+ DEBUG_F("chosen=%d\n", chosen);
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bootp_response_properties); i++) {
+ propname = bootp_response_properties[i].name;
+ size = prom_getproplen(chosen, propname);
+ if (size <= 0)
+ continue;
+
+ DEBUG_F("using /chosen/%s\n", propname);
+ offset = bootp_response_properties[i].offset;
+ break;
+ }
+
+ if (size <= 0)
+ return NULL;
+
+ if (sizeof(*packet) > size - offset) {
+ prom_printf("Malformed %s property?\n", propname);
+ return NULL;
+ }
+
+ bootp_response = malloc(size);
+ if (!bootp_response)
+ return NULL;
+
+ if (prom_getprop(chosen, propname, bootp_response, size) < 0)
+ return NULL;
+
+ packet = bootp_response + offset;
+ return packet;
+}
+
+/*
+ * prom_get_mac()
+ * returns the mac addr of an net card
+ */
+char * prom_get_mac (struct bootp_packet * packet)
+{
+ char * conf_path;
+ int i;
+
+ if (!packet)
+ return NULL;
+
+ /* 3 chars per byte in chaddr + \0 */
+ conf_path = malloc(packet->hlen * 3 + 1);
+ if (!conf_path)
+ return NULL;
+ sprintf(conf_path, "%02x", packet->chaddr[0]);
+
+ for (i = 1; i < packet->hlen; i++) {
+ char tmp[4];
+ sprintf(tmp, "-%02x", packet->chaddr[i]);
+ strcat(conf_path, tmp);
+ }
+
+ return conf_path;
+}
+
+/*
+ * prom_get_ip()
+ * returns the ip addr of an net card
+ */
+char * prom_get_ip (struct bootp_packet * packet)
+{
+ char * conf_path;
+
+ if (!packet)
+ return NULL;
+
+ /* 8 chars in yiaddr + \0 */
+ conf_path = malloc(9);
+ if (!conf_path)
+ return NULL;
+ sprintf(conf_path, "%08x", packet->yiaddr);
+
+ return conf_path;
+}
+
+/*
* Local variables:
* c-file-style: "k&r"
* c-basic-offset: 5