blob: c3ce610eebaa640afcd0d1f8a5565e9460fee52d [file] [log] [blame]
Benjamin Faire5aafa52020-06-05 21:04:24 -07001/*
2 * Copyright 2020 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Benjamin Fair20a18092020-06-08 11:12:21 -070017#include "internal_sys_mock.hpp"
Benjamin Faire5aafa52020-06-05 21:04:24 -070018#include "pci.hpp"
Benjamin Fair20a18092020-06-08 11:12:21 -070019#include "pciaccess_mock.hpp"
Benjamin Faire5aafa52020-06-05 21:04:24 -070020#include "tool_errors.hpp"
21
22#include <stdplus/raw.hpp>
23
24#include <algorithm>
25#include <cstdlib>
Patrick Williams28c00d62022-04-27 08:37:13 -050026#include <span>
Benjamin Faire5aafa52020-06-05 21:04:24 -070027#include <string>
28#include <vector>
Benjamin Fair20a18092020-06-08 11:12:21 -070029
30#include <gtest/gtest.h>
31
32namespace host_tool
33{
34namespace
35{
36
Benjamin Faire5aafa52020-06-05 21:04:24 -070037using namespace std::string_literals;
38
39using ::testing::Assign;
40using ::testing::ContainerEq;
41using ::testing::DoAll;
42using ::testing::Each;
43using ::testing::Eq;
44using ::testing::InSequence;
45using ::testing::NotNull;
46using ::testing::Return;
47using ::testing::SetArgPointee;
48
49// TODO: switch to ConainerEq for C++20
50MATCHER_P(SpanEq, s, "")
51{
52 return arg.size() == s.size() && !memcmp(arg.data(), s.data(), s.size());
53}
54
55MATCHER_P(PciIdMatch, m, "")
56{
57 return (arg->vendor_id == m->vendor_id && arg->device_id == m->device_id &&
58 arg->subvendor_id == m->subvendor_id &&
59 arg->subdevice_id == m->subdevice_id);
60}
61
62pci_device_iterator* mockIter = reinterpret_cast<pci_device_iterator*>(0x42);
63
64constexpr pciaddr_t mockBaseAddr = 0xdeadbeef;
65constexpr pciaddr_t mockRegionSize = 0x20000;
66
67class Device
68{
69 public:
Patrick Venturee261ca22020-09-28 12:47:39 -070070 virtual ~Device() = default;
Benjamin Faire5aafa52020-06-05 21:04:24 -070071 virtual const struct pci_id_match* getMatch() const = 0;
72 virtual struct pci_device getDevice() const = 0;
Willy Tub487eb42021-09-16 21:44:43 -070073 virtual void expectSetup(PciAccessMock&, const struct pci_device&) const {};
Willy Tu8a9de242020-10-30 11:00:21 -070074 virtual std::unique_ptr<PciBridgeIntf>
75 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const = 0;
Benjamin Faire5aafa52020-06-05 21:04:24 -070076 virtual std::string getName() const = 0;
77};
78
79class NuvotonDevice : public Device
80{
81 public:
82 const struct pci_id_match* getMatch() const override
83 {
84 return &match;
85 }
86
87 struct pci_device getDevice() const override
88 {
89 struct pci_device dev;
90
91 dev.vendor_id = match.vendor_id;
92 dev.device_id = match.device_id;
93
94 dev.regions[0].is_IO = false;
95 dev.regions[0].base_addr = mockBaseAddr;
96 dev.regions[0].size = mockRegionSize;
97
98 return dev;
99 }
100
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700101 void expectSetup(PciAccessMock& pciMock,
102 const struct pci_device& dev) const override
103 {
104 static constexpr std::uint8_t defaultVal = 0x40;
105
106 InSequence in;
107
108 EXPECT_CALL(pciMock,
109 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
110 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
111 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(
112 Eq(&dev), defaultVal | bridgeEnabled, config))
113 .WillOnce(Return(0));
114
115 EXPECT_CALL(pciMock,
116 pci_device_cfg_read_u8(Eq(&dev), NotNull(), config))
117 .WillOnce(
118 DoAll(SetArgPointee<1>(defaultVal | bridgeEnabled), Return(0)));
119 EXPECT_CALL(pciMock,
120 pci_device_cfg_write_u8(Eq(&dev), defaultVal, config))
121 .WillOnce(Return(0));
122 }
123
Willy Tu8a9de242020-10-30 11:00:21 -0700124 std::unique_ptr<PciBridgeIntf>
125 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override
Benjamin Faire5aafa52020-06-05 21:04:24 -0700126 {
Willy Tu8a9de242020-10-30 11:00:21 -0700127 return std::make_unique<NuvotonPciBridge>(pci, skipBridgeDisable);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700128 }
129
130 std::string getName() const override
131 {
132 return "Nuvoton"s;
133 }
134
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700135 /* Offset to the config register */
136 static constexpr int config = 0x04;
137 /* Second bit determines whether bridge is enabled */
138 static constexpr std::uint8_t bridgeEnabled = 0x02;
139
Benjamin Faire5aafa52020-06-05 21:04:24 -0700140 private:
141 static constexpr struct pci_id_match match
142 {
Willy Tub487eb42021-09-16 21:44:43 -0700143 0x1050, 0x0750, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0
Benjamin Faire5aafa52020-06-05 21:04:24 -0700144 };
145};
146
147class AspeedDevice : public Device
148{
149 public:
150 const struct pci_id_match* getMatch() const override
151 {
152 return &match;
153 }
154
155 struct pci_device getDevice() const override
156 {
157 struct pci_device dev;
158
159 dev.vendor_id = match.vendor_id;
160 dev.device_id = match.device_id;
161
162 dev.regions[1].is_IO = false;
163 dev.regions[1].base_addr = mockBaseAddr;
164 dev.regions[1].size = mockRegionSize;
165
166 return dev;
167 }
168
Willy Tu8a9de242020-10-30 11:00:21 -0700169 std::unique_ptr<PciBridgeIntf>
170 getBridge(PciAccess* pci, bool skipBridgeDisable = false) const override
Benjamin Faire5aafa52020-06-05 21:04:24 -0700171 {
Willy Tu8a9de242020-10-30 11:00:21 -0700172 return std::make_unique<AspeedPciBridge>(pci, skipBridgeDisable);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700173 }
174
175 std::string getName() const override
176 {
177 return "Aspeed"s;
178 }
179
180 /* Offset to the config region */
181 static constexpr int config = 0x0f000;
182 /* Lower bit determines whether bridge is enabled */
183 static constexpr std::uint8_t bridgeEnabled = 0x01;
184 /* Offset to the MMIO address configuration */
185 static constexpr int bridge = 0x0f004;
186
187 private:
188 static constexpr struct pci_id_match match
189 {
Willy Tub487eb42021-09-16 21:44:43 -0700190 0x1a03, 0x2000, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, 0
Benjamin Faire5aafa52020-06-05 21:04:24 -0700191 };
192};
193
194NuvotonDevice nuvotonDevice;
195AspeedDevice aspeedDevice;
196
197class PciSetupTest : public testing::TestWithParam<Device*>
198{};
199
200/* Handle device not found */
201TEST_P(PciSetupTest, NotFound)
Benjamin Fair20a18092020-06-08 11:12:21 -0700202{
203 PciAccessMock pciMock;
204
Benjamin Faire5aafa52020-06-05 21:04:24 -0700205 InSequence in;
206
207 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
208 PciIdMatch(GetParam()->getMatch())))
209 .WillOnce(Return(mockIter));
210 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
211 .WillOnce(Return(nullptr));
212 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
213
214 EXPECT_THROW(GetParam()->getBridge(&pciMock), NotFoundException);
215}
216
217/* Test finding device but probe fails */
218TEST_P(PciSetupTest, ProbeFail)
219{
220 PciAccessMock pciMock;
221 struct pci_device dev;
222
223 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
224 PciIdMatch(GetParam()->getMatch())))
225 .WillOnce(Return(mockIter));
226 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
227 .WillOnce(Return(&dev))
228 .WillRepeatedly(Return(nullptr));
229
230 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev))).WillOnce(Return(EFAULT));
231
232 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
233
234 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
235}
236
237/* Test finding device but mapping fails */
238TEST_P(PciSetupTest, MapFail)
239{
240 PciAccessMock pciMock;
241 struct pci_device dev;
242
243 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
244 PciIdMatch(GetParam()->getMatch())))
245 .WillOnce(Return(mockIter));
246 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
247 .WillOnce(Return(&dev))
248 .WillRepeatedly(Return(nullptr));
249
250 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
251 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
252
253 EXPECT_CALL(pciMock,
254 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
255 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
256 .WillOnce(Return(EFAULT));
257
258 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
259
260 EXPECT_THROW(GetParam()->getBridge(&pciMock), std::system_error);
261}
262
263/* Test finding device but unmapping fails */
264TEST_P(PciSetupTest, UnmapFail)
265{
266 PciAccessMock pciMock;
267 struct pci_device dev;
268 std::vector<std::uint8_t> region(mockRegionSize);
269
270 EXPECT_CALL(pciMock, pci_id_match_iterator_create(
271 PciIdMatch(GetParam()->getMatch())))
272 .WillOnce(Return(mockIter));
273 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
274 .WillOnce(Return(&dev))
275 .WillRepeatedly(Return(nullptr));
276
277 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
278 .WillOnce(DoAll(Assign(&dev, GetParam()->getDevice()), Return(0)));
279
280 EXPECT_CALL(pciMock,
281 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
282 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
283 .WillOnce(DoAll(SetArgPointee<4>(region.data()), Return(0)));
284
285 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
286 EXPECT_CALL(pciMock, pci_device_unmap_range(Eq(&dev), Eq(region.data()),
287 mockRegionSize))
288 .WillOnce(Return(EFAULT));
289
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700290 GetParam()->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700291 // This will print an error but not throw
292 GetParam()->getBridge(&pciMock);
293}
294
295/* Create expectations on pciMock for finding device and mapping memory region
296 */
297void expectSetup(PciAccessMock& pciMock, struct pci_device& dev, Device* param,
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700298 std::uint8_t* region, bool deviceExpectations = true)
Benjamin Faire5aafa52020-06-05 21:04:24 -0700299{
300 EXPECT_CALL(pciMock,
301 pci_id_match_iterator_create(PciIdMatch(param->getMatch())))
302 .WillOnce(Return(mockIter));
303 EXPECT_CALL(pciMock, pci_device_next(Eq(mockIter)))
304 .WillOnce(Return(&dev))
305 .WillRepeatedly(Return(nullptr));
306
307 EXPECT_CALL(pciMock, pci_device_probe(Eq(&dev)))
308 .WillOnce(DoAll(Assign(&dev, param->getDevice()), Return(0)));
309
310 EXPECT_CALL(pciMock,
311 pci_device_map_range(Eq(&dev), mockBaseAddr, mockRegionSize,
312 PCI_DEV_MAP_FLAG_WRITABLE, NotNull()))
313 .WillOnce(DoAll(SetArgPointee<4>(region), Return(0)));
314
315 EXPECT_CALL(pciMock, pci_iterator_destroy(Eq(mockIter))).Times(1);
316 EXPECT_CALL(pciMock,
317 pci_device_unmap_range(Eq(&dev), Eq(region), mockRegionSize))
318 .WillOnce(Return(0));
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700319
Vivekanand Veeracholan55b1a712021-02-18 12:06:37 -0800320 EXPECT_CALL(pciMock, pci_device_enable(Eq(&dev))).Times(1);
321
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700322 if (deviceExpectations)
323 param->expectSetup(pciMock, dev);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700324}
325
326/* Test finding device and mapping memory region */
327TEST_P(PciSetupTest, Success)
328{
329 PciAccessMock pciMock;
330 struct pci_device dev;
331 std::vector<std::uint8_t> region(mockRegionSize);
332
333 expectSetup(pciMock, dev, GetParam(), region.data());
334
335 GetParam()->getBridge(&pciMock);
336}
337
338INSTANTIATE_TEST_SUITE_P(Default, PciSetupTest,
339 ::testing::Values(&nuvotonDevice, &aspeedDevice),
340 [](const testing::TestParamInfo<Device*>& info) {
341 return info.param->getName();
342 });
343
344TEST(NuvotonWriteTest, TooLarge)
345{
346 PciAccessMock pciMock;
347 struct pci_device dev;
348 std::vector<std::uint8_t> region(mockRegionSize);
349 std::vector<std::uint8_t> data(0x4001);
350
351 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
352
353 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500354 EXPECT_THROW(bridge->write(std::span<std::uint8_t>(data)), ToolException);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700355}
356
357TEST(NuvotonWriteTest, Success)
358{
359 PciAccessMock pciMock;
360 struct pci_device dev;
361 std::vector<std::uint8_t> region(mockRegionSize);
362 std::vector<std::uint8_t> data(0x4000);
363
364 std::generate(data.begin(), data.end(), std::rand);
365
366 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
367
368 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500369 bridge->write(std::span<std::uint8_t>(data));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700370
Patrick Williams28c00d62022-04-27 08:37:13 -0500371 EXPECT_THAT(std::span<uint8_t>(&region[0], data.size()),
372 SpanEq(std::span<uint8_t>(data)));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700373}
374
375TEST(NuvotonConfigureTest, Success)
376{
377 PciAccessMock pciMock;
378 struct pci_device dev;
379 std::vector<std::uint8_t> region(mockRegionSize);
380 ipmi_flash::PciConfigResponse config{0x123bea51};
381
382 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
383
384 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
385 bridge->configure(config);
386
387 /* No effect from calling configure(), so the whole region should be 0 */
388 EXPECT_THAT(region, Each(0));
389}
390
391TEST(NuvotonDataLengthTest, Success)
392{
393 PciAccessMock pciMock;
394 struct pci_device dev;
395 std::vector<std::uint8_t> region(mockRegionSize);
396
397 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
398
399 std::unique_ptr<PciBridgeIntf> bridge = nuvotonDevice.getBridge(&pciMock);
400 EXPECT_EQ(bridge->getDataLength(), 0x4000);
401}
402
Benjamin Fairc1a30c02020-06-09 11:46:34 -0700403/* Make sure config register is left alone if the bridge is already enabled */
404TEST(NuvotonBridgeTest, AlreadyEnabledSuccess)
405{
406 PciAccessMock pciMock;
407 struct pci_device dev;
408 std::vector<std::uint8_t> region(mockRegionSize);
409
410 constexpr std::uint8_t defaultVal = 0x40;
411
412 /* Only set standard expectations; not those from nuvotonDevice */
413 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
414
415 {
416 InSequence in;
417
418 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
419 NuvotonDevice::config))
420 .WillOnce(DoAll(
421 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
422 Return(0)));
423
424 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
425 NuvotonDevice::config))
426 .WillOnce(DoAll(
427 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
428 Return(0)));
429 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
430 NuvotonDevice::config))
431 .WillOnce(Return(0));
432 }
433
434 nuvotonDevice.getBridge(&pciMock);
435}
436
437/* Read fails when attempting to setup the bridge */
438TEST(NuvotonBridgeTest, ReadSetupFail)
439{
440 PciAccessMock pciMock;
441 struct pci_device dev;
442 std::vector<std::uint8_t> region(mockRegionSize);
443
444 /* Only set standard expectations; not those from nuvotonDevice */
445 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
446
447 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
448 NuvotonDevice::config))
449 .WillOnce(Return(EFAULT));
450
451 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
452}
453
454/* Write fails when attempting to setup the bridge */
455TEST(NuvotonBridgeTest, WriteSetupFail)
456{
457 PciAccessMock pciMock;
458 struct pci_device dev;
459 std::vector<std::uint8_t> region(mockRegionSize);
460
461 constexpr std::uint8_t defaultVal = 0x40;
462
463 /* Only set standard expectations; not those from nuvotonDevice */
464 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
465
466 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
467 NuvotonDevice::config))
468 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
469 EXPECT_CALL(pciMock,
470 pci_device_cfg_write_u8(
471 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
472 NuvotonDevice::config))
473 .WillOnce(Return(EFAULT));
474
475 EXPECT_THROW(nuvotonDevice.getBridge(&pciMock), std::system_error);
476}
477
478/* Read fails when attempting to disable the bridge */
479TEST(NuvotonBridgeTest, ReadDisableFail)
480{
481 PciAccessMock pciMock;
482 struct pci_device dev;
483 std::vector<std::uint8_t> region(mockRegionSize);
484
485 constexpr std::uint8_t defaultVal = 0x40;
486
487 /* Only set standard expectations; not those from nuvotonDevice */
488 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
489
490 {
491 InSequence in;
492
493 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
494 NuvotonDevice::config))
495 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
496 EXPECT_CALL(pciMock,
497 pci_device_cfg_write_u8(
498 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
499 NuvotonDevice::config))
500 .WillOnce(Return(0));
501
502 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
503 NuvotonDevice::config))
504 .WillOnce(Return(EFAULT));
505 }
506
507 nuvotonDevice.getBridge(&pciMock);
508}
509
510/* Write fails when attempting to disable the bridge */
511TEST(NuvotonBridgeTest, WriteDisableFail)
512{
513 PciAccessMock pciMock;
514 struct pci_device dev;
515 std::vector<std::uint8_t> region(mockRegionSize);
516
517 constexpr std::uint8_t defaultVal = 0x40;
518
519 /* Only set standard expectations; not those from nuvotonDevice */
520 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
521
522 {
523 InSequence in;
524
525 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
526 NuvotonDevice::config))
527 .WillOnce(DoAll(SetArgPointee<1>(defaultVal), Return(0)));
528 EXPECT_CALL(pciMock,
529 pci_device_cfg_write_u8(
530 Eq(&dev), defaultVal | NuvotonDevice::bridgeEnabled,
531 NuvotonDevice::config))
532 .WillOnce(Return(0));
533
534 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
535 NuvotonDevice::config))
536 .WillOnce(DoAll(
537 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
538 Return(0)));
539 EXPECT_CALL(pciMock, pci_device_cfg_write_u8(Eq(&dev), defaultVal,
540 NuvotonDevice::config))
541 .WillOnce(Return(EFAULT));
542 }
543
544 nuvotonDevice.getBridge(&pciMock);
545}
546
547/* Make sure the bridge gets enabled when needed */
548TEST(NuvotonBridgeTest, NotEnabledSuccess)
549{
550 PciAccessMock pciMock;
551 struct pci_device dev;
552 std::vector<std::uint8_t> region(mockRegionSize);
553
554 expectSetup(pciMock, dev, &nuvotonDevice, region.data());
555 nuvotonDevice.getBridge(&pciMock);
556}
557
Willy Tu8a9de242020-10-30 11:00:21 -0700558/* Make sure it skips the disable bridge call when skipBridgeDisable is true */
559TEST(NuvotonBridgeTest, SkipDisable)
560{
561 PciAccessMock pciMock;
562 struct pci_device dev;
563 std::vector<std::uint8_t> region(mockRegionSize);
564
565 constexpr std::uint8_t defaultVal = 0x40;
566
567 /* Only set standard expectations; not those from nuvotonDevice */
568 expectSetup(pciMock, dev, &nuvotonDevice, region.data(), false);
569
570 {
571 InSequence in;
572
573 /* Only expect call for enableBridge() */
574 EXPECT_CALL(pciMock, pci_device_cfg_read_u8(Eq(&dev), NotNull(),
575 NuvotonDevice::config))
576 .WillOnce(DoAll(
577 SetArgPointee<1>(defaultVal | NuvotonDevice::bridgeEnabled),
578 Return(0)));
579 }
580
581 /* Setting skipBridgeDisable to true */
582 nuvotonDevice.getBridge(&pciMock, true);
583}
584
Benjamin Faire5aafa52020-06-05 21:04:24 -0700585TEST(AspeedWriteTest, TooLarge)
586{
587 PciAccessMock pciMock;
588 struct pci_device dev;
589 std::vector<std::uint8_t> region(mockRegionSize);
590 std::vector<std::uint8_t> data(0x10001);
591
592 expectSetup(pciMock, dev, &aspeedDevice, region.data());
593
594 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500595 EXPECT_THROW(bridge->write(std::span<std::uint8_t>(data)), ToolException);
Benjamin Faire5aafa52020-06-05 21:04:24 -0700596}
597
598TEST(AspeedWriteTest, Success)
599{
600 PciAccessMock pciMock;
601 struct pci_device dev;
602 std::vector<std::uint8_t> region(mockRegionSize);
603 std::vector<std::uint8_t> data(0x10000);
604
605 std::generate(data.begin(), data.end(), std::rand);
606
607 expectSetup(pciMock, dev, &aspeedDevice, region.data());
608
609 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
Patrick Williams28c00d62022-04-27 08:37:13 -0500610 bridge->write(std::span<std::uint8_t>(data));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700611
Patrick Williams28c00d62022-04-27 08:37:13 -0500612 EXPECT_THAT(std::span<uint8_t>(&region[0x10000], data.size()),
613 SpanEq(std::span<uint8_t>(data)));
Benjamin Faire5aafa52020-06-05 21:04:24 -0700614}
615
616TEST(AspeedConfigureTest, Success)
617{
618 PciAccessMock pciMock;
619 struct pci_device dev;
620 std::vector<std::uint8_t> region(mockRegionSize);
621 ipmi_flash::PciConfigResponse config{0x123bea51};
622
623 expectSetup(pciMock, dev, &aspeedDevice, region.data());
624
625 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
626 bridge->configure(config);
627
628 auto configSpan = stdplus::raw::asSpan<uint8_t>(config);
629 EXPECT_THAT(
Patrick Williams28c00d62022-04-27 08:37:13 -0500630 std::span<uint8_t>(&region[AspeedDevice::bridge], sizeof(config)),
Benjamin Faire5aafa52020-06-05 21:04:24 -0700631 SpanEq(configSpan));
632}
633
634TEST(AspeedDataLengthTest, Success)
635{
636 PciAccessMock pciMock;
637 struct pci_device dev;
638 std::vector<std::uint8_t> region(mockRegionSize);
639
640 expectSetup(pciMock, dev, &aspeedDevice, region.data());
641
642 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
643 EXPECT_EQ(bridge->getDataLength(), 0x10000);
644}
645
646/* Make sure config region is left alone if the bridge is already enabled */
647TEST(AspeedBridgeTest, AlreadyEnabledSuccess)
648{
649 PciAccessMock pciMock;
650 struct pci_device dev;
651 std::vector<std::uint8_t> region(mockRegionSize);
652
653 constexpr std::uint8_t defaultVal = 0x42;
654
655 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
656
657 expectSetup(pciMock, dev, &aspeedDevice, region.data());
658
659 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
660
661 {
662 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
663 enabledRegion[AspeedDevice::config] =
664 defaultVal | AspeedDevice::bridgeEnabled;
665 EXPECT_THAT(region, ContainerEq(enabledRegion));
666 }
667
668 bridge.reset();
669
670 {
671 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
672 disabledRegion[AspeedDevice::config] = defaultVal;
673 EXPECT_THAT(region, ContainerEq(disabledRegion));
674 }
675}
676
Willy Tu8a9de242020-10-30 11:00:21 -0700677/* Make sure the config region remains the same even after cleanup if
678 * skipBridgeDisable is true */
679TEST(AspeedBridgeTest, SkipDisable)
680{
681 PciAccessMock pciMock;
682 struct pci_device dev;
683 std::vector<std::uint8_t> region(mockRegionSize);
684
685 constexpr std::uint8_t defaultVal = 0x42;
686
687 region[AspeedDevice::config] = defaultVal | AspeedDevice::bridgeEnabled;
688
689 expectSetup(pciMock, dev, &aspeedDevice, region.data());
690
691 /* Setting skipBridgeDisable to true */
692 std::unique_ptr<PciBridgeIntf> bridge =
693 aspeedDevice.getBridge(&pciMock, true);
694
695 {
696 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
697 enabledRegion[AspeedDevice::config] =
698 defaultVal | AspeedDevice::bridgeEnabled;
699 EXPECT_THAT(region, ContainerEq(enabledRegion));
700 }
701
702 bridge.reset();
703
704 {
705 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
706 disabledRegion[AspeedDevice::config] =
707 defaultVal | AspeedDevice::bridgeEnabled;
708 EXPECT_THAT(region, ContainerEq(disabledRegion));
709 }
710}
711
Benjamin Faire5aafa52020-06-05 21:04:24 -0700712/* Make sure the bridge gets enabled when needed */
713TEST(AspeedBridgeTest, NotEnabledSuccess)
714{
715 PciAccessMock pciMock;
716 struct pci_device dev;
717 std::vector<std::uint8_t> region(mockRegionSize);
718
719 constexpr std::uint8_t defaultVal = 0x42;
720
721 region[AspeedDevice::config] = defaultVal;
722
723 expectSetup(pciMock, dev, &aspeedDevice, region.data());
724
725 std::unique_ptr<PciBridgeIntf> bridge = aspeedDevice.getBridge(&pciMock);
726
727 {
728 std::vector<std::uint8_t> enabledRegion(mockRegionSize);
729 enabledRegion[AspeedDevice::config] =
730 defaultVal | AspeedDevice::bridgeEnabled;
731 EXPECT_THAT(region, ContainerEq(enabledRegion));
732 }
733
734 bridge.reset();
735
736 {
737 std::vector<std::uint8_t> disabledRegion(mockRegionSize);
738 disabledRegion[AspeedDevice::config] = defaultVal;
739 EXPECT_THAT(region, ContainerEq(disabledRegion));
740 }
Benjamin Fair20a18092020-06-08 11:12:21 -0700741}
742
743} // namespace
744} // namespace host_tool