|
| 1 | +/* |
| 2 | + * EFI Boot Guard |
| 3 | + * |
| 4 | + * Copyright (c) Siemens AG, 2024 |
| 5 | + * |
| 6 | + * Ported by Cedric Hombourger <[email protected]> |
| 7 | + * From unpublished code created by XingTong Wu <[email protected]> |
| 8 | + * |
| 9 | + * This work is licensed under the terms of the GNU GPL, version 2. See |
| 10 | + * the COPYING file in the top-level directory. |
| 11 | + * |
| 12 | + * SPDX-License-Identifier: GPL-2.0 |
| 13 | + */ |
| 14 | + |
| 15 | +#include <efi.h> |
| 16 | +#include <efilib.h> |
| 17 | +#include <pci/header.h> |
| 18 | +#include <sys/io.h> |
| 19 | +#include "simatic.h" |
| 20 | +#include "utils.h" |
| 21 | + |
| 22 | +#define WDT_CTRL_REG_BX_21A 0x1854 |
| 23 | +#define TIMEOUT_MIN_BX_21A (1) |
| 24 | +#define TIMEOUT_DEF_BX_21A (60) |
| 25 | +#define TIMEOUT_MAX_BX_21A (1024) |
| 26 | +/* Over-Clocking WDT Timeout Value */ |
| 27 | +#define WDT_CTRL_REG_TOV_MASK_BX_21A (0x3FF) |
| 28 | +/* Over-Clocking WDT ICC Survivability Impact */ |
| 29 | +#define WDT_CTRL_REG_ICCSURV_BIT_BX_21A BIT(13) |
| 30 | +/* Over-Clocking WDT Enable */ |
| 31 | +#define WDT_CTRL_REG_EN_BIT_BX_21A BIT(14) |
| 32 | +/* Over-Clocking WDT Force All */ |
| 33 | +#define WDT_CTRL_REG_FORCE_ALL_BIT_BX_21A BIT(15) |
| 34 | +/* Over-Clocking WDT Non-ICC Survivability Mode Timeout Status */ |
| 35 | +#define WDT_CTRL_REG_NO_ICCSURV_STS_BIT_BX_21A BIT(24) |
| 36 | +/* Over-Clocking WDT ICC Survivability Mode Timeout Status */ |
| 37 | +#define WDT_CTRL_REG_ICCSURV_STS_BIT_BX_21A BIT(25) |
| 38 | + |
| 39 | +static EFI_STATUS init(EFI_PCI_IO __attribute__((unused)) * pci_io, |
| 40 | + UINT16 __attribute__((unused)) pci_vendor_id, |
| 41 | + UINT16 __attribute__((unused)) pci_device_id, |
| 42 | + UINTN timeout) |
| 43 | +{ |
| 44 | + UINT32 regval; |
| 45 | + |
| 46 | + if (simatic_station_id() != SIMATIC_IPCBX_21A) |
| 47 | + return EFI_UNSUPPORTED; |
| 48 | + |
| 49 | + INFO(L"Detected SIMATIC BX-21A watchdog\n"); |
| 50 | + |
| 51 | + if (timeout < TIMEOUT_MIN_BX_21A || timeout > TIMEOUT_MAX_BX_21A) { |
| 52 | + WARNING(L"Invalid timeout value (%d), default (%ds) is used.\n", |
| 53 | + timeout, TIMEOUT_DEF_BX_21A); |
| 54 | + timeout = TIMEOUT_DEF_BX_21A; |
| 55 | + } |
| 56 | + |
| 57 | + regval = inl(WDT_CTRL_REG_BX_21A); |
| 58 | + /* setup timeout value */ |
| 59 | + regval &= (~WDT_CTRL_REG_TOV_MASK_BX_21A); |
| 60 | + regval |= (timeout - 1); |
| 61 | + /* get and clear status */ |
| 62 | + regval |= WDT_CTRL_REG_NO_ICCSURV_STS_BIT_BX_21A; |
| 63 | + regval |= WDT_CTRL_REG_ICCSURV_STS_BIT_BX_21A; |
| 64 | + outl(regval, WDT_CTRL_REG_BX_21A); |
| 65 | + |
| 66 | + /* start watchdog */ |
| 67 | + regval = inl(WDT_CTRL_REG_BX_21A); |
| 68 | + regval |= (WDT_CTRL_REG_EN_BIT_BX_21A | |
| 69 | + WDT_CTRL_REG_ICCSURV_BIT_BX_21A | |
| 70 | + WDT_CTRL_REG_FORCE_ALL_BIT_BX_21A); |
| 71 | + outl(regval, WDT_CTRL_REG_BX_21A); |
| 72 | + |
| 73 | + return EFI_SUCCESS; |
| 74 | +} |
| 75 | + |
| 76 | +WATCHDOG_REGISTER(init); |
0 commit comments