[PATCH] support firmware reboot when CAS changes are detected.

Mike Wolf mjw at linux.vnet.ibm.com
Thu Jan 3 07:12:34 EST 2008


The CAS (Client-Architecture Support) call tells firmware what 
capabilities the
OS has.  These capabilities result in different modes which the 
device-tree is
configured in, as well as what processor capabilities are presented.  
So, if the
capabilities are different from what was previously booted, firmware has to
reboot to reconfigure the device-tree.  The second boot will have the 
updated
device-tree and we can boot as normal.

When this firmware initiated reboot occurs yaboot will now boot the same 
kernel
as the previous boot attempt with no action by the user needed.
I have successfully booted on POWER5 and POWER6 machines using various 
levels of
the kernel.


------

diff --git a/include/prom.h b/include/prom.h
index 6e4d890..eacee77 100644
--- a/include/prom.h
+++ b/include/prom.h
@@ -38,6 +38,8 @@ #define PROM_INVALID_HANDLE	((prom_handl
 #define BOOTDEVSZ               (2048) /* iscsi args can be in excess of 1040 bytes */
 #define TOK_ISCSI               "iscsi"
 #define PROM_CLAIM_MAX_ADDR	0x8000000
+#define BOOTLASTSZ		1024
+#define FW_NBR_REBOOTSZ		4
 
 struct prom_args;
 typedef int (*prom_entry)(struct prom_args *);
diff --git a/second/yaboot.c b/second/yaboot.c
index 46ab0ef..5fc1213 100644
--- a/second/yaboot.c
+++ b/second/yaboot.c
@@ -114,6 +114,9 @@ int useconf = 0;
 char bootdevice[BOOTDEVSZ];
 char bootoncelabel[1024];
 char bootargs[1024];
+char bootlastlabel[BOOTLASTSZ] = {0};
+char fw_nbr_reboots[FW_NBR_REBOOTSZ] = {0};
+long  fw_reboot_cnt = 0;
 char *password = NULL;
 struct boot_fspec_t boot;
 int _machine = _MACH_Pmac;
@@ -674,7 +677,7 @@ int get_params(struct boot_param_t* para
 
      cmdinit();
 
-     if (first) {
+     if (first && !fw_reboot_cnt) {
 	  first = 0;
 	  imagename = bootargs;
 	  word_split(&imagename, &params->args);
@@ -689,6 +692,13 @@ int get_params(struct boot_param_t* para
 	       timeout = simple_strtol(q, NULL, 0);
      }
 
+     /* If this is a reboot due to FW detecting CAS changes then 
+      * set timeout to 1.  The last kernel booted will be booted 
+      * again automatically.  It should seem seamless to the user
+     */
+     if (fw_reboot_cnt) 
+          timeout = 1;
+
      prom_printf("boot: ");
      c = -1;
      if (timeout != -1) {
@@ -725,7 +735,9 @@ int get_params(struct boot_param_t* para
 	  if (!imagename) {
 	       if (bootoncelabel[0] != 0)
 		    imagename = bootoncelabel;
-	       else
+	       else if (bootlastlabel[0] != 0)
+                         imagename = bootlastlabel;
+               else
 		    imagename = cfg_get_default();
 	  }
 	  if (imagename)
@@ -786,6 +798,9 @@ int get_params(struct boot_param_t* para
      if ( useconf && (!imagename || imagename[0] == 0 ))
 	  imagename = cfg_get_default();
 
+     /* write the imagename out so it can be reused on reboot if necessary */
+     prom_set_options("boot-last-label", imagename, strlen(imagename));
+
      label = 0;
      defdevice = boot.dev;
 
@@ -1676,6 +1691,7 @@ int
 yaboot_main(void)
 {
      char *ptype;
+     char *endp;
      int conf_given = 0;
      char conf_path[1024];
 
@@ -1686,6 +1702,10 @@ yaboot_main(void)
      DEBUG_F("/chosen/bootargs = %s\n", bootargs);
      prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
      DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
+     prom_get_options("ibm,fw-nbr-reboots",fw_nbr_reboots, FW_NBR_REBOOTSZ);
+     fw_reboot_cnt = simple_strtol(fw_nbr_reboots,&endp,10);
+     if (fw_reboot_cnt > 0L)
+          prom_get_options("boot-last-label", bootlastlabel, BOOTLASTSZ);
 
      /* If conf= specified on command line, it overrides
         Usage: conf=device:partition,/path/to/conffile





More information about the Yaboot-devel mailing list