Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+175
View File
@@ -0,0 +1,175 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
+12
View File
@@ -0,0 +1,12 @@
Different components of meta-google are under different licenses (a mix
of MIT and Apache-2.0). Please see:
COPYING.Apache-2.0
COPYING.MIT (MIT)
All metadata is MIT licensed unless otherwise stated. Source code
included in tree for individual recipes is under the LICENSE stated in
the associated recipe (.bb file) unless otherwise stated.
License information for any other files is either explicitly stated
or defaults to Apache-2.0.
+8
View File
@@ -0,0 +1,8 @@
owners:
- yuenn@google.com
- wak@google.com
- benjaminfair@google.com
- edtanous@google.com
- brandonkim@google.com
- wltu@google.com
- nanzhoumails@gmail.com
+60
View File
@@ -0,0 +1,60 @@
This README file contains information on the contents of the meta-google layer.
Please see the corresponding sections below for details.
Dependencies
============
This layer depends on:
URI: https://github.com/openbmc/meta-phosphor
branch: master
Patches
=======
Please submit any patches against the meta-google layer to the OpenBMC gerrit https://gerrit.openbmc.org/
Layer maintainer: Patrick Venture <venture@google.com>
When sending patches, follow the OpenBMC guidelines.
Table of Contents
=================
I. Adding the filesystems layer to your build
II. Purpose
III. Customizations
I. Adding the meta-google layer to your build
=================================================
In order to use this layer, you need to make the build system aware of
it.
Assuming the meta-google layer exists at the top-level of your
yocto build tree, you can add it to the build system by adding the
location of the meta-google layer to bblayers.conf, along with any
other layers needed. e.g.:
BBLAYERS ?= " \
/path/to/yocto/meta-phosphor \
/path/to/yocto/meta-google \
"
II. Purpose
============
Including this layer adds the following packages to your obmc-phosphor-image:
* google-ipmi-sys: OEM IPMI Handler for providing specific information to the host.
* phosphor-ipmi-blobs: OEM IPMI Blobs Handler for providing the framework for specific blob handlers.
* phosphor-ipmi-ethstats: OEM IPMI Handler for reporting ethernet device statistics from the BMCs ethernet devices.
* phosphor-ipmi-flash: OEM IPMI Handler for controlling in-band firmware updates.
III. Customizations
Presently, this layer also enables the Google Iana for registering phosphor-ipmi-ethstats in addition to the OpenBMC one.
@@ -0,0 +1,209 @@
# The offsets of the partitions that change when Hoth is enabled
# From the device tree, in kB
FLASH_IMAGE_DESC_OFFSET:hoth = "${@960 if FLASH_SIZE == '65536' else 7232}"
FLASH_HOTH_UPDATE_OFFSET:hoth = "${@1024 if FLASH_SIZE == '65536' else 31744}"
FLASH_HOTH_MAILBOX_OFFSET:hoth = "${@65472 if FLASH_SIZE == '65536' else 7168}"
FLASH_HOTH_SECONDARY_OFFSET:hoth = "${@61376 if FLASH_SIZE == '65536' else 7296}"
# 64 bit kernels are larger, so they require a different layout
FLASH_IMAGE_DESC_OFFSET:hoth:aarch64 = "${@61312 if FLASH_SIZE == '65536' else 7232}"
FLASH_HOTH_UPDATE_OFFSET:hoth:aarch64 = "${@61376 if FLASH_SIZE == '65536' else 31744}"
# Leave a zero-size u-boot env partition.
FLASH_UBOOT_ENV_OFFSET = "${FLASH_KERNEL_OFFSET}"
FLASH_UBOOT_ENV_OFFSET:flash-65536 = "${FLASH_KERNEL_OFFSET:flash-65536}"
# Support BMC image to have secondary hoth firmware
ENABLE_HOTH_SECONDARY ?= "no"
python do_generate_static:append() {
_append_image(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
'image-hoth-update'),
int(d.getVar('FLASH_HOTH_UPDATE_OFFSET', True)),
int(d.getVar('FLASH_SIZE', True)))
if d.getVar('ENABLE_HOTH_SECONDARY',True) == 'yes':
_append_image(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
'image-hoth-update-2nd'),
int(d.getVar('FLASH_HOTH_SECONDARY_OFFSET', True)),
int(d.getVar('FLASH_RWFS_OFFSET', True)))
}
do_generate_static[depends] += "virtual/hoth-firmware:do_deploy"
do_generate_static[depends] += "${@'virtual/hoth-firmware-2nd:do_deploy' if ENABLE_HOTH_SECONDARY == 'yes' else ''}"
python do_generate_layout () {
import time
import json
def convertPart(name, startKb, endKb, static=False, wp=False, persist=False):
regionTypes = []
extraAttrs = {}
if static:
regionTypes.append('STATIC')
if wp:
regionTypes.append('WRITE_PROTECTED')
if persist:
regionTypes.append('PERSISTENT')
if name == 'hoth_mailbox':
regionTypes.append('MAILBOX')
extraAttrs['mailbox_length'] = 1024
start = int(startKb) * 1024
end = int(endKb) * 1024
return {
'name': name,
'offset': start,
'length': end - start,
'region_type': regionTypes,
**extraAttrs,
}
# TODO: make this work for Aspeed too
region = [
convertPart(
'u_boot',
d.getVar('FLASH_UBOOT_OFFSET'),
d.getVar('FLASH_KERNEL_OFFSET'),
static=True,
wp=True),
convertPart(
'kernel',
d.getVar('FLASH_KERNEL_OFFSET'),
d.getVar('FLASH_ROFS_OFFSET'),
static=True,
wp=True),
convertPart(
'rofs',
d.getVar('FLASH_ROFS_OFFSET'),
d.getVar('FLASH_IMAGE_DESC_OFFSET'),
static=True,
wp=True),
convertPart(
'image_descriptor',
d.getVar('FLASH_IMAGE_DESC_OFFSET'),
d.getVar('FLASH_HOTH_UPDATE_OFFSET'),
static=True,
wp=True),
convertPart(
'hoth_update',
d.getVar('FLASH_HOTH_UPDATE_OFFSET'),
d.getVar('FLASH_RWFS_OFFSET')),
convertPart(
'rwfs',
d.getVar('FLASH_RWFS_OFFSET'),
d.getVar('FLASH_HOTH_MAILBOX_OFFSET'),
persist=True),
convertPart(
'hoth_mailbox',
d.getVar('FLASH_HOTH_MAILBOX_OFFSET'),
d.getVar('FLASH_SIZE')),
] if d.getVar('TARGET_ARCH') == "aarch64" else [
convertPart(
'u_boot',
d.getVar('FLASH_UBOOT_OFFSET'),
d.getVar('FLASH_IMAGE_DESC_OFFSET'),
static=True,
wp=True),
convertPart(
'image_descriptor',
d.getVar('FLASH_IMAGE_DESC_OFFSET'),
d.getVar('FLASH_HOTH_UPDATE_OFFSET'),
static=True,
wp=True),
convertPart(
'hoth_update',
d.getVar('FLASH_HOTH_UPDATE_OFFSET'),
d.getVar('FLASH_KERNEL_OFFSET')),
convertPart(
'kernel',
d.getVar('FLASH_KERNEL_OFFSET'),
d.getVar('FLASH_ROFS_OFFSET'),
static=True,
wp=True),
convertPart(
'rofs',
d.getVar('FLASH_ROFS_OFFSET'),
d.getVar('FLASH_HOTH_SECONDARY_OFFSET'),
static=True,
wp=True),
convertPart(
'hoth_secondary',
d.getVar('FLASH_HOTH_SECONDARY_OFFSET'),
d.getVar('FLASH_RWFS_OFFSET')),
convertPart(
'rwfs',
d.getVar('FLASH_RWFS_OFFSET'),
d.getVar('FLASH_HOTH_MAILBOX_OFFSET'),
persist=True),
convertPart(
'hoth_mailbox',
d.getVar('FLASH_HOTH_MAILBOX_OFFSET'),
d.getVar('FLASH_SIZE')),
] if d.getVar('FLASH_SIZE') == '65536' else [
convertPart(
'u_boot',
d.getVar('FLASH_UBOOT_OFFSET'),
d.getVar('FLASH_KERNEL_OFFSET'),
static=True,
wp=True),
convertPart(
'kernel',
d.getVar('FLASH_KERNEL_OFFSET'),
d.getVar('FLASH_HOTH_MAILBOX_OFFSET'),
static=True,
wp=True),
convertPart(
'hoth_mailbox',
d.getVar('FLASH_HOTH_MAILBOX_OFFSET'),
d.getVar('FLASH_IMAGE_DESC_OFFSET')),
convertPart(
'image_descriptor',
d.getVar('FLASH_IMAGE_DESC_OFFSET'),
d.getVar('FLASH_ROFS_OFFSET'),
static=True,
wp=True),
convertPart(
'rofs',
d.getVar('FLASH_ROFS_OFFSET'),
d.getVar('FLASH_RWFS_OFFSET'),
static=True,
wp=True),
convertPart(
'rwfs',
d.getVar('FLASH_RWFS_OFFSET'),
d.getVar('FLASH_HOTH_UPDATE_OFFSET'),
persist=True),
convertPart(
'hoth_update',
d.getVar('FLASH_HOTH_UPDATE_OFFSET'),
d.getVar('FLASH_SIZE')),
]
machine = d.getVar('MACHINE')
platform = d.getVar('PLATFORM')
name = '{} {} image'.format(machine, d.getVar('DISTRO'))
version = d.getVar('GBMC_VERSION').split('.')
if not platform:
raise NameError('PLATFORM not found, unable to generate layout, stopping build')
layout = {
'name': name,
'major': int(version[0]),
'minor': int(version[1]),
'point': int(version[2]),
'subpoint': int(version[3]),
'platform': platform,
'flash_capacity': int(d.getVar('FLASH_SIZE')) * 1024,
'build_timestamp': int(time.time()),
'region': region,
}
dir = d.getVar('DEPLOY_DIR_IMAGE')
os.makedirs(dir, exist_ok=True)
path = os.path.join(dir, 'cr51-image-layout.json')
with open(path, 'w') as f:
json.dump(layout, f, sort_keys=True, indent=4)
}
addtask generate_layout before do_image_complete
+41
View File
@@ -0,0 +1,41 @@
require conf/distro/openbmc-phosphor.conf
require conf/distro/include/phosphor-isolation.inc
GBMC_VERSION ?= "0.5.0.0"
DISTRO = "gbmc"
DISTRO_NAME = "gBMC (OpenBMC + Google customizations)"
DISTRO_VERSION = "gbmc-release-${GBMC_VERSION}"
EXTENDED_VERSION = "${DISTRO_VERSION}"
DISTROOVERRIDES .= ":gbmc"
# Possible values: "dev", "prod"
GBMC_CONFIG ?= "dev"
OVERRIDES .= ":${GBMC_CONFIG}:"
DISTRO_FEATURES:remove = "ldap"
DISTRO_FEATURES:remove = "slp"
# Required to get entity-manager to build with FruDevice service
DISTRO_FEATURES:append = " ipmi-fru"
# Disable u-boot shell for prod builds
DISTRO_FEATURES:append:prod = " disable-u-boot-shell"
WATCHDOG_PKG ?= "watchdog"
SANITY_TESTED_DISTROS:append = " Debian-rodete \n debian-rodete \n "
PREFERRED_PROVIDER_virtual/bmc-update ?= "inplace-gbmc-update"
# Provides reasonable data integrity and faster than sha*
FIT_HASH_ALG = "crc32"
OBMC_ORG_YAML_SUBDIRS += " com/google"
# Force the patches to not have any fuzz for gBMC
ERROR_QA:append = " patch-fuzz"
IGPS_MACHINE:npcm8xx = "Google"
# Remove dependencies on python3-core when using nftables
PACKAGECONFIG:remove:pn-nftables = "python"
+18
View File
@@ -0,0 +1,18 @@
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILES_DYNAMIC += " \
aspeed-layer:${LAYERDIR}/dynamic-layers/aspeed-layer/recipes-*/*/*.bb \
aspeed-layer:${LAYERDIR}/dynamic-layers/aspeed-layer/recipes-*/*/*.bbappend \
nuvoton-layer:${LAYERDIR}/dynamic-layers/nuvoton-layer/recipes-*/*/*.bb \
nuvoton-layer:${LAYERDIR}/dynamic-layers/nuvoton-layer/recipes-*/*/*.bbappend \
"
BBFILE_COLLECTIONS += "google-layer"
BBFILE_PATTERN_google-layer := "^${LAYERDIR}/"
LAYERVERSION_google-layer = "1"
LAYERSERIES_COMPAT_google-layer = "langdale mickledore"
LAYERDEPENDS_google-layer += "core phosphor-layer tpm-layer"
@@ -0,0 +1,4 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/../../../../recipes-kernel/linux/files:"
SRC_URI:append:gbmc = " file://gbmc.cfg"
SRC_URI:append:gbmc:dev = " file://gbmc-dev.cfg"
SRC_URI:append:gbmc:prod = " file://gbmc-prod.cfg"
@@ -0,0 +1,3 @@
FILESEXTRAPATHS:prepend:gbmc:hoth := "${THISDIR}/${BPN}:"
SRC_URI:append:gbmc:hoth = " file://0001-Set-FIU0_DRD_CFG-and-FIU_Clk_divider-for-gbmc-hoth.patch"
@@ -0,0 +1,50 @@
From 107b6f3cb217b80985a400c658836510ce226168 Mon Sep 17 00:00:00 2001
From: Benjamin Fair <benjaminfair@google.com>
Date: Wed, 20 Nov 2019 14:20:38 -0800
Subject: [PATCH] Set FIU0_DRD_CFG and FIU_Clk_divider for gbmc hoth
This is to set the SPI frequency to 20MHz
Signed-off-by: Benjamin Fair <benjaminfair@google.com>
Signed-off-by: Brandon Kim <brandonkim@google.com>
---
ImageGeneration/references/BootBlockAndHeader_EB.xml | 4 ++--
ImageGeneration/references/UbootHeader_EB.xml | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/ImageGeneration/references/BootBlockAndHeader_EB.xml b/ImageGeneration/references/BootBlockAndHeader_EB.xml
index 157535d..ef77cbb 100644
--- a/ImageGeneration/references/BootBlockAndHeader_EB.xml
+++ b/ImageGeneration/references/BootBlockAndHeader_EB.xml
@@ -63,7 +63,7 @@
<offset>0x108</offset>
<size>0x4</size>
</config>
- <content format='32bit'>0x030011BB</content> <!-- content the user should fill -->
+ <content format='32bit'>0x0300100B</content> <!-- content the user should fill -->
</BinField>
<BinField>
@@ -73,7 +73,7 @@
<offset>0x10C</offset>
<size>0x1</size>
</config>
- <content format='bytes'>4</content> <!-- content the user should fill -->
+ <content format='bytes'>10</content> <!-- content the user should fill -->
</BinField>
<BinField>
diff --git a/ImageGeneration/references/UbootHeader_EB.xml b/ImageGeneration/references/UbootHeader_EB.xml
index 475ec45..b99e7e6 100644
--- a/ImageGeneration/references/UbootHeader_EB.xml
+++ b/ImageGeneration/references/UbootHeader_EB.xml
@@ -63,7 +63,7 @@
<offset>0x108</offset> <!-- offset in the header -->
<size>0x4</size> <!-- size in the header -->
</config>
- <content format='32bit'>0x030111BC</content> <!-- content the user should fill 0x030032EB -->
+ <content format='32bit'>0x0300100B</content> <!-- content the user should fill 0x030032EB -->
</BinField>
<BinField>
@@ -0,0 +1,6 @@
# Enable EDAC support
CONFIG_EDAC_SUPPORT=y
CONFIG_EDAC=y
CONFIG_EDAC_NPCM7XX=y
CONFIG_EDAC_NPCM=y
CONFIG_RAS=y
@@ -0,0 +1,5 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/files:${THISDIR}/../../../../recipes-kernel/linux/files:"
SRC_URI:append:gbmc = " file://gbmc.cfg"
SRC_URI:append:gbmc = " file://gbmc-nuvoton.cfg"
SRC_URI:append:gbmc:dev = " file://gbmc-dev.cfg"
SRC_URI:append:gbmc:prod = " file://gbmc-prod.cfg"
@@ -0,0 +1,5 @@
FILESEXTRAPATHS:prepend:gbmc := "${THISDIR}/files:"
SRC_URI:append:gbmc = " file://avahi-daemon.conf"
do_install:append:gbmc() {
install -m0644 ${WORKDIR}/avahi-daemon.conf ${D}${sysconfdir}/avahi/
}
@@ -0,0 +1,8 @@
[server]
allow-interfaces=mgmt,gbmcbr
[publish]
disable-user-service-publishing=yes
add-service-cookie=yes
publish-hinfo=no
publish-workstation=no
@@ -0,0 +1,4 @@
# LTO and static enabled to reduce image size, saves ~50%
CFLAGS:append:gbmc = " -flto"
EXTRA_OECONF:remove:gbmc = "--disable-static"
EXTRA_OECONF:append:gbmc = " --enable-relay-port --disable-shared"
@@ -0,0 +1,3 @@
FILESEXTRAPATHS:prepend:gbmc := "${THISDIR}/files:"
SRC_URI:append:gbmc = " file://gbmc.cfg"
SRC_URI:remove:gbmc = "file://syslog.cfg"
@@ -0,0 +1,55 @@
# gBMC uses iproute2
CONFIG_IP=n
CONFIG_NETSTAT=n
# Debugging utilities
CONFIG_LSOF=y
CONFIG_LSUSB=y
# Used for line buffering
CONFIG_SCRIPT=y
# Used by NC-SId
CONFIG_FEATURE_IPV6=y
CONFIG_UDHCPC6=y
CONFIG_FEATURE_UDHCPC6_RFC3646=y
CONFIG_FEATURE_UDHCPC6_RFC4704=y
CONFIG_FEATURE_UDHCPC6_RFC4833=y
CONFIG_FEATURE_UDHCPC6_RFC5970=y
# Misc
CONFIG_BC=y
CONFIG_TRUNCATE=y
CONFIG_BASE64=y
CONFIG_FEATURE_TOP_INTERACTIVE=y
CONFIG_FEATURE_TOP_SMP_CPU=y
CONFIG_FEATURE_TOP_SMP_PROCESS=y
CONFIG_FEATURE_TOPMEM=y
CONFIG_FEATURE_CPIO_O=y
# Remove unused things
CONFIG_BUNZIP2=n
CONFIG_BZIP2=n
CONFIG_UNZIP=n
CONFIG_ADDGROUP=n
CONFIG_ADDUSER=n
CONFIG_DELGROUP=n
CONFIG_DELUSER=n
CONFIG_LOGIN=n
CONFIG_SU=n
CONFIG_SULOGIN=n
CONFIG_FDISK=n
CONFIG_FSTRIM=n
CONFIG_MKSWAP=n
CONFIG_SWAPON=n
CONFIG_SWAPOFF=n
CONFIG_IFCONFIG=n
CONFIG_IFUP=n
CONFIG_IFDOWN=n
CONFIG_ROUTE=n
CONFIG_TFTP=n
CONFIG_TLS=n
CONFIG_TRACEROUTE=n
CONFIG_KLOGD=n
CONFIG_LOGREAD=n
CONFIG_SYSLOGD=n
@@ -0,0 +1 @@
DROPBEAR_EXTRA_ARGS=""
@@ -0,0 +1,18 @@
FILESEXTRAPATHS:prepend:gbmc := "${THISDIR}/${PN}:"
SRC_URI:append:gbmc = " file://dropbear.default"
SYSTEMD_AUTO_ENABLE:${PN}:prod = "disable"
FILESEXTRAPATHS:remove:gbmc:bandaid := "${THISDIR}/${PN}:"
SYSTEMD_AUTO_ENABLE:${PN}:bandaid:prod = "enable"
# Allow SSH to the gbmc-bridge node on DEV builds
do_install:append:gbmc:dev() {
nftables_dir=${D}${sysconfdir}/nftables
rules=$nftables_dir/50-dropbear-dev.rules
install -d -m0755 $nftables_dir
echo 'table inet filter {' >"$rules"
echo ' chain gbmc_br_pub_input {' >>"$rules"
echo ' tcp dport 22 accept' >>"$rules"
echo ' }' >>"$rules"
echo '}' >>"$rules"
}
@@ -0,0 +1,13 @@
python() {
# Instead of using BB_ENV_EXTRAWHITE, we can get info from the
# shell environment this way.
origenv = d.getVar("BB_ORIGENV", False)
memo = origenv.getVar("BUILD_MEMO", False)
if memo:
d.setVar("BUILD_MEMO", memo)
}
IMAGE_TYPE = "${GBMC_CONFIG}"
GBMC_TARGET_MACHINE ?= "${MACHINE}"
OS_RELEASE_FIELDS:append:gbmc = " BUILD_MEMO IMAGE_TYPE GBMC_TARGET_MACHINE"
@@ -0,0 +1,3 @@
# Reduces the size of the output binaries by ~300K
CFLAGS:append:class-target = " -flto"
CXXFLAGS:append:class-target = " -flto"
@@ -0,0 +1,32 @@
LICENSE = "BSD-2-Clause"
LIC_FILES_CHKSUM = "file://COPYING;md5=667d4ad55f5fbf4c3e853e8acd0f74de"
PV = "0.1+git${SRCPV}"
SRC_URI = "git://github.com/yrutschle/conf2struct;branch=master;protocol=https"
SRCREV = "6bc9eed1eb50175e5fda791f27d85e72f5a6ac78"
S = "${WORKDIR}/git"
SRC_URI += " \
file://0001-makefile-Add-missing-LDFLAGS.patch \
file://0001-conf2struct-Use-the-right-perl.patch \
"
inherit native
DEPENDS += " \
libconfig-native \
libconfig-perl-native \
"
EXTRA_OEMAKE += " \
DESTDIR=${D} \
prefix=${prefix} \
"
do_compile() {
oe_runmake checker
}
do_install() {
oe_runmake install
}
@@ -0,0 +1,23 @@
From b44f0d3dbcadb20396dc83a2aa307d54490388ea Mon Sep 17 00:00:00 2001
From: "William A. Kennington III" <wak@google.com>
Date: Thu, 28 May 2020 23:07:58 -0700
Subject: [PATCH] conf2struct: Use the right perl
---
conf2struct | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/conf2struct b/conf2struct
index 8d68741..b88a9b7 100755
--- a/conf2struct
+++ b/conf2struct
@@ -1,4 +1,5 @@
-#! /usr/bin/perl -w
+#!/usr/bin/env perl
+use warnings;
my $license = <<EOF;
# conf2struct: generate libconf parsers that read to structs
--
2.27.0.rc0.183.gde8f92d652-goog
@@ -0,0 +1,34 @@
From 8fc429f59df50e1f468c8e9616a6e7ef42cc6ebf Mon Sep 17 00:00:00 2001
From: "William A. Kennington III" <wak@google.com>
Date: Thu, 28 May 2020 22:51:47 -0700
Subject: [PATCH] makefile: Add missing LDFLAGS
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index a4d5f10..4976726 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ all: example checker
CFLAGS=-g
checker: confcheck.o
- $(CC) $(CFLAGS) -o confcheck confcheck.o -lconfig
+ $(CC) $(CFLAGS) -o confcheck confcheck.o $(LDFLAGS) -lconfig
install:
@@ -19,7 +19,7 @@ uninstall:
EG_OBJ=example.o parser.o argtable3.o
example: $(EG_OBJ)
- $(CC) $(CFLAGS) -o example $(EG_OBJ) -lconfig
+ $(CC) $(CFLAGS) -o example $(EG_OBJ) $(LDFLAGS) -lconfig
example.c: eg_conf.cfg
./conf2struct eg_conf.cfg
--
2.27.0.rc0.183.gde8f92d652-goog
@@ -0,0 +1,16 @@
HOMEPAGE = "https://metacpan.org/pod/Conf::Libconfig"
LICENSE = "BSD-3-Clause"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9"
SRC_URI = "https://cpan.metacpan.org/authors/id/C/CN/CNANGEL/Conf-Libconfig-${PV}.tar.gz"
SRC_URI[sha256sum] = "2f13d926a6e51fd549da9ea4ed01277a99748d75236c2a1b5f26f57a1abebe61"
S = "${WORKDIR}/Conf-Libconfig-${PV}"
DEPENDS += "libconfig"
EXTRA_PERLFLAGS = "-I ${PERLHOSTLIB}"
inherit cpan
BBCLASSEXTEND += "native"
@@ -0,0 +1 @@
BBCLASSEXTEND += "native"
@@ -0,0 +1,18 @@
#!/bin/sh
if [ "$#" -lt 2 ]; then
echo "Missing args: bridge-stp <bridge> <start|stop>" >&2
exit 1
fi
case "$2" in
start)
/usr/sbin/mstpctl addbridge "$1"
exit
;;
stop)
/usr/sbin/mstpctl delbridge "$1"
exit
;;
*)
echo "Invalid operation: $2" >&2
exit 1
esac
@@ -0,0 +1,12 @@
[Unit]
Description=Multiple Spanning Tree Protocol Daemon
Before=network-pre.target
Wants=network-pre.target
[Service]
Restart=always
Type=simple
ExecStart=/usr/sbin/mstpd -d -v 2
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,30 @@
PR = "r1"
PV = "0.1+git${SRCPV}"
LICENSE = "GPL-2.0-or-later"
LIC_FILES_CHKSUM = "file://LICENSE;md5=4325afd396febcb659c36b49533135d4"
SRC_URI = "git://github.com/mstpd/mstpd;branch=master;protocol=https"
SRCREV = "181c453fc1a00573e19f14960dcc54ad84beea7c"
S = "${WORKDIR}/git"
SRC_URI += "file://bridge-stp"
SRC_URI += "file://mstpd.service"
inherit autotools pkgconfig systemd
PACKAGES =+ "${PN}-mstpd"
FILES:${PN}-mstpd = "${sbindir}/mstpd ${sbindir}/mstpctl ${sbindir}/bridge-stp"
SYSTEMD_PACKAGES = "${PN}-mstpd"
SYSTEMD_SERVICE:${PN}-mstpd = "mstpd.service"
do_install:append() {
rm -rf ${D}${libexecdir} ${D}${libdir}/NetworkManager
rmdir ${D}${libdir} || true
install -d -m 0755 ${D}/${sbindir}
install -m 0755 ${WORKDIR}/bridge-stp ${D}/${sbindir}
install -d -m 0755 ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/mstpd.service ${D}${systemd_system_unitdir}/
}
@@ -0,0 +1,42 @@
PR = "r2"
PV = "0.1+git${SRCPV}"
LICENSE = "GPL-2.0-or-later"
LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
SRC_URI = "git://github.com/yrutschle/sslh;branch=master;protocol=https"
SRCREV = "7e3f723699764a9d000902af55e15e0eb151281f"
S = "${WORKDIR}/git"
inherit perlnative
DEPENDS += "conf2struct-native"
DEPENDS += "libbsd"
DEPENDS += "libcap"
DEPENDS += "libconfig"
DEPENDS += "libev"
DEPENDS += "systemd"
DEPENDS += "pcre2"
EXTRA_OEMAKE += "DESTDIR=${D}"
EXTRA_OEMAKE += "PREFIX=${prefix}"
EXTRA_OEMAKE += "USELIBCAP=1"
EXTRA_OEMAKE += "USELIBBSD=1"
EXTRA_OEMAKE += "USESYSTEMD=1"
do_configure() {
oe_runmake distclean
}
do_compile() {
# Workaround for a non-installed and broken echosrv
sed -i 's,^\(all:.*\) echosrv,\1,' ${S}/Makefile
# Workaround for the broken dependencies in the Makefile
oe_runmake sslh-conf.h
oe_runmake
}
do_install() {
oe_runmake install
}
@@ -0,0 +1,22 @@
# Remove pwquality from PAM, to avoid breaking PAM and further dependencies
# This allows pwquality to be neatly severed from the system.
RDEPENDS:${PN}-runtime:remove:gbmc = "libpwquality"
do_install:append:gbmc() {
# Remove reference to pwquality library from PAM config file
sed -i '/pam_pwquality.so/d' ${D}${sysconfdir}/pam.d/common-password
# Remove the first occurrence of "use_authtok" in the first line starting
# with "password". This makes sure that if pam_pwquality.so was the first
# entry, we didn't invalidate the next entry in the stack. If the first
# entry has the "use_authtok" set, this "forces the module to not prompt
# the user for a new password but use the one provided by the previously
# stacked password module". Since there is no "previous" entry, it never
# asks for a password which causes the process to fail.
awk '/^password/ && !f{sub(/ use_authtok/, ""); f=1} 1' \
${D}${sysconfdir}/pam.d/common-password \
> ${D}${sysconfdir}/pam.d/common-password.new
mv ${D}${sysconfdir}/pam.d/common-password.new \
${D}${sysconfdir}/pam.d/common-password
}
@@ -0,0 +1,12 @@
module(load="imuxsock" SysSock.Use="off")
module(
load="imjournal"
StateFile="/var/log/state"
RateLimit.Interval="60"
RateLimit.Burst="4000"
)
#
# Include all config files in /etc/rsyslog.d/
#
include(file="/etc/rsyslog.d/*.conf")
@@ -0,0 +1,7 @@
FILESEXTRAPATHS:prepend:gbmc := "${THISDIR}/${PN}:"
SRC_URI:append:gbmc = " \
file://rsyslog.conf \
"
PACKAGECONFIG:append:gbmc = " imjournal"
@@ -0,0 +1 @@
DEFAULT_TIMEZONE:gbmc = "PST8PDT"
@@ -0,0 +1,19 @@
SUMMARY = "ACPI Power/Sleep state daemon to allow host state events"
DESCRIPTION = "ACPI Power/Sleep state daemon to allow host state events"
GOOGLE_MISC_PROJ = "acpi-power-state-daemon"
require ../google-misc/google-misc.inc
inherit pkgconfig systemd
DEPENDS += " \
phosphor-dbus-interfaces \
sdbusplus \
systemd \
"
SYSTEMD_SERVICE:${PN} = " \
acpi-power-state.service \
host-s0-state.target \
host-s5-state.target \
"
@@ -0,0 +1,39 @@
SUMMARY = "Glome Config"
DESCRIPTION = "Glome config file provides a glome config file"
PR = "r1"
# This is required to replace the glome/config that is removed in glome_git.bb
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
# Example Privkey: A0F1D0A0CB254839D04637F567325B850B5174850B129E811F5E203A42CC3B6C
GLOME_PUBLIC_KEY ?= "AC11D4582261F2D05CDDE1BD94383393D26C5C269642EE26D7EABD1EADC03C14"
GLOME_KEY_VERSION ?= "4"
GLOME_URL_PREFIX ?= "http://example-glome-service/"
SRC_URI = "file://config.in"
do_install:append() {
if [ -z '${GLOME_PUBLIC_KEY}' ]; then
echo 'Missing GLOME_PUBLIC_KEY' >&2
exit 1
fi
if [ -z '${GLOME_KEY_VERSION}' ]; then
echo 'Missing GLOME_KEY_VERSION' >&2
exit 1
fi
if [ -z '${GLOME_URL_PREFIX}' ]; then
echo 'Missing GLOME_URL_PREFIX' >&2
exit 1
fi
sed ${WORKDIR}/config.in \
-e 's#@PUBLIC_KEY@#${GLOME_PUBLIC_KEY}#' \
-e 's#@KEY_VERSION@#${GLOME_KEY_VERSION}#' \
-e 's#@URL_PREFIX@#${GLOME_URL_PREFIX}#' \
> ${WORKDIR}/config
install -d ${D}${sysconfdir}/glome
install -m 0644 ${WORKDIR}/config ${D}${sysconfdir}/glome
}
@@ -0,0 +1,8 @@
# This is the configuration file for serial console authentication with glome.
# /usr/sbin/glome-login tries to read this file on startup at its canonical
# location /etc/glome/config.
[service]
key = @PUBLIC_KEY@
key-version = @KEY_VERSION@
url-prefix = @URL_PREFIX@
@@ -0,0 +1,59 @@
SUMMARY = "Glome Login Scripts"
DESCRIPTION = "Glome Login Scripts"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
GLOME_FALLBACK_SERV ?= ""
GLOME_FALLBACK_OBJ ?= ""
GLOME_HOSTNAME_SUFFIX ?= ""
GLOME_BOARDSN_KEY ?= "bmc-boardsn"
RDEPENDS:${PN} += "bash"
RDEPENDS:${PN} += "glome"
RDEPENDS:${PN} += "jq"
RDEPENDS:${PN} += "obmc-console"
SRC_URI += "file://glome-login.sh.in"
do_install:append() {
if [ -z '${GLOME_FALLBACK_SERV}' ]; then
echo 'Missing GLOME_FALLBACK_SERV' >&2
exit 1
fi
if [ -z '${GLOME_FALLBACK_OBJ}' ]; then
echo 'Missing GLOME_FALLBACK_OBJ' >&2
exit 1
fi
if [ -z '${GLOME_HOSTNAME_SUFFIX}' ]; then
echo 'Missing GLOME_HOSTNAME_SUFFIX' >&2
exit 1
fi
sed ${WORKDIR}/glome-login.sh.in \
-e 's#@INV_SERV@#${GLOME_FALLBACK_SERV}#' \
-e 's#@INV_OBJ@#${GLOME_FALLBACK_OBJ}#' \
-e 's#@HOSTNAME_SUFFIX@#${GLOME_HOSTNAME_SUFFIX}#' \
-e 's#@BOARDSN_KEY@#${GLOME_BOARDSN_KEY}#' \
> ${WORKDIR}/glome-login.sh
install -d ${D}${bindir}
install -m 0755 ${WORKDIR}/glome-login.sh ${D}${bindir}
}
# This is an example to override the glome login service in the bbappend for 'prod'
#
#FILES:${PN}:append:prod = " \
# ${systemd_system_unitdir}/serial-to-bmc@.service.d/bmc-login-glome-override.conf \
# ${systemd_system_unitdir}/serial-getty@.service.d/bmc-login-glome-override.conf \
# "
#
#do_install:append:prod() {
# install -D -m 0644 ${WORKDIR}/bmc-login-glome-override.conf \
# ${D}${systemd_system_unitdir}/serial-to-bmc@.service.d/bmc-login-glome-override.conf
# install -D -m 0644 ${WORKDIR}/bmc-login-glome-override.conf \
# ${D}${systemd_system_unitdir}/serial-getty@.service.d/bmc-login-glome-override.conf
#}
@@ -0,0 +1,42 @@
#!/bin/bash
# Copyright 2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -eo pipefail
HOSTNAME="$(hostname)"
USER="${1?Missing first param: USER (Usually passed by agetty via \\u)}"
if [[ "$HOSTNAME" =~ ^([^-.]+)[^.]*(.*[.]corp[.]google[.]com)$ ]]; then
# for google corp address the suffix must be removed from the name
HOSTNAME="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
fi
if [[ "${HOSTNAME}" == *"@HOSTNAME_SUFFIX@" ]]; then
# Valid hostname is already set, invoke normal glome
exec /usr/sbin/glome-login -M "${HOSTNAME}" "${USER}"
fi
# Get the board serial number from the FRU EEPROM
# Service passed in as a parameter would be either inventory-manager or
# entity-manager depending on platforms
# Path to the FRU EEPROM object has to be passed in as a parameter
# If the target platform has neither of them, the fallback mechanism is useless
INT="xyz.openbmc_project.Inventory.Decorator.Asset"
PART="SerialNumber"
BOARDSN="$(busctl get-property -j "@INV_SERV@" "@INV_OBJ@" "${INT}" "${PART}" | jq -r '.data')"
WARN_MSG="WARNING: Hostname is not set, using Board Serial Number"
echo "${WARN_MSG}"
echo "${WARN_MSG}" | systemd-cat -t gbmc-glome -p warning
exec /usr/sbin/glome-login -M "@BOARDSN_KEY@:${BOARDSN}" "${USER}"
@@ -0,0 +1,29 @@
SUMMARY = "GLOME Login Client"
DESCRIPTION = "GLOME login is first application of the GLOME protocol. It is used to authorize serial console access to Linux machines"
PR = "r1"
PV = "0.1+git${SRCPV}"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57"
inherit meson pkgconfig
DEPENDS += " \
openssl \
glome-config \
"
S = "${WORKDIR}/git"
SRC_URI = "git://github.com/google/glome.git;branch=master;protocol=https"
SRCREV = "978ad9fb165f1e382c875f2ce08a1fc4f2ddcf1b"
PACKAGECONFIG ??= ""
PACKAGECONFIG[glome-cli] = "-Dglome-cli=true,-Dglome-cli=false"
PACKAGECONFIG[pam-glome] = "-Dpam-glome=true,-Dpam-glome=false,libpam"
EXTRA_OEMESON = "-Dtests=false"
# remove the default glome config so it can be overridden by `glome-config`
do_install:append() {
rm -f ${D}${sysconfdir}/glome/config
}
@@ -0,0 +1,14 @@
SUMMARY = "Add dev default CA"
DESCRIPTION = "Add dev default CA"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
SRC_URI += "file://certs/authority/"
FILES:${PN} = "${sysconfdir}/ssl/certs/authority/*"
do_install(){
install -d ${D}${sysconfdir}/ssl/certs/authority
install -m 0644 -D ${WORKDIR}/certs/authority/* \
${D}${sysconfdir}/ssl/certs/authority
}
@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDdDCCAlygAwIBAgIBBjANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJUVzEP
MA0GA1UEChMGUXVhbnRhMQswCQYDVQQLEwJDQTEQMA4GA1UEAxMHT3BlbkJNQzAe
Fw03MDAxMDEwMDAwMDBaFw0zNTEyMzExMjAwMDBaMD0xCzAJBgNVBAYTAlRXMQ8w
DQYDVQQKEwZRdWFudGExCzAJBgNVBAsTAkNBMRAwDgYDVQQDEwdPcGVuQk1DMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3IEc5ydpW3grWW2axOYXMgF/
Wwj8dXtdbpUwgI44RJS/++szEI07OGKXgn4JakWPCSTzMYrq2IteYx7f+hrqqoc3
QZd3tejIGfddGuv8vaAqKlSxaViTjdarRNfa6ARwJao6vQ6XhNy4Phn6mzCSAfGo
m1t+JZ3WxMqlsK+NueU30QqKvnYNFmJ7SbwA0htOn8o9WZj5QBTtXP9Clh6aiWyv
C6nNYlvPfiMLauc3DwcUEcgzI0slWhxSQJVjLmRrR1GT4A8LdVZfgLrUaZR3hlBm
zgtrLJ9BwrdNv4+Q0J/0DEETx4h3SUem5+rZSGaXUvCt+H/VM5sLCRa5+C/oewID
AQABo38wfTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTpEhTEnCIZo7dCDFtq
UjMRcOI9SDAfBgNVHSMEGDAWgBTpEhTEnCIZo7dCDFtqUjMRcOI9SDALBgNVHQ8E
BAMCAb4wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEB
CwUAA4IBAQAT+DvCSEZq+nHmvFP05zFS4IN6DikccDZFyG/O06htFLo3NFYxugGI
OSDXyR3QzhVsDApIwFsNfYzK7asQMqIBdCTHLQNz8YtW4+lwr/WOijgNMK6H0MqI
sisuESpHJgg6XcvfqPkFUBT+sV9ae55QpbvPLalVDZ+JQEyxwfJYnO0AKoepWv/3
H5cXTIpgoxD225MeLOu1F5yg3M3DQd2vPmtykgixMDR+dShxR0AFIwfy94XWTZ7K
JSp5JysdLcekJ5g2c53CYQCqKIYPhKd/VCt/pERjyAcxHnm/PnmTFRA7ft2aAY82
QzkGV2F6gz+GGWjG8cVp3h0T/FF72UFe
-----END CERTIFICATE-----
@@ -0,0 +1,23 @@
SUMMARY = "Add default Users"
DESCRIPTION = "Add Users"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
EXCLUDE_FROM_WORLD = "1"
DEPENDS = "bmcweb"
DEPENDS += "phosphor-ipmi-host"
DEPENDS += "phosphor-user-manager"
RDEPENDS:${PN} = "bmcweb"
RDEPENDS:${PN} += "phosphor-ipmi-host"
RDEPENDS:${PN} += "phosphor-user-manager"
inherit useradd
USERADD_PACKAGES = "${PN}"
USERADD_PARAM:${PN} = "-m -N -u 1000 -g 100 -s /bin/nologin \
-G 'web,redfish,priv-admin' Megapede; "
GROUPMEMS_PARAM:${PN} = "-g priv-admin -a root; "
GROUPMEMS_PARAM:${PN} += "-g ipmi -a root; "
ALLOW_EMPTY:${PN} = "1"
@@ -0,0 +1,26 @@
SUMMARY = "Google BIOS Public Keys"
DESCRIPTION = "Google BIOS Public Keys"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
FILESEXTRAPATHS:prepend:gbmc := "${THISDIR}/${PN}:"
SRC_URI:append:gbmc = " \
file://platforms_secure.pem \
file://platforms_bringup.pem \
"
FILES:${PN} += "${datadir}/google-bios-key/platforms_secure.pem"
FILES:${PN} += "${datadir}/google-bios-key/platforms_bringup.pem"
FILES:${PN} += "${datadir}/platforms_secure.pem"
FILES:${PN} += "${datadir}/platforms_bringup.pem"
do_install() {
install -d ${D}${datadir}/google-bios-key
install -m 0644 ${WORKDIR}/platforms_secure.pem ${D}${datadir}/google-bios-key
install -m 0644 ${WORKDIR}/platforms_bringup.pem ${D}${datadir}/google-bios-key
ln -s -r ${D}${datadir}/google-bios-key/platforms_secure.pem ${D}${datadir}/platforms_secure.pem
ln -s -r ${D}${datadir}/google-bios-key/platforms_bringup.pem ${D}${datadir}/platforms_bringup.pem
}
@@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq1licj5L+p5orm2eQsjW
7z1L5As2q0ZbyFtE/xeH/8NAbKfTA1LSKiqElcPTM47oFDixGtCm7bubcClWT8Uq
Ol6t4CITlgRLFPP06z63mnE83EKj1ZBTATgtO+PN1P/RrQXp0pCPy0AFYtWZPT4J
GzxACBwVI/XEuUnCOG4ErXLfgfPZadOMUmP9X5pXeyBgN/al0vThIVpQ7DUix6jd
awYd2AwM1TG9qRX1Fmlsut9zUGDoqEOCAdIgx5z9GOTfwzbIg1NWk12iLQyufJ4P
FAa4a5QVZYTKcDUNYadx7Qwg/gNspiAIdtB/1ORz1ew1d1csCHqUZcgkCwtaqMYg
ZiQ6+7tpJY0vnWyaNXcylOvmZjOlovV3i5NUJ/r74bDC8U+5XKH3ZSmhA6AsnA54
QnNHLgsnG89JvfBP2c9UJqb49sw6VkEE3Y8lc134QBaLU3N3LmRVmM4zzPRGbbEK
+nmZtBztbKiSHTqMoYGCY5aN1peQdzgNYk5P8mnVWzAIh5y1MzxkEVeu82/zCj+/
T54D3jS+a/jxAGnUUmTMYsOYXNqJsPKz36qvrFLstSjrjHVEZjniaetjAuWtVGsO
DziPDyywN14iIeR5HdNpqeJ6mCZnY2rLtBzIZRK/JK0LpCvqdEmqg2u/J2Vx2ClE
DnNnPSr8XSpsFkaxGYyFjEUCAwEAAQ==
-----END PUBLIC KEY-----
@@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzCYi0R3IiNenOlVNlpOC
mIZ/0nq6OGS5Dt1Yex5nr7/bIr+Phk7mct+V7gMJzfdyCOI3n2S2sGDWADUNfvDJ
LQgV4xOfoUwhzQ292cp2UFUrPblfZaz0C5x7BRVtj7yfBp8FRFVSpZTNI6QjEQ6m
JxVh5C8CYjdQQJLz+wayVZTk72z0iaSBdua+eZYrAc3+ckTvTWJ9V7yO40iyJOXQ
ixxHo/p49oHoNp4+q0a6DYYmjka6MESeFbbkND5PkyNV4+vAbgtzkoGnnutk+zQ3
K374d9+aOqXlbLBXAUaNkfnF1XjUYQFLrNkFbvOqYura1mBxWuz/OIAfbWxQltzo
6cYl0YNw7zbHzSwiTPvt31wxg9EqqIV7QD4hXLAgoclJIK5vhUqIbn3kjSwOv2Rv
MQ17wLeCkYaxL4Ovscx6lDnOw+Y76KGia5zky0GvidjaDgzUZTt46/uOtjxxXy5k
KhDwqs1QoU0LKBvJL8O7bYj6t0LLQTsI2UW9szVGGsiKB3l0SfIzfvz6eNNng7Uf
T9zLPW9jq0BGG61KiYK+Dy/0JwauPub3WzcZwSXnl1OCMLD90HIA2/YsFtfE+mm/
Wlta+cR3REHd//DiRlkT59K0H5H8JBrJKhkAVi/gzqoAYhLAOj9irWzsZ2Assm74
oa3/lWlmVsKQTAGOCQFeAHsCAwEAAQ==
-----END PUBLIC KEY-----
@@ -0,0 +1,14 @@
HOMEPAGE = "http://github.com/openbmc/google-misc"
PR = "r1"
PV = "1.0+git${SRCPV}"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://../../LICENSE;md5=34400b68072d710fecd0a2940a0d1658"
SRC_URI += "git://github.com/openbmc/google-misc;branch=master;protocol=https"
SRCREV = "f8bb4779279d8f4e054d9601fc508598b2ba3007"
S = "${WORKDIR}/git/subprojects/${GOOGLE_MISC_PROJ}"
inherit meson pkgconfig
EXTRA_OEMESON += "-Dwerror=false"
@@ -0,0 +1,249 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This is intended to be used as a library for managing gpio line values.
# Executing this directly will do nothing.
[ -n "${gpio_ctrl_init-}" ] && return
# Map names of GPIOs to GPIO number
# This maps a schematic name to a gpiochip and line at a specific offset
declare -A GPIO_NAMES_TO_SCM=(
# Examples
#['SYS_RESET_N']='label=/pinctrl@f0800000/gpio@f0012000 21'
#['PWRBTN_N']='label=/pinctrl@f0800000/gpio@f0012000 23'
#['PCH_SLP_S5_R_N']='of_node=/ahb/apb/i2c@8e000/cpu_seq@6b 9'
#['PCH_PWRGOOD_R']='of_node=/ahb/apb/i2c@8e000/cpu_seq@6b 6'
)
# Load configurations from a known location in the filesystem to populate
# named GPIOs
shopt -s nullglob
for conf in /usr/share/gpio-ctrl/conf.d/*.sh; do
# shellcheck source=/dev/null
source "$conf"
done
declare -A gpio_sysfs_lookup_cache=()
declare -A gpio_lookup_cache=()
declare -A gpio_init=()
##################################################
# Looks up the sysfs GPIO number
# Arguments:
# $1: GPIO name
# Return:
# 0 if success, non-zero if error
# stdout: The GPIO number
##################################################
gpio_name_to_num() {
local name="$1"
if [ -n "${gpio_lookup_cache["$name"]+1}" ]; then
echo "${gpio_lookup_cache["$name"]}"
return 0
fi
local scm="${GPIO_NAMES_TO_SCM["$name"]-}"
if [ -z "$scm" ]; then
echo "Missing gpio definition: $name" >&2
return 1
fi
local id="${scm% *}"
local type="${id%=*}"
local val="${id#*=}"
local offset="${scm#* }"
local sysfs
if [ -n "${gpio_sysfs_lookup_cache["$id"]+1}" ]; then
sysfs="${gpio_sysfs_lookup_cache["$id"]}"
else
case "$type" in
label)
if ! sysfs="$(grep -xl "$val" /sys/class/gpio/gpiochip*/label)"; then
echo "Failed to find gpiochip: $val" >&2
return 1
fi
sysfs="${sysfs%/label}"
;;
of_node)
for sysfs in $(echo /sys/class/gpio/gpiochip*); do
local link
# Ignore errors because not all devices have of_nodes
link="$(readlink -f "$sysfs/device/of_node" 2>/dev/null)" || continue
[ "${link#/sys/firmware/devicetree/base}" = "$val" ] && break
sysfs=
done
if [ -z "$sysfs" ]; then
echo "Failed to find gpiochip: $val" >&2
return 1
fi
;;
*)
echo "Invalid GPIO type $type" >&2
return 1
;;
esac
gpio_sysfs_lookup_cache["$id"]="$sysfs"
fi
local ngpio
ngpio=$(<"$sysfs"/ngpio)
if (( ngpio <= offset )); then
echo "$name with gpiochip $sysfs only has $ngpio but wants $offset" >&2
return 1
fi
gpio_lookup_cache["$name"]=$(( $(<"$sysfs"/base) + offset ))
echo "${gpio_lookup_cache["$name"]}"
}
##################################################
# Populates the GPIO lookup cache
# Most calls to gpio_name_to_num that would
# normally cache the sysfs lookups for gpios run
# inside subshells. This prevents them from
# populating a global cache and greatly speeding
# up future lookups. This call allows scripts to
# populate the cache prior to looking up gpios.
##################################################
gpio_build_cache() {
local timeout="${1-0}"
shift
local gpios=("$@")
if (( ${#gpios[@]} == 0 )); then
gpios=("${!GPIO_NAMES_TO_SCM[@]}")
fi
local deadline=$(( timeout + SECONDS ))
local name
for name in "${gpios[@]}"; do
while true; do
gpio_name_to_num "$name" >/dev/null && break
if (( deadline <= SECONDS )); then
echo "Timed out building gpio cache" >&2
return 1
fi
done
done
}
##################################################
# Initializes the gpio state
# This operation is idempotent and can be applied
# repeatedly to the same gpio. It will make sure the
# gpio ends up in the initialized state even if it
# was.
# Arguments:
# $1: GPIO name
# Return:
# 0 if success, non-zero if error
##################################################
gpio_init_() {
local name="$1"
local num="$2"
if [ -n "${gpio_init["$name"]+1}" ]; then
return 0
fi
if [ ! -e "/sys/class/gpio/gpio$num" ]; then
if ! echo "$num" >'/sys/class/gpio/export'; then
echo "Failed to export $name gpio$num" >&2
return 1
fi
fi
local active_low=0
if [[ "${name%_N}" != "$name" ]]; then
active_low=1
fi
if ! echo "$active_low" >"/sys/class/gpio/gpio$num/active_low"; then
echo "Failed to set active_low for $name gpio$num" >&2
return 1
fi
gpio_init["$name"]=1
}
gpio_init() {
local name="$1"
# Ensure the cache is updated by not running in a subshell
gpio_name_to_num "$name" >/dev/null || return
gpio_init_ "$name" "$(gpio_name_to_num "$name")"
}
##################################################
# Sets the output GPIO value.
# Arguments:
# $1: GPIO name
# $2: GPIO value, "1" or "0"
# Return:
# 0 if success, non-zero if error
##################################################
gpio_set_value_() {
local name="$1"
local num="$2"
local val="$3"
gpio_init_ "$name" "$num" || return
if ! echo out >"/sys/class/gpio/gpio$num/direction"; then
echo "Failed to set output for $name gpio$num" >&2
return 1
fi
if ! echo "$val" >"/sys/class/gpio/gpio$num/value"; then
echo "Failed to set $name gpio$num = $val" >&2
return 1
fi
}
gpio_set_value() {
local name="$1"
local val="$2"
# Ensure the cache is updated by not running in a subshell
gpio_name_to_num "$name" >/dev/null || return
gpio_set_value_ "$name" "$(gpio_name_to_num "$name")" "$val"
}
##################################################
# Get GPIO value
# Arguments:
# $1: GPIO name
# Return:
# 0 if success, non-zero if error
# stdout: The value of the gpio
##################################################
gpio_get_value_() {
local name="$1"
local num="$2"
gpio_init_ "$name" "$num" || return
if ! cat "/sys/class/gpio/gpio$num/value"; then
echo "Failed to get $name gpio$num value" >&2
return 1
fi
}
gpio_get_value() {
local name="$1"
# Ensure the cache is updated by not running in a subshell
gpio_name_to_num "$name" >/dev/null || return
gpio_get_value_ "$name" "$(gpio_name_to_num "$name")"
}
gpio_ctrl_init=1
@@ -0,0 +1,14 @@
SUMMARY = "GPIO control library for bash scripts"
DESCRIPTION = "GPIO control library for bash scripts."
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
PR = "r1"
SRC_URI += "file://lib.sh"
RDEPENDS:${PN} = "bash"
do_install() {
install -d ${D}${datadir}/gpio-ctrl
install -m 0755 ${WORKDIR}/lib.sh ${D}${datadir}/gpio-ctrl/
}
@@ -0,0 +1,11 @@
[Unit]
Description=Ensure host is off on clean AC cycle
Before=host-poweron.service
Before=firmware-updates-pre.target
[Service]
Type=oneshot
ExecStart=/usr/bin/host_ensure_off.sh
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,7 @@
[Unit]
Description=Powercycle host
[Service]
Type=oneshot
Environment=DONT_STOP_WATCHDOG=1
ExecStart=/usr/bin/host_powercycle.sh
@@ -0,0 +1,6 @@
[Unit]
Description=Powercycle host
[Service]
Type=oneshot
ExecStart=/usr/bin/host_powercycle.sh
@@ -0,0 +1,7 @@
[Unit]
Description=Power off host
[Service]
Type=oneshot
Environment=DONT_STOP_WATCHDOG=1
ExecStart=/usr/bin/host_poweroff.sh
@@ -0,0 +1,6 @@
[Unit]
Description=Power off host
[Service]
Type=oneshot
ExecStart=/usr/bin/host_poweroff.sh
@@ -0,0 +1,10 @@
[Unit]
Description=Power on host
After=firmware-updates.target
[Service]
Type=oneshot
ExecStart=/usr/bin/host_poweron.sh
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,7 @@
[Unit]
Description=Cold Reset Host
[Service]
Type=oneshot
Environment=DONT_STOP_WATCHDOG=1
ExecStart=/usr/bin/host_reset.sh cold
@@ -0,0 +1,6 @@
[Unit]
Description=Cold Reset Host
[Service]
Type=oneshot
ExecStart=/usr/bin/host_reset.sh cold
@@ -0,0 +1,7 @@
[Unit]
Description=Warm Reset Host
[Service]
Type=oneshot
Environment=DONT_STOP_WATCHDOG=1
ExecStart=/usr/bin/host_reset.sh warm
@@ -0,0 +1,6 @@
[Unit]
Description=Warm Reset Host
[Service]
Type=oneshot
ExecStart=/usr/bin/host_reset.sh warm
@@ -0,0 +1,22 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if ! was_ac_reset.sh; then
echo "Not a tray reset, ignoring" >&2
exit 0
fi
echo "Powering off the host" >&2
host_poweroff.sh
@@ -0,0 +1,22 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# shellcheck source=meta-google/recipes-google/gpio/gpio-ctrl/lib.sh
source /usr/share/gpio-host-pwr/lib.sh || exit
gpio_build_cache 10 "$HOST_GPIO_PGOOD" || exit 255
pgood="$(gpio_get_value "$HOST_GPIO_PGOOD")" || exit 255
echo "HOST_PGOOD=$pgood" >&2
(( pgood == 0 ))
@@ -0,0 +1,25 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# shellcheck source=meta-google/recipes-google/gpio/gpio-ctrl/lib.sh
source /usr/share/gpio-host-pwr/lib.sh || exit
gpio_build_cache 10 "$HOST_GPIO_PGOOD" "$HOST_GPIO_PWR_BTN" || exit
rc=0
host_poweroff.sh || rc=$?
# We want to ensure we aren't too quickly bouncing the power button
sleep 0.5
host_poweron.sh || rc=$?
exit $rc
@@ -0,0 +1,66 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# shellcheck source=meta-google/recipes-google/gpio/gpio-ctrl/lib.sh
source /usr/share/gpio-host-pwr/lib.sh || exit
gpio_build_cache 10 "$HOST_GPIO_PGOOD" "$HOST_GPIO_PWR_BTN" || exit
gpio_init "$HOST_GPIO_PGOOD" || exit
# Set the power status LED
if [ -n "$HOST_LED_PWR" ]; then
echo 'none' > /sys/class/leds/"$HOST_LED_PWR"/trigger || true
echo '0' > /sys/class/leds/"$HOST_LED_PWR"/brightness || true
fi
# Ensure the watchdog is no longer going to run
host_pwr_stop_watchdog || true
# We don't want to do anything if the machine is already off
pgood="$(gpio_get_value "$HOST_GPIO_PGOOD")" || exit
if (( pgood == 0 )); then
echo 'Host is already off, doing nothing' >&2
exit 0
fi
# Do a long push of the button if PGOOD
echo 'Stopping host power' >&2
rc=0
gpio_set_value "$HOST_GPIO_PWR_BTN" 1 || rc=$?
# Loop until we realize that host power is off
# Limit the loop count to 10 seconds as we should never
# have to wait this long for poweroff
s=$SECONDS
while true; do
if ! pgood="$(gpio_get_value "$HOST_GPIO_PGOOD")"; then
rc=1
break
fi
if (( pgood == 0 )); then
echo 'Host is now off' >&2
break
fi
if (( SECONDS - s > 10 )); then
echo 'Poweroff timed out, terminating' >&2
rc=2
break
fi
sleep 0.1
done
gpio_set_value "$HOST_GPIO_PWR_BTN" 0 || rc=$?
exit $rc
@@ -0,0 +1,66 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# shellcheck source=meta-google/recipes-google/gpio/gpio-ctrl/lib.sh
source /usr/share/gpio-host-pwr/lib.sh || exit
gpio_build_cache 10 "$HOST_GPIO_PGOOD" "$HOST_GPIO_PWR_BTN" || exit
gpio_init "$HOST_GPIO_PGOOD" || exit
# Set the power status LED
if [ -n "$HOST_LED_PWR" ]; then
echo 'none' > /sys/class/leds/"$HOST_LED_PWR"/trigger || true
echo '255' > /sys/class/leds/"$HOST_LED_PWR"/brightness || true
fi
# Ensure the watchdog is available before the host starts
host_pwr_start_watchdog || true
# We don't want to do anything if the machine is already on
pgood="$(gpio_get_value "$HOST_GPIO_PGOOD")" || exit
if (( pgood == 1 )); then
echo 'Host is already running, doing nothing' >&2
exit 0
fi
# Do a quick push of the button if PGOOD
echo "Starting host power" >&2
rc=0
gpio_set_value "$HOST_GPIO_PWR_BTN" 1 || rc=$?
sleep 0.1
gpio_set_value "$HOST_GPIO_PWR_BTN" 0 || rc=$?
# Loop until we realize that host power is on
# Limit the loop count to 10 seconds as we should never
# have to wait this long for poweroff
s=$SECONDS
while true; do
if ! pgood="$(gpio_get_value "$HOST_GPIO_PGOOD")"; then
rc=1
break
fi
if (( pgood == 1 )); then
echo 'Host is now on' >&2
break
fi
if (( SECONDS - s > 10 )); then
echo 'Poweron timed out, terminating' >&2
rc=2
break
fi
sleep 0.1
done
exit $rc
@@ -0,0 +1,40 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# shellcheck source=meta-google/recipes-google/gpio/gpio-ctrl/lib.sh
source /usr/share/gpio-host-pwr/lib.sh || exit
if [[ "${1-}" == "warm" ]]; then
rst_txt='WARM' >&2
rst_gpio="$HOST_GPIO_WARM_RESET"
else
rst_txt='COLD' >&2
rst_gpio="$HOST_GPIO_COLD_RESET"
fi
gpio_build_cache 10 "$rst_gpio" || exit
# Do a quick push of the button if PGOOD
echo "Issuing $rst_txt reset" >&2
rc=0
gpio_set_value "$rst_gpio" 1 || rc=$?
sleep 0.1
gpio_set_value "$rst_gpio" 0 || rc=$?
# Make sure the watchdog is stopped while the host is in reset
# and can't possibly restart it.
host_pwr_stop_watchdog || true
exit $rc
@@ -0,0 +1,73 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This is intended to be used as a library for managing gpio line values.
# Executing this directly will do nothing.
[ -n "${host_pwr_init-}" ] && return
# shellcheck source=meta-google/recipes-google/gpio/gpio-ctrl/lib.sh
source /usr/share/gpio-ctrl/lib.sh || exit
# Read by the tooling to determine if the machine is powered on or off
# shellcheck disable=SC2034
HOST_GPIO_PGOOD='unset'
# Set according to whether the host is powered on or off
# shellcheck disable=SC2034
HOST_LED_PWR=''
# Written by the tooling to assert the power button
# shellcheck disable=SC2034
HOST_GPIO_PWR_BTN='unset'
# Written by the tooling to assert a cold reset
# shellcheck disable=SC2034
HOST_GPIO_COLD_RESET='unset'
# Written by the tooling to assert a warm reset
# shellcheck disable=SC2034
HOST_GPIO_WARM_RESET='unset'
# Load configurations from a known location in the filesystem to populate
# named GPIOs
shopt -s nullglob
for conf in /usr/share/gpio-host-pwr/conf.d/*.sh; do
# shellcheck source=/dev/null
source "$conf"
done
##################################################
# Stop the host watchdog
# Return:
# 0 if success, non-zero if error
##################################################
host_pwr_stop_watchdog() {
# Check to see if we can stop the watchdog safely
# We don't want to stop if we are called from the watchdog itself
if [ -n "${DONT_STOP_WATCHDOG-}" ]; then
return 0
fi
echo 'Stopping the host watchdog' >&2
systemctl stop phosphor-watchdog@host0
}
##################################################
# Start the host watchdog
# Return:
# 0 if success, non-zero if error
##################################################
host_pwr_start_watchdog() {
echo 'Starting the host watchdog' >&2
systemctl start phosphor-watchdog@host0
}
host_pwr_init=1
@@ -0,0 +1,57 @@
SUMMARY = "GPIO based powercontrol for a host system"
DESCRIPTION = "GPIO based powercontrol for a host system."
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit systemd
RDEPENDS:${PN} += " \
bash \
gpio-ctrl \
"
SRC_URI += " \
file://host-ensure-off.service \
file://host-powercycle-watchdog.service \
file://host-powercycle.service \
file://host-poweroff-watchdog.service \
file://host-poweroff.service \
file://host-poweron.service \
file://host-reset-cold-watchdog.service \
file://host-reset-cold.service \
file://host-reset-warm-watchdog.service \
file://host-reset-warm.service \
file://host_ensure_off.sh \
file://host_isoff.sh \
file://host_powercycle.sh \
file://host_poweroff.sh \
file://host_poweron.sh \
file://host_reset.sh \
file://lib.sh \
"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} += " \
host-reset-cold.service \
host-reset-cold-watchdog.service \
host-reset-warm.service \
host-reset-warm-watchdog.service \
host-ensure-off.service \
host-powercycle.service \
host-powercycle-watchdog.service \
host-poweroff.service \
host-poweroff-watchdog.service \
host-poweron.service \
"
do_install() {
install -d ${D}${bindir}
install -m 0755 ${WORKDIR}/host_*.sh ${D}${bindir}/
install -d ${D}${datadir}/gpio-host-pwr
install -m 0755 ${WORKDIR}/lib.sh ${D}${datadir}/gpio-host-pwr/
install -d ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/*.service ${D}${systemd_system_unitdir}/
}
@@ -0,0 +1,33 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##################################################
# Stop the host watchdog
# Return:
# 0 if success, non-zero if error
##################################################
stop_host_watchdog() {
if (( $# != 0 )); then
echo 'Usage: stop_host_watchdog' >&2
return 1
fi
local srv='xyz.openbmc_project.Watchdog'
local obj='/xyz/openbmc_project/watchdog/host0'
local intf='xyz.openbmc_project.State.Watchdog'
local method='Enabled'
local args=('b' 'false')
busctl set-property "${srv}" "${obj}" "${intf}" "${method}" "${args[@]}"
}
@@ -0,0 +1,16 @@
SUMMARY = "Watchdog Shell Library"
DESCRIPTION = "Watchdog Shell Library"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
SRC_URI += " \
file://libwatchdog.sh \
"
RDEPENDS:${PN} = "bash"
do_install() {
install -d ${D}${libexecdir}
install -m 0755 ${WORKDIR}/libwatchdog.sh ${D}${libexecdir}/
}
@@ -0,0 +1,21 @@
SUMMARY = "Google i2c OEM commands"
DESCRIPTION = "Google i2c OEM commands"
HOMEPAGE = "https://github.com/openbmc/google-ipmi-i2c"
PR = "r1"
PV = "0.1+git${SRCPV}"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
inherit meson pkgconfig
DEPENDS += "phosphor-ipmi-host"
S = "${WORKDIR}/git"
SRC_URI = "git://github.com/openbmc/google-ipmi-i2c;branch=master;protocol=https"
SRCREV = "6c84db51ea55f247e1f8054b62fff3b66b8017b7"
FILES:${PN}:append = " ${libdir}/ipmid-providers"
FILES:${PN}:append = " ${libdir}/host-ipmid"
FILES:${PN}:append = " ${libdir}/net-ipmid"
HOSTIPMI_PROVIDER_LIBRARY += "libi2ccmds.so"
@@ -0,0 +1,38 @@
SUMMARY = "Google Sys OEM commands"
DESCRIPTION = "Google Sys OEM commands"
HOMEPAGE = "https://github.com/openbmc/google-ipmi-sys"
PR = "r1"
PV = "0.1+git${SRCPV}"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
inherit meson pkgconfig systemd
DEPENDS += " \
nlohmann-json \
phosphor-dbus-interfaces \
phosphor-logging \
phosphor-ipmi-host \
sdbusplus \
systemd \
"
S = "${WORKDIR}/git"
SRC_URI = "git://github.com/openbmc/google-ipmi-sys;branch=master;protocol=https"
SRCREV = "15d4d21c091cd57a0e25888a8d360ba3a32965ff"
FILES:${PN} += "${libdir}/ipmid-providers"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} += " \
gbmc-bare-metal-active.target \
gbmc-host-poweroff.target \
gbmc-psu-hardreset.target \
gbmc-psu-hardreset-pre.target \
gbmc-psu-hardreset-time.service \
"
EXTRA_OEMESON += "-Dtests=disabled"
CXXFLAGS:append:gbmc = '${@"" if not d.getVar("GBMC_NCSI_IF_NAME") else \
" -DNCSI_IPMI_CHANNEL=1 -DNCSI_IF_NAME=" + d.getVar("GBMC_NCSI_IF_NAME")}'
@@ -0,0 +1,16 @@
SUMMARY = "Shell functions for manipulating IPMI formatted EEPROMs"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://lib.sh"
S = "${WORKDIR}"
DATA = "${datadir}/ipmi-fru"
FILES:${PN} += "${DATA}"
do_install:append() {
install -d -m0755 ${D}${DATA}
install -m0644 lib.sh ${D}${DATA}/
}
@@ -0,0 +1,247 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[ -n "${ipmi_fru_init-}" ] && return
# shellcheck disable=SC2034
IPMI_FRU_COMMON_HEADER_INTERNAL_OFFSET_IDX=1
# shellcheck disable=SC2034
IPMI_FRU_COMMON_HEADER_CHASSIS_OFFSET_IDX=2
# shellcheck disable=SC2034
IPMI_FRU_COMMON_HEADER_BOARD_OFFSET_IDX=3
# shellcheck disable=SC2034
IPMI_FRU_COMMON_HEADER_PRODUCT_OFFSET_IDX=4
# shellcheck disable=SC2034
IPMI_FRU_COMMON_HEADER_MULTI_RECORD_OFFSET_IDX=5
# shellcheck disable=SC2034
IPMI_FRU_AREA_HEADER_SIZE_IDX=1
# shellcheck disable=SC2034
IPMI_FRU_CHECKSUM_IDX=-1
offset_1bw() {
local addr="$1"
local off="$2"
local extra="${3-0}"
echo "w$((1+extra))@$addr $(( off & 0xff ))"
}
offset_2bw() {
local addr="$1"
local off="$2"
local extra="${3-0}"
echo "w$((2+extra))@$addr $(( (off >> 8) & 0xff )) $(( off & 0xff ))"
}
of_name_to_eeproms() {
local names
if ! names="$(grep -xl "$1" /sys/bus/i2c/devices/*/of_node/name)"; then
echo "Failed to find eeproms with of_name '$1'" >&2
return 1
fi
echo "${names//of_node\/name/eeprom}"
}
of_name_to_eeprom() {
local eeproms
eeproms="$(of_name_to_eeproms "$1")" || return
if (( "$(echo "$eeproms" | wc -l)" != 1 )); then
echo "Got more than one eeprom for '$1': $eeproms" >&2
return 1
fi
echo "$eeproms"
}
# Each element is a `filename`
declare -A IPMI_FRU_EEPROM_FILE=()
# Each element is a `bus` + `addr` + `offset_bytes_func`
declare -A IPMI_FRU_EEPROM_BUSADDR=()
ipmi_fru_device_alloc() {
local fdn="$1"
local idx="$2"
local json
json="$(busctl -j call xyz.openbmc_project.FruDevice \
/xyz/openbmc_project/FruDevice/"$fdn" org.freedesktop.DBus.Properties \
GetAll s xyz.openbmc_project.FruDevice)" || return 80
local jqq='.data[0] | (.BUS.data | tostring) + " " + (.ADDRESS.data | tostring)'
local busaddr
# shellcheck disable=SC2207
busaddr=($(echo "$json" | jq -r "$jqq")) || return
# FRU 0 is hardcoded and FruDevice does not report the correct bus for it
# Hardcode a workaround for this specifically known bus
if (( busaddr[0] == 0 && busaddr[1] == 0 )); then
IPMI_FRU_EEPROM_FILE["$idx"]=/etc/fru/baseboard.fru.bin
else
local offset_bw=offset_2bw
local last=0
local rsp=0x100
local start=$SECONDS
# Query the FRU multiple times to ensure the return value is stabilized
while (( last != rsp )); do
# It shouldn't take > 0.1s to stabilize, limit instability
if (( SECONDS - start >= 10 )); then
echo "Timed out determining offset for ${busaddr[0]}@${busaddr[1]}" >&2
return 1
fi
last=$rsp
# shellcheck disable=SC2046
rsp=$(i2ctransfer -f -y "${busaddr[0]}" $(offset_1bw "${busaddr[1]}" 0) r1) || return
done
# FRUs never start with 0xff bytes, so we can figure out addressing mode
if (( rsp != 0xff )); then
offset_bw=offset_1bw
fi
IPMI_FRU_EEPROM_BUSADDR["$idx"]="${busaddr[*]} $offset_bw"
fi
}
ipmi_fru_alloc() {
local name="$1"
local -n ret="$2"
# Pick the first free index to return as the allocated entry
for (( ret = 0; ret < "${#IPMI_FRU_EEPROM_FILE[@]}"; ++ret )); do
[ -n "${IPMI_FRU_EEPROM_FILE[*]+1}" ] || \
[ -n "${IPMI_FRU_EEPROM_BUSADDR[*]+1}" ]|| break
done
if [[ "$name" =~ ^of-name:(.*)$ || "$name" =~ ^([^:]*)$ ]]; then
local ofn="${BASH_REMATCH[1]}"
local file
file="$(of_name_to_eeprom "$ofn")" || return
IPMI_FRU_EEPROM_FILE["$ret"]="$file"
elif [[ "$name" =~ ^frudev-name:(.*)$ ]]; then
local fdn="${BASH_REMATCH[1]}"
local start=$SECONDS
local file
while (( SECONDS - start < 300 )); do
local rc=0
ipmi_fru_device_alloc "$fdn" "$ret" || rc=$?
(( rc == 0 )) && break
# Immediately return any errors, 80 is special to signify retry
(( rc != 80 )) && return $rc
sleep 1
done
else
echo "Invalid IPMI FRU eeprom specification: $name" >&2
return 1
fi
}
ipmi_fru_free() {
unset 'IPMI_FRU_EEPROM_FILE[$1]'
unset 'IPMI_FRU_EEPROM_BUSADDR[$1]'
}
checksum() {
local -n checksum_arr="$1"
local checksum=0
for byte in "${checksum_arr[@]}"; do
checksum=$((checksum + byte))
done
echo $((checksum & 0xff))
}
fix_checksum() {
local -n fix_checksum_arr="$1"
old_cksum=${fix_checksum_arr[$IPMI_FRU_CHECKSUM_IDX]}
((fix_checksum_arr[IPMI_FRU_CHECKSUM_IDX]-=$(checksum fix_checksum_arr)))
((fix_checksum_arr[IPMI_FRU_CHECKSUM_IDX]&=0xff))
printf 'Corrected %s checksum from 0x%02X -> 0x%02X\n' \
"$1" "${old_cksum}" "${fix_checksum_arr[$IPMI_FRU_CHECKSUM_IDX]}" >&2
}
read_bytes() {
# shellcheck disable=SC2206
local busaddr=(${IPMI_FRU_EEPROM_BUSADDR["$1"]-})
local file="${IPMI_FRU_EEPROM_FILE["$1"]-$1}"
local offset="$2"
local size="$3"
if (( "${#busaddr[@]}" > 0)); then
echo "Reading ${busaddr[*]} at $offset for $size" >&2
# shellcheck disable=SC2046
i2ctransfer -f -y "${busaddr[0]}" $("${busaddr[2]}" "${busaddr[1]}" "$offset") "r$size"
else
echo "Reading $file at $offset for $size" >&2
dd if="$file" bs=1 count="$size" skip="$offset" 2>/dev/null | \
hexdump -v -e '1/1 "%d "'
fi
}
write_bytes() {
# shellcheck disable=SC2206
local busaddr=(${IPMI_FRU_EEPROM_BUSADDR["$1"]-})
local file="${IPMI_FRU_EEPROM_FILE["$1"]-$1}"
local offset="$2"
local -n bytes_arr="$3"
if (( "${#busaddr[@]}" > 0)); then
echo "Writing ${busaddr[*]} at $offset for ${#bytes_arr[@]}" >&2
# shellcheck disable=SC2046
i2ctransfer -f -y "${busaddr[0]}" $("${busaddr[2]}" "${busaddr[1]}" "$offset" "${#bytes_arr[@]}") "${bytes_arr[@]}"
else
local hexstr
hexstr="$(printf '\\x%x' "${bytes_arr[@]}")" || return
echo "Writing $file at $offset for ${#bytes_arr[@]}" >&2
# shellcheck disable=SC2059
printf "$hexstr" | dd of="$file" bs=1 seek="$offset" 2>/dev/null
fi
}
read_header() {
local eeprom="$1"
local -n header_arr="$2"
# shellcheck disable=SC2207
header_arr=($(read_bytes "$eeprom" 0 8)) || return
echo "Checking $eeprom FRU Header version" >&2
# FRU header is always version 1
(( header_arr[0] == 1 )) || return
echo "Checking $eeprom FRU Header checksum" >&2
local sum
sum="$(checksum header_arr)" || return
# Checksums should be valid
(( sum == 0 )) || return 10
}
read_area() {
local eeprom="$1"
local offset="$2"
local -n area_arr="$3"
local area_size="${4-0}"
offset=$((offset*8))
# shellcheck disable=SC2207
area_arr=($(read_bytes "$eeprom" "$offset" 8)) || return
echo "Checking $eeprom $offset FRU Area version" >&2
# FRU Area is always version 1
(( area_arr[0] == 1 )) || return
if (( area_size == 0 )); then
area_size=${area_arr[$IPMI_FRU_AREA_HEADER_SIZE_IDX]}
fi
# shellcheck disable=SC2207
area_arr=($(read_bytes "$eeprom" "$offset" $((area_size*8)))) || return
echo "Checking $eeprom $offset FRU Area checksum" >&2
local sum
sum="$(checksum area_arr)" || return
# Checksums should be valid
(( sum == 0 )) || return 10
}
ipmi_fru_init=1
@@ -0,0 +1,18 @@
SUMMARY = "gBMC Health Metrics Blob"
DESCRIPTION = "BMC health metrics IPMI blob handler."
GOOGLE_MISC_PROJ = "metrics-ipmi-blobs"
require ../google-misc/google-misc.inc
inherit pkgconfig
DEPENDS += " \
phosphor-ipmi-blobs \
phosphor-logging \
protobuf-native \
protobuf \
"
FILES:${PN} += "${libdir}/blob-ipmid"
EXTRA_OEMESON += "-Dtests=disabled"
@@ -0,0 +1,16 @@
SUMMARY = "Google libcr51sign"
DESCRIPTION = "Google libcr51sign"
GOOGLE_MISC_PROJ = "libcr51sign"
require ../google-misc/google-misc.inc
inherit pkgconfig
# We need to suppress these warnings in OpenSSL 3.0+ until a fix is available
CFLAGS += " \
-Wno-deprecated-declarations \
"
DEPENDS += " \
openssl \
"
@@ -0,0 +1,24 @@
SUMMARY = "Nanopb library"
DESCRIPTION = "Nanopb - Protocol Buffers for Embedded Systems"
HOMEPAGE = "https://github.com/nanopb/nanopb"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=9db4b73a55a3994384112efcdb37c01f"
inherit cmake python3native
SRC_URI = "git://github.com/nanopb/nanopb;branch=master;protocol=https"
SRCREV = "f7e4140a27d9e63517b5d596bc117bd6d5248888"
S = "${WORKDIR}/git"
DEPENDS = "protobuf-native python3-protobuf"
RDEPENDS:${PN}-generator += "python3 python3-protobuf"
PACKAGES:prepend = "${PN}-generator ${PN}-runtime "
FILES:${PN}-generator = "${libdir}/python* ${bindir}"
FILES:${PN}-runtime = "${libdir}/*.so.*"
BBCLASSEXTEND = "native"
@@ -0,0 +1,5 @@
[NetDev]
Name=gbmcbrncsidhcp
Kind=veth
[Peer]
Name=gbmcncsidhcp
@@ -0,0 +1,4 @@
[Match]
Name=gbmcbrncsidhcp
[Network]
Bridge=gbmcbr
@@ -0,0 +1,5 @@
[NetDev]
Name=gbmcncsidhcp
Kind=veth
[Peer]
Name=gbmcbrncsidhcp
@@ -0,0 +1,10 @@
[Match]
Name=gbmcncsidhcp
[Network]
DHCP=false
IPv6AcceptRA=false
LLMNR=false
MulticastDNS=false
LinkLocalAddressing=ipv6
# TODO: Change address back to fdb5:0481:10ce::1/64
Address=fdb5:0481:10ce::2/64
@@ -0,0 +1,33 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[ -n "${gbmc_ncsi_clear_ip-}" ] && return
source /usr/libexec/ncsid_lib.sh || exit
gbmc_ncsi_clear_ip_hook() {
local ip="${1-}"
# We only want to clear our IPs if we are assigning a new IP
[ -z "$ip" ] && return
echo "Removing Persistent NCSI IPs" >&2
SetStatic xyz.openbmc_project.Network '@NCSI_IF@' 2>/dev/null || true
UpdateIP xyz.openbmc_project.Network '@NCSI_IF@' '0.0.0.0' '0' 2>/dev/null || true
UpdateIP xyz.openbmc_project.Network '@NCSI_IF@' '::' '0' 2>/dev/null || true
}
GBMC_BR_LIB_SET_IP_HOOKS+=(gbmc_ncsi_clear_ip_hook)
gbmc_ncsi_clear_ip=1
@@ -0,0 +1,45 @@
table inet filter {
chain ncsi_input {
type filter hook input priority 0; policy drop;
iifname != @NCSI_IF@ accept
ct state established accept
ip6 daddr ff00::/8 goto ncsi_brd_input
ip6 daddr fe80::/64 goto ncsi_legacy_input
}
chain ncsi_gbmc_br_pub_input {
jump gbmc_br_pub_input
jump ncsi_legacy_input
reject
}
chain gbmc_br_pub_input {
ip6 nexthdr icmpv6 accept
}
chain ncsi_legacy_input {
jump ncsi_any_input
tcp dport 3959 accept
udp dport 3959 accept
tcp dport 3967 accept
udp dport 3967 accept
}
chain ncsi_brd_input {
jump ncsi_any_input
}
chain ncsi_any_input {
icmpv6 type nd-neighbor-advert accept
icmpv6 type nd-neighbor-solicit accept
icmpv6 type nd-router-advert accept
}
chain ncsi_forward {
type filter hook forward priority 0; policy drop;
iifname != @NCSI_IF@ accept
oifname != gbmcbr drop
ip6 daddr fdb5:0481:10ce::/64 drop
ip6 saddr fdb5:0481:10ce::/64 drop
}
chain ncsi_dhcp_input {
type filter hook input priority 0; policy drop;
iifname != ncsigbmc accept
ip6 nexthdr icmpv6 accept
udp dport 547 accept
}
}
@@ -0,0 +1,12 @@
[Unit]
BindsTo=ncsid@@NCSI_IF@.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/ip link set @NCSI_IF@ alias ncsi
ExecStop=/sbin/ip link set @NCSI_IF@ alias ''
[Install]
WantedBy=nic-hostful@@NCSI_IF@.target
WantedBy=nic-hostless@@NCSI_IF@.target
@@ -0,0 +1,152 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[ -n "${gbmc_ncsi_br_deprecated_ips_lib-}" ] && return
source /usr/share/network/lib.sh || exit
gbmc_ncsi_br_deprecated_ips_init=
gbmc_ncsi_br_deprecated_ips_confip=
gbmc_ncsi_br_deprecated_ips_lastip=
gbmc_ncsi_br_deprecated_ips_lastncsi=
gbmc_ncsi_br_deprecated_ips_confncsi=
gbmc_ncsi_br_deprecated_ips_update() {
[ -n "$gbmc_ncsi_br_deprecated_ips_init" ] || return
[ "$gbmc_ncsi_br_deprecated_ips_confip" != "$gbmc_ncsi_br_deprecated_ips_lastip" ] || \
[ "$gbmc_ncsi_br_deprecated_ips_confncsi" != "$gbmc_ncsi_br_deprecated_ips_lastncsi" ] || return
gbmc_ncsi_br_deprecated_ips_confip="$gbmc_ncsi_br_deprecated_ips_lastip"
gbmc_ncsi_br_deprecated_ips_confncsi="$gbmc_ncsi_br_deprecated_ips_lastncsi"
printf 'gBMC NCSI Deprecated Addrs: %s\n' \
"${gbmc_ncsi_br_deprecated_ips_lastip:-(deleted)}" >&2
local contents=
local nfcontents=
if [ -n "$gbmc_ncsi_br_deprecated_ips_lastip" ]; then
local pfx_bytes=()
ip_to_bytes pfx_bytes "$gbmc_ncsi_br_deprecated_ips_lastip"
local pfx="$(ip_bytes_to_str pfx_bytes)"
(( pfx_bytes[9] &= 0xf0 ))
local stateless_pfx="$(ip_bytes_to_str pfx_bytes)"
local stateless_ip=
if [ -e /sys/class/net/gbmcbr ]; then
local gbmcbr_mac="$(ip link show gbmcbr | tail -n 1 | awk '{print $2}')"
local gbmcbr_eui48="$(mac_to_eui48 "$gbmcbr_mac")"
stateless_ip="$(ip_pfx_concat "$stateless_pfx/80" "$gbmcbr_eui48")"
stateless_ip="${stateless_ip%/*}"
fi
pfx_bytes[8]=0
pfx_bytes[9]=0
local host_pfx=
if [ -n "${gbmc_ncsi_br_deprecated_ips_confncsi}" ]; then
# Only impersonate the host if we have an NCSI state machine
host_pfx="$(ip_bytes_to_str pfx_bytes)"
fi
read -r -d '' contents <<EOF
[Network]
IPv6ProxyNDP=yes
IPv6ProxyNDPAddress=$pfx
IPv6ProxyNDPAddress=$stateless_pfx
${host_pfx:+IPv6ProxyNDPAddress=}$host_pfx
${stateless_ip:+IPv6ProxyNDPAddress=}$stateless_ip
EOF
read -r -d '' nfcontents <<EOF
table inet filter {
chain ncsi_input {
ip6 saddr != $pfx/76 ip6 daddr $pfx/76 goto ncsi_gbmc_br_pub_input
${host_pfx:+ip6 daddr $host_pfx/64 goto ncsi_legacy_input}
}
chain ncsi_forward {
ip6 saddr != $pfx/76 ip6 daddr $pfx/76 accept
}
}
EOF
fi
local file
for file in /run/systemd/network/{00,}-bmc-@NCSI_IF@.network.d/50-deprecated.conf; do
mkdir -p -m 755 "$(dirname "$file")"
if [ -z "$contents" ]; then
rm -f "$file"
else
printf '%s' "$contents" >"$file"
fi
done
# Ensure that systemd-networkd performs a reconfiguration as it doesn't
# currently check the mtime of drop-in files.
touch -c /etc/systemd/network/*-bmc-@NCSI_IF@.network
if [ "$(systemctl is-active systemd-networkd)" != 'inactive' ]; then
networkctl reload && networkctl reconfigure @NCSI_IF@
fi
local rfile=/run/nftables/40-gbmc-ncsi-br.rules
mkdir -p -m 755 "$(dirname "$rfile")"
if [ -z "$nfcontents" ]; then
rm -f "$rfile"
else
printf '%s' "$nfcontents" >"$rfile"
fi
systemctl reset-failed nftables && systemctl --no-block reload-or-restart nftables || true
}
gbmc_ncsi_br_deprecated_ips_hook() {
if [ "$change" = 'init' ]; then
gbmc_ncsi_br_deprecated_ips_init=1
gbmc_ip_monitor_defer
elif [ "$change" = 'defer' ]; then
gbmc_ncsi_br_deprecated_ips_update
elif [ "$change" = 'addr' -a "$scope" = 'global' -a "$fam" = 'inet6' ] &&
[ "$intf" = 'gbmcbr' -o "$intf" = '@NCSI_IF@' ] &&
[[ "$flags" != *deprecated* ]]; then
local pfx_bytes=()
ip_to_bytes pfx_bytes "$ip" || return
# No ULA Addresses
if (( pfx_bytes[0] & 0xfe == 0xfc )); then
return
fi
# We only want to allow a <pfx>::fd0x address, where x>0
if (( pfx_bytes[8] != 0xfd || pfx_bytes[9] & 0xf == 0 )); then
return
fi
for (( i = 10; i < 16; ++i )); do
if (( pfx_bytes[i] != 0 )); then
return
fi
done
if [ "$action" = 'add' -a "$ip" != "$gbmc_ncsi_br_deprecated_ips_lastip" ]; then
gbmc_ncsi_br_deprecated_ips_lastip="$ip"
gbmc_ip_monitor_defer
fi
if [ "$action" = 'del' -a "$ip" = "$gbmc_ncsi_br_deprecated_ips_lastip" ]; then
gbmc_ncsi_br_deprecated_ips_lastip=
gbmc_ip_monitor_defer
fi
elif [ "$change" = 'link' -a "$action" = 'add' -a "$intf" = '@NCSI_IF@' ]; then
if ip link show '@NCSI_IF@' | grep -q '^ *alias ncsi$'; then
gbmc_ncsi_br_deprecated_ips_lastncsi=1
gbmc_ip_monitor_defer
else
gbmc_ncsi_br_deprecated_ips_lastncsi=
gbmc_ip_monitor_defer
fi
fi
}
GBMC_IP_MONITOR_HOOKS+=(gbmc_ncsi_br_deprecated_ips_hook)
gbmc_ncsi_br_deprecated_ips_lib=1
@@ -0,0 +1,87 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[ -n "${gbmc_ncsi_br_pub_addr_lib-}" ] && return
[ ! -e /usr/share/gbmc-br-lib.sh ] && return
source /usr/share/network/lib.sh || exit
source /usr/share/gbmc-br-lib.sh || exit
gbmc_ncsi_br_pub_addr_init=
gbmc_ncsi_br_pub_addr_lastip=
gbmc_ncsi_br_pub_addr_confip=
gbmc_ncsi_br_pub_addr_update() {
[ -n "$gbmc_ncsi_br_pub_addr_init" ] || return
[ "$gbmc_ncsi_br_pub_addr_confip" != "$gbmc_ncsi_br_pub_addr_lastip" ] || return
gbmc_ncsi_br_pub_addr_confip="$gbmc_ncsi_br_pub_addr_lastip"
printf 'gBMC Bridge Pub Addr from NCSI: %s\n' \
"${gbmc_ncsi_br_pub_addr_lastip:-(deleted)}" >&2
local pfx_bytes=()
if [ -n "$gbmc_ncsi_br_pub_addr_lastip" ]; then
ip_to_bytes pfx_bytes "$gbmc_ncsi_br_pub_addr_lastip"
# Ensure we have a /64 or an fdxx address
if (( pfx_bytes[8] != 0xfd || pfx_bytes[9] == 0 )); then
local i
for (( i = 8; i < 16; ++i )); do
if (( pfx_bytes[$i] != 0 )); then
pfx_bytes=()
break
fi
done
fi
fi
local contents=
if (( ${#pfx_bytes[@]} != 0 )); then
pfx_bytes[8]=0xfd
# We never want to use the stateless pfx
if (( pfx_bytes[9] == 0 )); then
pfx_bytes[9]=0x01
fi
# Remove any existing persisted IP
gbmc_br_set_ip
# Load the IP to the bridge non-persistently
gbmc_br_reload_ip "$(ip_bytes_to_str pfx_bytes)"
else
gbmc_br_reload_ip
fi
}
gbmc_ncsi_br_pub_addr_hook() {
if [ "$change" = 'init' ]; then
gbmc_ncsi_br_pub_addr_init=1
gbmc_ip_monitor_defer
elif [ "$change" = 'defer' ]; then
gbmc_ncsi_br_pub_addr_update
elif [ "$change" = 'addr' -a "$intf" = '@NCSI_IF@' ] &&
[ "$scope" = 'global' -a "$fam" = 'inet6' ] &&
[[ "$flags" != *deprecated* ]]; then
if [ "$action" = 'add' -a "$ip" != "$gbmc_ncsi_br_pub_addr_lastip" ]; then
gbmc_ncsi_br_pub_addr_lastip="$ip"
gbmc_ip_monitor_defer
fi
if [ "$action" = 'del' -a "$ip" = "$gbmc_ncsi_br_pub_addr_lastip" ]; then
gbmc_ncsi_br_pub_addr_lastip=
gbmc_ip_monitor_defer
fi
fi
}
GBMC_IP_MONITOR_HOOKS+=(gbmc_ncsi_br_pub_addr_hook)
gbmc_ncsi_br_pub_addr_lib=1
@@ -0,0 +1,13 @@
[Unit]
Description=gBMC DHCP Relay Agent Daemon
After=network.target
StartLimitIntervalSec=10
StartLimitBurst=3
[Service]
Restart=always
RestartSec=5
ExecStart=/usr/sbin/dhcrelay -d --no-pid -rp 3967 -l gbmcncsidhcp -u ff02::1:2%%@NCSI_IF@
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,15 @@
[Unit]
Description=gBMC NCSI RA Discovery
After=network.target
StartLimitIntervalSec=10
StartLimitBurst=3
Conflicts=nic-hostless@@NCSI_IF@.target
Conflicts=nic-hostful@@NCSI_IF@.target
[Service]
Restart=always
RestartSec=5
ExecStart=/usr/libexec/gbmc-ncsi-ip-from-ra.sh
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,95 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[ ! -e /usr/share/gbmc-br-lib.sh ] && exit
# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
source /usr/share/network/lib.sh || exit
# shellcheck source=meta-google/recipes-google/networking/gbmc-bridge/gbmc-br-lib.sh
source /usr/share/gbmc-br-lib.sh || exit
NCSI_IF='@NCSI_IF@'
old_pfx=
old_fqdn=
old_rtr=
set_host() {
[[ -n "$host" && -n "$domain" && -n "$hextet" ]] || return
local fqdn="$host-n$hextet.$domain"
[ "$fqdn" != "$old_fqdn" ] || return
old_fqdn="$fqdn"
echo "Found hostname $fqdn" >&2
hostnamectl set-hostname "$fqdn" || true
}
set_net() {
[[ -n "$pfx" && -n "$rtr" ]] || return
[[ "$pfx" != "$old_pfx" || "$rtr" != "$old_rtr" ]] || return
old_pfx="$pfx"
old_rtr="$rtr"
echo "Found prefix $pfx from $rtr" >&2
# We no longer need NCSId if we are in this configuration
systemctl stop --no-block ncsid@"$NCSI_IF" || true
# Save the IP address for the interface
gbmc_br_set_ip "$pfx" || true
# DHCP Relay workaround until alternate source port is supported
# TODO: Remove this once internal relaying cleanups land
gbmc-ncsi-smartnic-wa.sh || true
}
w=60
while true; do
start=$SECONDS
while read -r line; do
if [ -z "$line" ]; then
hextet=
pfx=
host=
domain=
elif [[ "$line" =~ ^Prefix' '*:' '*(.*)/([0-9]+)$ ]]; then
t_pfx="${BASH_REMATCH[1]}"
t_pfx_len="${BASH_REMATCH[2]}"
ip_to_bytes t_pfx_b "$t_pfx" || continue
(( t_pfx_len == 76 && t_pfx_b[8] & 0xfd == 0xfd )) || continue
(( t_pfx_b[9] |= 1 ))
hextet="fd$(printf '%02x' "${t_pfx_b[9]}")"
pfx="$(ip_bytes_to_str t_pfx_b)"
elif [[ "$line" =~ ^'DNS search list'' '*:' '*([^.]+)(.*[.]google[.]com)$ ]]; then
# Ideally, we use PCRE and with lookahead and can do this in a single regex
# ^([a-zA-Z0-9-]+(?=-n[a-fA-F0-9]{1,4})|[a-zA-Z0-9-]+(?!-n[a-fA-F0-9]{1,4}))[^.]*[.]((?:[a-zA-Z0-9]*[.])*google[.]com)$
# Instead we do multiple steps to extract the needed info
host="${BASH_REMATCH[1]}"
domain="${BASH_REMATCH[2]#.}"
if [[ "$host" =~ (-n[a-fA-F0-9]{1,4})$ ]]; then
host="${host%"${BASH_REMATCH[1]}"}"
fi
elif [[ "$line" =~ ^from' '(.*)$ ]]; then
rtr="${BASH_REMATCH[1]}"
set_net || true
set_host || true
fi
done < <(rdisc6 -d -m "$NCSI_IF" -w $(( w * 1000 )) 2>/dev/null)
# If rdisc6 exits early we still want to wait the full `w` time before
# starting again.
(( timeout = start + w - SECONDS ))
sleep $(( timeout < 0 ? 0 : timeout ))
done
@@ -0,0 +1,85 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[ -n "${gbmc_ncsi_nft_lib-}" ] && return
source /usr/share/network/lib.sh || exit
gbmc_ncsi_nft_init=
gbmc_ncsi_nft_lastip4=
gbmc_ncsi_nft_lastip6=
gbmc_ncsi_nft_update() {
[ -n "$gbmc_ncsi_nft_init" ] || return
printf 'NCSI firewall for IPv4(%s) IPv6(%s)\n' \
"${gbmc_ncsi_nft_lastip4:-(deleted)}" \
"${gbmc_ncsi_nft_lastip6:-(deleted)}" >&2
local contents=
contents+='table inet filter {'$'\n'
contents+=' chain ncsi_input {'$'\n'
local ip4="$gbmc_ncsi_nft_lastip4"
if [ -n "$ip4" ]; then
contents+=" ip daddr $ip4 goto ncsi_legacy_input"$'\n'
fi
local ip6="$gbmc_ncsi_nft_lastip6"
if [ -n "$ip6" ]; then
contents+=" ip6 daddr $ip6 goto ncsi_legacy_input"$'\n'
fi
contents+=' }'$'\n'
contents+='}'$'\n'
local rfile=/run/nftables/30-gbmc-ncsi-in.rules
mkdir -p -m 755 "$(dirname "$rfile")"
printf '%s' "$contents" >"$rfile"
systemctl reset-failed nftables && systemctl --no-block reload-or-restart nftables || true
}
gbmc_ncsi_nft_hook() {
if [ "$change" = 'init' ]; then
gbmc_ncsi_nft_init=1
gbmc_ncsi_nft_update
elif [ "$change" = 'addr' -a "$intf" = '@NCSI_IF@' -a "$scope" = 'global' ]; then
if [ "$fam" = 'inet6' ]; then
local -n lastip='gbmc_ncsi_nft_lastip6'
local pfx_bytes=()
ip_to_bytes pfx_bytes "$ip" || return
# We only want to allow a <pfx>:: address
for (( i = 8; i < 16; ++i )); do
if (( pfx_bytes[i] != 0 )); then
return
fi
done
else
local -n lastip='gbmc_ncsi_nft_lastip4'
fi
if [ "$action" = 'add' -a "$ip" != "$lastip" ]; then
lastip="$ip"
gbmc_ncsi_nft_update
fi
if [ "$action" = 'del' -a "$ip" = "$lastip" ]; then
lastip=
gbmc_ncsi_nft_update
fi
fi
}
GBMC_IP_MONITOR_HOOKS+=(gbmc_ncsi_nft_hook)
gbmc_ncsi_nft_lib=1
@@ -0,0 +1,17 @@
[Unit]
Description=Set NICEnabled property to true
Wants=xyz.openbmc_project.Network.service
After=xyz.openbmc_project.Network.service
Wants=mapper-wait@-xyz-openbmc_project-network-@NCSI_IF@.service
After=mapper-wait@-xyz-openbmc_project-network-@NCSI_IF@.service
StartLimitIntervalSec=10
StartLimitBurst=3
[Service]
Type=oneshot
ExecStart=busctl set-property xyz.openbmc_project.Network /xyz/openbmc_project/network/@NCSI_IF@ xyz.openbmc_project.Network.EthernetInterface NICEnabled b true
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,52 @@
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
override=/run/systemd/system/gbmc-ncsi-dhcrelay.service.d/10-nosp.conf
mkdir -p "$(dirname "$override")"
echo '[Service]' >"$override"
echo 'ExecStart=' >>"$override"
# Remove the source relay port from the relay, bringing it back to run on
# the default port 547. Our relays don't support the source port option needed
# to run on 3967 for our legacy NICs.
grep '^ExecStart=' /lib/systemd/system/gbmc-ncsi-dhcrelay.service | \
sed 's, -rp 3967,,' >>"$override"
override=/run/systemd/system/gbmc-br-dhcp.service.d/10-direct.conf
mkdir -p "$(dirname "$override")"
echo '[Service]' >"$override"
echo 'ExecStart=' >>"$override"
# Switch the gbmcbr interface for the NCSI one to avoid passing the SOLICIT
# message through the BMC relay.
grep '^ExecStart=' /lib/systemd/system/gbmc-br-dhcp.service | \
sed 's, -i gbmcbr, -i @NCSI_IF@,' >>"$override"
systemctl daemon-reload
systemctl reset-failed gbmc-ncsi-dhcrelay
systemctl restart --no-block gbmc-ncsi-dhcrelay
systemctl reset-failed gbmc-br-dhcp
systemctl restart --no-block gbmc-br-dhcp
read -r -d '' contents <<EOF
table inet filter {
chain ncsi_legacy_input {
udp dport {546,547} accept
}
}
EOF
rfile=/run/nftables/60-gbmc-ncsi-ra.rules
mkdir -p "$(dirname "$rfile")"
printf '%s' "$contents" >"$rfile"
systemctl reset-failed nftables
systemctl --no-block reload-or-restart nftables
@@ -0,0 +1,21 @@
[Unit]
Description=SSL/SSH multiplexer
Requires=gbmc-ncsi-sslh.socket
After=gbmc-ncsi-sslh.socket
[Service]
ExecStart=/usr/sbin/sslh -n -f --ssh [::1]:22 --http [::1]:80 --tls [::1]:443
KillMode=process
#Hardening
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
MountFlags=private
NoNewPrivileges=true
PrivateDevices=true
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
MemoryDenyWriteExecute=true
DynamicUser=true
@@ -0,0 +1,6 @@
[Socket]
BindToDevice=@NCSI_IF@
ListenStream=3967
[Install]
WantedBy=sockets.target
@@ -0,0 +1,149 @@
SUMMARY = "Configures ncsi for a gBMC system"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit systemd
SRC_URI += " \
file://-bmc-gbmcbrncsidhcp.netdev \
file://-bmc-gbmcbrncsidhcp.network \
file://-bmc-gbmcncsidhcp.netdev \
file://-bmc-gbmcncsidhcp.network \
file://50-gbmc-ncsi.rules.in \
file://gbmc-ncsi-dhcrelay.service.in \
file://gbmc-ncsi-ip-from-ra.service.in \
file://gbmc-ncsi-ip-from-ra.sh.in \
file://gbmc-ncsi-smartnic-wa.sh.in \
file://gbmc-ncsi-sslh.socket.in \
file://gbmc-ncsi-sslh.service \
file://gbmc-ncsi-nft.sh.in \
file://gbmc-ncsi-br-pub-addr.sh.in \
file://gbmc-ncsi-br-deprecated-ips.sh.in \
file://gbmc-ncsi-set-nicenabled.service.in \
file://gbmc-ncsi-alias.service.in \
file://50-gbmc-ncsi-clear-ip.sh.in \
"
S = "${WORKDIR}"
RDEPENDS:${PN} += " \
bash \
dhcp-relay \
gbmc-ip-monitor \
ncsid \
network-sh \
nftables-systemd \
sslh \
ndisc6-rdisc6 \
"
FILES:${PN} += " \
${datadir}/gbmc-br-lib \
${datadir}/gbmc-ip-monitor \
${systemd_unitdir} \
"
SYSTEMD_SERVICE:${PN} += " \
gbmc-ncsi-dhcrelay.service \
gbmc-ncsi-sslh.service \
gbmc-ncsi-sslh.socket \
gbmc-ncsi-set-nicenabled.service \
gbmc-ncsi-ip-from-ra.service \
"
do_install:append() {
if_name='${GBMC_NCSI_IF_NAME}'
if [ -z "$if_name" ]; then
echo "Missing if_name" >&2
exit 1
fi
install -d -m0755 ${D}${sysconfdir}/sysctl.d
echo "net.ipv6.conf.$if_name.accept_dad=0" \
>>${D}${sysconfdir}/sysctl.d/25-gbmc-ncsi.conf
echo "net.ipv6.conf.$if_name.dad_transmits=0" \
>>${D}${sysconfdir}/sysctl.d/25-gbmc-ncsi.conf
install -d -m0755 ${D}${systemd_unitdir}/network
install -m0644 ${WORKDIR}/-bmc-gbmcbrncsidhcp.netdev \
${D}${systemd_unitdir}/network/
install -m0644 ${WORKDIR}/-bmc-gbmcbrncsidhcp.network \
${D}${systemd_unitdir}/network/
install -m0644 ${WORKDIR}/-bmc-gbmcncsidhcp.netdev \
${D}${systemd_unitdir}/network/
install -m0644 ${WORKDIR}/-bmc-gbmcncsidhcp.network \
${D}${systemd_unitdir}/network/
netdir=${D}${systemd_unitdir}/network/00-bmc-$if_name.network.d
install -d -m0755 "$netdir"
echo '[Network]' >>"$netdir"/gbmc-ncsi.conf
echo 'DHCP=false' >>"$netdir"/gbmc-ncsi.conf
echo 'IPv6AcceptRA=false' >>"$netdir"/gbmc-ncsi.conf
echo 'LLMNR=false' >>"$netdir"/gbmc-ncsi.conf
echo 'MulticastDNS=false' >>"$netdir"/gbmc-ncsi.conf
echo 'LinkLocalAddressing=ipv6' >>"$netdir"/gbmc-ncsi.conf
nftdir=${D}${sysconfdir}/nftables
install -d -m0755 "$nftdir"
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/50-gbmc-ncsi.rules.in \
>"$nftdir"/50-gbmc-ncsi.rules
wantdir=${D}${systemd_system_unitdir}/multi-user.target.wants
install -d -m0755 "$wantdir"
ln -sv ../ncsid@.service "$wantdir"/ncsid@$if_name.service
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-alias.service.in \
>${D}${systemd_system_unitdir}/gbmc-ncsi-alias.service
install -d -m0755 "${D}${systemd_system_unitdir}/nic-hostless@$if_name.target.wants"
ln -sv ../gbmc-ncsi-alias.service "${D}${systemd_system_unitdir}/nic-hostless@$if_name.target.wants"/
install -d -m0755 "${D}${systemd_system_unitdir}/nic-hostful@$if_name.target.wants"
ln -sv ../gbmc-ncsi-alias.service "${D}${systemd_system_unitdir}/nic-hostful@$if_name.target.wants"/
install -m 0644 ${WORKDIR}/gbmc-ncsi-sslh.service ${D}${systemd_system_unitdir}
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-sslh.socket.in \
>${D}${systemd_system_unitdir}/gbmc-ncsi-sslh.socket
mondir=${D}${datadir}/gbmc-ip-monitor/
install -d -m0755 $mondir
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-nft.sh.in \
>${WORKDIR}/gbmc-ncsi-nft.sh
install -m644 ${WORKDIR}/gbmc-ncsi-nft.sh $mondir
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-br-pub-addr.sh.in \
>${WORKDIR}/gbmc-ncsi-br-pub-addr.sh
install -m644 ${WORKDIR}/gbmc-ncsi-br-pub-addr.sh $mondir
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-br-deprecated-ips.sh.in \
>${WORKDIR}/gbmc-ncsi-br-deprecated-ips.sh
install -m644 ${WORKDIR}/gbmc-ncsi-br-deprecated-ips.sh $mondir
brlibdir=${D}${datadir}/gbmc-br-lib/
install -d -m0755 $brlibdir
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/50-gbmc-ncsi-clear-ip.sh.in \
>${WORKDIR}/50-gbmc-ncsi-clear-ip.sh
install -m644 ${WORKDIR}/50-gbmc-ncsi-clear-ip.sh $brlibdir
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-set-nicenabled.service.in \
>${D}${systemd_system_unitdir}/gbmc-ncsi-set-nicenabled.service
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-dhcrelay.service.in \
>${D}${systemd_system_unitdir}/gbmc-ncsi-dhcrelay.service
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-ip-from-ra.service.in \
>${WORKDIR}/gbmc-ncsi-ip-from-ra.service
install -m0644 ${WORKDIR}/gbmc-ncsi-ip-from-ra.service ${D}${systemd_system_unitdir}
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-ip-from-ra.sh.in \
>${WORKDIR}/gbmc-ncsi-ip-from-ra.sh
install -d -m0755 ${D}${libexecdir}
install -m0755 ${WORKDIR}/gbmc-ncsi-ip-from-ra.sh ${D}${libexecdir}/
sed "s,@NCSI_IF@,$if_name,g" ${WORKDIR}/gbmc-ncsi-smartnic-wa.sh.in \
>${WORKDIR}/gbmc-ncsi-smartnic-wa.sh
install -d -m0755 ${D}${bindir}
install -m0755 ${WORKDIR}/gbmc-ncsi-smartnic-wa.sh ${D}${bindir}/
}
do_rm_work:prepend() {
# HACK: Work around broken do_rm_work not properly calling rm with `--`
# It doesn't like filenames that start with `-`
rm -rf -- ${WORKDIR}/-*
}
@@ -0,0 +1,40 @@
SUMMARY = "Google NCSI daemon"
DESCRIPTION = "Google NCSI daemon."
GOOGLE_MISC_PROJ = "ncsid"
require ../google-misc/google-misc.inc
inherit systemd
EXTRA_OEMESON = " \
-Dtests=disabled \
"
SYSTEMD_SERVICE:${PN} += " \
dhcp4@.service \
dhcp6@.service \
ncsid@.service \
nic-hostful@.target \
nic-hostless@.target \
update-ra-gw@.service \
update-ra-neighbor@.service \
update-ra-neighbor@.timer \
update-static-neighbors@.service \
update-static-neighbors@.timer \
"
DEPENDS += " \
fmt \
sdbusplus \
stdplus \
"
RDEPENDS:${PN} += " \
bash \
busybox \
iputils-arping \
jq \
ndisc6-ndisc6 \
ndisc6-rdisc6 \
systemd \
"
@@ -0,0 +1,5 @@
table inet filter {
chain gbmc_br_pub_input {
tcp dport 23 accept
}
}
@@ -0,0 +1,22 @@
SUMMARY = "Google DHCP completion daemon"
DESCRIPTION = "Google DHCP completion daemon"
GOOGLE_MISC_PROJ = "dhcp-done"
require ../google-misc/google-misc.inc
inherit systemd
SYSTEMD_SERVICE:${PN} += "dhcp-done@.service"
DEPENDS += " \
sdeventplus \
stdplus \
"
SRC_URI += "file://50-dhcp-done.rules"
FILES:${PN} += "${sysconfdir}/nftables"
do_install:append() {
nftables_dir=${D}${sysconfdir}/nftables
install -d -m0755 "$nftables_dir"
install -m0644 ${WORKDIR}/50-dhcp-done.rules $nftables_dir/
}
@@ -0,0 +1,185 @@
#!/bin/bash
# shellcheck disable=SC2317
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cd "$(dirname "$0")" || exit
if [ -e ../gbmc-ip-monitor.bb ]; then
# shellcheck source=meta-google/recipes-google/test/test-sh/lib.sh
source '../../test/test-sh/lib.sh'
else
# shellcheck source=meta-google/recipes-google/test/test-sh/lib.sh
source "$SYSROOT/usr/share/test/lib.sh"
fi
# shellcheck source=meta-google/recipes-google/networking/files/gbmc-ip-monitor.sh
source gbmc-ip-monitor.sh
test_init_empty() {
ip() {
return 0
}
str="$(gbmc_ip_monitor_generate_init)" || fail
expect_streq "$str" '[INIT]'
}
test_init_link_populated() {
ip() {
if [ "$1" = 'link' ]; then
cat <<EOF
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff
altname enp0s31f6
EOF
fi
return 0
}
str="$(gbmc_ip_monitor_generate_init)" || fail
expect_streq "$str" <<EOF
[LINK]1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[LINK]2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff
altname enp0s31f6
[INIT]
EOF
}
test_init_addr_populated() {
ip() {
if [ "$1" = 'addr' ]; then
cat <<EOF
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff
altname enp0s31f6
inet 192.168.242.57/23 brd 192.168.243.255 scope global dynamic noprefixroute eno2
valid_lft 83967sec preferred_lft 83967sec
inet6 fd01:ff2:5687:4:cf03:45f3:983a:96eb/64 scope global temporary dynamic
valid_lft 518788sec preferred_lft 183sec
EOF
fi
return 0
}
str="$(gbmc_ip_monitor_generate_init)" || fail
expect_streq "$str" <<EOF
[ADDR]1: lo inet 127.0.0.1/8 scope host lo
[ADDR]1: lo inet6 ::1/128 scope host
[ADDR]2: eno2 inet 192.168.242.57/23 brd 192.168.243.255 scope global dynamic noprefixroute eno2
[ADDR]2: eno2 inet6 fd01:ff2:5687:4:cf03:45f3:983a:96eb/64 scope global temporary dynamic
[INIT]
EOF
}
test_init_route_populated() {
ip() {
if [[ "$1" == "-4" && "${2-}" == 'route' ]]; then
cat <<EOF
default via 192.168.243.254 dev eno2 proto dhcp metric 100
192.168.242.0/23 dev eno2 proto kernel scope link src 192.168.242.57 metric 100
EOF
elif [[ "$1" == "-6" && "${2-}" == 'route' ]]; then
cat <<EOF
::1 dev lo proto kernel metric 256 pref medium
fd01:ff2:5687:4::/64 dev eno2 proto ra metric 100 pref medium
fe80::/64 dev eno2 proto kernel metric 100 pref medium
EOF
fi
return 0
}
str="$(gbmc_ip_monitor_generate_init)" || fail
expect_streq "$str" <<EOF
[ROUTE]default via 192.168.243.254 dev eno2 proto dhcp metric 100
[ROUTE]192.168.242.0/23 dev eno2 proto kernel scope link src 192.168.242.57 metric 100
[ROUTE]::1 dev lo proto kernel metric 256 pref medium
[ROUTE]fd01:ff2:5687:4::/64 dev eno2 proto ra metric 100 pref medium
[ROUTE]fe80::/64 dev eno2 proto kernel metric 100 pref medium
[INIT]
EOF
}
testParseNonTag() {
expect_err 2 gbmc_ip_monitor_parse_line ''
expect_err 2 gbmc_ip_monitor_parse_line ' '
expect_err 2 gbmc_ip_monitor_parse_line ' Data'
expect_err 2 gbmc_ip_monitor_parse_line ' [LINK]'
expect_err 2 gbmc_ip_monitor_parse_line ' [ROUTE]'
}
testParseInit() {
expect_err 0 gbmc_ip_monitor_parse_line '[INIT]'
expect_streq "$change" 'init'
}
testParseAddrAdd() {
expect_err 0 gbmc_ip_monitor_parse_line '[ADDR]2: eno2 inet6 fd01:ff2:5687:4:cf03:45f3:983a:96eb/128 metric 1024 scope global temporary dynamic'
expect_streq "$change" 'addr'
expect_streq "$action" 'add'
expect_streq "$intf" 'eno2'
expect_streq "$fam" 'inet6'
expect_streq "$ip" 'fd01:ff2:5687:4:cf03:45f3:983a:96eb'
expect_streq "$scope" 'global'
expect_streq "$flags" 'temporary dynamic'
}
testParseAddrDel() {
expect_err 0 gbmc_ip_monitor_parse_line '[ADDR]Deleted 2: eno2 inet6 fe80::aaaa:aaff:feaa:aaaa/64 scope link'
expect_streq "$change" 'addr'
expect_streq "$action" 'del'
expect_streq "$intf" 'eno2'
expect_streq "$fam" 'inet6'
expect_streq "$ip" 'fe80::aaaa:aaff:feaa:aaaa'
expect_streq "$scope" 'link'
expect_streq "$flags" ''
}
testParseRouteAdd() {
expect_err 0 gbmc_ip_monitor_parse_line "[ROUTE]fd01:ff2:5687:4::/64 dev eno2 proto ra metric 100 pref medium"
expect_streq "$change" 'route'
expect_streq "$action" 'add'
expect_streq "$route" 'fd01:ff2:5687:4::/64 dev eno2 proto ra metric 100 pref medium'
}
testParseRouteDel() {
expect_err 0 gbmc_ip_monitor_parse_line "[ROUTE]Deleted fd01:ff2:5687:4::/64 dev eno2 proto ra metric 100 pref medium"
expect_streq "$change" 'route'
expect_streq "$action" 'del'
expect_streq "$route" 'fd01:ff2:5687:4::/64 dev eno2 proto ra metric 100 pref medium'
}
testParseLinkAdd() {
expect_err 0 gbmc_ip_monitor_parse_line "[LINK]2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000" \
< <(echo 'link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff')
expect_streq "$change" 'link'
expect_streq "$action" 'add'
expect_streq "$intf" 'eno2'
expect_streq "$mac" 'aa:aa:aa:aa:aa:aa'
}
testParseLinkDel() {
expect_err 0 gbmc_ip_monitor_parse_line "[LINK]Deleted 2: eno2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000" \
< <(echo 'link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff')
expect_streq "$change" 'link'
expect_streq "$action" 'del'
expect_streq "$intf" 'eno2'
expect_streq "$mac" 'aa:aa:aa:aa:aa:aa'
}
main
@@ -0,0 +1,10 @@
[Unit]
Before=systemd-networkd.service
[Service]
Type=notify
ExecStart=/usr/libexec/gbmc-ip-monitor.sh
TimeoutStartSec=5min
[Install]
WantedBy=multi-user.target

Some files were not shown because too many files have changed in this diff Show More