[PATCH 0/2] add support for the SIMATIC IPC BX-59A watchdog

98 views
Skip to first unread message

Cedric Hombourger

unread,
Oct 19, 2023, 3:32:21 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
While the original intent was to use WDAT to program the external
watchdog found in the SIMATIC IPC BX-59A, it turned out to be
impossible because it would require holding precious shared I/O
registers. See [1]

As the WDAT abstraction cannot be used, a specific driver needs
to be introduced. The w83627hf code from the Linux kernel was
greatly reused to support the NCT6116 chip.

As for the IPC 4x7E, we need to detect that we are running on
a BX-59A (we are really wanting other platforms to either use
iTCO or WDAT). The code to extract the station ID from DMI
tables is moved to its own compile unit (simatic.c) so it may
be shared between the 4x7e and bx59a support code.

[1] https://lore.kernel.org/all/df8d53db-0056-434d...@roeck-us.net/

Cedric Hombourger (2):
simatic: prepare to share code for identifying SIMATIC IPCs
drivers/watchdog: add support the SIMATIC IPC BX-59A watchdog

Makefile.am | 2 +
README.md | 1 +
drivers/watchdog/ipc4x7e_wdt.c | 54 +-------
drivers/watchdog/ipcbx59a_wdt.c | 226 ++++++++++++++++++++++++++++++++
include/simatic.h | 37 ++++++
simatic.c | 63 +++++++++
6 files changed, 331 insertions(+), 52 deletions(-)
create mode 100644 drivers/watchdog/ipcbx59a_wdt.c
create mode 100644 include/simatic.h
create mode 100644 simatic.c

--
2.39.2

Cedric Hombourger

unread,
Oct 19, 2023, 3:32:23 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
A unique product identifier for SIMATIC IPCs may be found in
the DMI data and is known as the station ID. This was up to
now used to identify IPC4x7e variants but will also be
necessary to support e.g. BX-59A. Move relevant code from
ipc4x7e_wdt.c to simatic.c and export simatic_station_id()

Signed-off-by: Cedric Hombourger <cedric.h...@siemens.com>
---
Makefile.am | 1 +
drivers/watchdog/ipc4x7e_wdt.c | 54 ++---------------------------
include/simatic.h | 36 +++++++++++++++++++
simatic.c | 63 ++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+), 52 deletions(-)
create mode 100644 include/simatic.h
create mode 100644 simatic.c

diff --git a/Makefile.am b/Makefile.am
index 64d94ef..6d4c160 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -186,6 +186,7 @@ efi_sources = \
env/fatvars.c \
utils.c \
loader_interface.c \
+ simatic.c \
bootguard.c \
main.c

diff --git a/drivers/watchdog/ipc4x7e_wdt.c b/drivers/watchdog/ipc4x7e_wdt.c
index f7e5e6a..046e3fe 100644
--- a/drivers/watchdog/ipc4x7e_wdt.c
+++ b/drivers/watchdog/ipc4x7e_wdt.c
@@ -18,24 +18,11 @@
#include <pci/header.h>
#include <sys/io.h>
#include <mmio.h>
+#include "simatic.h"
#include "utils.h"

#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_LPC 0xa150

-#define SMBIOS_TYPE_OEM_129 129
-
-#define SIMATIC_OEM_ENTRY_TYPE_BINARY 0xff
-
-#define SIMATIC_IPC427E 0xa01
-#define SIMATIC_IPC477E 0xa02
-
-typedef struct {
- UINT8 type;
- UINT8 length;
- UINT8 reserved[3];
- UINT32 station_id;
-} __attribute__((packed)) SIMATIC_OEM_ENTRY;
-
#define SIMATIC_WD_ENABLE_REG 0x62
#define SIMATIC_WD_ENABLE (1 << 0)
#define SIMATIC_WD_MACRO_MOD (1 << 1)
@@ -57,29 +44,6 @@ typedef struct {
#define PAD_CFG_DW0_GPP_A_23 0x4b8
#define PAD_CFG_GPIOTXSTATE (1 << 0)

-static UINT32 get_station_id(SMBIOS_STRUCTURE_POINTER oem_strct)
-{
- SIMATIC_OEM_ENTRY *entry;
- UINTN n;
-
- entry = (SIMATIC_OEM_ENTRY *)(oem_strct.Raw + sizeof(*oem_strct.Hdr));
-
- /* Find 4th entry in OEM data. */
- for (n = 0; n < 3; n++) {
- if (entry->type != SIMATIC_OEM_ENTRY_TYPE_BINARY) {
- return 0;
- }
- entry = (SIMATIC_OEM_ENTRY *)((UINT8 *)entry + entry->length);
- }
-
- if (entry->type == SIMATIC_OEM_ENTRY_TYPE_BINARY &&
- entry->length == sizeof(SIMATIC_OEM_ENTRY)) {
- return entry->station_id;
- }
-
- return 0;
-}
-
static UINTN mmcfg_address(UINTN bus, UINTN device, UINTN function,
UINTN offset)
{
@@ -114,9 +78,6 @@ static EFI_STATUS __attribute__((constructor))
init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
UINTN timeout)
{
- SMBIOS_STRUCTURE_TABLE *smbios_table;
- SMBIOS_STRUCTURE_POINTER smbios_struct;
- EFI_STATUS status;
UINTN pad_cfg;
UINT8 val;

@@ -125,18 +86,7 @@ init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
return EFI_UNSUPPORTED;
}

- status = LibGetSystemConfigurationTable(&SMBIOSTableGuid,
- (VOID **)&smbios_table);
- if (status != EFI_SUCCESS) {
- return EFI_UNSUPPORTED;
- }
-
- smbios_struct = smbios_find_struct(smbios_table, SMBIOS_TYPE_OEM_129);
- if (smbios_struct.Raw == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- switch (get_station_id(smbios_struct)) {
+ switch (simatic_station_id()) {
case SIMATIC_IPC427E:
case SIMATIC_IPC477E:
INFO(L"Detected SIMATIC IPC4x7E watchdog\n");
diff --git a/include/simatic.h b/include/simatic.h
new file mode 100644
index 0000000..33429c5
--- /dev/null
+++ b/include/simatic.h
@@ -0,0 +1,36 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Authors:
+ * Dr. Johann Pfefferl <johann....@siemens.com>
+ * Jan Kiszka <jan.k...@siemens.com>
+ * Cedric Hombourger <cedric.h...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#pragma once
+
+#include <efi.h>
+#include <efilib.h>
+
+#define SMBIOS_TYPE_OEM_129 129
+
+#define SIMATIC_OEM_ENTRY_TYPE_BINARY 0xff
+
+#define SIMATIC_IPC427E 0xa01
+#define SIMATIC_IPC477E 0xa02
+
+typedef struct {
+ UINT8 type;
+ UINT8 length;
+ UINT8 reserved[3];
+ UINT32 station_id;
+} __attribute__((packed)) SIMATIC_OEM_ENTRY;
+
+UINT32 simatic_station_id(void);
diff --git a/simatic.c b/simatic.c
new file mode 100644
index 0000000..7309cdf
--- /dev/null
+++ b/simatic.c
@@ -0,0 +1,63 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2020
+ *
+ * Authors:
+ * Dr. Johann Pfefferl <johann....@siemens.com>
+ * Jan Kiszka <jan.k...@siemens.com>
+ * Cedric Hombourger <cedric.h...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <efi.h>
+#include <efilib.h>
+#include "simatic.h"
+#include "utils.h"
+
+static UINT32 get_station_id(SMBIOS_STRUCTURE_POINTER oem_strct)
+{
+ SIMATIC_OEM_ENTRY *entry;
+ UINTN n;
+
+ entry = (SIMATIC_OEM_ENTRY *)(oem_strct.Raw + sizeof(*oem_strct.Hdr));
+
+ /* Find 4th entry in OEM data. */
+ for (n = 0; n < 3; n++) {
+ if (entry->type != SIMATIC_OEM_ENTRY_TYPE_BINARY) {
+ return 0;
+ }
+ entry = (SIMATIC_OEM_ENTRY *)((UINT8 *)entry + entry->length);
+ }
+
+ if (entry->type == SIMATIC_OEM_ENTRY_TYPE_BINARY &&
+ entry->length == sizeof(SIMATIC_OEM_ENTRY)) {
+ return entry->station_id;
+ }
+
+ return 0;
+}
+
+UINT32 simatic_station_id(VOID)
+{
+ SMBIOS_STRUCTURE_TABLE *smbios_table;
+ SMBIOS_STRUCTURE_POINTER smbios_struct;
+ EFI_STATUS status;
+
+ status = LibGetSystemConfigurationTable(&SMBIOSTableGuid,
+ (VOID **)&smbios_table);
+ if (status != EFI_SUCCESS) {
+ return 0;
+ }
+
+ smbios_struct = smbios_find_struct(smbios_table, SMBIOS_TYPE_OEM_129);
+ if (smbios_struct.Raw == NULL) {
+ return 0;
+ }
+
+ return get_station_id(smbios_struct);
+}
--
2.39.2

Cedric Hombourger

unread,
Oct 19, 2023, 3:32:23 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
Re-use the w83627hf code from the Linux kernel to support the
NCT6116 chip found on the SIMATIC IPC BX-59A. The code was
greatly simplified to only support that particular chip.

The original intent was to use WDAT for this platform but it
turned out to be impossible because it would require holding
precious shared I/O registers.

See https://lore.kernel.org/all/df8d53db-0056-434d...@roeck-us.net/

Signed-off-by: Cedric Hombourger <cedric.h...@siemens.com>
---
Makefile.am | 1 +
README.md | 1 +
drivers/watchdog/ipcbx59a_wdt.c | 226 ++++++++++++++++++++++++++++++++
include/simatic.h | 5 +-
4 files changed, 231 insertions(+), 2 deletions(-)
create mode 100644 drivers/watchdog/ipcbx59a_wdt.c

diff --git a/Makefile.am b/Makefile.am
index 6d4c160..ef9df19 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -171,6 +171,7 @@ efi_sources_watchdogs = \
drivers/watchdog/i6300esb.c \
drivers/watchdog/atom-quark.c \
drivers/watchdog/ipc4x7e_wdt.c \
+ drivers/watchdog/ipcbx59a_wdt.c \
drivers/watchdog/ipmi_wdt.c \
drivers/watchdog/itco.c \
drivers/watchdog/hpwdt.c
diff --git a/README.md b/README.md
index c6d13fd..ef8a2fe 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ The following watchdog drivers are implemented (and are probed in this order):
* Intel i6300esb
* Intel Quark
* Siemens SIMATIC IPC4x7E
+* Siemens SIMATIC BX-59A
* Intel TCO
* HPE ProLiant

diff --git a/drivers/watchdog/ipcbx59a_wdt.c b/drivers/watchdog/ipcbx59a_wdt.c
new file mode 100644
index 0000000..8163099
--- /dev/null
+++ b/drivers/watchdog/ipcbx59a_wdt.c
@@ -0,0 +1,226 @@
+/*
+ * EFI Boot Guard
+ *
+ * Modified version of the w83627hf_wdt.c driver found in the Linux kernel
+ *
+ * (c) Copyright 2013 Guenter Roeck
+ * converted to watchdog infrastructure
+ *
+ * (c) Copyright 2007 Vlad Drukker <vl...@storewiz.com>
+ * added support for W83627THF.
+ *
+ * (c) Copyright 2003,2007 Pádraig Brady <P...@draigBrady.com>
+ *
+ * Based on advantechwdt.c which is based on wdt.c.
+ * Original copyright messages:
+ *
+ * (c) Copyright 2000-2001 Marek Michalkiewicz <mar...@linux.org.pl>
+ *
+ * (c) Copyright 1996 Alan Cox <al...@lxorguk.ukuu.org.uk>,
+ * All Rights Reserved.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
+ *
+ * (c) Copyright 1995 Alan Cox <al...@lxorguk.ukuu.org.uk>
+ *
+ * Changes and EFI Boot Guard specific code:
+ *
+ * by Cedric Hombourger <cedric.h...@siemens.com>
+ * (c) Copyright (c) Siemens AG, 2023
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <efi.h>
+#include <efilib.h>
+#include <pci/header.h>
+#include <sys/io.h>
+#include <mmio.h>
+#include "simatic.h"
+#include "utils.h"
+
+/* Use the host bridge device found on the BX-59A to limit probing to Intel
+ * based machines that may be a BX59A; technically we do not use/need PCI
+ * for this driver but only port I/Os */
+#define PCI_DEVICE_ID_INTEL_HOST_BRIDGE 0xa700
+
+#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */
+#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register
+ (same as EFER) */
+#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */
+
+#define W83627HF_LD_WDT 0x08
+
+#define NCT6116_ID 0xd2
+
+#define NCT6102D_WDT_TIMEOUT 0xf1
+#define NCT6102D_WDT_CONTROL 0xf0
+#define NCT6102D_WDT_CSR 0xf2
+
+#define WDT_CSR_STATUS 0x10
+#define WDT_CSR_KBD 0x40
+#define WDT_CSR_MOUSE 0x80
+
+enum chips { nct6116 };
+
+static int wdt_io;
+static int cr_wdt_timeout; /* WDT timeout register */
+static int cr_wdt_control; /* WDT control register */
+static int cr_wdt_csr; /* WDT control & status register */
+static int wdt_cfg_enter = 0x87;/* key to unlock configuration space */
+static int wdt_cfg_leave = 0xAA;/* key to lock configuration space */
+
+static void superio_outb(int reg, int val)
+{
+ outb(reg, WDT_EFER);
+ outb(val, WDT_EFDR);
+}
+
+static inline int superio_inb(int reg)
+{
+ outb(reg, WDT_EFER);
+ return inb(WDT_EFDR);
+}
+
+static int superio_enter(void)
+{
+ outb_p(wdt_cfg_enter, WDT_EFER); /* Enter extended function mode */
+ outb_p(wdt_cfg_enter, WDT_EFER); /* Again according to manual */
+ return 0;
+}
+
+static void superio_select(int ld)
+{
+ superio_outb(0x07, ld);
+}
+
+static void superio_exit(void)
+{
+ outb_p(wdt_cfg_leave, WDT_EFER); /* Leave extended function mode */
+}
+
+static int wdt_find(int addr)
+{
+ UINT8 val;
+ int ret;
+
+ wdt_io = addr;
+ ret = superio_enter();
+ if (ret)
+ return ret;
+ superio_select(W83627HF_LD_WDT);
+ val = superio_inb(0x20);
+ switch(val) {
+ case NCT6116_ID:
+ ret = nct6116;
+ cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
+ cr_wdt_control = NCT6102D_WDT_CONTROL;
+ cr_wdt_csr = NCT6102D_WDT_CSR;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ superio_exit();
+ return ret;
+}
+
+static int w83627hf_init(enum chips chip)
+{
+ int ret;
+ unsigned char t;
+
+ ret = superio_enter();
+ if (ret)
+ return ret;
+
+ superio_select(W83627HF_LD_WDT);
+
+ /* set CR30 bit 0 to activate GPIO2 */
+ t = superio_inb(0x30);
+ if (!(t & 0x01))
+ superio_outb(0x30, t | 0x01);
+
+ switch (chip) {
+ case nct6116:
+ /*
+ * These chips have a fixed WDTO# output pin (W83627UHG),
+ * or support more than one WDTO# output pin.
+ * Don't touch its configuration, and hope the BIOS
+ * does the right thing.
+ */
+ t = superio_inb(cr_wdt_control);
+ t |= 0x02; /* enable the WDTO# output low pulse
+ * to the KBRST# pin */
+ superio_outb(cr_wdt_control, t);
+ break;
+ default:
+ break;
+ }
+
+ t = superio_inb(cr_wdt_timeout);
+ if (t != 0) {
+ WARNING(L"Watchdog already running.\n");
+ }
+
+ /* set second mode & disable keyboard turning off watchdog */
+ t = superio_inb(cr_wdt_control) & ~0x0C;
+ superio_outb(cr_wdt_control, t);
+
+ /* reset status, disable keyboard & mouse turning off watchdog */
+ t = superio_inb(cr_wdt_csr);
+ t &= ~(WDT_CSR_STATUS | WDT_CSR_KBD | WDT_CSR_MOUSE);
+ superio_outb(cr_wdt_csr, t);
+
+ superio_exit();
+
+ return 0;
+}
+
+static int wdt_set_time(unsigned int timeout)
+{
+ int ret;
+
+ ret = superio_enter();
+ if (ret)
+ return ret;
+
+ superio_select(W83627HF_LD_WDT);
+ superio_outb(cr_wdt_timeout, timeout);
+ superio_exit();
+
+ return 0;
+}
+
+static EFI_STATUS __attribute__((constructor))
+init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
+ UINTN timeout)
+{
+ int chip, ret;
+
+ if (!pci_io || pci_vendor_id != PCI_VENDOR_ID_INTEL ||
+ pci_device_id != PCI_DEVICE_ID_INTEL_HOST_BRIDGE) {
+ return EFI_UNSUPPORTED;
+ }
+
+ switch (simatic_station_id()) {
+ case SIMATIC_IPCBX_59A:
+ chip = wdt_find(0x2e);
+ if (chip < 0)
+ return EFI_UNSUPPORTED;
+ INFO(L"Detected SIMATIC BX59A watchdog\n");
+ ret = w83627hf_init(chip);
+ if (ret < 0)
+ return EFI_UNSUPPORTED;
+ ret = wdt_set_time(timeout);
+ if (ret < 0)
+ return EFI_UNSUPPORTED;
+ return EFI_SUCCESS;
+ }
+ return EFI_UNSUPPORTED;
+}
diff --git a/include/simatic.h b/include/simatic.h
index 33429c5..724e79d 100644
--- a/include/simatic.h
+++ b/include/simatic.h
@@ -23,8 +23,9 @@

#define SIMATIC_OEM_ENTRY_TYPE_BINARY 0xff

-#define SIMATIC_IPC427E 0xa01
-#define SIMATIC_IPC477E 0xa02
+#define SIMATIC_IPC427E 0x0a01
+#define SIMATIC_IPC477E 0x0a02
+#define SIMATIC_IPCBX_59A 0x1202

typedef struct {
UINT8 type;
--
2.39.2

Jan Kiszka

unread,
Oct 19, 2023, 4:17:43 AM10/19/23
to Cedric Hombourger, efibootg...@googlegroups.com
In Linux, we use the pre-existing w83627hf_wdt unmodified for this
purpose. Wouldn't it make sense to at least name this driver here
generically so that we could add support for other systems using it
later on without much hassle?

Jan

--
Siemens AG, Technology
Linux Expert Center

cedric.h...@siemens.com

unread,
Oct 19, 2023, 4:22:54 AM10/19/23
to Kiszka, Jan, efibootg...@googlegroups.com
I was debating with myself on that. I'm happy either way. Would we just
rename or are you suggesting we somehow get the station id check out of
w83627hf_wdt.c (and e.g. have ipcbx59a.c call into w83627hf_wdt.c)?
> Jan
>

Jan Kiszka

unread,
Oct 19, 2023, 4:49:23 AM10/19/23
to cedric.h...@siemens.com, efibootg...@googlegroups.com
I wouldn't mind keeping the ID check there. Some other check would have
to be added anyway when expanding beyond our hardware. So: rename.

Cedric Hombourger

unread,
Oct 19, 2023, 5:00:19 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
A unique product identifier for SIMATIC IPCs may be found in
the DMI data and is known as the station ID. This was up to
now used to identify IPC4x7e variants but will also be
necessary to support e.g. BX-59A. Move relevant code from
ipc4x7e_wdt.c to simatic.c and export simatic_station_id()

Signed-off-by: Cedric Hombourger <cedric.h...@siemens.com>
---
Makefile.am | 1 +
drivers/watchdog/ipc4x7e_wdt.c | 54 ++---------------------------
include/simatic.h | 36 +++++++++++++++++++
simatic.c | 63 ++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+), 52 deletions(-)
create mode 100644 include/simatic.h
create mode 100644 simatic.c

diff --git a/Makefile.am b/Makefile.am
index 64d94ef..6d4c160 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -186,6 +186,7 @@ efi_sources = \
env/fatvars.c \
utils.c \
loader_interface.c \
+ simatic.c \
bootguard.c \
main.c

diff --git a/drivers/watchdog/ipc4x7e_wdt.c b/drivers/watchdog/ipc4x7e_wdt.c
index f7e5e6a..046e3fe 100644
--- a/drivers/watchdog/ipc4x7e_wdt.c
+++ b/drivers/watchdog/ipc4x7e_wdt.c
@@ -18,24 +18,11 @@
#include <pci/header.h>
#include <sys/io.h>
#include <mmio.h>
+#include "simatic.h"
#include "utils.h"

#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_LPC 0xa150

-#define SMBIOS_TYPE_OEM_129 129
-
-#define SIMATIC_OEM_ENTRY_TYPE_BINARY 0xff
-
-#define SIMATIC_IPC427E 0xa01
-#define SIMATIC_IPC477E 0xa02
init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
new file mode 100644
index 0000000..33429c5
--- /dev/null
+++ b/include/simatic.h
@@ -0,0 +1,36 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Authors:
+ * Dr. Johann Pfefferl <johann....@siemens.com>
+ * Jan Kiszka <jan.k...@siemens.com>
+ * Cedric Hombourger <cedric.h...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#pragma once
+
+#include <efi.h>
+#include <efilib.h>
+
+#define SMBIOS_TYPE_OEM_129 129
+
+#define SIMATIC_OEM_ENTRY_TYPE_BINARY 0xff
+
+#define SIMATIC_IPC427E 0xa01
+#define SIMATIC_IPC477E 0xa02
+
+typedef struct {
+ UINT8 type;
+ UINT8 length;
+ UINT8 reserved[3];
+ UINT32 station_id;
+} __attribute__((packed)) SIMATIC_OEM_ENTRY;
+
+UINT32 simatic_station_id(void);
diff --git a/simatic.c b/simatic.c
new file mode 100644
index 0000000..7309cdf
--- /dev/null
+++ b/simatic.c
@@ -0,0 +1,63 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2020
+ *
+ * Authors:
+ * Dr. Johann Pfefferl <johann....@siemens.com>
+ * Jan Kiszka <jan.k...@siemens.com>
+ * Cedric Hombourger <cedric.h...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <efi.h>
+#include <efilib.h>
+#include "simatic.h"
+#include "utils.h"
+
+static UINT32 get_station_id(SMBIOS_STRUCTURE_POINTER oem_strct)
+{
+ SIMATIC_OEM_ENTRY *entry;
+ UINTN n;
+
+ entry = (SIMATIC_OEM_ENTRY *)(oem_strct.Raw + sizeof(*oem_strct.Hdr));
+
+ /* Find 4th entry in OEM data. */
+ for (n = 0; n < 3; n++) {
+ if (entry->type != SIMATIC_OEM_ENTRY_TYPE_BINARY) {
+ return 0;
+ }
+ entry = (SIMATIC_OEM_ENTRY *)((UINT8 *)entry + entry->length);
+ }
+
+ if (entry->type == SIMATIC_OEM_ENTRY_TYPE_BINARY &&
+ entry->length == sizeof(SIMATIC_OEM_ENTRY)) {
+ return entry->station_id;
+ }
+
+ return 0;
+}
+
+UINT32 simatic_station_id(VOID)
+{
+ SMBIOS_STRUCTURE_TABLE *smbios_table;
+ SMBIOS_STRUCTURE_POINTER smbios_struct;
+ EFI_STATUS status;
+
+ status = LibGetSystemConfigurationTable(&SMBIOSTableGuid,
+ (VOID **)&smbios_table);
+ if (status != EFI_SUCCESS) {
+ return 0;
+ }
+
+ smbios_struct = smbios_find_struct(smbios_table, SMBIOS_TYPE_OEM_129);
+ if (smbios_struct.Raw == NULL) {
+ return 0;
+ }
+

Cedric Hombourger

unread,
Oct 19, 2023, 5:00:19 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
While the original intent was to use WDAT to program the external
watchdog found in the SIMATIC IPC BX-59A, it turned out to be
impossible because it would require holding precious shared I/O
registers. See [1]

As the WDAT abstraction cannot be used, a specific driver needs
to be introduced. The w83627hf code from the Linux kernel was
greatly reused to support the NCT6116 chip.

As for the IPC 4x7E, we need to detect that we are running on
a BX-59A (we are really wanting other platforms to either use
iTCO or WDAT). The code to extract the station ID from DMI
tables is moved to its own compile unit (simatic.c) so it may
be shared between the ipc4x7e_wdt and w83627hf_wdt drivers.

Changes between v1 and v2:
- rename ipcbx59a_wdt.c to w83627hf_wdt.c as suggested by Jan Kiszka

[1] https://lore.kernel.org/all/df8d53db-0056-434d...@roeck-us.net/

Cedric Hombourger (2):
simatic: prepare to share code for identifying SIMATIC IPCs
drivers/watchdog: add support for w83627hf watchdog

Makefile.am | 2 +
README.md | 1 +
drivers/watchdog/ipc4x7e_wdt.c | 54 +-------
drivers/watchdog/w83627hf_wdt.c | 226 ++++++++++++++++++++++++++++++++
include/simatic.h | 37 ++++++
simatic.c | 63 +++++++++
6 files changed, 331 insertions(+), 52 deletions(-)
create mode 100644 drivers/watchdog/w83627hf_wdt.c

Cedric Hombourger

unread,
Oct 19, 2023, 5:00:20 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
Re-use the w83627hf code from the Linux kernel to support the
NCT6116 chip found on the SIMATIC IPC BX-59A. The code was
greatly simplified to only support that particular chip.

The original intent was to use WDAT for this platform but it
turned out to be impossible because it would require holding
precious shared I/O registers.

See https://lore.kernel.org/all/df8d53db-0056-434d...@roeck-us.net/

Signed-off-by: Cedric Hombourger <cedric.h...@siemens.com>
---
Makefile.am | 1 +
README.md | 1 +
drivers/watchdog/w83627hf_wdt.c | 226 ++++++++++++++++++++++++++++++++
include/simatic.h | 5 +-
4 files changed, 231 insertions(+), 2 deletions(-)
create mode 100644 drivers/watchdog/w83627hf_wdt.c

diff --git a/Makefile.am b/Makefile.am
index 6d4c160..b7b3936 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -171,6 +171,7 @@ efi_sources_watchdogs = \
drivers/watchdog/i6300esb.c \
drivers/watchdog/atom-quark.c \
drivers/watchdog/ipc4x7e_wdt.c \
+ drivers/watchdog/w83627hf_wdt.c \
drivers/watchdog/ipmi_wdt.c \
drivers/watchdog/itco.c \
drivers/watchdog/hpwdt.c
diff --git a/README.md b/README.md
index c6d13fd..ef8a2fe 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ The following watchdog drivers are implemented (and are probed in this order):
* Intel i6300esb
* Intel Quark
* Siemens SIMATIC IPC4x7E
+* Siemens SIMATIC BX-59A
* Intel TCO
* HPE ProLiant

diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
new file mode 100644
index 0000000..8163099
--- /dev/null
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -0,0 +1,226 @@
+/*
+ * EFI Boot Guard
+ *
+ * by Cedric Hombourger <cedric.h...@siemens.com>
+ * (c) Copyright (c) Siemens AG, 2023
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <efi.h>
+#include <efilib.h>
+#include <pci/header.h>
+#include <sys/io.h>
+#include <mmio.h>
+#include "simatic.h"
+#include "utils.h"
+
+ return 0;
+}
+
+
+ return 0;
+}
+
+static int wdt_set_time(unsigned int timeout)
+{
+ int ret;
+
+ ret = superio_enter();
+ if (ret)
+ return ret;
+
+ superio_select(W83627HF_LD_WDT);
+ superio_outb(cr_wdt_timeout, timeout);
+ superio_exit();
+
+ return 0;
+}
+
-#define SIMATIC_IPC427E 0xa01
-#define SIMATIC_IPC477E 0xa02
+#define SIMATIC_IPC427E 0x0a01
+#define SIMATIC_IPC477E 0x0a02
+#define SIMATIC_IPCBX_59A 0x1202

typedef struct {
UINT8 type;
--
2.39.2

Jan Kiszka

unread,
Oct 19, 2023, 9:47:15 AM10/19/23
to Cedric Hombourger, efibootg...@googlegroups.com
Thanks, applied. I will follow up with some cleanups on top as I noticed
that smbios_find_struct() and now also the whole simatic.c is included
also into non-x86 builds.

Cedric Hombourger

unread,
Oct 19, 2023, 11:30:25 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
A unique product identifier for SIMATIC IPCs may be found in
the DMI data and is known as the station ID. This was up to
now used to identify IPC4x7e variants but will also be
necessary to support e.g. BX-59A. Move relevant code from
ipc4x7e_wdt.c to simatic.c and export simatic_station_id()

Signed-off-by: Cedric Hombourger <cedric.h...@siemens.com>
---
Makefile.am | 1 +
drivers/watchdog/ipc4x7e_wdt.c | 54 ++---------------------------
include/simatic.h | 36 +++++++++++++++++++
simatic.c | 63 ++++++++++++++++++++++++++++++++++
4 files changed, 102 insertions(+), 52 deletions(-)
create mode 100644 include/simatic.h
create mode 100644 simatic.c

diff --git a/Makefile.am b/Makefile.am
index 64d94ef..6d4c160 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -186,6 +186,7 @@ efi_sources = \
env/fatvars.c \
utils.c \
loader_interface.c \
+ simatic.c \
bootguard.c \
main.c

diff --git a/drivers/watchdog/ipc4x7e_wdt.c b/drivers/watchdog/ipc4x7e_wdt.c
index f7e5e6a..046e3fe 100644
--- a/drivers/watchdog/ipc4x7e_wdt.c
+++ b/drivers/watchdog/ipc4x7e_wdt.c
@@ -18,24 +18,11 @@
#include <pci/header.h>
#include <sys/io.h>
#include <mmio.h>
+#include "simatic.h"
#include "utils.h"

#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_LPC 0xa150

-#define SMBIOS_TYPE_OEM_129 129
-
-#define SIMATIC_OEM_ENTRY_TYPE_BINARY 0xff
-
-#define SIMATIC_IPC427E 0xa01
-#define SIMATIC_IPC477E 0xa02
init(EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
new file mode 100644
index 0000000..33429c5
--- /dev/null
+++ b/include/simatic.h
@@ -0,0 +1,36 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2023
+ *
+ * Authors:
+ * Dr. Johann Pfefferl <johann....@siemens.com>
+ * Jan Kiszka <jan.k...@siemens.com>
+ * Cedric Hombourger <cedric.h...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#pragma once
+
+#include <efi.h>
+#include <efilib.h>
+
+#define SMBIOS_TYPE_OEM_129 129
+
+#define SIMATIC_OEM_ENTRY_TYPE_BINARY 0xff
+
+#define SIMATIC_IPC427E 0xa01
+#define SIMATIC_IPC477E 0xa02
+
+typedef struct {
+ UINT8 type;
+ UINT8 length;
+ UINT8 reserved[3];
+ UINT32 station_id;
+} __attribute__((packed)) SIMATIC_OEM_ENTRY;
+
+UINT32 simatic_station_id(void);
diff --git a/simatic.c b/simatic.c
new file mode 100644
index 0000000..7309cdf
--- /dev/null
+++ b/simatic.c
@@ -0,0 +1,63 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2020
+ *
+ * Authors:
+ * Dr. Johann Pfefferl <johann....@siemens.com>
+ * Jan Kiszka <jan.k...@siemens.com>
+ * Cedric Hombourger <cedric.h...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <efi.h>
+#include <efilib.h>
+#include "simatic.h"
+#include "utils.h"
+
+static UINT32 get_station_id(SMBIOS_STRUCTURE_POINTER oem_strct)
+{
+ SIMATIC_OEM_ENTRY *entry;
+ UINTN n;
+
+ entry = (SIMATIC_OEM_ENTRY *)(oem_strct.Raw + sizeof(*oem_strct.Hdr));
+
+ /* Find 4th entry in OEM data. */
+ for (n = 0; n < 3; n++) {
+ if (entry->type != SIMATIC_OEM_ENTRY_TYPE_BINARY) {
+ return 0;
+ }
+ entry = (SIMATIC_OEM_ENTRY *)((UINT8 *)entry + entry->length);
+ }
+
+ if (entry->type == SIMATIC_OEM_ENTRY_TYPE_BINARY &&
+ entry->length == sizeof(SIMATIC_OEM_ENTRY)) {
+ return entry->station_id;
+ }
+
+ return 0;
+}
+
+UINT32 simatic_station_id(VOID)
+{
+ SMBIOS_STRUCTURE_TABLE *smbios_table;
+ SMBIOS_STRUCTURE_POINTER smbios_struct;
+ EFI_STATUS status;
+
+ status = LibGetSystemConfigurationTable(&SMBIOSTableGuid,
+ (VOID **)&smbios_table);
+ if (status != EFI_SUCCESS) {
+ return 0;
+ }
+
+ smbios_struct = smbios_find_struct(smbios_table, SMBIOS_TYPE_OEM_129);
+ if (smbios_struct.Raw == NULL) {
+ return 0;
+ }
+

Cedric Hombourger

unread,
Oct 19, 2023, 11:30:25 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
While the original intent was to use WDAT to program the external
watchdog found in the SIMATIC IPC BX-59A, it turned out to be
impossible because it would require holding precious shared I/O
registers. See [1]

As the WDAT abstraction cannot be used, a specific driver needs
to be introduced. The w83627hf code from the Linux kernel was
greatly reused to support the NCT6116 chip.

As for the IPC 4x7E, we need to detect that we are running on
a BX-59A (we are really wanting other platforms to either use
iTCO or WDAT). The code to extract the station ID from DMI
tables is moved to its own compile unit (simatic.c) so it may
be shared between the ipc4x7e_wdt and w83627hf_wdt drivers.

Changes between v2 and v3:
- fix "Parameter 'pci_io' can be declared with const" (raised by
cppcheck)

Changes between v1 and v2:
- rename ipcbx59a_wdt.c to w83627hf_wdt.c as suggested by Jan Kiszka


*** BLURB HERE ***

Cedric Hombourger (2):
simatic: prepare to share code for identifying SIMATIC IPCs
drivers/watchdog: add support for w83627hf watchdog

Makefile.am | 2 +
README.md | 1 +
drivers/watchdog/ipc4x7e_wdt.c | 54 +-------
drivers/watchdog/w83627hf_wdt.c | 226 ++++++++++++++++++++++++++++++++
include/simatic.h | 37 ++++++
simatic.c | 63 +++++++++
6 files changed, 331 insertions(+), 52 deletions(-)
create mode 100644 drivers/watchdog/w83627hf_wdt.c
create mode 100644 include/simatic.h
create mode 100644 simatic.c

--
2.39.2

Cedric Hombourger

unread,
Oct 19, 2023, 11:30:26 AM10/19/23
to efibootg...@googlegroups.com, Cedric Hombourger
Re-use the w83627hf code from the Linux kernel to support the
NCT6116 chip found on the SIMATIC IPC BX-59A. The code was
greatly simplified to only support that particular chip.

The original intent was to use WDAT for this platform but it
turned out to be impossible because it would require holding
precious shared I/O registers.

See https://lore.kernel.org/all/df8d53db-0056-434d...@roeck-us.net/

Signed-off-by: Cedric Hombourger <cedric.h...@siemens.com>
---
Makefile.am | 1 +
README.md | 1 +
drivers/watchdog/w83627hf_wdt.c | 226 ++++++++++++++++++++++++++++++++
include/simatic.h | 5 +-
4 files changed, 231 insertions(+), 2 deletions(-)
create mode 100644 drivers/watchdog/w83627hf_wdt.c

diff --git a/Makefile.am b/Makefile.am
index 6d4c160..b7b3936 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -171,6 +171,7 @@ efi_sources_watchdogs = \
drivers/watchdog/i6300esb.c \
drivers/watchdog/atom-quark.c \
drivers/watchdog/ipc4x7e_wdt.c \
+ drivers/watchdog/w83627hf_wdt.c \
drivers/watchdog/ipmi_wdt.c \
drivers/watchdog/itco.c \
drivers/watchdog/hpwdt.c
diff --git a/README.md b/README.md
index c6d13fd..ef8a2fe 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,7 @@ The following watchdog drivers are implemented (and are probed in this order):
* Intel i6300esb
* Intel Quark
* Siemens SIMATIC IPC4x7E
+* Siemens SIMATIC BX-59A
* Intel TCO
* HPE ProLiant

diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
new file mode 100644
index 0000000..547fd29
--- /dev/null
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -0,0 +1,226 @@
+/*
+ * EFI Boot Guard
+ *
+ * by Cedric Hombourger <cedric.h...@siemens.com>
+ * (c) Copyright (c) Siemens AG, 2023
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <efi.h>
+#include <efilib.h>
+#include <pci/header.h>
+#include <sys/io.h>
+#include <mmio.h>
+#include "simatic.h"
+#include "utils.h"
+
+ return 0;
+}
+
+
+ return 0;
+}
+
+static int wdt_set_time(unsigned int timeout)
+{
+ int ret;
+
+ ret = superio_enter();
+ if (ret)
+ return ret;
+
+ superio_select(W83627HF_LD_WDT);
+ superio_outb(cr_wdt_timeout, timeout);
+ superio_exit();
+
+ return 0;
+}
+
+static EFI_STATUS __attribute__((constructor))
+init(const EFI_PCI_IO *pci_io, UINT16 pci_vendor_id, UINT16 pci_device_id,
-#define SIMATIC_IPC427E 0xa01
-#define SIMATIC_IPC477E 0xa02

Jan Kiszka

unread,
Oct 19, 2023, 12:14:43 PM10/19/23
to Cedric Hombourger, efibootg...@googlegroups.com
Looking at the whole thing again, I guess it is better for follow the
ipc4x7e_wdt precedence and exempt also this module from constParameter
check. I can do that on top of current next, planning to pull out
scripts/cppcheck.sh from the CI script so that local execution becomes
easier.

Jan

JEMS EBERHARD HORBEL

unread,
Dec 9, 2023, 1:56:42 PM12/9/23
to EFI Boot Guard
DIRECT SENDER IS HERE LETS DEAL.

JENS EBERHARD



MT103/202 DIRECT WIRE TRANSFER
PAYPAL TRANSFER
CASHAPP TRANSFER
ZELLE TRANSFER
TRANSFER WISE
WESTERN UNION TRANSFER
BITCOIN FLASHING 
BANK ACCOUNT LOADING/FLASHING
IBAN TO IBAN TRANSFER
MONEYGRAM TRANSFER
SLBC PROVIDER
CREDIT CARD TOP UP
SEPA TRANSFER
WIRE TRANSFER
GLOBALPAY INC US

Thanks.


NOTE; ONLY SERIOUS / RELIABLE RECEIVERS CAN CONTACT.

DM ME ON WHATSAPP FOR A SERIOUS DEAL.

+447405129573
Reply all
Reply to author
Forward
0 new messages