Subject: prom_open() problems.

From: Alex deVries <[email-masked]>
Date: Mon, 18 May 1998 17:49:53 -0400 (EDT)

Attached is the start of an implementation to allow for initrd's to sit on
an EFS or VH, and be read using prom_open/read/close.  The file is
hardcoded right now, although there is the start of parameter handling
(before start_kernel()).

The problem that I'm having is that prom_open() always returns 13, which I
think means that there is no such device.  I've used all possible strings,
but I've not found any paths that work, so I can't read the file.

No, you're not allowed to pick on my code, yet.

Could someone (Ralf?) explain why my prom_open() in
arch/mips/sgi/prom/initrd.c doesn't work?

- A
-- 
Alex deVries, puffin on LinuxNet.
http://www.engsoc.carleton.ca/~adevries/ .

diff -Nrc -x .depend -x Entries linux/arch/mips/kernel/setup.c linux-mine-prom-initrd/arch/mips/kernel/setup.c
*** linux/arch/mips/kernel/setup.c	Mon May 18 17:16:25 1998
--- linux-mine-prom-initrd/arch/mips/kernel/setup.c	Mon May 18 00:07:27 1998
***************
*** 121,128 ****
  #endif
  #define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
  #define KERNEL_START (*(unsigned long *) (PARAM+0x214))
- #define INITRD_START (*(unsigned long *) (PARAM+0x218))
- #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
  
  static char command_line[CL_SIZE] = { 0, };
         char saved_command_line[CL_SIZE];
--- 121,126 ----
***************
*** 218,229 ****
  	memory_end -= 128;
  	memory_end &= PAGE_MASK;
  
- #ifdef CONFIG_BLK_DEV_RAM
- 	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
- 	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
- 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
- #endif
- 
  	atag = bi_TagFind(tag_mount_root_rdonly);
  	if (atag)
  	  root_mountflags |= MS_RDONLY;
--- 216,221 ----
***************
*** 241,248 ****
  
  #ifdef CONFIG_BLK_DEV_INITRD
  	if (LOADER_TYPE) {
! 		initrd_start = INITRD_START;
! 		initrd_end = INITRD_START+INITRD_SIZE;
  		if (initrd_end > memory_end) {
  			printk("initrd extends beyond end of memory "
  			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
--- 233,240 ----
  
  #ifdef CONFIG_BLK_DEV_INITRD
  	if (LOADER_TYPE) {
! 		initrd_start = 0 ;
! 		initrd_end = 0 ; 
  		if (initrd_end > memory_end) {
  			printk("initrd extends beyond end of memory "
  			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
diff -Nrc -x .depend -x Entries linux/arch/mips/sgi/prom/Makefile linux-mine-prom-initrd/arch/mips/sgi/prom/Makefile
*** linux/arch/mips/sgi/prom/Makefile	Mon May 18 17:16:38 1998
--- linux-mine-prom-initrd/arch/mips/sgi/prom/Makefile	Sun May 17 23:07:32 1998
***************
*** 9,15 ****
  # Note 2! The CFLAGS definitions are now in the main makefile...
  
  OBJS  = console.o init.o printf.o memory.o tree.o tags.o env.o \
!       cmdline.o misc.o time.o file.o
  
  all: promlib.a
  
--- 9,15 ----
  # Note 2! The CFLAGS definitions are now in the main makefile...
  
  OBJS  = console.o init.o printf.o memory.o tree.o tags.o env.o \
!       cmdline.o misc.o time.o file.o initrd.o
  
  all: promlib.a
  
diff -Nrc -x .depend -x Entries linux/arch/mips/sgi/prom/cmdline.c linux-mine-prom-initrd/arch/mips/sgi/prom/cmdline.c
*** linux/arch/mips/sgi/prom/cmdline.c	Mon May 18 17:16:38 1998
--- linux-mine-prom-initrd/arch/mips/sgi/prom/cmdline.c	Mon May 18 03:03:50 1998
***************
*** 12,17 ****
--- 12,21 ----
  #include <asm/sgialib.h>
  #include <asm/bootinfo.h>
  
+ #include <errno.h>
+ 
+ #include "initrd.h"
+ 
  /* #define DEBUG_CMDLINE */
  
  extern char arcs_cmdline[CL_SIZE];
***************
*** 46,57 ****
  			if(!strncmp(prom_argv[actr], ignored[i], len))
  				goto pic_cont;
  		}
- 		/* Ok, we want it. */
- 		strcpy(cp, prom_argv[actr]);
- 		cp += strlen(prom_argv[actr]);
- 		*cp++ = ' ';
  
! 	pic_cont:
  		actr++;
  	}
  	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
--- 50,85 ----
  			if(!strncmp(prom_argv[actr], ignored[i], len))
  				goto pic_cont;
  		}
  
!                 /* So far, it means it isn't a tag to be ignored */
! 
! 
!                 if (!strncmp(prom_argv[actr],"prom_initrd_file=",17)) {
! 
!                         strncpy(prom_initrd_filename,
!                                 prom_argv[actr]+17,
!                                 strlen(prom_argv[actr])-17);
! 
!                 } else if (!strncmp(prom_argv[actr],"prom_initrd_size=",17)) {
!                        /* This is just an strtol replacement */
!                        for (i=0;i<strlen(prom_argv[actr]);i++) {
!                                 if ((prom_argv[actr][i]<'0') ||
!                                     (prom_argv[actr][i]>'9')) {
!                                         prom_initrd_size=0;
!                                         printk("Error in PROM ramdisk size formatting\n");
!                                         break;
!                                 }
!                                 prom_initrd_size*=10;
!                                 prom_initrd_size+=prom_argv[actr][i]-'0';      
!                         } 
!                 } else {
!                         /* Ok, we want it. */
!                         strcpy(cp, prom_argv[actr]);
!                         cp += strlen(prom_argv[actr]);
!                         *cp++ = ' ';
!                 }
! 
!         pic_cont:
  		actr++;
  	}
  	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
diff -Nrc -x .depend -x Entries linux/arch/mips/sgi/prom/init.c linux-mine-prom-initrd/arch/mips/sgi/prom/init.c
*** linux/arch/mips/sgi/prom/init.c	Mon May 18 17:16:38 1998
--- linux-mine-prom-initrd/arch/mips/sgi/prom/init.c	Mon May 18 00:01:17 1998
***************
*** 7,12 ****
--- 7,13 ----
   */
  #include <linux/init.h>
  #include <linux/kernel.h>
+ #include "initrd.h"
  
  #include <asm/sgialib.h>
  
***************
*** 19,24 ****
--- 20,28 ----
  char **prom_argv, **prom_envp;
  unsigned short prom_vers, prom_rev;
  
+ 
+ extern int prom_initrd_load(void * initrd_start);
+ 
  extern void prom_testtree(void);
  
  __initfunc(int prom_init(int argc, char **argv, char **envp))
***************
*** 43,49 ****
--- 47,73 ----
  	prom_rev = pb->rev;
  	printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n",
  		    prom_vers, prom_rev);
+ 
+         /* If the initrd size hasn't been set yet with a command line, try to
+            stat it with arc. If that doesn't work, assume it is the 
+            default.  */
+ 
+         if (prom_initrd_size == 0) {
+                /* I don't undertand how to do the stat yet */
+                if (1) {
+                        prom_initrd_size = DEFAULT_INITRD_SIZE;
+                } else {
+                        prom_initrd_size = DEFAULT_INITRD_SIZE;
+               }
+         }
+ 
  	prom_meminit();
+ 
+         /* Load the device into memory */
+         printk("About to load initrd....\n");
+         initrd_load(prom_initrd_start);
+         printk("finished trying to load initrd....\n");
+ 
  	prom_setup_archtags();
  
  #if 0
diff -Nrc -x .depend -x Entries linux/arch/mips/sgi/prom/initrd.c linux-mine-prom-initrd/arch/mips/sgi/prom/initrd.c
*** linux/arch/mips/sgi/prom/initrd.c	Thu Jan  1 00:00:00 1970
--- linux-mine-prom-initrd/arch/mips/sgi/prom/initrd.c	Sun May 17 23:48:25 1998
***************
*** 0 ****
--- 1,35 ----
+ /*
+  * initrd.c: Initial Ramdisk ARC loader
+  *
+  * Copyright (C) 1998 Alex deVries <[email-masked]>
+  *
+  */
+ 
+ #include <asm/sgialib.h>
+ #include <asm/sgiarcs.h>
+ #include <linux/kernel.h>
+ #include "initrd.h"
+ 
+ int initrd_load (void * initrd_start) {
+ 
+         unsigned int result;
+         unsigned long size;
+         unsigned long fd;
+ 
+         printk("Adv: starting read_initrd\n");
+ 
+         result = prom_open(prom_initrd_filename,rdonly,&fd);
+         printk("Adv: after open: %d\n",result);
+ 
+         result = prom_read(fd,prom_initrd_start, prom_initrd_size,&size);
+ 
+         printk("Adv: after read: %d\n",result);
+         printk("SGI PROM Init Ramdisk loaded %lu bytes of %lu of ramdisk %s.\n",size,prom_initrd_size,prom_initrd_filename);
+ 
+         result = prom_close(fd);
+         printk("Adv: after close: %d\n",result);
+ 
+ 
+         return 1;
+ 
+ }
diff -Nrc -x .depend -x Entries linux/arch/mips/sgi/prom/initrd.h linux-mine-prom-initrd/arch/mips/sgi/prom/initrd.h
*** linux/arch/mips/sgi/prom/initrd.h	Thu Jan  1 00:00:00 1970
--- linux-mine-prom-initrd/arch/mips/sgi/prom/initrd.h	Sun May 17 23:50:25 1998
***************
*** 0 ****
--- 1,30 ----
+ 
+ #ifndef _SGI_PROM_INITRD_H
+ #define _SGI_PROM_INITRD_H
+ 
+ /*
+  * PROM init ramdisk interfaces.
+  *
+  * This file is subject to the terms and conditions of the GNU General Public
+  * License.  See the file "COPYING" in the main directory of this archive
+  * for more details.
+  *
+  * Copyright (C) 1995, 1996 by Alex deVries
+  *
+  */
+ 
+ /* Define the default initrd memory size to be 4MB */
+ 
+ #define DEFAULT_INITRD_SIZE 4194304
+ #define MAX_PROM_INITRD_FILENAME 200
+ 
+ 
+ unsigned long prom_initrd_size;
+ unsigned long prom_initrd_start;
+ char prom_initrd_filename[MAX_PROM_INITRD_FILENAME];
+ int prom_initrd_load (void * initrd_start);
+ 
+ extern int rd_image_start;
+ 
+ #endif
+ 
diff -Nrc -x .depend -x Entries linux/arch/mips/sgi/prom/memory.c linux-mine-prom-initrd/arch/mips/sgi/prom/memory.c
*** linux/arch/mips/sgi/prom/memory.c	Mon May 18 17:16:38 1998
--- linux-mine-prom-initrd/arch/mips/sgi/prom/memory.c	Mon May 18 00:03:46 1998
***************
*** 18,23 ****
--- 18,25 ----
  #include <asm/pgtable.h>
  #include <asm/bootinfo.h>
  
+ #include "initrd.h"
+ 
  /* #define DEBUG */
  
  __initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr))
***************
*** 68,73 ****
--- 70,77 ----
  	int totram;
  	int i = 0;
  
+ 	struct linux_mdesc *initrd_p = NULL;
+ 
  	p = prom_getmdesc(PROM_NULL_MDESC);
  #ifdef DEBUG
  	prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
***************
*** 92,97 ****
--- 96,106 ----
  				    i, prom_pblocks[i].base,
  				    prom_pblocks[i].size);
  #endif
+ 
+                         /* remember the last block */
+                         if (prom_initrd_size <=prom_pblocks[i].size) {
+                                 initrd_p=p;
+                         }
  			i++;
  		}
  		p = prom_getmdesc(p);
***************
*** 100,105 ****
--- 109,124 ----
  	prom_pblocks[i].size = 0; /* indicates last elem. of array */
  	printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n",
  		    totram, (totram/1024), (totram/1024/1024));
+ 
+         if (initrd_p != NULL) {
+ 		initrd_p->type = aperm;
+                 rd_image_start = (int) initrd_p->base;
+                 printk("Putting initrd at %d\n",rd_image_start);
+         } else {
+                 printk("Cannot find %uld contiguous free bytes "
+                        "for the ramdisk\n",prom_initrd_size);
+                 rd_image_start = 0;
+        }
  
  	/* Setup upper physical memory bound. */
  	prom_setup_memupper();