Hey Dan,

Responses inlined below.

On Tue, 2010-08-17 at 16:19 -0700, Dan Lukes wrote:
> On 08/17/10 23:10, Albert Chu:
> > Attached is my reworked patch for ipmi-oem.  Can you give it a shot and
> > LMK if it works?
> 
> Done. Some notes:
> 
> 1. --------------
> if user call for record id >= 65536 the number record ID is silently 
> changed to something else. I recommend not to allow out-of-range values 
> at all.

Doh!  Good catch.

> 2. --------------
> > bytes_rq[8] = UCHAR_MAX;
> 
> Requests with MaxResponseDataSize>100 will fail.
> Also response packet can't be larger than IPMI_OEM_MAX_BYTES
> 
> So you can't ask for more than min(IPMI_OEM_MAX_BYTES-17,100) bytes.

Ahhh.  That's a subtlety I didn't get.  Also, based on Holger's earlier
response (which now makes more sense to me).

---
Unfortunately due to memory constrains in the previous BMC generation
the maximum length of a single response is limited to 64bytes, while on
the current product line you should be able to get the full 100bytes
translated SEL text with a single request at least over LAN. Maximum
(non standard) KCS transfer size is also different between current (255)
and previous (64) generation, so the code should compare the data
received with the total length reported in the response. 
----

We should probably use 64 instead of 100.

> 3. --------------
> > component_length = (rs_len - 16);
> 
> I prefer more safe approach - I assume that string may end before packet 
> end (e.g. len is obtained by strlen). And I doesn't assume that string 
> is '\0' terminated in response also.
> 
> The so-called documentation from Fujitsu is so vague to be trusted so 
> much, IMHO ...
> 
> 4. ----------------
> ... in advance, you count the length including the trailing '\0' (which 
> is present in every response - not only the last part of string), so the 
> concatenation doesn't work (off-by-one bug)

Ahh, this wasn't clear in the Fujitsu docs.  I'll add a comment to make
that more clear.

> 
> 5. ----------------
> >  while (offset < data_length)
> 
> ... will be neverending loop when
> IPMI_OEM_FUJITSU_SEL_ENTRY_LONG_TEXT_MAX_STRING_LENGTH < data_length
> 
> You should replace
> offset = IPMI_OEM_FUJITSU_SEL_ENTRY_LONG_TEXT_MAX_STRING_LENGTH
> with
> offset = data_length
> to resolve the issue. Or use "break;" ...
> 
> 6. ----------------
> bytes_rq array need not to be intialized every round (only offset is 
> changing). Also, most of results needs to be extracted from bytes_rs 
> only once.
> 
> 7. ----------------
> If user asked for 'first' or 'last' record then use actual_record id for 
> subsequent (looped) requests to obtain consistent results as last SEL 
> may become non-last in meantime.
>
>   ======================
> 
> > I did (atleast try) to implement the code to loop if there was more text
> > to retrieve.  Hopefully I implemented it right.
> 
> See [4], [5] and [7]
> 
> > Also, I slightly tweaked the output to more similarly match ipmi-sel
> > output, adding in semi-colons and stuff.  I admit, I'm not entirely sure
> > of the output.  You may have specifically chosen your output
> 
> I tried to follow output format of ipmi-sel.
> 
> I attached the another iteration of patch.
> 
>                               Dan

Attached is the current diff I have in ipmi-oem compared to freeipmi
0.8.8.  Look good?

Al


-- 
Albert Chu
[email protected]
Computer Scientist
High Performance Systems Division
Lawrence Livermore National Laboratory
Index: ipmi-oem/src/ipmi-oem-fujitsu.c
===================================================================
--- ipmi-oem/src/ipmi-oem-fujitsu.c	(revision 7219)
+++ ipmi-oem/src/ipmi-oem-fujitsu.c	(working copy)
@@ -223,6 +223,25 @@
 #define IPMI_OEM_FUJITSU_ERROR_LED_CSS_BLINK_GEL_ON    7
 #define IPMI_OEM_FUJITSU_ERROR_LED_CSS_BLINK_GEL_BLINK 8
 
+/* achu: one byte field, so max is 255 */
+#define IPMI_OEM_FUJITSU_SEL_ENTRY_LONG_TEXT_MAX_STRING_LENGTH 255
+
+#define IPMI_OEM_FUJITSU_CSS_BITMASK      0x80
+#define IPMI_OEM_FUJITSU_CSS_SHIFT        7
+
+#define IPMI_OEM_FUJITSU_SEVERITY_BITMASK 0x70
+#define IPMI_OEM_FUJITSU_SEVERITY_SHIFT   4
+
+#define IPMI_OEM_FUJITSU_CSS_COMPONENT    1
+#define IPMI_OEM_FUJITSU_NO_CSS_COMPONENT 0
+
+#define IPMI_OEM_FUJITSU_SEVERITY_INFORMATIONAL 0
+#define IPMI_OEM_FUJITSU_SEVERITY_MINOR         1
+#define IPMI_OEM_FUJITSU_SEVERITY_MAJOR         2
+#define IPMI_OEM_FUJITSU_SEVERITY_CRITICAL      3
+
+#define ipmi_oem_min(a,b) ((a) < (b) ? (a) : (b))
+
 static int
 _ipmi_oem_get_power_source (ipmi_oem_state_data_t *state_data,
                             uint8_t command_specifier,
@@ -1290,3 +1309,247 @@
  cleanup:
   return (rv);
 }
+
+int
+ipmi_oem_fujitsu_get_sel_entry_long_text (ipmi_oem_state_data_t *state_data)
+{
+  uint8_t bytes_rq[IPMI_OEM_MAX_BYTES];
+  uint8_t bytes_rs[IPMI_OEM_MAX_BYTES];
+  int rs_len;
+  long value;
+  uint16_t sel_record_id;
+  uint16_t actual_record_id = 0;
+  uint32_t timestamp = 0;
+  uint8_t css = 0;
+  uint8_t severity = 0;
+  time_t timetmp;
+  struct tm time_tm;
+  char time_buf[IPMI_OEM_TIME_BUFLEN + 1];
+  char string_buf[IPMI_OEM_FUJITSU_SEL_ENTRY_LONG_TEXT_MAX_STRING_LENGTH + 1];
+  uint8_t data_length = UCHAR_MAX;
+  uint8_t offset = 0;
+  uint8_t component_length = 0;
+  char *css_str = NULL;
+  char *severity_str = NULL;
+  char *ptr = NULL;
+  int rv = -1;
+
+  assert (state_data);
+  assert (state_data->prog_data->args->oem_options_count == 1);
+  
+  errno = 0;
+  
+  value = strtol (state_data->prog_data->args->oem_options[0], &ptr, 0);
+  if (errno
+      || ptr[0] != '\0'
+      || value < IPMI_SEL_GET_RECORD_ID_FIRST_ENTRY
+      || value > IPMI_SEL_GET_RECORD_ID_LAST_ENTRY)
+    {
+      pstdout_fprintf (state_data->pstate,
+                       stderr,
+                       "%s:%s invalid OEM option argument '%s'\n",
+                       state_data->prog_data->args->oem_id,
+                       state_data->prog_data->args->oem_command,
+                       state_data->prog_data->args->oem_options[0]);
+      goto cleanup;
+    }
+
+  sel_record_id = value;
+
+  memset (string_buf, '\0', IPMI_OEM_FUJITSU_SEL_ENTRY_LONG_TEXT_MAX_STRING_LENGTH + 1);
+
+  /* Fujitsu OEM
+   * 
+   * http://manuals.ts.fujitsu.com/file/4390/irmc_s2-ug-en.pdf
+   *
+   * Request
+   *
+   * 0x2E - OEM network function
+   * 0xF5 - OEM cmd
+   * 0x?? - Fujitsu IANA (LSB first)
+   * 0x?? - Fujitsu IANA
+   * 0x?? - Fujitsu IANA
+   * 0x43 - Command Specifier
+   * 0x?? - Record ID (LSB first)
+   * 0x?? - Record ID ; 0x0000 = "first record", 0xFFFF = "last record"
+   * 0x?? - Offset (in response SEL text)
+   * 0x?? - MaxResponseDataSize (size of converted SEL data 16:n in response, maximum is 100)
+   *
+   * Response
+   *
+   * 0xF5 - OEM cmd
+   * 0x?? - Completion code
+   * 0x?? - Fujitsu IANA (LSB first)
+   * 0x?? - Fujitsu IANA
+   * 0x?? - Fujitsu IANA
+   * 0x?? - Next Record ID (LSB)
+   * 0x?? - Next Record ID (MSB)
+   * 0x?? - Actual Record ID (LSB)
+   * 0x?? - Actual Record ID (MSB)
+   * 0x?? - Record type
+   * 0x?? - timestamp (LSB first)
+   * 0x?? - timestamp
+   * 0x?? - timestamp
+   * 0x?? - timestamp
+   * 0x?? - severity   
+   *      bit 7   - CSS component
+   *              - 0 - No CSS component
+   *              - 1 - CSS component
+   *      bit 6-4 - 000 = INFORMATIONAL
+   *                001 = MINOR
+   *                010 = MAJOR
+   *                011 = CRITICAL
+   *                1xx = unknown
+   *      bit 3-0 - reserved
+   * 0x?? - data length (of the whole text)
+   * 0x?? - converted SEL data
+   *      - requested number of bytes starting at requested offset (MaxResponseDataSize-1 bytes of data)
+   * 0x00 - trailing '\0' character
+   */
+     
+  bytes_rq[0] = IPMI_CMD_OEM_FUJITSU_SYSTEM;
+  bytes_rq[1] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x0000FF);
+  bytes_rq[2] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0x00FF00) >> 8;
+  bytes_rq[3] = (IPMI_IANA_ENTERPRISE_ID_FUJITSU & 0xFF0000) >> 16;
+  bytes_rq[4] = IPMI_OEM_FUJITSU_COMMAND_SPECIFIER_GET_SEL_ENTRY_LONG_TEXT;
+  bytes_rq[5] = (sel_record_id & 0x00FF);
+  bytes_rq[6] = (sel_record_id & 0xFF00) >> 8;
+
+  /*
+   * From Holger Liebig <holger.liebig at ts.fujitsu.com>
+   *
+   * "Unfortunately due to memory constrains in the previous BMC
+   * generation the maximum length of a single response is limited to
+   * 64bytes, while on the current product line you should be able to
+   * get the full 100bytes translated SEL text with a single request
+   * at least over LAN. Maximum (non standard) KCS transfer size is
+   * also different between current (255) and previous (64)
+   * generation, so the code should compare the data received with the
+   * total length reported in the response."
+   */
+
+  bytes_rq[8] = ipmi_oem_min (IPMI_OEM_MAX_BYTES - 17, 64);
+
+  while (offset < data_length)
+    {
+      bytes_rq[7] = offset;
+      
+      if ((rs_len = ipmi_cmd_raw (state_data->ipmi_ctx,
+                                  0, /* lun */
+                                  IPMI_NET_FN_OEM_GROUP_RQ, /* network function */
+                                  bytes_rq, /* data */
+                                  9, /* num bytes */
+                                  bytes_rs,
+                                  IPMI_OEM_MAX_BYTES)) < 0)
+        {
+          pstdout_fprintf (state_data->pstate,
+                           stderr,
+                           "ipmi_cmd_raw: %s\n",
+                           ipmi_ctx_errormsg (state_data->ipmi_ctx));
+          goto cleanup;
+        }
+      
+      if (ipmi_oem_check_response_and_completion_code (state_data,
+                                                       bytes_rs,
+                                                       rs_len,
+                                                       17,
+                                                       IPMI_CMD_OEM_FUJITSU_SYSTEM,
+                                                       IPMI_NET_FN_OEM_GROUP_RS,
+                                                       NULL) < 0)
+        goto cleanup;
+  
+      /* achu: assume a lot of this will be the same not matter how many times we loop */
+      if (!offset)
+        {
+          actual_record_id = bytes_rs[7];
+          actual_record_id |= (bytes_rs[8] << 8);
+
+          /* use actual_record_id for subsequent requests to obtain consistent results */
+          bytes_rq[5] = bytes_rs[7];
+          bytes_rq[6] = bytes_rs[8];
+
+          timestamp = bytes_rs[10];
+          timestamp |= (bytes_rs[11] << 8);
+          timestamp |= (bytes_rs[12] << 16);
+          timestamp |= (bytes_rs[13] << 24);
+          
+          css = (bytes_rs[14] & IPMI_OEM_FUJITSU_CSS_BITMASK);
+          css >>= IPMI_OEM_FUJITSU_CSS_SHIFT;
+          
+          severity = (bytes_rs[14] & IPMI_OEM_FUJITSU_SEVERITY_BITMASK);
+          severity >>= IPMI_OEM_FUJITSU_SEVERITY_SHIFT;
+        }
+      
+      data_length = bytes_rs[15];
+      
+      /* Every response should be NUL terminated, not just the last
+       * component.
+       */
+
+      bytes_rs[rs_len - 1] = '\0'; /* just to be sure it's terminated */
+
+      component_length = strlen ((char *)bytes_rs + 16);
+  
+      /* achu: truncate if there is overflow */
+      if (offset + component_length > IPMI_OEM_FUJITSU_SEL_ENTRY_LONG_TEXT_MAX_STRING_LENGTH)
+        {
+          memcpy (string_buf + offset,
+                  &bytes_rs[16],
+                  IPMI_OEM_FUJITSU_SEL_ENTRY_LONG_TEXT_MAX_STRING_LENGTH - offset);
+          offset = data_length;
+        }
+      else
+        {
+          memcpy (string_buf + offset,
+                  &bytes_rs[16],
+                  component_length);
+          offset += component_length;
+        }
+    }
+  
+  if (css == IPMI_OEM_FUJITSU_CSS_COMPONENT)
+    css_str = "CSS Component";
+
+  if (severity == IPMI_OEM_FUJITSU_SEVERITY_INFORMATIONAL)
+    severity_str = "INFORMATIONAL";
+  else if (severity == IPMI_OEM_FUJITSU_SEVERITY_MINOR)
+    severity_str = "MINOR";
+  else if (severity == IPMI_OEM_FUJITSU_SEVERITY_MAJOR)
+    severity_str = "MAJOR";
+  else if (severity == IPMI_OEM_FUJITSU_SEVERITY_CRITICAL)
+    severity_str = "CRITICAL";
+  else
+    severity_str = "Unknown Severity";
+
+  /* Posix says individual calls need not clear/set all portions of
+   * 'struct tm', thus passing 'struct tm' between functions could
+   * have issues.  So we need to memset.
+   */
+  memset (&time_tm, '\0', sizeof(struct tm));
+
+  timetmp = timestamp;
+  localtime_r (&timetmp, &time_tm);
+  memset (time_buf, '\0', IPMI_OEM_TIME_BUFLEN + 1);
+  strftime (time_buf, IPMI_OEM_TIME_BUFLEN, "%b-%d-%Y | %H:%M:%S", &time_tm);
+
+  if (css_str)
+    pstdout_printf (state_data->pstate,
+                    "%u | %s | %s ; %s ; %s\n",
+                    actual_record_id,
+                    time_buf,
+                    css_str,
+                    severity_str,
+                    string_buf);
+  else
+    pstdout_printf (state_data->pstate,
+                    "%u | %s | %s ; %s\n",
+                    actual_record_id,
+                    time_buf,
+                    severity_str,
+                    string_buf);
+
+  rv = 0;
+ cleanup:
+  return (rv);
+}
+
Index: ipmi-oem/src/ipmi-oem-fujitsu.h
===================================================================
--- ipmi-oem/src/ipmi-oem-fujitsu.h	(revision 7219)
+++ ipmi-oem/src/ipmi-oem-fujitsu.h	(working copy)
@@ -36,4 +36,6 @@
 
 int ipmi_oem_fujitsu_get_error_led (ipmi_oem_state_data_t *state_data);
 
+int ipmi_oem_fujitsu_get_sel_entry_long_text (ipmi_oem_state_data_t *state_data);
+
 #endif
Index: ipmi-oem/src/ipmi-oem.c
===================================================================
--- ipmi-oem/src/ipmi-oem.c	(revision 7219)
+++ ipmi-oem/src/ipmi-oem.c	(working copy)
@@ -431,6 +431,13 @@
       ipmi_oem_fujitsu_get_error_led
     },
     {
+      "get-sel-entry-long-text",
+      "<sel_record_id>",
+      1,
+      IPMI_OEM_COMMAND_FLAGS_DEFAULT,
+      ipmi_oem_fujitsu_get_sel_entry_long_text
+    },
+    {
       NULL,
       NULL,
       0,
Index: ipmi-oem/ipmi-oem.8.pre.in
===================================================================
--- ipmi-oem/ipmi-oem.8.pre.in	(revision 7219)
+++ ipmi-oem/ipmi-oem.8.pre.in	(working copy)
@@ -334,6 +334,15 @@
 .B get-error-led
 This OEM command will get the current error LED status.  Command
 confirmed to work on Fujitsu RX100 S5.
+.TP
+.B get-sel-entry-long-text \fIsel_record_id\fR
+This OEM command will retrieve the Fujitsu specific string
+interpreation of a SEL record.  This command may be useful for
+interpreting Fujitsu OEM hex codes found in the SEL.  A specific SEL
+record ID must be specified.  Please see
+.B ipmi-sel(8),
+for retrieving SEL records.  Command confirmed to work on Fujitsu
+RX100 S5.
 .RE
 .TP
 .B IBM
_______________________________________________
Freeipmi-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/freeipmi-devel

Reply via email to