#!/usr/bin/env python3
# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
# $Source: op-test-framework/testcases/OpTestPNOR.py $
#
# OpenPOWER Automated Test Project
#
# Contributors Listed Below - COPYRIGHT 2017
# [+] International Business Machines Corp.
#
#
# 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.
#
# IBM_PROLOG_END_TAG
#
'''
OpTestPNOR
----------
This testcase will deal with testing access to the host pnor
from petitboot through the pflash program
'''
import time
import subprocess
import subprocess
import re
import sys
import os
import os.path
import unittest
import OpTestConfiguration
from common.OpTestSystem import OpSystemState
from common.OpTestConstants import OpTestConstants as BMC_CONST
from common.Exceptions import CommandFailed
import logging
import OpTestLogger
log = OpTestLogger.optest_logger_glob.get_logger(__name__)
class OpTestPNOR():
def setUp(self):
conf = OpTestConfiguration.conf
self.cv_HOST = conf.host()
self.cv_IPMI = conf.ipmi()
self.cv_SYSTEM = conf.system()
def pflashErase(self, offset, length):
self.c.run_command("pflash -e -f -a %d -s %d" % (offset, length))
def pflashErasePartition(self, partition):
self.c.run_command("pflash -e -f -P %s" % (partition))
def pflashRead(self, filename, offset, length):
self.c.run_command("pflash -r %s -a %d -s %d" %
(filename, offset, length))
def pflashReadPartition(self, filename, partition):
self.c.run_command("pflash -r %s -P %s" % (filename, partition))
def pflashWrite(self, filename, offset, length):
self.c.run_command("pflash -f -p %s -a %d -s %d" %
(filename, offset, length))
def pflashWritePartition(self, filename, partition):
self.c.run_command("pflash -f -p %s -P %s" % (filename, partition))
def pflashGetPartition(self, partition):
d = self.c.run_command("pflash --info")
for line in d:
s = re.search(partition, line)
if s:
m = re.match(
r'ID=\d+\s+\S+\s+((0[xX])?[0-9a-fA-F]+)..(0[xX])?[0-9a-fA-F]+\s+\(actual=((0[xX])?[0-9a-fA-F]+)\)\s(\[)?([A-Za-z-]+)?(\])?.*', line)
if not m:
continue
offset = int(m.group(1), 16)
length = int(m.group(4), 16)
ret = {'offset': offset,
'length': length
}
flags = m.group(7)
if flags:
ret['flags'] = [x for x in list(flags) if x != '-']
return ret
def comparePartitionFile(self, filename, partition):
self.c.run_command("pflash -r /tmp/tmp -P %s" % (partition))
try:
self.c.run_command("diff /tmp/tmp %s" % (filename))
except CommandFailed as cf:
self.assertEqual(cf.output, "0")
def runTestReadEraseWriteNVRAM(self):
# Read NVRAM to file /tmp/nvram
self.pflashReadPartition("/tmp/nvram", "NVRAM")
nvramInfo = self.pflashGetPartition("NVRAM")
# Erase the NVRAM partition
self.pflashErase(nvramInfo['offset'], nvramInfo['length'])
# Read the (hopefully) erased NVRAM
self.pflashReadPartition("/tmp/null", "NVRAM")
# Write back to the NVRAM partition
self.pflashWrite(
"/tmp/nvram", nvramInfo['offset'], nvramInfo['length'])
# Compare /tmp/nvram to rewritten nvram contents
self.comparePartitionFile("/tmp/nvram", "NVRAM")
# Check /tmp/null all "erased" (377 is 0xFF in octal)
d = self.c.run_command("cat /tmp/null | tr -d '\\377' | wc -c")
self.assertEqual(d[0], "0")
def runTestReadWritePAYLOAD(self):
payloadInfo = self.pflashGetPartition("PAYLOAD")
log.debug(repr(payloadInfo))
# Read PAYLOAD to file /tmp/payload
self.pflashReadPartition("/tmp/payload", "PAYLOAD")
# Write /tmp/payload to PAYLOAD
try:
self.pflashWrite(
"/tmp/payload", payloadInfo['offset'], payloadInfo['length'])
except CommandFailed as cf:
log.debug("pflashWrite Flags={} cf={} cf.output={} cf.exitcode={}"
.format(payloadInfo.get('flags'), cf, cf.output, cf.exitcode))
if payloadInfo.get('flags'):
# we have an iterable, so check it
if not ('R' in payloadInfo.get('flags') and cf.exitcode in [8]):
raise cf
else:
# we have no flags
if cf.exitcode in [8]:
raise cf
# Check the same
self.comparePartitionFile("/tmp/payload", "PAYLOAD")
# Try using the pflash -P option as well
try:
self.pflashWritePartition("/tmp/payload", "PAYLOAD")
except CommandFailed as cf:
log.debug("pflashWritePartition Flags={} cf={} cf.output={} cf.exitcode={}"
.format(payloadInfo.get('flags'), cf, cf.output, cf.exitcode))
if payloadInfo.get('flags'):
# we have an iterable, so check it
if not ('R' in payloadInfo.get('flags') and cf.exitcode in [8]):
raise cf
else:
# we have no flags
if cf.exitcode in [8]:
raise cf
# Check the same
self.comparePartitionFile("/tmp/payload", "PAYLOAD")
def runTestWriteTOC(self):
tocInfo = self.pflashGetPartition("part")
# Read the toc so we can write it back later
self.pflashRead("/tmp/toc", tocInfo['offset'], tocInfo['length'])
# Write all zeros to the toc (Because why not :D)
self.c.run_command(
"dd if=/dev/zero of=/tmp/zeros bs=1 count=%s" % (tocInfo['length']))
try:
self.pflashWrite(
"/tmp/zeros", tocInfo['offset'], tocInfo['length'])
except CommandFailed as cf:
self.assertEqual(cf.exitcode, 8,
"pflash did not exit with correct exit code for "
"a Read Only TOC. Expeceted 8, got {}.".format(
cf.exitcode))
# Read and compare
self.pflashRead("/tmp/tmp", tocInfo['offset'], tocInfo['length'])
try:
self.c.run_command("diff /tmp/tmp /tmp/zeros")
except CommandFailed as cf:
# This is not an error -> expected for vPNOR (prior to RO-TOC)
log.debug("Failed to zero TOC")
# Better write the toc back now
try:
self.pflashWrite("/tmp/toc", tocInfo['offset'], tocInfo['length'])
except CommandFailed as cf:
self.assertEqual(cf.exitcode, 8,
"pflash did not exit with correct exit code for "
"a Read Only TOC. Expeceted 8, got {}.".format(
cf.exitcode))
def runTest(self):
self.setup_test()
if not self.cv_SYSTEM.has_mtd_pnor_access():
self.skipTest("Host doesn't have MTD PNOR access")
# retry in case this comes after a hung console recovery
self.c.run_command("uname -a", retry=5)
self.c.run_command("cat /etc/os-release", retry=5)
# Read Erase Write NVRAM
self.runTestReadEraseWriteNVRAM()
# Read and then reWrite PAYLOAD
self.runTestReadWritePAYLOAD()
# Try write to the TOC
self.runTestWriteTOC()
[docs]class Skiroot(OpTestPNOR, unittest.TestCase):
def setup_test(self):
self.cv_SYSTEM.goto_state(OpSystemState.PETITBOOT_SHELL)
self.c = self.cv_SYSTEM.console
[docs]class Host(OpTestPNOR, unittest.TestCase):
def setup_test(self):
self.cv_SYSTEM.goto_state(OpSystemState.OS)
self.c = self.cv_SYSTEM.cv_HOST.get_ssh_connection()