]> git.ozlabs.org Git - yaboot.git/blobdiff - second/prom.c
Fix typo courtesy of Kenichi Nagai
[yaboot.git] / second / prom.c
index 209dd87d777fcf52d99b91d28541751578480781..e9c5843e1efec04b25baa7185e16a9025b8e0905 100644 (file)
@@ -1,25 +1,27 @@
 /*
 /*
-    Routines for talking to the Open Firmware PROM on
-    Power Macintosh computers.
-    Copyright (C) 1999 Benjamin Herrenschmidt
-    Copyright (C) 1999 Marius Vollmer
-    Copyright (C) 1996 Paul Mackerras.
-
-    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, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
+ *  prom.c - Routines for talking to the Open Firmware PROM
+ *
+ *  Copyright (C) 2001, 2002 Ethan Benson
+ *
+ *  Copyright (C) 1999 Benjamin Herrenschmidt
+ *
+ *  Copyright (C) 1999 Marius Vollmer
+ *
+ *  Copyright (C) 1996 Paul Mackerras.
+ *
+ *  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, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
 #include "prom.h"
  */
 
 #include "prom.h"
@@ -31,6 +33,7 @@
 #include "asm/processor.h"
 #include "errors.h"
 #include "debug.h"
 #include "asm/processor.h"
 #include "errors.h"
 #include "debug.h"
+#include "string.h"
 
 #define READ_BLOCKS_USE_READ   1
 
 
 #define READ_BLOCKS_USE_READ   1
 
@@ -56,7 +59,7 @@ call_prom (const char *service, int nargs, int nret, ...)
      va_list list;
      int i;
      struct prom_args prom_args;
      va_list list;
      int i;
      struct prom_args prom_args;
-  
+
      prom_args.service = service;
      prom_args.nargs = nargs;
      prom_args.nret = nret;
      prom_args.service = service;
      prom_args.nargs = nargs;
      prom_args.nret = nret;
@@ -80,7 +83,7 @@ call_prom_return (const char *service, int nargs, int nret, ...)
      int i;
      void* result;
      struct prom_args prom_args;
      int i;
      void* result;
      struct prom_args prom_args;
-  
+
      prom_args.service = service;
      prom_args.nargs = nargs;
      prom_args.nret = nret;
      prom_args.service = service;
      prom_args.nargs = nargs;
      prom_args.nret = nret;
@@ -109,7 +112,7 @@ call_method_1 (char *method, prom_handle h, int nargs, ...)
      va_list list;
      int i;
      struct prom_args prom_args;
      va_list list;
      int i;
      struct prom_args prom_args;
-  
+
      prom_args.service = "call-method";
      prom_args.nargs = nargs+2;
      prom_args.nret = 2;
      prom_args.service = "call-method";
      prom_args.nargs = nargs+2;
      prom_args.nret = 2;
@@ -121,7 +124,7 @@ call_method_1 (char *method, prom_handle h, int nargs, ...)
      va_end(list);
      prom_args.args[2+nargs] = 0;
      prom_args.args[2+nargs+1] = 0;
      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)
      prom (&prom_args);
 
      if (prom_args.args[2+nargs] != 0)
@@ -151,6 +154,18 @@ prom_getprop (prom_handle pack, char *name, void *mem, int len)
      return (int)call_prom ("getprop", 4, 1, pack, name, mem, len);
 }
 
      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)
 {
 int
 prom_get_chosen (char *name, void *mem, int len)
 {
@@ -165,6 +180,14 @@ prom_get_options (char *name, void *mem, int len)
      return prom_getprop (prom_options, name, mem, 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
 prom_get_devtype (char *device)
 {
@@ -172,6 +195,9 @@ prom_get_devtype (char *device)
      int        result;
      char       tmp[64];
 
      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) {
      /* Find OF device phandle */
      dev = prom_finddevice(device);
      if (dev == PROM_INVALID_HANDLE) {
@@ -219,11 +245,11 @@ prom_init (prom_entry pp)
      /* Add a few OF methods (thanks Darwin) */
 #if DEBUG
      prom_printf ("Adding OF methods...\n");
      /* 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 */
 
      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
          /* 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
@@ -276,7 +302,7 @@ prom_read (prom_handle file, void *buf, int n)
 {
      int result = 0;
      int retries = 10;
 {
      int result = 0;
      int retries = 10;
-  
+
      if (n == 0)
          return 0;
      while(--retries) {
      if (n == 0)
          return 0;
      while(--retries) {
@@ -285,7 +311,7 @@ prom_read (prom_handle file, void *buf, int n)
               break;
          call_prom("interpret", 1, 1, " 10 ms");
      }
               break;
          call_prom("interpret", 1, 1, " 10 ms");
      }
-  
+
      return result;
 }
 
      return result;
 }
 
@@ -328,7 +354,7 @@ prom_readblocks (prom_handle dev, int blockNum, int blockCount, void *buffer)
 #if READ_BLOCKS_USE_READ
      int status;
      unsigned int blksize;
 #if READ_BLOCKS_USE_READ
      int status;
      unsigned int blksize;
-  
+
      blksize = prom_getblksize(dev);
      if (blksize <= 1)
          blksize = 512;
      blksize = prom_getblksize(dev);
      if (blksize <= 1)
          blksize = 512;
@@ -337,16 +363,16 @@ prom_readblocks (prom_handle dev, int blockNum, int blockCount, void *buffer)
          return 0;
          prom_printf("Can't seek to 0x%x\n", blockNum * blksize);
      }
          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);
      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;
      int result;
      int retries = 10;
-  
+
      if (blockCount == 0)
          return blockCount;
      while(--retries) {
      if (blockCount == 0)
          return blockCount;
      while(--retries) {
@@ -355,9 +381,9 @@ prom_readblocks (prom_handle dev, int blockNum, int blockCount, void *buffer)
               break;
          call_prom("interpret", 1, 1, " 10 ms");
      }
               break;
          call_prom("interpret", 1, 1, " 10 ms");
      }
-  
+
      return result;
      return result;
-#endif  
+#endif
 }
 
 int
 }
 
 int
@@ -397,24 +423,24 @@ prom_puts (prom_handle file, char *s)
 {
      const char *p, *q;
 
 {
      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);
      {
          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);
          }
      }
 }
          {
               ++q;
               call_prom ("write", 3, 1, file, "\r\n", 2);
          }
      }
 }
+
 void
 prom_vfprintf (prom_handle file, char *fmt, va_list ap)
 {
 void
 prom_vfprintf (prom_handle file, char *fmt, va_list ap)
 {
-     static char printf_buf[1536];
+     static char printf_buf[2048];
      vsprintf (printf_buf, fmt, ap);
      prom_puts (file, printf_buf);
 }
      vsprintf (printf_buf, fmt, ap);
      prom_puts (file, printf_buf);
 }
@@ -422,7 +448,7 @@ prom_vfprintf (prom_handle file, char *fmt, va_list ap)
 void
 prom_vprintf (char *fmt, va_list ap)
 {
 void
 prom_vprintf (char *fmt, va_list ap)
 {
-     static char printf_buf[1536];
+     static char printf_buf[2048];
      vsprintf (printf_buf, fmt, ap);
      prom_puts (prom_stdout, printf_buf);
 }
      vsprintf (printf_buf, fmt, ap);
      prom_puts (prom_stdout, printf_buf);
 }
@@ -457,7 +483,7 @@ prom_perror (int error, char *filename)
      else if (error == FILE_IOERR)
          prom_printf("%s: Input/output error\n", filename);
      else if (error == FILE_BAD_PATH)
      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)
      else if (error == FILE_ERR_BAD_TYPE)
          prom_printf("%s: Not a regular file\n", filename);
      else if (error == FILE_ERR_NOTDIR)
@@ -551,7 +577,9 @@ prom_claim (void *virt, unsigned int size, unsigned int align)
 void
 prom_release(void *virt, unsigned int size)
 {
 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
      /* 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
@@ -566,8 +594,9 @@ prom_release(void *virt, unsigned int size)
                "2dup \" unmap\" ^mmu "                 // Unmap the space first
                "2dup \" release\" ^mmu "               // Then free the virtual pages
                "\" release\" ^mem "                    // Then free the physical pages
                "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
 }
 
 void
@@ -626,9 +655,105 @@ prom_pause(void)
      call_prom("enter", 0, 0);
 }
 
      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:
  * Local variables:
- * c-file-style: "K&R"
+ * c-file-style: "k&r"
  * c-basic-offset: 5
  * End:
  */
  * c-basic-offset: 5
  * End:
  */